Merge branch 'StefanSchippers:master' into master

This commit is contained in:
Chayan Deb 2025-03-12 04:10:20 +00:00 committed by GitHub
commit d9ed2f0e09
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 354 additions and 100 deletions

View File

@ -813,6 +813,7 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
<li><kbd> textlayer </kbd> layer number for texts </li>
<li><kbd> top_path </kbd> get top hier path of current window (always "" for tabbed if) </li>
<li><kbd> topwindow </kbd> same as top_path but main window returned as "." </li>
<li><kbd> ui_state </kbd> return UI state </li>
<li><kbd> version </kbd> return xschem version </li>
<li><kbd> wirelayer </kbd> layer used for wires </li>
<li><kbd> wires </kbd> number of wires </li>
@ -989,13 +990,17 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
<li><kbd> is_generator symbol</kbd></li><pre>
tell if 'symbol' is a generator (symbol(param1,param2,...) </pre>
<li><kbd> line [x1 y1 x2 y2] [pos] [propstring] [draw]</kbd></li><pre>
line
line gui
if 'x1 y1 x2 y2'is given place line on current
layer (rectcolor) at indicated coordinates.
if 'pos' is given insert at given position in rectangle array.
if 'pos' is given insert at given position in line array.
if 'pos' set to -1 append to last element in line array.
'propstring' is the attribute string. Set to empty if not given.
if 'draw' is set to 1 (default) draw the new object, else don't
If no coordinates are given start a GUI operation of line placement </pre>
If no coordinates are given start a GUI operation of line placement
if `gui` argument is given start a line GUI placement with 1st point
set to current mouse coordinates </pre>
<li><kbd> line_width n</kbd></li><pre>
set line width to floating point number 'n' </pre>
<li><kbd> list_hierarchy</kbd></li><pre>
@ -1161,8 +1166,10 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
If not given take from symbol template attribute.</pre>
<li><kbd> place_text</kbd></li><pre>
Start a GUI placement of a text object </pre>
<li><kbd> polygon</kbd></li><pre>
Start a GUI placement of a polygon </pre>
<li><kbd> polygon [gui]</kbd></li><pre>
Start a GUI placement of a polygon
if `gui` argument is given start a polygon GUI placement with 1st point
set to current mouse coordinates </pre>
<li><kbd> preview_window create|draw|destroy|close [win_path] [file]</kbd></li><pre>
destroy: will delete preview schematic data and destroy container window
close: same as destroy but leave the container window.
@ -1337,14 +1344,19 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
Rebuild selection list</pre>
<li><kbd> record_global_node n node</kbd></li><pre>
call the record_global_node function (list of netlist global nodes) </pre>
<li><kbd> rect [x1 y1 x2 y2] [pos] [propstring] [draw]</kbd></li><pre>
if 'x1 y1 x2 y2'is given place recangle on current
layer (rectcolor) at indicated coordinates.
if 'pos' is given insert at given position in rectangle array.
if 'pos' set to -1 append rectangle to last element in rectangle array.
'propstring' is the attribute string. Set to empty if not given.
if 'draw' is set to 1 (default) draw the new object, else don't
If no coordinates are given start a GUI operation of rectangle placement </pre>
<li><kbd> rect ...</kbd></li><pre>
rect [x1 y1 x2 y2] [pos] [propstring] [draw]
if 'x1 y1 x2 y2'is given place recangle on current
layer (rectcolor) at indicated coordinates.
if 'pos' is given insert at given position in rectangle array.
if 'pos' set to -1 append rectangle to last element in rectangle array.
'propstring' is the attribute string. Set to empty if not given.
if 'draw' is set to 1 (default) draw the new object, else don't
rect
If no coordinates are given start a GUI operation of rectangle placement
rect gui
if `gui` argument is given start a GUI placement of a rectangle with 1st
point starting from current mouse coordinates </pre>
<li><kbd> redo</kbd></li><pre>
Redo last undone action </pre>
<li><kbd> redraw</kbd></li><pre>
@ -1664,8 +1676,12 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
<li><kbd> wire_coord n</kbd></li><pre>
return 4 coordinates of wire[n] </pre>
<li><kbd> wire [x1 y1 x2 y2] [pos] [prop] [sel]</kbd></li><pre>
wire
wire gui
Place a new wire
if no coordinates are given start a GUI wire placement </pre>
if no coordinates are given start a GUI wire placement
if `gui` argument is given start a GUI placement of a wire with 1st point
starting from current mouse coordinates </pre>
<li><kbd> wire_cut [x y] [noalign]</kbd></li><pre>
start a wire cut operation. Point the mouse in the middle of a wire and
Alt-click right button.

View File

@ -213,7 +213,7 @@ static void start_place_symbol(void)
}
}
static void start_line(double mx, double my)
void start_line(double mx, double my)
{
xctx->last_command = STARTLINE;
if(xctx->ui_state & STARTLINE) {
@ -233,7 +233,7 @@ static void start_line(double mx, double my)
new_line(PLACE, mx, my);
}
static void start_wire(double mx, double my)
void start_wire(double mx, double my)
{
dbg(1, "start_wire(): ui_state=%d, ui_state2=%d last_command=%d\n",
xctx->ui_state, xctx->ui_state2, xctx->last_command);

View File

@ -1725,6 +1725,12 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
Tcl_SetResult(interp, top_path,TCL_VOLATILE);
}
break;
case 'u':
if(!strcmp(argv[2], "ui_state")) { /* return UI state */
if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
Tcl_SetResult(interp, my_itoa(xctx->ui_state), TCL_VOLATILE);
}
break;
case 'v':
if(!strcmp(argv[2], "version")) { /* return xschem version */
Tcl_SetResult(interp, XSCHEM_VERSION, TCL_VOLATILE);
@ -2787,13 +2793,17 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
break;
case 'l': /*----------------------------------------------*/
/* line [x1 y1 x2 y2] [pos] [propstring] [draw]
* line
* line gui
* if 'x1 y1 x2 y2'is given place line on current
* layer (rectcolor) at indicated coordinates.
* if 'pos' is given insert at given position in rectangle array.
* if 'pos' is given insert at given position in line array.
* if 'pos' set to -1 append to last element in line array.
* 'propstring' is the attribute string. Set to empty if not given.
* if 'draw' is set to 1 (default) draw the new object, else don't
* If no coordinates are given start a GUI operation of line placement */
* If no coordinates are given start a GUI operation of line placement
* if `gui` argument is given start a line GUI placement with 1st point
* set to current mouse coordinates */
if(!strcmp(argv[1], "line"))
{
double x1,y1,x2,y2;
@ -2819,6 +2829,21 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
}
set_modify(1);
}
else if(argc == 3 && !strcmp(argv[2], "gui")) {
int prev_state = xctx->ui_state;
int infix_interface = tclgetboolvar("infix_interface");
if(infix_interface) {
start_line(xctx->mousex_snap, xctx->mousey_snap);
if(prev_state == STARTLINE) {
tcleval("set constr_mv 0" );
xctx->constr_mv=0;
}
} else {
xctx->last_command = 0;
xctx->ui_state |= MENUSTART;
xctx->ui_state2 = MENUSTARTLINE;
}
}
else {
xctx->last_command = 0;
xctx->ui_state |= MENUSTART;
@ -3701,13 +3726,28 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
Tcl_ResetResult(interp);
}
/* polygon
* Start a GUI placement of a polygon */
/* polygon [gui]
* Start a GUI placement of a polygon
* if `gui` argument is given start a polygon GUI placement with 1st point
* set to current mouse coordinates */
else if(!strcmp(argv[1], "polygon"))
{
if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
xctx->ui_state |= MENUSTART;
xctx->ui_state2 = MENUSTARTPOLYGON;
if(argc > 2 && !strcmp(argv[2], "gui")) {
int infix_interface = tclgetboolvar("infix_interface");
if(infix_interface) {
xctx->mx_double_save=xctx->mousex_snap;
xctx->my_double_save=xctx->mousey_snap;
xctx->last_command = 0;
new_polygon(PLACE, xctx->mousex_snap, xctx->mousey_snap);
} else {
xctx->ui_state |= MENUSTART;
xctx->ui_state2 = MENUSTARTPOLYGON;
}
} else {
xctx->ui_state |= MENUSTART;
xctx->ui_state2 = MENUSTARTPOLYGON;
}
}
/* preview_window create|draw|destroy|close [win_path] [file]
@ -4434,7 +4474,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
}
/* rebuild_connectivity
Rebuild logical connectivity abstraction of schematic */
* Rebuild logical connectivity abstraction of schematic */
else if(!strcmp(argv[1], "rebuild_connectivity"))
{
int err = 0;
@ -4473,14 +4513,19 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
Tcl_SetResult(interp, my_itoa(ret), TCL_VOLATILE);
}
/* rect [x1 y1 x2 y2] [pos] [propstring] [draw]
* if 'x1 y1 x2 y2'is given place recangle on current
* layer (rectcolor) at indicated coordinates.
* if 'pos' is given insert at given position in rectangle array.
* if 'pos' set to -1 append rectangle to last element in rectangle array.
* 'propstring' is the attribute string. Set to empty if not given.
* if 'draw' is set to 1 (default) draw the new object, else don't
* If no coordinates are given start a GUI operation of rectangle placement */
/* rect ...
* rect [x1 y1 x2 y2] [pos] [propstring] [draw]
* if 'x1 y1 x2 y2'is given place recangle on current
* layer (rectcolor) at indicated coordinates.
* if 'pos' is given insert at given position in rectangle array.
* if 'pos' set to -1 append rectangle to last element in rectangle array.
* 'propstring' is the attribute string. Set to empty if not given.
* if 'draw' is set to 1 (default) draw the new object, else don't
* rect
* If no coordinates are given start a GUI operation of rectangle placement
* rect gui
* if `gui` argument is given start a GUI placement of a rectangle with 1st
* point starting from current mouse coordinates */
else if(!strcmp(argv[1], "rect"))
{
double x1,y1,x2,y2;
@ -4510,8 +4555,18 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
xctx->draw_window = save;
}
set_modify(1);
}
else {
} else if(argc > 2 && !strcmp(argv[2], "gui")) {
int infix_interface = tclgetboolvar("infix_interface");
if(infix_interface) {
xctx->mx_double_save=xctx->mousex_snap;
xctx->my_double_save=xctx->mousey_snap;
xctx->last_command = 0;
new_rect(PLACE,xctx->mousex_snap, xctx->mousey_snap);
} else {
xctx->ui_state |= MENUSTART;
xctx->ui_state2 = MENUSTARTRECT;
}
} else {
xctx->ui_state |= MENUSTART;
xctx->ui_state2 = MENUSTARTRECT;
}
@ -6374,8 +6429,12 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
}
}
/* wire [x1 y1 x2 y2] [pos] [prop] [sel]
* wire
* wire gui
* Place a new wire
* if no coordinates are given start a GUI wire placement */
* if no coordinates are given start a GUI wire placement
* if `gui` argument is given start a GUI placement of a wire with 1st point
* starting from current mouse coordinates */
else if(!strcmp(argv[1], "wire"))
{
double x1,y1,x2,y2;
@ -6403,7 +6462,21 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
if(tclgetboolvar("autotrim_wires")) trim_wires();
set_modify(1);
}
else {
else if(argc > 2 && !strcmp(argv[2], "gui")) {
int prev_state = xctx->ui_state;
int infix_interface = tclgetboolvar("infix_interface");
if(infix_interface) {
start_wire(xctx->mousex_snap, xctx->mousey_snap);
if(prev_state == STARTWIRE) {
tcleval("set constr_mv 0" );
xctx->constr_mv=0;
}
} else {
xctx->last_command = 0;
xctx->ui_state |= MENUSTART;
xctx->ui_state2 = MENUSTARTWIRE;
}
} else {
xctx->last_command = 0;
xctx->ui_state |= MENUSTART;
xctx->ui_state2 = MENUSTARTWIRE;

View File

@ -1179,7 +1179,7 @@ static int source_tcl_file(char *s)
fprintf(errfp, "Tcl_AppInit() error: can not execute %s, please fix:\n", s);
fprintf(errfp, "%s", tclresult());
#if TCL_MAJOR_VERSION >= 8 && TCL_MINOR_VERSION >=6
fprintf(errfp, "Line No: %d\n", Tcl_GetErrorLine(interp));
fprintf(errfp, "\nLine No: %d\n", Tcl_GetErrorLine(interp));
#endif
fprintf(errfp, "\n");
#if TCL_MAJOR_VERSION >= 8 && TCL_MINOR_VERSION >=6

View File

@ -1401,6 +1401,8 @@ extern void tclmainloop(void);
extern int Tcl_AppInit(Tcl_Interp *interp);
extern void abort_operation(void);
extern void draw_crosshair(int what, int state);
extern void start_line(double mx, double my);
extern void start_wire(double mx, double my);
extern void backannotate_at_cursor_b_pos(xRect *r, Graph_ctx *gr);
/* extern void snapped_wire(double c_snap); */
extern void unselect_attached_floaters(void);

View File

@ -4490,7 +4490,8 @@ proc load_file_dialog {{msg {}} {ext {}} {global_initdir {INITIALINSTDIR}}
set_ne file_dialog_files2 {}
panedwindow .load.l -orient horizontal -height 8c
if { $loadfile == 2} {frame .load.l.recent -takefocus 0}
frame .load.l.paneleft -takefocus 0 -highlightcolor red -highlightthickness 2 -bg {grey90}
frame .load.l.paneleft -takefocus 0 -highlightcolor red -highlightthickness 2 -bg {grey90} \
-highlightbackground [option get . background {}]
eval [subst {listbox .load.l.paneleft.list -listvariable file_dialog_names1 -width 40 -height 12 \
-fg black -background {grey90} -highlightthickness 0 -relief flat -borderwidth 0 \
-yscrollcommand ".load.l.paneleft.yscroll set" -selectmode browse \
@ -4518,14 +4519,12 @@ proc load_file_dialog {{msg {}} {ext {}} {global_initdir {INITIALINSTDIR}}
}
}
panedwindow .load.l.paneright -orient vertical
frame .load.l.paneright.f -takefocus 0
frame .load.l.paneright.draw -background white -height 3.8c -takefocus 0
.load.l.paneright add .load.l.paneright.f
.load.l.paneright add .load.l.paneright.draw -minsize 150
if { ![catch {.load.l.paneright panecget .load.l.paneright.f -stretch}]} {
set optnever {-stretch never}
set optalways {-stretch always}
@ -4546,6 +4545,7 @@ proc load_file_dialog {{msg {}} {ext {}} {global_initdir {INITIALINSTDIR}}
listbox .load.l.paneright.f.list -background {grey90} -listvariable file_dialog_files2 -width 20 -height 12\
-fg black -highlightcolor red -highlightthickness 2 \
-highlightbackground [option get . background {}] \
-yscrollcommand ".load.l.paneright.f.yscroll set" -selectmode $selmode \
-xscrollcommand ".load.l.paneright.f.xscroll set" -exportselection 0
scrollbar .load.l.paneright.f.yscroll -command ".load.l.paneright.f.list yview" -takefocus 0
@ -4596,10 +4596,12 @@ proc load_file_dialog {{msg {}} {ext {}} {global_initdir {INITIALINSTDIR}}
.load.l.paneleft.list selection set $file_dialog_index1
}
label .load.buttons_bot.label -text { File:}
entry .load.buttons_bot.entry -highlightcolor red -highlightthickness 2
entry .load.buttons_bot.entry -highlightcolor red -highlightthickness 2 \
-highlightbackground [option get . background {}]
entry_replace_selection .load.buttons_bot.entry
label .load.buttons_bot.srclab -text { Search:}
entry .load.buttons_bot.src -width 18 -highlightcolor red -highlightthickness 2
entry .load.buttons_bot.src -width 18 -highlightcolor red -highlightthickness 2 \
-highlightbackground [option get . background {}]
entry_replace_selection .load.buttons_bot.src
.load.buttons_bot.src delete 0 end
.load.buttons_bot.src insert 0 $file_dialog_globfilter
@ -4627,28 +4629,6 @@ proc load_file_dialog {{msg {}} {ext {}} {global_initdir {INITIALINSTDIR}}
set file_dialog_retval { }
}
# radiobutton .load.buttons_bot.all -text All -variable file_dialog_globfilter -value {*} -takefocus 0 \
# -command {
# set file_dialog_ext $file_dialog_globfilter
# setglob $file_dialog_dir1
# .load.buttons_bot.src delete 0 end
# .load.buttons_bot.src insert 0 $file_dialog_globfilter
# }
# radiobutton .load.buttons_bot.sym -text .sym -variable file_dialog_globfilter -value {*.sym} -takefocus 0 \
# -command {
# set file_dialog_ext $file_dialog_globfilter
# setglob $file_dialog_dir1
# .load.buttons_bot.src delete 0 end
# .load.buttons_bot.src insert 0 $file_dialog_globfilter
# }
# radiobutton .load.buttons_bot.sch -text .sch -variable file_dialog_globfilter -value {*.sch} -takefocus 0 \
# -command {
# set file_dialog_ext $file_dialog_globfilter
# setglob $file_dialog_dir1
# .load.buttons_bot.src delete 0 end
# .load.buttons_bot.src insert 0 $file_dialog_globfilter
# }
button .load.buttons.up -width 5 -text Up -command {load_file_dialog_up $file_dialog_dir1} -takefocus 0
label .load.buttons.mkdirlab -text { New dir: }
entry .load.buttons.newdir -width 16 -takefocus 0
@ -4717,7 +4697,8 @@ proc load_file_dialog {{msg {}} {ext {}} {global_initdir {INITIALINSTDIR}}
destroy .load
set $global_initdir \"\$file_dialog_dir1\"
"
bind .load <KeyPress-H> {.load.buttons.home invoke }
bind .load <KeyPress-U> {.load.buttons.up invoke }
### update
if { [info exists file_dialog_v_sp0] } {
@ -4806,6 +4787,157 @@ proc load_file_dialog {{msg {}} {ext {}} {global_initdir {INITIALINSTDIR}}
return [file_dialog_getresult $loadfile $confirm_overwrt]
}
#### Display preview of selected symbol
proc insert_symbol_focusin {} {
# puts insert_symbol_focusin
set sel [.ins.center.left.l curselection]
if {$sel eq {}} {
set sel [.ins.center.left.l index active]
.ins.center.left.l selection set active
insert_symbol_preview
}
}
proc insert_symbol_preview {} {
# puts insert_symbol_preview
global insert_symbol
xschem preview_window close .ins.center.right {}
.ins.center.right configure -bg white
bind .ins.center.right <Expose> {}
bind .ins.center.right <Configure> {}
set sel [.ins.center.left.l curselection]
if {$sel eq {}} {
set sel [.ins.center.left.l index active]
.ins.center.left.l selection set active
}
if {$sel ne {}} {
set f [lindex $insert_symbol(fullpathlist) $sel 0]
if {$f ne {}} {
set type [is_xschem_file $f]
if {$type ne {0}} {
.ins.top.dir_e configure -state normal
.ins.top.dir_e delete 0 end
.ins.top.dir_e insert 0 [file dirname [rel_sym_path $f]]
.ins.top.dir_e configure -state readonly
.ins.center.right configure -bg {}
xschem preview_window create .ins.center.right {}
xschem preview_window draw .ins.center.right [list $f]
bind .ins.center.right <Expose> "xschem preview_window draw .ins.center.right [list $f]"
bind .ins.center.right <Configure> "xschem preview_window draw .ins.center.right [list $f]"
}
insert_symbol_place
}
}
}
# new alternate insert_symbol browser
#### fill list of files matching pattern
proc insert_symbol_filelist {paths {maxdepth -1}} {
# puts insert_symbol_filelist
global insert_symbol
set insert_symbol(regex) [.ins.top.pat_e get]
#check if regex is valid
set err [catch {regexp $insert_symbol(regex) {12345}} res]
if {$err} {return}
set f [match_file $insert_symbol(regex) $paths $maxdepth]
set insert_symbol(list) {}
set insert_symbol(fullpathlist) {}
.ins.center.left.l activate 0
foreach i $f {
set type [regexp $insert_symbol(ext) $i]
if {$type} {
set fname [rel_sym_path $i]
lappend insert_symbol(list) $fname
lappend insert_symbol(fullpathlist) $i
}
}
}
proc insert_symbol_place {} {
# puts insert_symbol_place
global insert_symbol
set sel [.ins.center.left.l curselection]
if {$sel eq {}} {
set sel [.ins.center.left.l index active]
.ins.center.left.l selection set active
}
if {$sel ne {}} {
set f [lindex $insert_symbol(fullpathlist) $sel 0]
if {$f ne {}} {
set type [is_xschem_file $f]
if {$type ne {0}} {
xschem abort_operation
xschem place_symbol $f
}
}
}
}
#### paths: list of paths to use for listing symbols
#### maxdepth: how many levels to descend for each $paths directory (-1: no limit)
proc insert_symbol {{paths {}} {maxdepth -1} {ext {.*}}} {
global insert_symbol
# xschem set semaphore [expr {[xschem get semaphore] +1}]
set insert_symbol(ext) $ext
toplevel .ins
frame .ins.top -takefocus 0
panedwindow .ins.center -orient horizontal -height 8c
frame .ins.center.left -takefocus 0
frame .ins.center.right -width 300 -height 250 -bg white -takefocus 0
.ins.center add .ins.center.left
.ins.center add .ins.center.right
frame .ins.bottom -takefocus 0
pack .ins.top -side top -fill x
pack .ins.center -side top -expand 1 -fill both
pack .ins.bottom -side top -fill x
listbox .ins.center.left.l -listvariable insert_symbol(list) -width 50 -height 20 \
-yscrollcommand ".ins.center.left.s set" -highlightcolor red -highlightthickness 2 \
-activestyle underline -highlightbackground [option get . background {}] \
-exportselection 0
scrollbar .ins.center.left.s -command ".ins.center.left.l yview" -takefocus 0
pack .ins.center.left.l -expand 1 -fill both -side left
pack .ins.center.left.s -fill y -side left
label .ins.top.pat_l -text Pattern:
entry .ins.top.pat_e -width 20 -highlightcolor red -highlightthickness 2 \
-highlightbackground [option get . background {}]
label .ins.top.dir_l -text Dir:
entry .ins.top.dir_e -width 50 -takefocus 0 -state readonly
if {[info exists insert_symbol(regex)]} {
.ins.top.pat_e insert 0 $insert_symbol(regex)
}
bind .ins <KeyPress-Escape> {.ins.bottom.dismiss invoke}
bind .ins.top.pat_e <KeyRelease> "
if {{%K} ne {Tab}} {
insert_symbol_filelist [list $paths] [list $maxdepth]
} else {
}
"
bind .ins.center.left.l <<ListboxSelect>> { insert_symbol_preview }
bind .ins.center.left.l <Enter> { insert_symbol_focusin }
button .ins.bottom.dismiss -takefocus 0 -text Dismiss -command {
if { [xschem get ui_state] & 8192 } {
xschem abort_operation
} else {
xschem preview_window close .ins.center.right {}
destroy .ins
}
}
pack .ins.bottom.dismiss -side left
pack .ins.top.pat_l -side left
pack .ins.top.pat_e -side left
pack .ins.top.dir_l -side left
pack .ins.top.dir_e -side left
insert_symbol_filelist $paths $maxdepth
# tkwait window .ins
# xschem set semaphore [expr {[xschem get semaphore] -1}]
}
# /new alternate insert_symbol browser
# get last n path components: example , n=1 --> /aaa/bbb/ccc/ddd.sch -> ccc/ddd.sch
proc get_cell {s n } {
set slist [file split $s]
@ -6608,27 +6740,39 @@ proc viewdata {data {ro {}} {win .view}} {
return $tctx::rcode
}
proc sub_match_file { f {paths {}} } {
global pathlist match_file_dir_arr
proc sub_match_file { f {paths {}} {maxdepth -1} } {
global pathlist match_file_dir_arr match_file_level nolist_libs
set res {}
if {$paths eq {}} {set paths $pathlist}
foreach i $paths {
foreach j [glob -nocomplain -directory $i *] {
# puts "--> $j $f"
# set jj [regsub {/ $} [file normalize ${j}/\ ] {}]
set skip 0
foreach k $nolist_libs {
if {[regexp $k $j]} {
set skip 1
break
}
}
if {$skip} { continue }
if {[file isdirectory $j] && [file readable $j]} {
set jj [regsub {/ $} [file normalize ${j}/\ ] {}]
if {[array names match_file_dir_arr -exact $jj] == {}} {
set match_file_dir_arr($jj) 1
# puts "********** directory $jj"
set sub_res [sub_match_file $f $j] ;# recursive call
if {$sub_res != {} } {set res [concat $res $sub_res]}
if { $maxdepth == -1 || $match_file_level < $maxdepth} {
set jj [regsub {/ $} [file normalize ${j}/\ ] {}]
# if {[array names match_file_dir_arr -exact $jj] == {}} { ... }
if {![info exists match_file_dir_arr($jj)]} {
set match_file_dir_arr($jj) 1
incr match_file_level
set sub_res [sub_match_file $f $j $maxdepth] ;# recursive call
incr match_file_level -1
if {$sub_res != {} } {set res [concat $res $sub_res]}
}
}
} else {
# set fname [file tail $j]
set fname $j
if {[regexp $f $fname]} {
lappend res $j
if {![info exists match_file_dir_arr($j)]} {
set match_file_dir_arr($j) 1
if {[regexp $f $j]} {
lappend res $j
}
}
}
}
@ -6639,37 +6783,54 @@ proc sub_match_file { f {paths {}} } {
# find files into $paths directories matching $f
# use $pathlist global search path if $paths empty
# recursively descend directories
proc match_file { f {paths {}} } {
global match_file_dir_arr
proc match_file { f {paths {}} {maxdepth -1} } {
global match_file_dir_arr match_file_level
set match_file_level 0
catch {unset match_file_dir_arr}
set res [sub_match_file $f $paths]
set res [sub_match_file $f $paths $maxdepth]
catch {unset match_file_dir_arr}
return $res
}
proc sub_find_file { f {paths {}} {first 0} } {
global pathlist match_file_dir_arr
proc sub_find_file { f {paths {}} {first 0} {maxdepth -1}} {
global pathlist match_file_dir_arr match_file_level nolist_libs
set res {}
if {$paths eq {}} {set paths $pathlist}
foreach i $paths {
foreach j [glob -nocomplain -directory $i *] {
# puts "--> $j $f"
set skip 0
foreach k $nolist_libs {
if {[regexp $k $j]} {
set skip 1
break
}
}
if {$skip} { continue }
if {[file isdirectory $j] && [file readable $j]} {
set jj [regsub {/ $} [file normalize ${j}/\ ] {}]
if {[array names match_file_dir_arr -exact $jj] == {}} {
set match_file_dir_arr($jj) 1
# puts "********** directory $jj"
set sub_res [sub_find_file $f $j $first] ;# recursive call
if {$sub_res != {} } {
set res [concat $res $sub_res]
if {$first} {return $res}
if { $maxdepth == -1 || $match_file_level < $maxdepth} {
set jj [regsub {/ $} [file normalize ${j}/\ ] {}]
# if {[array names match_file_dir_arr -exact $jj] == {}} { ... }
if {![info exists match_file_dir_arr($jj)]} {
set match_file_dir_arr($jj) 1
incr match_file_level
set sub_res [sub_find_file $f $j $first $maxdepth] ;# recursive call
incr match_file_level -1
if {$sub_res != {} } {
set res [concat $res $sub_res]
if {$first} {return $res}
}
}
}
} else {
set fname [file tail $j]
if {$fname == $f} {
lappend res $j
if {$first} {return $res}
if {![info exists match_file_dir_arr($j)]} {
set match_file_dir_arr($j) 1
if {$fname == $f} {
lappend res $j
if {$first} {return $res}
}
}
}
}
@ -6680,10 +6841,11 @@ proc sub_find_file { f {paths {}} {first 0} } {
# find given file $f into $paths directories
# use $pathlist global search path if $paths empty
# recursively descend directories
proc find_file { f {paths {}} } {
global match_file_dir_arr
proc find_file { f {paths {}} {maxdepth -1}} {
global match_file_dir_arr match_file_level
set match_file_level 0
catch {unset match_file_dir_arr}
set res [sub_find_file $f $paths 0]
set res [sub_find_file $f $paths 0 $maxdepth]
catch {unset match_file_dir_arr}
return $res
}
@ -6692,10 +6854,11 @@ proc find_file { f {paths {}} } {
# use $pathlist global search path if $paths empty
# recursively descend directories
# only return FIRST FOUND
proc find_file_first { f {paths {}} } {
global match_file_dir_arr
proc find_file_first { f {paths {}} {maxdepth -1}} {
global match_file_dir_arr match_file_level
set match_file_level 0
catch {unset match_file_dir_arr}
set res [sub_find_file $f $paths 1]
set res [sub_find_file $f $paths 1 $maxdepth]
catch {unset match_file_dir_arr}
return $res
}