diff --git a/src/callback.c b/src/callback.c index 75db7767..a25d5a90 100644 --- a/src/callback.c +++ b/src/callback.c @@ -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; } diff --git a/src/xinit.c b/src/xinit.c index d85ef416..3d325f59 100644 --- a/src/xinit.c +++ b/src/xinit.c @@ -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; diff --git a/src/xschem.tcl b/src/xschem.tcl index a101497f..32248885 100644 --- a/src/xschem.tcl +++ b/src/xschem.tcl @@ -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] &&