diff --git a/doc/xschem_man/developer_info.html b/doc/xschem_man/developer_info.html index 25369cc1..e5676ad7 100644 --- a/doc/xschem_man/developer_info.html +++ b/doc/xschem_man/developer_info.html @@ -813,6 +813,7 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
  • textlayer layer number for texts
  • top_path get top hier path of current window (always "" for tabbed if)
  • topwindow same as top_path but main window returned as "."
  • +
  • ui_state return UI state
  • version return xschem version
  • wirelayer layer used for wires
  • wires number of wires
  • @@ -989,13 +990,17 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
  • is_generator symbol
  •     tell if 'symbol' is a generator (symbol(param1,param2,...) 
  • 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
  • line_width n
  •     set line width to floating point number 'n' 
  • list_hierarchy
  • @@ -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.
  • place_text
  •     Start a GUI placement of a text object 
    -
  • 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 
  • preview_window create|draw|destroy|close [win_path] [file]
  •     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
  • record_global_node n node
  •     call the record_global_node function (list of netlist global nodes) 
    -
  • 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 
  • redo
  •     Redo last undone action 
  • redraw
  • @@ -1664,8 +1676,12 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
        
  • wire_coord n
  •     return 4 coordinates of wire[n] 
  • 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
  • wire_cut [x y] [noalign]
  •     start a wire cut operation. Point the mouse in the middle of a wire and
        Alt-click right button.
    diff --git a/src/callback.c b/src/callback.c
    index 44ab24cb..4dd7d3bf 100644
    --- a/src/callback.c
    +++ b/src/callback.c
    @@ -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);
    diff --git a/src/scheduler.c b/src/scheduler.c
    index 84f94fa5..f25ead3d 100644
    --- a/src/scheduler.c
    +++ b/src/scheduler.c
    @@ -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;
    diff --git a/src/xinit.c b/src/xinit.c
    index 192ae975..8ffe0f5c 100644
    --- a/src/xinit.c
    +++ b/src/xinit.c
    @@ -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
    diff --git a/src/xschem.h b/src/xschem.h
    index eb62ea35..93c93b09 100644
    --- a/src/xschem.h
    +++ b/src/xschem.h
    @@ -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);
    diff --git a/src/xschem.tcl b/src/xschem.tcl
    index ca58107d..eda78050 100644
    --- a/src/xschem.tcl
    +++ b/src/xschem.tcl
    @@ -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  {.load.buttons.home invoke }
    +  bind .load  {.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  {}
    +  bind .ins.center.right  {}
    +  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  "xschem preview_window draw .ins.center.right [list $f]"
    +        bind .ins.center.right  "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  {.ins.bottom.dismiss invoke}
    +  bind .ins.top.pat_e  "
    +    if {{%K} ne {Tab}} {
    +      insert_symbol_filelist [list $paths] [list $maxdepth]
    +    } else {
    +    }
    +  "
    +  bind .ins.center.left.l <> { insert_symbol_preview }
    +  bind .ins.center.left.l  { 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
     }