Merge branch 'master' into SuperChayan

This commit is contained in:
stefan schippers 2025-03-23 15:30:18 +01:00
commit 936b7157f5
3 changed files with 294 additions and 289 deletions

View File

@ -4130,7 +4130,8 @@ static void handle_key_press(int event, KeySym key, int state, int rstate, int m
}
static void handle_button_press(int event, int state, int rstate, KeySym key, int button, int mx, int my,
double c_snap, int draw_xhair, int crosshair_size, int enable_stretch, int aux)
double c_snap, int draw_xhair, int crosshair_size,
int enable_stretch, int cadence_compat, int aux)
{
int use_cursor_for_sel = tclgetintvar("use_cursor_for_selection");
int excl = xctx->ui_state & (STARTWIRE | STARTRECT | STARTLINE | STARTPOLYGON | STARTARC);
@ -4270,10 +4271,10 @@ static void handle_button_press(int event, int state, int rstate, KeySym key, in
}
#endif
/* In *NON* intuitive interface a button1 press with no modifiers will
* first unselect everything...
/* In *NON* intuitive interface (or cadence compatibility)
* a button1 press with no modifiers will first unselect everything...
* For intuitive interface unselection see below... */
if(!xctx->intuitive_interface && no_shift_no_ctrl ) unselect_all(1);
if((cadence_compat || !xctx->intuitive_interface) && no_shift_no_ctrl) unselect_all(1);
/* find closest object. Use snap coordinates if full crosshair is enabled
* since the mouse pointer is obscured and crosshair is snapped to grid points */
@ -4524,255 +4525,259 @@ static void handle_double_click(int event, int state, KeySym key, int button,
}
static void update_statusbar(int persistent_command, int wire_draw_active)
{
int line_draw_active = (xctx->ui_state & STARTLINE) ||
((xctx->ui_state2 & MENUSTARTLINE) && (xctx->ui_state & MENUSTART)) ||
(persistent_command && (xctx->last_command & STARTLINE));
int poly_draw_active = (xctx->ui_state & STARTPOLYGON) ||
((xctx->ui_state2 & MENUSTARTPOLYGON) && (xctx->ui_state & MENUSTART)) ||
(persistent_command && (xctx->last_command & STARTPOLYGON));
int arc_draw_active = (xctx->ui_state & STARTARC) ||
((xctx->ui_state2 & MENUSTARTARC) && (xctx->ui_state & MENUSTART)) ||
(persistent_command && (xctx->last_command & STARTARC));
int rect_draw_active = (xctx->ui_state & STARTRECT) ||
((xctx->ui_state2 & MENUSTARTRECT) && (xctx->ui_state & MENUSTART)) ||
(persistent_command && (xctx->last_command & STARTRECT));
if(wire_draw_active) {
tclvareval(xctx->top_path, ".statusbar.10 configure -state active -text {DRAW WIRE! }", NULL);
} else if(line_draw_active) {
tclvareval(xctx->top_path, ".statusbar.10 configure -state active -text {DRAW LINE! }", NULL);
} else if(poly_draw_active) {
tclvareval(xctx->top_path, ".statusbar.10 configure -state active -text {DRAW POLYGON! }", NULL);
} else if(arc_draw_active) {
tclvareval(xctx->top_path, ".statusbar.10 configure -state active -text {DRAW ARC! }", NULL);
} else if(rect_draw_active) {
tclvareval(xctx->top_path, ".statusbar.10 configure -state active -text {DRAW RECTANGLE! }", NULL);
} else {
tclvareval(xctx->top_path, ".statusbar.10 configure -state normal -text { }", NULL);
}
tclvareval(xctx->top_path, ".statusbar.7 configure -text $netlist_type", NULL);
tclvareval(xctx->top_path, ".statusbar.3 delete 0 end;",
xctx->top_path, ".statusbar.3 insert 0 $cadsnap", NULL);
tclvareval(xctx->top_path, ".statusbar.5 delete 0 end;",
xctx->top_path, ".statusbar.5 insert 0 $cadgrid", NULL);
}
/* main window callback */
/* mx and my are set to the mouse coord. relative to window */
/* win_path: set to .drw or sub windows .x1.drw, .x2.drw, ... */
int callback(const char *win_path, int event, int mx, int my, KeySym key,
int button, int aux, int state)
int callback(const char *win_path, int event, int mx, int my, KeySym key, int button, int aux, int state)
{
char str[PATH_MAX + 100];
int redraw_only;
double c_snap;
#ifndef __unix__
short cstate = GetKeyState(VK_CAPITAL);
short nstate = GetKeyState(VK_NUMLOCK);
#else
XKeyboardState kbdstate;
#endif
int enable_stretch = tclgetboolvar("enable_stretch");
int draw_xhair = tclgetboolvar("draw_crosshair");
int crosshair_size = tclgetintvar("crosshair_size");
int infix_interface = tclgetboolvar("infix_interface");
int rstate; /* (reduced state, without ShiftMask) */
int snap_cursor = tclgetboolvar("snap_cursor");
int cadence_compat = tclgetboolvar("cadence_compat");
int persistent_command = tclgetboolvar("persistent_command");
int wire_draw_active = (xctx->ui_state & STARTWIRE) ||
((xctx->ui_state2 & MENUSTARTWIRE) && (xctx->ui_state & MENUSTART)) ||
(persistent_command && (xctx->last_command & STARTWIRE));
int line_draw_active = (xctx->ui_state & STARTLINE) ||
((xctx->ui_state2 & MENUSTARTLINE) && (xctx->ui_state & MENUSTART)) ||
(persistent_command && (xctx->last_command & STARTLINE));
int poly_draw_active = (xctx->ui_state & STARTPOLYGON) ||
((xctx->ui_state2 & MENUSTARTPOLYGON) && (xctx->ui_state & MENUSTART)) ||
(persistent_command && (xctx->last_command & STARTPOLYGON));
int arc_draw_active = (xctx->ui_state & STARTARC) ||
((xctx->ui_state2 & MENUSTARTARC) && (xctx->ui_state & MENUSTART)) ||
(persistent_command && (xctx->last_command & STARTARC));
int rect_draw_active = (xctx->ui_state & STARTRECT) ||
((xctx->ui_state2 & MENUSTARTRECT) && (xctx->ui_state & MENUSTART)) ||
(persistent_command && (xctx->last_command & STARTRECT));
/* this fix uses an alternative method for getting mouse coordinates on KeyPress/KeyRelease
* events. Some remote connection softwares do not generate the correct coordinates
* on such events */
if(fix_mouse_coord) {
if(event == KeyPress || event == KeyRelease) {
tclvareval("getmousex ", win_path, NULL);
mx = atoi(tclresult());
tclvareval("getmousey ", win_path, NULL);
my = atoi(tclresult());
dbg(1, "mx = %d my=%d\n", mx, my);
}
}
#ifndef __unix__
if(cstate & 0x0001) { /* caps lock */
tclvareval(xctx->top_path, ".statusbar.8 configure -state active -text {CAPS LOCK SET! }", NULL);
} else if (nstate & 0x0001) { /* num lock */
tclvareval(xctx->top_path, ".statusbar.8 configure -state active -text {NUM LOCK SET! }", NULL);
} else { /* normal state */
tclvareval(xctx->top_path, ".statusbar.8 configure -state normal -text {}", NULL);
}
#else
XGetKeyboardControl(display, &kbdstate);
if(kbdstate.led_mask & 1) { /* caps lock */
tclvareval(xctx->top_path, ".statusbar.8 configure -state active -text {CAPS LOCK SET! }", NULL);
} else if(kbdstate.led_mask & 2) { /* num lock */
tclvareval(xctx->top_path, ".statusbar.8 configure -state active -text {NUM LOCK SET! }", NULL);
} else { /* normal state */
tclvareval(xctx->top_path, ".statusbar.8 configure -state normal -text {}", NULL);
}
#endif
if(wire_draw_active) {
tclvareval(xctx->top_path, ".statusbar.10 configure -state active -text {DRAW WIRE! }", NULL);
} else if(line_draw_active) {
tclvareval(xctx->top_path, ".statusbar.10 configure -state active -text {DRAW LINE! }", NULL);
} else if(poly_draw_active) {
tclvareval(xctx->top_path, ".statusbar.10 configure -state active -text {DRAW POLYGON! }", NULL);
} else if(arc_draw_active) {
tclvareval(xctx->top_path, ".statusbar.10 configure -state active -text {DRAW ARC! }", NULL);
} else if(rect_draw_active) {
tclvareval(xctx->top_path, ".statusbar.10 configure -state active -text {DRAW RECTANGLE! }", NULL);
} else {
tclvareval(xctx->top_path, ".statusbar.10 configure -state normal -text { }", NULL);
}
tclvareval(xctx->top_path, ".statusbar.7 configure -text $netlist_type", NULL);
tclvareval(xctx->top_path, ".statusbar.3 delete 0 end;",
xctx->top_path, ".statusbar.3 insert 0 $cadsnap",
NULL);
tclvareval(xctx->top_path, ".statusbar.5 delete 0 end;",
xctx->top_path, ".statusbar.5 insert 0 $cadgrid",
NULL);
#if 0
/* exclude Motion and Expose events */
if(event!=6 /* && event!=12 */) {
dbg(0, "callback(): state=%d event=%d, win_path=%s, old_win_path=%s, semaphore=%d\n",
state, event, win_path, old_win_path, xctx->semaphore+1);
}
#endif
char str[PATH_MAX + 100];
int redraw_only;
double c_snap;
#ifndef __unix__
short cstate = GetKeyState(VK_CAPITAL);
short nstate = GetKeyState(VK_NUMLOCK);
#else
XKeyboardState kbdstate;
#endif
int enable_stretch = tclgetboolvar("enable_stretch");
int draw_xhair = tclgetboolvar("draw_crosshair");
int crosshair_size = tclgetintvar("crosshair_size");
int infix_interface = tclgetboolvar("infix_interface");
int rstate; /* (reduced state, without ShiftMask) */
int snap_cursor = tclgetboolvar("snap_cursor");
int cadence_compat = tclgetboolvar("cadence_compat");
int persistent_command = tclgetboolvar("persistent_command");
int wire_draw_active = (xctx->ui_state & STARTWIRE) ||
((xctx->ui_state2 & MENUSTARTWIRE) && (xctx->ui_state & MENUSTART)) ||
(persistent_command && (xctx->last_command & STARTWIRE));
/* Schematic window context switch */
redraw_only =0;
if(strcmp(old_win_path, win_path) ) {
if( xctx->semaphore >= 1 || event == Expose) {
dbg(1, "callback(): semaphore >=2 (or Expose) switching window context: %s --> %s\n", old_win_path, win_path);
redraw_only = 1;
new_schematic("switch_no_tcl_ctx", win_path, "", 1);
} else {
dbg(1, "callback(): switching window context: %s --> %s, semaphore=%d\n",
old_win_path, win_path, xctx->semaphore);
new_schematic("switch", win_path, "", 1);
}
tclvareval("housekeeping_ctx", NULL);
}
/* artificially set semaphore to allow only redraw operations in switched schematic,
* so we don't need to switch tcl context which is costly performance-wise
*/
if(redraw_only) {
dbg(1, "callback(): incrementing semaphore for redraw_only\n");
xctx->semaphore++;
}
xctx->semaphore++; /* to recognize recursive callback() calls */
c_snap = tclgetdoublevar("cadsnap");
#ifdef __unix__
state &= (1 <<13) -1; /* filter out anything above bit 12 (4096) */
#endif
state &= ~Mod2Mask; /* 20170511 filter out NumLock status */
state &= ~LockMask; /* filter out Caps Lock */
rstate = state; /* rstate does not have ShiftMask bit, so easier to test for KeyPress events */
rstate &= ~ShiftMask; /* don't use ShiftMask, identifying characters is sufficient */
rstate &= ~Button1Mask; /* ignore button-1 */
if(xctx->semaphore >= 2)
{
if(debug_var>=2)
if(event != MotionNotify)
fprintf(errfp, "callback(): reentrant call of callback(), semaphore=%d, ev=%d, ui_state=%d\n",
xctx->semaphore, event, xctx->ui_state);
}
xctx->mousex=X_TO_XSCHEM(mx);
xctx->mousey=Y_TO_XSCHEM(my);
xctx->mousex_snap=my_round(xctx->mousex / c_snap) * c_snap;
xctx->mousey_snap=my_round(xctx->mousey / c_snap) * c_snap;
if(abs(mx-xctx->mx_save) > 8 || abs(my-xctx->my_save) > 8 ) {
my_snprintf(str, S(str), "mouse = %.16g %.16g - selected: %d path: %s",
xctx->mousex_snap, xctx->mousey_snap, xctx->lastsel, xctx->sch_path[xctx->currsch] );
statusmsg(str,1);
}
dbg(1, "key=%d EQUAL_MODMASK=%d, SET_MODMASK=%d\n", key, SET_MODMASK, EQUAL_MODMASK);
#if defined(__unix__) && HAS_CAIRO==1
if(xctx->ui_state & GRABSCREEN) {
grabscreen(win_path, event, mx, my, key, button, aux, state);
} else
#endif
switch(event)
{
case LeaveNotify:
if(draw_xhair) draw_crosshair(1, state); /* clear crosshair when exiting window */
if(snap_cursor) draw_snap_cursor(1); /* erase */
tclvareval(xctx->top_path, ".drw configure -cursor {}" , NULL);
xctx->mouse_inside = 0;
break;
case EnterNotify:
handle_enter_notify(draw_xhair, crosshair_size);
break;
case Expose:
dbg(1, "callback: Expose, win_path=%s, %dx%d+%d+%d\n", win_path, button, aux, mx, my);
MyXCopyArea(display, xctx->save_pixmap, xctx->window, xctx->gc[0], mx,my,button,aux,mx,my);
{
XRectangle xr[1];
xr[0].x=(short)mx;
xr[0].y=(short)my;
xr[0].width=(unsigned short)button;
xr[0].height=(unsigned short)aux;
/* redraw selection on expose, needed if no backing store available on the server 20171112 */
XSetClipRectangles(display, xctx->gc[SELLAYER], 0,0, xr, 1, Unsorted);
rebuild_selected_array();
if(tclgetboolvar("compare_sch") /* && xctx->sch_to_compare[0] */){
compare_schematics("");
} else {
draw_selection(xctx->gc[SELLAYER],0);
}
XSetClipMask(display, xctx->gc[SELLAYER], None);
/* this fix uses an alternative method for getting mouse coordinates on KeyPress/KeyRelease
* events. Some remote connection softwares do not generate the correct coordinates
* on such events */
if(fix_mouse_coord) {
if(event == KeyPress || event == KeyRelease) {
tclvareval("getmousex ", win_path, NULL);
mx = atoi(tclresult());
tclvareval("getmousey ", win_path, NULL);
my = atoi(tclresult());
dbg(1, "mx = %d my=%d\n", mx, my);
}
dbg(1, "callback(): Expose\n");
break;
}
#ifndef __unix__
if(cstate & 0x0001) { /* caps lock */
tclvareval(xctx->top_path, ".statusbar.8 configure -state active -text {CAPS LOCK SET! }", NULL);
} else if (nstate & 0x0001) { /* num lock */
tclvareval(xctx->top_path, ".statusbar.8 configure -state active -text {NUM LOCK SET! }", NULL);
} else { /* normal state */
tclvareval(xctx->top_path, ".statusbar.8 configure -state normal -text {}", NULL);
}
#else
XGetKeyboardControl(display, &kbdstate);
if(kbdstate.led_mask & 1) { /* caps lock */
tclvareval(xctx->top_path, ".statusbar.8 configure -state active -text {CAPS LOCK SET! }", NULL);
} else if(kbdstate.led_mask & 2) { /* num lock */
tclvareval(xctx->top_path, ".statusbar.8 configure -state active -text {NUM LOCK SET! }", NULL);
} else { /* normal state */
tclvareval(xctx->top_path, ".statusbar.8 configure -state normal -text {}", NULL);
}
#endif
case ConfigureNotify:
dbg(1,"callback(): ConfigureNotify event\n");
resetwin(1, 1, 0, 0, 0);
draw();
break;
update_statusbar(persistent_command, wire_draw_active);
case MotionNotify:
handle_motion_notify(event, key, state, rstate, button, mx, my,
aux, draw_xhair, enable_stretch,
snap_cursor, wire_draw_active);
#if 0
/* exclude Motion and Expose events */
if(event!=6 /* && event!=12 */) {
dbg(0, "callback(): state=%d event=%d, win_path=%s, old_win_path=%s, semaphore=%d\n",
state, event, win_path, old_win_path, xctx->semaphore+1);
}
#endif
/* Schematic window context switch */
redraw_only =0;
if(strcmp(old_win_path, win_path) ) {
if( xctx->semaphore >= 1 || event == Expose) {
dbg(1, "callback(): semaphore >=2 (or Expose) switching window context: %s --> %s\n", old_win_path, win_path);
redraw_only = 1;
new_schematic("switch_no_tcl_ctx", win_path, "", 1);
} else {
dbg(1, "callback(): switching window context: %s --> %s, semaphore=%d\n",
old_win_path, win_path, xctx->semaphore);
new_schematic("switch", win_path, "", 1);
}
/* done in switch_window() */
/* tclvareval("housekeeping_ctx", NULL); */
}
/* artificially set semaphore to allow only redraw operations in switched schematic,
* so we don't need to switch tcl context which is costly performance-wise
*/
if(redraw_only) {
dbg(1, "callback(): incrementing semaphore for redraw_only\n");
xctx->semaphore++;
}
xctx->semaphore++; /* to recognize recursive callback() calls */
c_snap = tclgetdoublevar("cadsnap");
#ifdef __unix__
state &= (1 <<13) -1; /* filter out anything above bit 12 (4096) */
#endif
state &= ~Mod2Mask; /* 20170511 filter out NumLock status */
state &= ~LockMask; /* filter out Caps Lock */
rstate = state; /* rstate does not have ShiftMask bit, so easier to test for KeyPress events */
rstate &= ~ShiftMask; /* don't use ShiftMask, identifying characters is sufficient */
rstate &= ~Button1Mask; /* ignore button-1 */
if(xctx->semaphore >= 2)
{
if(debug_var>=2)
if(event != MotionNotify)
fprintf(errfp, "callback(): reentrant call of callback(), semaphore=%d, ev=%d, ui_state=%d\n",
xctx->semaphore, event, xctx->ui_state);
}
xctx->mousex=X_TO_XSCHEM(mx);
xctx->mousey=Y_TO_XSCHEM(my);
xctx->mousex_snap=my_round(xctx->mousex / c_snap) * c_snap;
xctx->mousey_snap=my_round(xctx->mousey / c_snap) * c_snap;
if(abs(mx-xctx->mx_save) > 8 || abs(my-xctx->my_save) > 8 ) {
my_snprintf(str, S(str), "mouse = %.16g %.16g - selected: %d path: %s",
xctx->mousex_snap, xctx->mousey_snap, xctx->lastsel, xctx->sch_path[xctx->currsch] );
statusmsg(str,1);
}
dbg(1, "key=%d EQUAL_MODMASK=%d, SET_MODMASK=%d\n", key, SET_MODMASK, EQUAL_MODMASK);
#if defined(__unix__) && HAS_CAIRO==1
if(xctx->ui_state & GRABSCREEN) {
grabscreen(win_path, event, mx, my, key, button, aux, state);
} else
#endif
switch(event)
{
case LeaveNotify:
if(draw_xhair) draw_crosshair(1, state); /* clear crosshair when exiting window */
if(snap_cursor) draw_snap_cursor(1); /* erase */
tclvareval(xctx->top_path, ".drw configure -cursor {}" , NULL);
xctx->mouse_inside = 0;
break;
case EnterNotify:
handle_enter_notify(draw_xhair, crosshair_size);
break;
case Expose:
dbg(1, "callback: Expose, win_path=%s, %dx%d+%d+%d\n", win_path, button, aux, mx, my);
MyXCopyArea(display, xctx->save_pixmap, xctx->window, xctx->gc[0], mx,my,button,aux,mx,my);
{
XRectangle xr[1];
xr[0].x=(short)mx;
xr[0].y=(short)my;
xr[0].width=(unsigned short)button;
xr[0].height=(unsigned short)aux;
/* redraw selection on expose, needed if no backing store available on the server 20171112 */
XSetClipRectangles(display, xctx->gc[SELLAYER], 0,0, xr, 1, Unsorted);
rebuild_selected_array();
if(tclgetboolvar("compare_sch") /* && xctx->sch_to_compare[0] */){
compare_schematics("");
} else {
draw_selection(xctx->gc[SELLAYER],0);
}
XSetClipMask(display, xctx->gc[SELLAYER], None);
}
dbg(1, "callback(): Expose\n");
break;
case ConfigureNotify:
dbg(1,"callback(): ConfigureNotify event\n");
resetwin(1, 1, 0, 0, 0);
draw();
break;
case MotionNotify:
handle_motion_notify(event, key, state, rstate, button, mx, my,
aux, draw_xhair, enable_stretch,
snap_cursor, wire_draw_active);
break;
case KeyRelease:
/* force clear (even if mouse pos not changed) */
/* if(snap_cursor && (key == XK_Shift_L || key == XK_Shift_R) ) draw_snap_cursor(5); */
break;
case KeyPress:
handle_key_press(event, key, state, rstate, mx, my, button, aux,
infix_interface, enable_stretch, win_path, c_snap,
cadence_compat, wire_draw_active, snap_cursor);
break;
case ButtonPress:
handle_button_press(event, state, rstate, key, button, mx, my,
c_snap, draw_xhair, crosshair_size, enable_stretch, cadence_compat, aux);
break;
case ButtonRelease:
handle_button_release(event, key, state, button, mx, my, aux, c_snap, enable_stretch,
draw_xhair, snap_cursor, wire_draw_active);
break;
case -3: /* double click : edit prop */
handle_double_click(event, state, key, button, mx, my, aux, cadence_compat);
break;
default:
dbg(1, "callback(): Event:%d\n",event);
break;
case KeyRelease:
/* force clear (even if mouse pos not changed) */
/* if(snap_cursor && (key == XK_Shift_L || key == XK_Shift_R) ) draw_snap_cursor(5); */
break;
case KeyPress:
handle_key_press(event, key, state, rstate, mx, my, button, aux,
infix_interface, enable_stretch, win_path, c_snap,
cadence_compat, wire_draw_active, snap_cursor);
break;
case ButtonPress:
handle_button_press(event, state, rstate, key, button, mx, my,
c_snap, draw_xhair, crosshair_size, enable_stretch, aux);
break;
case ButtonRelease:
handle_button_release(event, key, state, button, mx, my, aux, c_snap, enable_stretch,
draw_xhair, snap_cursor, wire_draw_active);
break;
case -3: /* double click : edit prop */
handle_double_click(event, state, key, button, mx, my, aux, cadence_compat);
break;
default:
dbg(1, "callback(): Event:%d\n",event);
break;
} /* switch(event) */
if(xctx->semaphore > 0) xctx->semaphore--;
if(redraw_only) {
xctx->semaphore--; /* decrement articially incremented semaphore (see above) */
dbg(1, "callback(): semaphore >=2 restoring window context: %s <-- %s\n", old_win_path, win_path);
if(old_win_path[0]) new_schematic("switch_no_tcl_ctx", old_win_path, "", 1);
}
else
if(strcmp(old_win_path, win_path)) {
if(old_win_path[0]) dbg(1, "callback(): reset old_win_path: %s <- %s\n", old_win_path, win_path);
my_strncpy(old_win_path, win_path, S(old_win_path));
}
} /* switch(event) */
if(xctx->semaphore > 0) xctx->semaphore--;
if(redraw_only) {
xctx->semaphore--; /* decrement articially incremented semaphore (see above) */
dbg(1, "callback(): semaphore >=2 restoring window context: %s <-- %s\n", old_win_path, win_path);
if(old_win_path[0]) new_schematic("switch_no_tcl_ctx", old_win_path, "", 1);
}
else
if(strcmp(old_win_path, win_path)) {
if(old_win_path[0]) dbg(1, "callback(): reset old_win_path: %s <- %s\n", old_win_path, win_path);
my_strncpy(old_win_path, win_path, S(old_win_path));
}
return 0;
}

View File

@ -1524,11 +1524,13 @@ static int switch_window(int *window_count, const char *win_path, int tcl_ctx)
}
}
/* if window was closed then tkwin == 0 --> do nothing */
if((!has_x || tkwin) && n >= 0 && n < MAX_NEW_WINDOWS) {
if(tkwin && n >= 0 && n < MAX_NEW_WINDOWS) {
if(tcl_ctx) tclvareval("save_ctx ", xctx->current_win_path, NULL);
xctx = save_xctx[n];
if(tcl_ctx) tclvareval("restore_ctx ", win_path, NULL);
tclvareval("housekeeping_ctx", NULL);
if(tcl_ctx) {
tclvareval("restore_ctx ", win_path, NULL);
tclvareval("housekeeping_ctx", NULL);
}
if(tcl_ctx && has_x) tclvareval("reconfigure_layers_button {}", NULL);
set_modify(-1); /* sets window title */
return 0;

View File

@ -699,6 +699,19 @@ proc ev0 {args} {
}
}
# create the 'lassign' command if tcl does not have it (pre 8.5)
if {[info commands lassign] eq {}} {
proc lassign { list args } {
set n 0
foreach i $args {
upvar $i v
set v [lindex $list $n]
incr n
}
return [lrange $list $n end]
}
}
# return "$n * $indent" spaces
proc spaces {n {indent 4}} {
set n [expr {$n * $indent}]
@ -709,40 +722,32 @@ proc spaces {n {indent 4}} {
# complex number operators
# a + b
proc cadd {a b} {
# lassign $a ra ia
# lassign $b rb ib
foreach {ra ia} $a break
foreach {rb ib} $b break
lassign $a ra ia
lassign $b rb ib
set c [list [expr {$ra + $rb}] [expr {$ia + $ib}]]
return $c
}
# a - b
proc csub {a b} {
# lassign $a ra ia
# lassign $b rb ib
foreach {ra ia} $a break
foreach {rb ib} $b break
lassign $a ra ia
lassign $b rb ib
set c [list [expr {$ra - $rb}] [expr {$ia - $ib}]]
return $c
}
# a * b
proc cmul {a b} {
# lassign $a ra ia
# lassign $b rb ib
foreach {ra ia} $a break
foreach {rb ib} $b break
lassign $a ra ia
lassign $b rb ib
set c [list [expr {$ra * $rb - $ia * $ib}] [expr {$ra * $ib + $rb * $ia}]]
return $c
}
# a / b
proc cdiv {a b} {
# lassign $a ra ia
# lassign $b rb ib
foreach {ra ia} $a break
foreach {rb ib} $b break
lassign $a ra ia
lassign $b rb ib
set ra [expr {double($ra)}]
set ia [expr {double($ia)}]
set rb [expr {double($rb)}]
@ -755,8 +760,7 @@ proc cdiv {a b} {
# 1/b
proc cinv {b} {
# lassign $b rb ib
foreach {rb ib} $b break
lassign $b rb ib
set rb [expr {double($rb)}]
set ib [expr {double($ib)}]
set m [expr {$rb * $rb + $ib * $ib}]
@ -766,15 +770,13 @@ proc cinv {b} {
# return real component
proc creal {a} {
# lassign $a ra ia
foreach {ra ia} $a break
lassign $a ra ia
return $ra
}
# return imaginary component
proc cimag {a} {
# lassign $a ra ia
foreach {ra ia} $a break
lassign $a ra ia
return $ia
}
@ -4825,8 +4827,8 @@ proc load_file_dialog {{msg {}} {ext {}} {global_initdir {INITIALINSTDIR}}
# if paths empty use XSCHEM_LIBRARY_PATH list.
# 'levels' is set to the number of levels to descend into.
# 'level' is used internally by the function and should not be set.
proc get_list_of_dirs_with_symbols {{paths {}} {levels -1} {ext {\.(sch|sym)$}} {level -1}} {
# puts "get_list_of_dirs_with_symbols paths=$paths"
proc get_list_of_dirs_with_files {{paths {}} {levels -1} {ext {\.(sch|sym)$}} {level -1}} {
# puts "get_list_of_dirs_with_files paths=$paths"
global pathlist
set dir_with_symbols {}
if {$level == -1} { set level 0}
@ -4847,7 +4849,7 @@ proc get_list_of_dirs_with_symbols {{paths {}} {levels -1} {ext {\.(sch|sym)$}}
set dirlist [glob -nocomplain -directory $i -type d *]
if {$levels >=0 && $level + 1 > $levels} {return}
foreach d $dirlist {
set dirs [get_list_of_dirs_with_symbols $d $levels $ext [expr {$level + 1} ]]
set dirs [get_list_of_dirs_with_files $d $levels $ext [expr {$level + 1} ]]
if { $dirs ne {}} {set dir_with_symbols [concat $dir_with_symbols $dirs]}
}
}
@ -4923,7 +4925,7 @@ proc insert_symbol_update_dirs {} {
global insert_symbol
# regenerate list of dirs
set insert_symbol(dirs) [
get_list_of_dirs_with_symbols $insert_symbol(paths) $insert_symbol(maxdepth) $insert_symbol(ext)
get_list_of_dirs_with_files $insert_symbol(paths) $insert_symbol(maxdepth) $insert_symbol(ext)
]
set insert_symbol(dirtails) {}
foreach i $insert_symbol(dirs) {
@ -4939,8 +4941,7 @@ proc insert_symbol_update_dirs {} {
set insert_symbol(dirs) {}
foreach f $files {
# lassign $f ff fff
foreach {ff fff} $f break ;# pre-tcl8.5
lassign $f ff fff
lappend insert_symbol(dirtails) $ff
lappend insert_symbol(dirs) $fff
}
@ -4957,17 +4958,17 @@ proc insert_symbol_filelist {} {
.ins.center.leftdir.l selection set active
}
set insert_symbol(dirindex) $sel
set paths [lindex $insert_symbol(dirs) $sel]
set path [lindex $insert_symbol(dirs) $sel]
.ins.top2.dir_e configure -state normal
.ins.top2.dir_e delete 0 end
.ins.top2.dir_e insert 0 $paths
.ins.top2.dir_e insert 0 $path
.ins.top2.dir_e configure -state readonly
# check if regex is valid
set err [catch {regexp $insert_symbol(regex) {12345}} res]
if {$err} {return}
set f {}
if {$paths ne {} } {
set f [match_file $insert_symbol(regex) $paths 0]
if {$path ne {} } {
set f [match_file $insert_symbol(regex) $path 0]
}
set filelist {}
set insert_symbol(fullpathlist) {}
@ -4995,8 +4996,7 @@ proc insert_symbol_filelist {} {
set filelist {}
set insert_symbol(fullpathlist) {}
foreach f $files {
# lassign $f ff fff
foreach {ff fff} $f break ;# pre-tcl8.5
lassign $f ff fff
lappend filelist $ff
lappend insert_symbol(fullpathlist) $fff
}
@ -5327,13 +5327,10 @@ proc schpins_to_sympins {} {
set textflip [expr {$flip}]
}
## lassign not available pre-tck8.5
# lassign [rotation $x0 $y0 $linex1 $liney1 $rot $flip] linex1 liney1
foreach {linex1 liney1} [rotation $x0 $y0 $linex1 $liney1 $rot $flip] break
# lassign [rotation $x0 $y0 $linex2 $liney2 $rot $flip] linex2 liney2
foreach {linex2 liney2} [rotation $x0 $y0 $linex2 $liney2 $rot $flip] break
# lassign [order $linex1 $liney1 $linex2 $liney2] linex1 liney1 linex2 liney2
foreach {linex1 liney1 linex2 liney2} [order $linex1 $liney1 $linex2 $liney2] break
# lassign [rotation $x0 $y0 $textx0 $texty0 $rot $flip] textx0 texty0
lassign [rotation $x0 $y0 $linex1 $liney1 $rot $flip] linex1 liney1
lassign [rotation $x0 $y0 $linex2 $liney2 $rot $flip] linex2 liney2
lassign [order $linex1 $liney1 $linex2 $liney2] linex1 liney1 linex2 liney2
lassign [rotation $x0 $y0 $textx0 $texty0 $rot $flip] textx0 texty0
foreach {textx0 texty0} [rotation $x0 $y0 $textx0 $texty0 $rot $flip] break
puts $fd "B 5 $pinx1 $piny1 $pinx2 $piny2 \{name=$lab dir=$dir\}"
puts $fd "L 4 $linex1 $liney1 $linex2 $liney2 \{\}"
@ -8236,7 +8233,8 @@ proc quit_xschem { {force {}}} {
proc raise_dialog {parent window_path } {
global file_dialog_loadfile component_browser_on_top
foreach i ".dialog .graphdialog .load" {
if {!$component_browser_on_top && [info exists file_dialog_loadfile ] && $file_dialog_loadfile == 2 && $i eq {.load} } {
if {!$component_browser_on_top && [info exists file_dialog_loadfile ] &&
$file_dialog_loadfile == 2 && $i eq {.load} } {
continue
}
if {[winfo exists $i] && [winfo ismapped $i] && [winfo ismapped $parent] &&