From 9ca81f8ea62083cf1c0b7fe7d730e4d0abccf200 Mon Sep 17 00:00:00 2001 From: "R. Timothy Edwards" Date: Wed, 8 Oct 2025 17:11:27 -0400 Subject: [PATCH] Modified the "tag" command to add an optional subcommand "add" or "replace" as the 2nd argument. This allows a simpler 'tag add ' than the existing awkward 'tag "[tag ]; '. Using "add" also helps avoid mistakes like one that was in the code for a long time which overwrites one of the helper window callbacks. With this done, added some additional callbacks to the "library manager" to update when a new file is created by "select save" or "writeall". Also added "Refresh" buttons to these windows, just in case. Implemented a zoom function on the mouse scroll wheel when the Control key is pressed. This is a stop-gap for a problem with overriding button bindings that re-establish themselves when the tool (box, wiring, etc.) changes. That needs to have a more comprehensive solution (such as tool-specific bindings). --- magic/proto.magicrc.in | 2 ++ tcltk/cellmgr.tcl | 9 +++-- tcltk/drcmgr.tcl | 4 +-- tcltk/libmgr.tcl | 16 +++++++-- tcltk/tclmagic.c | 76 ++++++++++++++++++++++++++++++++++++------ tcltk/texthelper.tcl | 2 +- tcltk/toolkit.tcl | 2 +- tcltk/wrapper.tcl | 34 +++++++++---------- 8 files changed, 109 insertions(+), 36 deletions(-) diff --git a/magic/proto.magicrc.in b/magic/proto.magicrc.in index 23655803..4c39e1fd 100644 --- a/magic/proto.magicrc.in +++ b/magic/proto.magicrc.in @@ -180,6 +180,8 @@ macro XK_Pointer_Button4 "scroll u .05 w" macro XK_Pointer_Button5 "scroll d .05 w" macro Shift_XK_Pointer_Button4 "scroll l .05 w" macro Shift_XK_Pointer_Button5 "scroll r .05 w" +macro Control_XK_Pointer_Button4 "zoom 1.6" +macro Control_XK_Pointer_Button5 "zoom 0.625" # Quick macro function keys for scmos tech (X11 versions only) macro XK_F1 "paint ndiff" macro XK_F2 "paint pdiff" diff --git a/tcltk/cellmgr.tcl b/tcltk/cellmgr.tcl index a239b81c..74cb5ae6 100644 --- a/tcltk/cellmgr.tcl +++ b/tcltk/cellmgr.tcl @@ -10,9 +10,9 @@ if {$::tk_version >= 8.5} { set Opts(cellmgr) 0 -magic::tag select "magic::mgrselect %r" -magic::tag load "catch {magic::clearstack}; magic::cellmanager" -magic::tag getcell "magic::cellmanager" +magic::tag add select "magic::mgrselect %r" +magic::tag add load "catch {magic::clearstack}; magic::cellmanager" +magic::tag add getcell "magic::cellmanager" # Callback to the cell manager @@ -110,11 +110,14 @@ proc magic::makecellmanager { mgrpath } { {magic::instcallback expand} button ${mgrpath}.actionbar.place -text "Place" -command \ {magic::instcallback place} + button ${mgrpath}.actionbar.refresh -text "Refresh" -command \ + {magic::cellmanager update} pack ${mgrpath}.actionbar.load -side left pack ${mgrpath}.actionbar.edit -side left pack ${mgrpath}.actionbar.expand -side left pack ${mgrpath}.actionbar.place -side left + pack ${mgrpath}.actionbar.refresh -side left pack ${mgrpath}.actionbar.done -side right label ${mgrpath}.target.name -text "Target window:" diff --git a/tcltk/drcmgr.tcl b/tcltk/drcmgr.tcl index 0dd5ca08..8d028190 100644 --- a/tcltk/drcmgr.tcl +++ b/tcltk/drcmgr.tcl @@ -10,8 +10,8 @@ if {$::tk_version >= 8.5} { set Opts(drcmgr) 0 -magic::tag addpath "magic::drcmanager" -magic::tag path "magic::drcmanager" +magic::tag add addpath "magic::drcmanager" +magic::tag add path "magic::drcmanager" # Callback to the DRC manager diff --git a/tcltk/libmgr.tcl b/tcltk/libmgr.tcl index 2361e8e6..71888059 100644 --- a/tcltk/libmgr.tcl +++ b/tcltk/libmgr.tcl @@ -10,8 +10,11 @@ if {$::tk_version >= 8.5} { set Opts(libmgr) 0 -magic::tag addpath "magic::libmanager" -magic::tag path "magic::libmanager" +magic::tag add addpath "magic::libmanager" +magic::tag add path "magic::libmanager" +magic::tag add save "magic::libmanager" +magic::tag add writeall "magic::libmanager" +magic::tag add select "magic::libmanager %1" # Callback to the library manager @@ -82,12 +85,15 @@ proc magic::makelibmanager { mgrpath } { button ${mgrpath}.actionbar.load -text "Load" -command {magic::libcallback load} button ${mgrpath}.actionbar.place -text "Place" -command {magic::libcallback place} button ${mgrpath}.actionbar.pick -text "Pick" -command {magic::libcallback pick} + button ${mgrpath}.actionbar.refresh -text "Refresh" \ + -command {magic::libmanager update} checkbutton ${mgrpath}.actionbar.filter -text "Filter" -variable filtered \ -command {magic::libmanager update} pack ${mgrpath}.actionbar.load -side left pack ${mgrpath}.actionbar.place -side left pack ${mgrpath}.actionbar.pick -side left + pack ${mgrpath}.actionbar.refresh -side left pack ${mgrpath}.actionbar.filter -side right label ${mgrpath}.target.name -text "Target window:" @@ -182,6 +188,12 @@ proc magic::libmanager {{option "update"}} { # Use of command "path" is recursive, so break if level > 0 if {[info level] > 1} {return} + # Because this has been tagged to the "select" command, avoid processing + # anything except the approved options. + if { $option != "update" && $option != "create" && $option != "save"} { + return + } + # Check for existence of the manager widget if {[catch {wm state .libmgr}]} { if {$option == "create"} { diff --git a/tcltk/tclmagic.c b/tcltk/tclmagic.c index 9b12aa85..dd1e3aec 100644 --- a/tcltk/tclmagic.c +++ b/tcltk/tclmagic.c @@ -220,7 +220,7 @@ TagCallback(interp, tkpath, argc, argv) if ((argidx >= 0) && (argidx < argc)) { newcmd = (char *)mallocMagic(strlen(substcmd) - + strlen(argv[argidx])); + + strlen(argv[argidx]) + 1); strcpy(newcmd, substcmd); strcpy(newcmd + (int)(sptr - substcmd), argv[argidx]); strcat(newcmd, sptr + 2); @@ -230,9 +230,16 @@ TagCallback(interp, tkpath, argc, argv) } else if (argidx >= argc) { - newcmd = (char *)mallocMagic(strlen(substcmd) + 1); + /* Note that the assumption is that a specific + * command option is expected. Therefore if there + * are fewer options given to the command, a + * placeholder should be added. Use an empty + * brace {} for this. + */ + newcmd = (char *)mallocMagic(strlen(substcmd) + 3); strcpy(newcmd, substcmd); - strcpy(newcmd + (int)(sptr - substcmd), sptr + 2); + strcpy(newcmd + (int)(sptr - substcmd), "{}"); + strcat(newcmd, sptr + 2); freeMagic(substcmd); substcmd = newcmd; sptr = substcmd; @@ -296,11 +303,43 @@ AddCommandTag(ClientData clientData, { HashEntry *entry; char *hstring; + int argstart = 1, idx; + bool doadd = FALSE; + Tcl_Obj *objv1; + + static char *tagtypes[] = + { + "add", "replace", NULL + }; + + typedef enum + { + IDX_ADD, IDX_REPLACE + } tagOption; + + if (argc == 4) + { + /* For four arguments, the 2nd must be "add" or "replace" */ + objv1 = Tcl_NewStringObj(argv[1], strlen(argv[1])); + if (Tcl_GetIndexFromObj(interp, objv1, (const char **)tagtypes, + "tag options", 0, &idx) == TCL_OK) + { + if (idx == IDX_ADD) + doadd = TRUE; + else if (idx == IDX_REPLACE) + doadd = FALSE; + } + else + return TCL_ERROR; + + argstart++; + argc--; + } if (argc != 2 && argc != 3) return TCL_ERROR; - entry = HashFind(&txTclTagTable, argv[1]); + entry = HashFind(&txTclTagTable, argv[argstart]); if (entry == NULL) return TCL_ERROR; @@ -312,16 +351,33 @@ AddCommandTag(ClientData clientData, return TCL_OK; } - if (hstring != NULL) freeMagic(hstring); + /* If there is no existing tag then "tag add" is just "tag replace" */ + if (doadd && (hstring == NULL)) doadd = FALSE; - if (strlen(argv[2]) == 0) + if (doadd) /* add to existing contents */ { - HashSetValue(entry, NULL); + if (strlen(argv[argstart + 1]) > 0) /* Only handle non-empty strings */ + { + char *newstring = mallocMagic(strlen(hstring) + + strlen(argv[argstart + 1]) + 4); + sprintf(newstring, "%s ; %s", hstring, argv[argstart + 1]); + HashSetValue(entry, newstring); + freeMagic(hstring); + } } - else + else /* replace */ { - hstring = StrDup((char **)NULL, argv[2]); - HashSetValue(entry, hstring); + if (hstring != NULL) freeMagic(hstring); + + if (strlen(argv[argstart + 1]) == 0) + { + HashSetValue(entry, NULL); + } + else + { + hstring = StrDup((char **)NULL, argv[argstart + 1]); + HashSetValue(entry, hstring); + } } return TCL_OK; } diff --git a/tcltk/texthelper.tcl b/tcltk/texthelper.tcl index ffa764e8..4b36f143 100644 --- a/tcltk/texthelper.tcl +++ b/tcltk/texthelper.tcl @@ -139,7 +139,7 @@ proc magic::make_texthelper { mgrpath } { # Set up tag callbacks - magic::tag select "[magic::tag select]; magic::update_texthelper" + magic::tag add select "magic::update_texthelper" } # For all editable selected labels, fill in entries in the diff --git a/tcltk/toolkit.tcl b/tcltk/toolkit.tcl index 8230f841..220759e1 100644 --- a/tcltk/toolkit.tcl +++ b/tcltk/toolkit.tcl @@ -105,7 +105,7 @@ magic::macro ^P "magic::gencell {} ; raise .params" # Add tag callback to select to update the gencell window #------------------------------------------------------------- -magic::tag select "[magic::tag select]; magic::gencell_update %1" +magic::tag add select "magic::gencell_update %1" #-------------------------------------------------------------- # Supporting procedures for netlist_to_layout procedure diff --git a/tcltk/wrapper.tcl b/tcltk/wrapper.tcl index 18ea23ed..c00777ff 100644 --- a/tcltk/wrapper.tcl +++ b/tcltk/wrapper.tcl @@ -542,23 +542,23 @@ proc magic::captions {{subcommand {}}} { # Note that the "box" tag doesn't apply to mouse-button events, so this function # is duplicated by Tk binding of mouse events in the layout window. -magic::tag load "[magic::tag load]; magic::captions" -magic::tag edit "magic::captions" -magic::tag save "magic::captions" -magic::tag down "magic::captions" -magic::tag box "magic::boxview %W %1" -magic::tag move "magic::boxview %W" -magic::tag scroll "magic::scrollupdate %W" -magic::tag view "magic::scrollupdate %W" -magic::tag zoom "magic::scrollupdate %W" -magic::tag findbox "magic::scrollupdate %W" -magic::tag see "magic::toolupdate %W %1 %2" -magic::tag tech "magic::techrebuild %W %1; magic::captions %1" -magic::tag drc "magic::drcupdate %1" -magic::tag path "[magic::tag path]; magic::techmanager update" -magic::tag cellname "magic::mgrupdate %W %1" -magic::tag cif "magic::mgrupdate %W %1" -magic::tag gds "magic::mgrupdate %W %1" +magic::tag add load "magic::captions" +magic::tag add edit "magic::captions" +magic::tag add save "magic::captions" +magic::tag add down "magic::captions" +magic::tag add box "magic::boxview %W %1" +magic::tag add move "magic::boxview %W" +magic::tag add scroll "magic::scrollupdate %W" +magic::tag add view "magic::scrollupdate %W" +magic::tag add zoom "magic::scrollupdate %W" +magic::tag add findbox "magic::scrollupdate %W" +magic::tag add see "magic::toolupdate %W %1 %2" +magic::tag add tech "magic::techrebuild %W %1; magic::captions %1" +magic::tag add drc "magic::drcupdate %1" +magic::tag add path "magic::techmanager update" +magic::tag add cellname "magic::mgrupdate %W %1" +magic::tag add cif "magic::mgrupdate %W %1" +magic::tag add gds "magic::mgrupdate %W %1" # This should be a list. . . do be done later set lwindow 0