Modified the "tag" command to add an optional subcommand "add" or

"replace" as the 2nd argument.  This allows a simpler 'tag add
<command> <value>' than the existing awkward 'tag <command>
"[tag <command>]; <value>'.  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).
This commit is contained in:
R. Timothy Edwards 2025-10-08 17:11:27 -04:00
parent d822353e85
commit 9ca81f8ea6
8 changed files with 109 additions and 36 deletions

View File

@ -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"

View File

@ -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:"

View File

@ -10,8 +10,8 @@ if {$::tk_version >= 8.5} {
set Opts(drcmgr) 0
magic::tag add addpath "magic::drcmanager"
magic::tag add path "magic::drcmanager"
magic::tag path "magic::drcmanager"
# Callback to the DRC manager

View File

@ -10,8 +10,11 @@ if {$::tk_version >= 8.5} {
set Opts(libmgr) 0
magic::tag add addpath "magic::libmanager"
magic::tag add path "magic::libmanager"
magic::tag 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"} {

View File

@ -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,17 +351,34 @@ AddCommandTag(ClientData clientData,
return TCL_OK;
}
/* If there is no existing tag then "tag add" is just "tag replace" */
if (doadd && (hstring == NULL)) doadd = FALSE;
if (doadd) /* add to existing contents */
{
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 /* replace */
{
if (hstring != NULL) freeMagic(hstring);
if (strlen(argv[2]) == 0)
if (strlen(argv[argstart + 1]) == 0)
{
HashSetValue(entry, NULL);
}
else
{
hstring = StrDup((char **)NULL, argv[2]);
hstring = StrDup((char **)NULL, argv[argstart + 1]);
HashSetValue(entry, hstring);
}
}
return TCL_OK;
}

View File

@ -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

View File

@ -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

View File

@ -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