From 70c1e542b2f1f57e2f62d6556308b1105ddf2345 Mon Sep 17 00:00:00 2001 From: stefan schippers Date: Wed, 5 Feb 2025 18:20:36 +0100 Subject: [PATCH 1/3] attributes within expr(...) where expr() contains an infix arith expression will evaluate if possible. Otherwise the string within expr(...) will be returned unchanged. Changes done in translate() and print_spice_element() --- src/eval_expr.y | 2 +- src/token.c | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/eval_expr.y b/src/eval_expr.y index c7d14773..8a94444b 100644 --- a/src/eval_expr.y +++ b/src/eval_expr.y @@ -93,7 +93,7 @@ exp: NUM { $$ = $1;} static void get_expr(double x) { char xx[100]; - my_snprintf(xx, S(xx), "%.17g", x); + my_snprintf(xx, S(xx), "%.16g", x); my_mstrcat(_ALLOC_ID_, &ret, xx, NULL); strptr = str; } diff --git a/src/token.c b/src/token.c index a0aa55d5..7eb1576c 100644 --- a/src/token.c +++ b/src/token.c @@ -2246,6 +2246,13 @@ int print_spice_element(FILE *fd, int inst) if (!xctx->tok_size) value=get_tok_value(template, token+1, 0); token_exists = xctx->tok_size; + if(strstr(value, "expr(") == value) { + char *ptr; + my_strdup(_ALLOC_ID_, &val, value); + ptr = strrchr(val + 5, ')'); + *ptr = '\0'; + value = eval_expr(translate3(val + 5, 1, xctx->inst[inst].prop_ptr, template, NULL)); + } if(!strcmp("@savecurrent", token)) { token_exists = 0; /* processed later */ value = NULL; @@ -4479,6 +4486,13 @@ const char *translate(int inst, const char* s) dbg(1, "2 translate(): lcc[%d].prop_ptr=%s, value1=%s\n", i-1, lcc[i-1].prop_ptr, value1); i--; } + if(strstr(value1, "expr(") == value1) { + char *ptr = strrchr(value1 + 5, ')'); + dbg(0, "translate(): expr():%s\n", value1); + *ptr = '\0'; + my_strdup2(_ALLOC_ID_, &value1, eval_expr( + translate3(value1 + 5, 1, xctx->inst[inst].prop_ptr, xctx->sym[xctx->inst[inst].ptr].templ, NULL))); + } tmp=strlen(value1); STR_ALLOC(&result, tmp + result_pos, &size); memcpy(result+result_pos, value1, tmp+1); From 0c4cdb3ea122eba2e0825ef85f8f7ad44657c04b Mon Sep 17 00:00:00 2001 From: stefan schippers Date: Thu, 6 Feb 2025 01:11:11 +0100 Subject: [PATCH 2/3] propagate changed key bindings to new opened windows (in no-tabs mode) --- src/callback.c | 46 +++++++++++++++++++++++----------------------- src/globals.c | 2 +- src/scheduler.c | 20 ++++++++++---------- src/xinit.c | 9 +++++---- src/xschem.h | 6 +++--- src/xschem.tcl | 24 ++++++++++++------------ 6 files changed, 54 insertions(+), 53 deletions(-) diff --git a/src/callback.c b/src/callback.c index b91a4076..2f2d4b3b 100644 --- a/src/callback.c +++ b/src/callback.c @@ -2158,7 +2158,7 @@ static void end_shape_point_edit(double c_snap) } #if defined(__unix__) && HAS_CAIRO==1 -static int grabscreen(const char *winpath, int event, int mx, int my, KeySym key, +static int grabscreen(const char *win_path, int event, int mx, int my, KeySym key, int button, int aux, int state) { static int grab_state = 0; @@ -2285,8 +2285,8 @@ static int grabscreen(const char *winpath, int event, int mx, int my, KeySym key /* main window callback */ /* mx and my are set to the mouse coord. relative to window */ -/* winpath: set to .drw or sub windows .x1.drw, .x2.drw, ... */ -int callback(const char *winpath, int event, int mx, int my, KeySym key, +/* 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) { char str[PATH_MAX + 100]; @@ -2310,9 +2310,9 @@ int rstate; /* (reduced state, without ShiftMask) */ * on such events */ if(fix_mouse_coord) { if(event == KeyPress || event == KeyRelease) { - tclvareval("getmousex ", winpath, NULL); + tclvareval("getmousex ", win_path, NULL); mx = atoi(tclresult()); - tclvareval("getmousey ", winpath, NULL); + tclvareval("getmousey ", win_path, NULL); my = atoi(tclresult()); dbg(1, "mx = %d my=%d\n", mx, my); } @@ -2348,21 +2348,21 @@ int rstate; /* (reduced state, without ShiftMask) */ #if 0 /* exclude Motion and Expose events */ if(event!=6 /* && event!=12 */) { - dbg(0, "callback(): state=%d event=%d, winpath=%s, old_winpath=%s, semaphore=%d\n", - state, event, winpath, old_winpath, xctx->semaphore+1); + 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_winpath, winpath) ) { + 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_winpath, winpath); + 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", winpath, "", 1); + new_schematic("switch_no_tcl_ctx", win_path, "", 1); } else { - dbg(1, "callback(): switching window context: %s --> %s, semaphore=%d\n", old_winpath, winpath, xctx->semaphore); - new_schematic("switch", winpath, "", 1); + 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); } @@ -2407,7 +2407,7 @@ int rstate; /* (reduced state, without ShiftMask) */ #if defined(__unix__) && HAS_CAIRO==1 if(xctx->ui_state & GRABSCREEN) { - grabscreen(winpath, event, mx, my, key, button, aux, state); + grabscreen(win_path, event, mx, my, key, button, aux, state); } else #endif switch(event) @@ -2450,7 +2450,7 @@ int rstate; /* (reduced state, without ShiftMask) */ break; case Expose: - dbg(1, "callback: Expose, winpath=%s, %dx%d+%d+%d\n", winpath, button, aux, mx, my); + 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]; @@ -2931,10 +2931,10 @@ int rstate; /* (reduced state, without ShiftMask) */ tclvareval("xschem set rectcolor ", n, NULL); if(has_x) { - if(!strcmp(winpath, ".drw")) { + if(!strcmp(win_path, ".drw")) { tclvareval("reconfigure_layers_button {}", NULL); } else { - tclvareval("reconfigure_layers_button [winfo parent ", winpath, "]", NULL); + tclvareval("reconfigure_layers_button [winfo parent ", win_path, "]", NULL); } } dbg(1, "callback(): new color: %d\n",xctx->color_index[xctx->rectcolor]); @@ -3652,8 +3652,8 @@ int rstate; /* (reduced state, without ShiftMask) */ if(key=='\\' && state==0) /* fullscreen */ { - dbg(1, "callback(): toggle fullscreen, winpath=%s\n", winpath); - toggle_fullscreen(winpath); + dbg(1, "callback(): toggle fullscreen, win_path=%s\n", win_path); + toggle_fullscreen(win_path); break; } if(key=='f' && EQUAL_MODMASK) /* flip objects around their anchor points 20171208 */ @@ -4433,13 +4433,13 @@ int rstate; /* (reduced state, without ShiftMask) */ 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_winpath, winpath); - if(old_winpath[0]) new_schematic("switch_no_tcl_ctx", old_winpath, "", 1); + 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_winpath, winpath)) { - if(old_winpath[0]) dbg(1, "callback(): reset old_winpath: %s <- %s\n", old_winpath, winpath); - my_strncpy(old_winpath, winpath, S(old_winpath)); + 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/globals.c b/src/globals.c index 36c2984a..7a270d4d 100644 --- a/src/globals.c +++ b/src/globals.c @@ -186,7 +186,7 @@ int yyparse_error = 0; char *xschem_executable=NULL; Tcl_Interp *interp = NULL; double *character[256]; /* array or per-char coordinates of xschem internal vector font */ -char old_winpath[PATH_MAX] = ".drw"; /* previously switched window, used in callback() */ +char old_win_path[PATH_MAX] = ".drw"; /* previously switched window, used in callback() */ #ifndef __unix__ char win_temp_dir[PATH_MAX]=""; const char fopen_read_mode[] = "rb"; diff --git a/src/scheduler.c b/src/scheduler.c index 8641ca0f..8cf1fc2c 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -431,7 +431,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg else { cmd_found = 0;} break; case 'c': /*----------------------------------------------*/ - /* callback winpath event mx my key button aux state + /* callback win_path event mx my key button aux state * Invoke the callback event dispatcher with a software event */ if(!strcmp(argv[1], "callback") ) { @@ -3404,22 +3404,22 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg Tcl_ResetResult(interp); } - /* new_schematic create|destroy|destroy_all|switch winpath file [draw] + /* new_schematic create|destroy|destroy_all|switch win_path file [draw] * Open/destroy a new tab or window * create: create new empty window or with 'file' loaded if 'file' given. - * The winpath must be given (even {} is ok). - * non empty winpath ({1}) will avoid warnings if opening the + * The win_path must be given (even {} is ok). + * non empty win_path ({1}) will avoid warnings if opening the * same file multiple times. - * destroy: destroy tab/window identified by winpath. Example: + * destroy: destroy tab/window identified by win_path. Example: * xschem new_schematic destroy .x1.drw * destroy_all: close all tabs/additional windows * if the 'force'argument is given do not issue a warning if modified * tabs are about to be closed. - * switch: switch context to specified 'winpath' window or specified schematic name + * switch: switch context to specified 'win_path' window or specified schematic name * If 'draw' is given and set to 0 do not redraw after switching tab * (only tab i/f) - * Main window/tab has winpath set to .drw, - * Additional windows/tabs have winpath set to .x1.drw, .x2.drw and so on... + * Main window/tab has win_path set to .drw, + * Additional windows/tabs have win_path set to .x1.drw, .x2.drw and so on... */ else if(!strcmp(argv[1], "new_schematic")) { @@ -3623,7 +3623,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg xctx->ui_state2 = MENUSTARTPOLYGON; } - /* preview_window create|draw|destroy|close [winpath] [file] + /* 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. * Used in fileselector to show a schematic preview. @@ -5759,7 +5759,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg /* switch [window_path |schematic_name] * Switch context to indicated window path or schematic name * returns 0 if switch was successfull or 1 in case of errors - * (no tabs/windows present or no matching winpath / schematic name + * (no tabs/windows present or no matching win_path / schematic name * found). */ else if(!strcmp(argv[1], "switch")) diff --git a/src/xinit.c b/src/xinit.c index deb35b6f..9d8438a6 100644 --- a/src/xinit.c +++ b/src/xinit.c @@ -187,7 +187,7 @@ static int window_state (Display *disp, Window win, char *arg) {/*{{{*/ /* ----------------------------------------------------------------------- */ /* used to set icon */ -void windowid(const char *winpath) +void windowid(const char *win_path) { #ifdef __unix__ int i; @@ -200,11 +200,11 @@ void windowid(const char *winpath) Window *framewin_child_ptr; unsigned int framewindow_nchildren; - dbg(1, "windowid(): winpath=%s\n", winpath); + dbg(1, "windowid(): win_path=%s\n", win_path); framewindow_nchildren =0; mainwindow=Tk_MainWindow(interp); display = Tk_Display(mainwindow); - tclvareval("winfo id ", winpath, NULL); + tclvareval("winfo id ", win_path, NULL); sscanf(tclresult(), "0x%x", (unsigned int *) &ww); framewin = ww; XQueryTree(display, framewin, &rootwindow, &parent_of_topwindow, &framewin_child_ptr, &framewindow_nchildren); @@ -1443,7 +1443,7 @@ void swap_windows(int dr) new_schematic("switch", wp_j, "", 0); resetwin(1, 1, 1, 0, 0); - my_snprintf(old_winpath, S(old_winpath), ""); + my_snprintf(old_win_path, S(old_win_path), ""); if(dr) draw(); } } @@ -1653,6 +1653,7 @@ static void create_new_window(int *window_count, const char *noconfirm, const ch load_schematic(1, fname, 1, confirm); if(dr) zoom_full(1, 0, 1 + 2 * tclgetboolvar("zoom_full_center"), 0.97); /* draw */ tclvareval("set_bindings ", window_path[n], NULL); + tclvareval("set_replace_key_binding ", window_path[n], NULL); tclvareval("save_ctx ", window_path[n], NULL); /* restore previous context, * because the Expose event after new window creation does a context switch prev win -> new win diff --git a/src/xschem.h b/src/xschem.h index b14bec10..1113aec1 100644 --- a/src/xschem.h +++ b/src/xschem.h @@ -1212,7 +1212,7 @@ extern int yyparse_error; extern char *xschem_executable; extern Tcl_Interp *interp; extern double *character[256]; -extern char old_winpath[PATH_MAX]; /* previously switched window, used in callback() */ +extern char old_win_path[PATH_MAX]; /* previously switched window, used in callback() */ extern const char fopen_read_mode[]; /* "r" on unix, "rb" on windows */ /*********** Cmdline options (used at xinit, and then not used anymore) ***********/ @@ -1395,7 +1395,7 @@ extern void abort_operation(void); extern void draw_crosshair(int what, int state); extern void backannotate_at_cursor_b_pos(xRect *r, Graph_ctx *gr); /* extern void snapped_wire(double c_snap); */ -extern int callback(const char *winpath, int event, int mx, int my, KeySym key, +extern int callback(const char *win_path, int event, int mx, int my, KeySym key, int button, int aux, int state); extern void resetwin(int create_pixmap, int clear_pixmap, int force, int w, int h); extern Selected find_closest_obj(double mx,double my, int override_lock); @@ -1740,7 +1740,7 @@ extern void print_hilight_net(int show); extern void list_hilights(int all); extern void change_layer(); extern void launcher(); -extern void windowid(const char *winpath); +extern void windowid(const char *win_path); extern int preview_window(const char *what, const char *tk_win_path, const char *fname); extern int new_schematic(const char *what, const char *win_path, const char *fname, int dr); extern void toggle_fullscreen(const char *topwin); diff --git a/src/xschem.tcl b/src/xschem.tcl index 7e08c6e1..ca04c085 100644 --- a/src/xschem.tcl +++ b/src/xschem.tcl @@ -1005,7 +1005,7 @@ proc convert_to_png {filename dest} { # Alt-Key-c # ButtonPress-4 # -proc key_binding { s d { topwin {} } } { +proc key_binding { s d { win_path {.drw} } } { regsub {.*-} $d {} key @@ -1039,14 +1039,14 @@ proc key_binding { s d { topwin {} } } { if { [regexp ButtonPress-3 $d] } { set state [expr {$state +0x400}] } # puts "$state $key <${s}>" if {[regexp ButtonPress- $d]} { - bind $topwin.drw "<${s}>" "xschem callback %W %T %x %y 0 $key 0 $state" + bind $win_path "<${s}>" "xschem callback %W %T %x %y 0 $key 0 $state" } else { if {![string compare $d {} ] } { # puts "bind .drw <${s}> {}" - bind $topwin.drw "<${s}>" {} + bind $win_path "<${s}>" {} } else { # puts "bind .drw <${s}> xschem callback %W %T %x %y $keysym 0 0 $state" - bind $topwin.drw "<${s}>" "xschem callback %W %T %x %y $keysym 0 0 $state" + bind $win_path "<${s}>" "xschem callback %W %T %x %y $keysym 0 0 $state" } } @@ -7831,33 +7831,33 @@ proc housekeeping_ctx {} { } # callback that resets simulate button color at end of simulation -proc set_simulate_button {top_path winpath} { +proc set_simulate_button {top_path win_path} { global simulate_bg execute has_x if {![info exists has_x]} return set current_win [xschem get current_win_path] - set simvar tctx::${winpath}_simulate + set simvar tctx::${win_path}_simulate set sim_button $top_path.menubar # puts "current_win=|$current_win|" # puts "simvar=|$simvar|" - # puts "winpath=|$winpath|" + # puts "win_path=|$win_path|" # puts "top_path=|$top_path|" # puts "sim_button=|$sim_button|" # puts "execute(exitcode,last)=|$execute(exitcode,last)|" if {![info exists execute(exitcode,last)]} { - if { $current_win eq $winpath} { + if { $current_win eq $win_path} { $sim_button entryconfigure Simulate -background $simulate_bg } set $simvar $simulate_bg } elseif { $execute(exitcode,last) == 0} { - if { $current_win eq $winpath} { + if { $current_win eq $win_path} { $sim_button entryconfigure Simulate -background Green } set $simvar Green } else { - if { $current_win eq $winpath} { + if { $current_win eq $win_path} { $sim_button entryconfigure Simulate -background red } set $simvar red @@ -8892,11 +8892,11 @@ proc create_layers_menu { {topwin {} } } { } } -proc set_replace_key_binding {} { +proc set_replace_key_binding { {win_path {.drw}}} { global replace_key if {[array exists replace_key]} { foreach i [array names replace_key] { - key_binding "$i" "$replace_key($i)" + key_binding "$i" "$replace_key($i)" $win_path } } } From 7926a833beedb7ea2b1802a5060dc23c9db94e00 Mon Sep 17 00:00:00 2001 From: stefan schippers Date: Thu, 6 Feb 2025 04:20:57 +0100 Subject: [PATCH 3/3] added `d` to unselect object under the mouse, `Shift-D` to unselect by area, both work with or without infix_interface, moved delete files to `Ctrl-d`, update keybinding docs --- doc/xschem_man/commands.html | 4 +- src/callback.c | 75 ++++++++++++++++++++++++++++-------- src/keys.help | 4 +- src/xschem.h | 6 ++- 4 files changed, 71 insertions(+), 18 deletions(-) diff --git a/doc/xschem_man/commands.html b/doc/xschem_man/commands.html index d6a9da20..0a4f589e 100644 --- a/doc/xschem_man/commands.html +++ b/doc/xschem_man/commands.html @@ -156,7 +156,9 @@ ctrl 'c' Save to clipboard shift 'C' Start arc placement shift+ctrl 'C' Start circle placement alt 'C' Toggle dim/brite background with rest of layers -shift 'D' Delete files +ctrl 'd' Delete files +- 'd' Unselect selected object under the mouse pointer +shift 'D' Unselect selected objects by area ctrl 'e' Back to parent schematic - 'e' Descend to schematic alt 'e' Edit selected schematic in a new window diff --git a/src/callback.c b/src/callback.c index 2f2d4b3b..17484caa 100644 --- a/src/callback.c +++ b/src/callback.c @@ -1571,6 +1571,16 @@ static int end_place_move_copy_zoom() return 0; } +static void unselect_at_mouse_pos(int mx, int my) +{ + xctx->last_command = 0; + xctx->mx_save = mx; xctx->my_save = my; + xctx->mx_double_save=xctx->mousex_snap; + xctx->my_double_save=xctx->mousey_snap; + select_object(xctx->mousex, xctx->mousey, 0, 0, NULL); + rebuild_selected_array(); /* sets or clears xctx->ui_state SELECTION flag */ +} + void snapped_wire(double c_snap) { double x, y; @@ -1590,11 +1600,22 @@ void snapped_wire(double c_snap) } } -static int check_menu_start_commands(double c_snap) +static int check_menu_start_commands(double c_snap, int mx, int my) { dbg(1, "check_menu_start_commands(): ui_state=%x, ui_state2=%x last_command=%d\n", xctx->ui_state, xctx->ui_state2, xctx->last_command); + if((xctx->ui_state & MENUSTART) && (xctx->ui_state2 & MENUSTARTDESEL) ) { + if(xctx->ui_state & DESEL_CLICK) { + unselect_at_mouse_pos(mx, my); + } else { /* unselect by area */ + xctx->mx_save = mx; xctx->my_save = my; + xctx->mx_double_save=xctx->mousex; + xctx->my_double_save=xctx->mousey; + xctx->ui_state |= DESEL_AREA; + } + return 1; + } if((xctx->ui_state & MENUSTART) && (xctx->ui_state2 & MENUSTARTWIRECUT)) { break_wires_at_point(xctx->mousex_snap, xctx->mousey_snap, 1); return 1; @@ -2510,7 +2531,7 @@ int rstate; /* (reduced state, without ShiftMask) */ /* determine direction of a rectangle selection (or unselection with ALT key) */ if(xctx->ui_state & STARTSELECT && !(xctx->ui_state & (PLACE_SYMBOL | STARTPAN | PLACE_TEXT)) ) { /* Unselect by area : determine direction */ - if( (state & Button1Mask) && SET_MODMASK) { + if( ((state & Button1Mask) && SET_MODMASK) || (xctx->ui_state & DESEL_AREA)) { if(mx >= xctx->mx_save) xctx->nl_dir = 0; else xctx->nl_dir = 1; select_rect(enable_stretch, RUBBER,0); @@ -2563,12 +2584,13 @@ int rstate; /* (reduced state, without ShiftMask) */ } } /* Unselect by area */ - if((state & Button1Mask) && (SET_MODMASK) && !(state & ShiftMask) && - !(xctx->ui_state & STARTPAN) && !xctx->shape_point_selected && + if( (((state & Button1Mask) && SET_MODMASK) || (xctx->ui_state & DESEL_AREA)) && + !(state & ShiftMask) && + !(xctx->ui_state & STARTPAN) && + !xctx->shape_point_selected && + !(xctx->ui_state & STARTSELECT) && !(xctx->ui_state & (PLACE_SYMBOL | PLACE_TEXT))) { /* unselect area */ - if( !(xctx->ui_state & STARTSELECT)) { - select_rect(enable_stretch, START,0); - } + select_rect(enable_stretch, START,0); } /* Select by area. Shift pressed */ else if((state&Button1Mask) && (state & ShiftMask) && !(xctx->ui_state & STARTWIRE) && @@ -3979,7 +4001,33 @@ int rstate; /* (reduced state, without ShiftMask) */ draw(); break; } - if(key=='D' && rstate == 0) /* delete files */ + if(key=='d' && rstate == 0) /* unselect object under the mouse */ + { + if(infix_interface) { + unselect_at_mouse_pos(mx, my); + } else { + xctx->ui_state |= (MENUSTART | DESEL_CLICK); + xctx->ui_state2 = MENUSTARTDESEL; + } + break; + } + if(key=='D' && rstate == 0) /* unselect by area */ + { + if( !(xctx->ui_state & STARTPAN) && !xctx->shape_point_selected && + !(xctx->ui_state & (PLACE_SYMBOL | PLACE_TEXT)) && !(xctx->ui_state & STARTSELECT)) { + if(infix_interface) { + xctx->mx_save = mx; xctx->my_save = my; + xctx->mx_double_save=xctx->mousex; + xctx->my_double_save=xctx->mousey; + xctx->ui_state |= DESEL_AREA; + } else { + xctx->ui_state |= MENUSTART; + xctx->ui_state2 = MENUSTARTDESEL; + } + } + break; + } + if(key=='d' && rstate == ControlMask) /* delete files */ { if(xctx->semaphore >= 2) break; delete_files(); @@ -4120,12 +4168,7 @@ int rstate; /* (reduced state, without ShiftMask) */ } /* Alt - Button1 click to unselect */ else if(button==Button1 && (SET_MODMASK) ) { - xctx->last_command = 0; - xctx->mx_save = mx; xctx->my_save = my; - xctx->mx_double_save=xctx->mousex_snap; - xctx->my_double_save=xctx->mousey_snap; - select_object(xctx->mousex, xctx->mousey, 0, 0, NULL); - rebuild_selected_array(); /* sets or clears xctx->ui_state SELECTION flag */ + unselect_at_mouse_pos(mx, my); } /* Middle button press (Button2) will pan the schematic. */ @@ -4165,7 +4208,7 @@ int rstate; /* (reduced state, without ShiftMask) */ break; } /* handle all object insertions started from Tools/Edit menu */ - if(check_menu_start_commands(c_snap)) break; + if(check_menu_start_commands(c_snap, mx, my)) break; /* complete the pending STARTWIRE, STARTRECT, STARTZOOM, STARTCOPY ... operations */ if(end_place_move_copy_zoom()) break; @@ -4303,6 +4346,7 @@ int rstate; /* (reduced state, without ShiftMask) */ waves_callback(event, mx, my, key, button, aux, state); break; } + xctx->ui_state &= ~DESEL_CLICK; dbg(1, "release: shape_point_selected=%d\n", xctx->shape_point_selected); /* bring up context menu if no pending operation */ if(state == Button3Mask && xctx->semaphore <2) { @@ -4378,6 +4422,7 @@ int rstate; /* (reduced state, without ShiftMask) */ select_rect(enable_stretch, END,-1); } } + xctx->ui_state &= ~DESEL_AREA; rebuild_selected_array(); 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] ); diff --git a/src/keys.help b/src/keys.help index cc2db919..a73197bf 100644 --- a/src/keys.help +++ b/src/keys.help @@ -96,7 +96,9 @@ ctrl 'c' Save to clipboard shift 'C' Start arc placement shift+ctrl 'C' Start circle placement alt 'C' Toggle dim/brite background with rest of layers -shift 'D' Delete files +ctrl 'd' Delete files +- 'd' Unselect selected object under the mouse pointer +shift 'D' Unselect selected objects by area ctrl 'e' Back to parent schematic - 'e' Descend to schematic alt 'e' Edit selected schematic in a new window diff --git a/src/xschem.h b/src/xschem.h index 1113aec1..34423304 100644 --- a/src/xschem.h +++ b/src/xschem.h @@ -229,7 +229,9 @@ extern char win_temp_dir[PATH_MAX]; #define START_SYMPIN 16384U #define GRAPHPAN 32768U /* bit 15 */ #define MENUSTART 65536U /* bit 16 */ -#define GRABSCREEN 131072 /* bit 17 */ +#define GRABSCREEN 131072U /* bit 17 */ +#define DESEL_CLICK 262144U /* bit 18 */ +#define DESEL_AREA 524288U /* bit 19 */ #define SELECTED 1U /* used in the .sel field for selected objs. */ #define SELECTED1 2U /* first point selected... */ @@ -238,6 +240,7 @@ extern char win_temp_dir[PATH_MAX]; #define SELECTED4 16U /* sub states encoded in global ui_state2 to reduce ui_state bits usage */ +/* also used when infix_interface=0 */ #define MENUSTARTWIRE 1U /* start wire invoked from menu */ #define MENUSTARTLINE 2U /* start line invoked from menu */ #define MENUSTARTRECT 4U /* start rect invoked from menu */ @@ -250,6 +253,7 @@ extern char win_temp_dir[PATH_MAX]; #define MENUSTARTWIRECUT 512U #define MENUSTARTWIRECUT2 1024U /* do not align cut point to snap */ #define MENUSTARTCOPY 2048U +#define MENUSTARTDESEL 4096U #define WIRE 1 /* types of defined objects */ #define xRECT 2