From 935ec2777202992e4dea70aeaae2425271201151 Mon Sep 17 00:00:00 2001 From: stefan schippers Date: Sat, 22 Feb 2025 01:30:38 +0100 Subject: [PATCH] floater objects: add command ctrl-u to unselect attached (so some instance with the attach=.. attribute) objects, that is objects (not element instances) with a non empty name=... atttribute. Extend upcate references of attached floaters to change instance name property and `xschem setprop instance name` command --- doc/xschem_man/commands.html | 1 + src/callback.c | 69 +++++++++++++++++++++++++++--------- src/editprop.c | 8 +++-- src/keys.help | 1 + src/move.c | 27 +++++++------- src/scheduler.c | 23 ++++++++++-- src/select.c | 2 +- src/xschem.h | 3 ++ src/xschem.tcl | 2 ++ 9 files changed, 101 insertions(+), 35 deletions(-) diff --git a/doc/xschem_man/commands.html b/doc/xschem_man/commands.html index 0a4f589e..02f5777a 100644 --- a/doc/xschem_man/commands.html +++ b/doc/xschem_man/commands.html @@ -229,6 +229,7 @@ ctrl+alt 's' Save-as symbol - 't' Place text shift 'T' Toggle *_ignore flag on selected instances alt 'u' Align to current grid selected objects +ctrl 'u' Unselect attached floater objects shift 'U' Redo - 'u' Undo - 'v' Constrained vertical move/copy of objects diff --git a/src/callback.c b/src/callback.c index d2ca603d..25e807b5 100644 --- a/src/callback.c +++ b/src/callback.c @@ -2383,6 +2383,54 @@ static int grabscreen(const char *win_path, int event, int mx, int my, KeySym ke } #endif +void unselect_attached_floaters(void) +{ + int c, i, found = 0; + for(c = 0; c < cadlayers; c++) { + for(i = 0; i < xctx->rects[c]; i++) { + if(get_tok_value(xctx->rect[c][i].prop_ptr, "name", 0)[0]) { + found = 1; + select_box(c, i, 0, 1, 0); + } + } + for(i = 0; i < xctx->lines[c]; i++) { + if(get_tok_value(xctx->line[c][i].prop_ptr, "name", 0)[0]) { + found = 1; + select_line(c, i, 0, 1); + } + } + + for(i = 0; i < xctx->polygons[c]; i++) { + if(get_tok_value(xctx->poly[c][i].prop_ptr, "name", 0)[0]) { + found = 1; + select_polygon(c, i, 0, 1); + } + } + for(i = 0; i < xctx->arcs[c]; i++) { + if(get_tok_value(xctx->arc[c][i].prop_ptr, "name", 0)[0]) { + found = 1; + select_arc(c, i, 0, 1); + } + } + } + for(i = 0; i < xctx->wires; i++) { + if(get_tok_value(xctx->wire[i].prop_ptr, "name", 0)[0]) { + found = 1; + select_wire(i, 0, 1); + } + } + for(i = 0; i < xctx->texts; i++) { + if(get_tok_value(xctx->text[i].prop_ptr, "name", 0)[0]) { + found = 1; + select_text(i, 0, 1); + } + } + if(found) { + rebuild_selected_array(); + draw_selection(xctx->gc[SELLAYER],0); + } +} + static void handle_enter_notify(int draw_xhair, int crosshair_size) { struct stat buf; @@ -3477,7 +3525,11 @@ static void handle_key_press(int event, KeySym key, int state, int rstate, int m draw(); return; } - if(0 && (key=='u') && rstate==ControlMask) /* testmode */ + if(key=='u' && rstate==ControlMask) /* unselect attached floater elements */ + { + unselect_attached_floaters(); + } + if(0 && (key=='|') && rstate==ControlMask) /* testmode */ { static int x = 0; @@ -3973,21 +4025,6 @@ static void handle_key_press(int event, KeySym key, int state, int rstate, int m check_unique_names(1); return; } - if( 0 && (key==';') && (state & ControlMask) ) /* testmode */ - { - return; - } - if(0 && key=='~' && (state & ControlMask)) { /* testmode */ - return; - } - if(0 && key=='|' && !(state & ControlMask)) { /* testmode */ - return; - } - if(0 && key=='|' && (state & ControlMask)) /* testmode */ - { - return; - } - if(key=='f' && rstate == ControlMask) /* search */ { if(xctx->semaphore >= 2) return; diff --git a/src/editprop.c b/src/editprop.c index 3a7f9323..ee8f1ac3 100644 --- a/src/editprop.c +++ b/src/editprop.c @@ -1637,6 +1637,7 @@ static int update_symbol(const char *result, int x, int selected_inst) /* preserve backslashes in name ---------0---------------------------------->. */ my_strdup(_ALLOC_ID_, &name, get_tok_value(xctx->inst[*ii].prop_ptr, "name", 1)); if(name && name[0] ) { + char *old_name = NULL; dbg(1, "update_symbol(): prefix!='\\0', name=%s\n", name); /* change prefix if changing symbol type; */ if(prefix && old_prefix && old_prefix != prefix) { @@ -1649,11 +1650,14 @@ static int update_symbol(const char *result, int x, int selected_inst) if(!pushed) { xctx->push_undo(); pushed=1;} if(!k) hash_names(-1, XINSERT); hash_names(*ii, XDELETE); - dbg(1, "update_symbol(): delete %s\n", xctx->inst[*ii].instname); + dbg(0, "update_symbol(): delete %s\n", xctx->inst[*ii].instname); + my_strdup2(_ALLOC_ID_, &old_name, xctx->inst[*ii].instname); new_prop_string(*ii, ptr, /* sets also inst[].instname */ tclgetboolvar("disable_unique_names")); /* set new prop_ptr */ hash_names(*ii, XINSERT); - dbg(1, "update_symbol(): insert %s\n", xctx->inst[*ii].instname); + update_attached_object_refs(old_name, *ii, 1); + dbg(0, "update_symbol(): insert %s\n", xctx->inst[*ii].instname); + my_free(_ALLOC_ID_, &old_name); } set_inst_flags(&xctx->inst[*ii]); } /* end for(k=0;klastsel; ++k) */ diff --git a/src/keys.help b/src/keys.help index a73197bf..a473aa45 100644 --- a/src/keys.help +++ b/src/keys.help @@ -169,6 +169,7 @@ ctrl+alt 's' Save-as symbol - 't' Place text shift 'T' Toggle *_ignore flag on selected instances alt 'u' Align to current grid selected objects +ctrl 'u' Unselect attached floater objects shift 'U' Redo - 'u' Undo - 'v' Constrained vertical move/copy of objects diff --git a/src/move.c b/src/move.c index f03b7871..20ee6f99 100644 --- a/src/move.c +++ b/src/move.c @@ -513,12 +513,13 @@ void draw_selection(GC g, int interruptable) xctx->movelastsel = i; } -static void update_attached_object_refs(int from, int to) +/* sel: if set to 1 change references only on selected items, like in a copy operation. + * If set to 0 operate on all objects with matching name=... attribute */ +void update_attached_object_refs(const char *from_name, int inst, int sel) { int i, c; - char *to_name = xctx->inst[to].instname; - char *from_name = xctx->inst[from].instname; - const char *attach = get_tok_value(xctx->inst[to].prop_ptr, "attach", 0); + char *to_name = xctx->inst[inst].instname; + const char *attach = get_tok_value(xctx->inst[inst].prop_ptr, "attach", 0); char *new_attach; if(!from_name || !from_name[0]) return; @@ -526,12 +527,12 @@ static void update_attached_object_refs(int from, int to) if(!attach[0]) return; new_attach = str_replace(attach, from_name, to_name, 1, 1); - my_strdup(_ALLOC_ID_, &xctx->inst[to].prop_ptr, - subst_token(xctx->inst[to].prop_ptr, "attach", new_attach) ); + my_strdup(_ALLOC_ID_, &xctx->inst[inst].prop_ptr, + subst_token(xctx->inst[inst].prop_ptr, "attach", new_attach) ); for(c = 0; c < cadlayers; c++) { for(i = 0; i < xctx->rects[c]; i++) { - if(xctx->rect[c][i].sel == SELECTED) { + if(!sel || xctx->rect[c][i].sel == SELECTED) { if( !strcmp(from_name, get_tok_value(xctx->rect[c][i].prop_ptr, "name", 0))) { my_strdup(_ALLOC_ID_, &xctx->rect[c][i].prop_ptr, subst_token(xctx->rect[c][i].prop_ptr, "name", to_name) ); @@ -547,7 +548,7 @@ static void update_attached_object_refs(int from, int to) } } for(i = 0; i < xctx->lines[c]; i++) { - if(xctx->line[c][i].sel == SELECTED && + if((!sel || xctx->line[c][i].sel == SELECTED) && !strcmp(from_name, get_tok_value(xctx->line[c][i].prop_ptr, "name", 0))) { my_strdup(_ALLOC_ID_, &xctx->line[c][i].prop_ptr, subst_token(xctx->line[c][i].prop_ptr, "name", to_name) ); @@ -555,7 +556,7 @@ static void update_attached_object_refs(int from, int to) } for(i = 0; i < xctx->polygons[c]; i++) { - if(xctx->poly[c][i].sel == SELECTED && + if((!sel || xctx->poly[c][i].sel == SELECTED) && !strcmp(from_name, get_tok_value(xctx->poly[c][i].prop_ptr, "name", 0))) { my_strdup(_ALLOC_ID_, &xctx->poly[c][i].prop_ptr, subst_token(xctx->poly[c][i].prop_ptr, "name", to_name) ); @@ -563,7 +564,7 @@ static void update_attached_object_refs(int from, int to) } } for(i = 0; i < xctx->arcs[c]; i++) { - if(xctx->arc[c][i].sel == SELECTED && + if((!sel || xctx->arc[c][i].sel == SELECTED) && !strcmp(from_name, get_tok_value(xctx->arc[c][i].prop_ptr, "name", 0))) { my_strdup(_ALLOC_ID_, &xctx->arc[c][i].prop_ptr, subst_token(xctx->arc[c][i].prop_ptr, "name", to_name) ); @@ -571,14 +572,14 @@ static void update_attached_object_refs(int from, int to) } } for(i = 0; i < xctx->wires; i++) { - if(xctx->wire[i].sel == SELECTED && + if((!sel || xctx->wire[i].sel == SELECTED) && !strcmp(from_name, get_tok_value(xctx->wire[i].prop_ptr, "name", 0))) { my_strdup(_ALLOC_ID_, &xctx->wire[i].prop_ptr, subst_token(xctx->wire[i].prop_ptr, "name", to_name) ); } } for(i = 0; i < xctx->texts; i++) { - if(xctx->text[i].sel == SELECTED && + if((!sel || xctx->text[i].sel == SELECTED) && !strcmp(from_name, get_tok_value(xctx->text[i].prop_ptr, "name", 0))) { my_strdup(_ALLOC_ID_, &xctx->text[i].prop_ptr, subst_token(xctx->text[i].prop_ptr, "name", to_name) ); @@ -957,7 +958,7 @@ void copy_objects(int what) new_prop_string(xctx->instances, xctx->inst[n].prop_ptr, /* sets also inst[].instname */ tclgetboolvar("disable_unique_names")); - update_attached_object_refs(n, xctx->instances); + update_attached_object_refs(xctx->inst[n].instname, xctx->instances, 1); hash_names(xctx->instances, XINSERT); xctx->instances++; /* symbol_bbox calls translate and translate must have updated xctx->instances */ diff --git a/src/scheduler.c b/src/scheduler.c index 38e6866e..538e1bbf 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -5461,7 +5461,8 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg } else { char *translated_sym = NULL; int sym_number = -1; - char *subst = NULL; + char *subst = NULL, *old_name = NULL;; + if(!fast) { symbol_bbox(inst, &xctx->inst[inst].x1, &xctx->inst[inst].y1, &xctx->inst[inst].x2, &xctx->inst[inst].y2); xctx->push_undo(); @@ -5469,7 +5470,12 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg xctx->prep_hash_inst=0; xctx->prep_net_structs=0; xctx->prep_hi_structs=0; - if(argc > 4 && !strcmp(argv[4], "name") && fast == 0) hash_names(-1, XINSERT); + if(argc > 4 && !strcmp(argv[4], "name")) { + if(fast == 0) { + hash_names(-1, XINSERT); + } + my_strdup2(_ALLOC_ID_, &old_name, xctx->inst[inst].instname); + } if(argc > 5) { if(!strcmp(argv[4], "allprops")) { hash_names(-1, XINSERT); @@ -5486,7 +5492,9 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg } hash_names(inst, XDELETE); new_prop_string(inst, subst, tclgetboolvar("disable_unique_names")); - + if(old_name) { + update_attached_object_refs(old_name, inst, 0); + } my_strdup2(_ALLOC_ID_, &translated_sym, translate(inst, xctx->inst[inst].name)); sym_number=match_symbol(translated_sym); @@ -5495,6 +5503,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg xctx->inst[inst].ptr=sym_number; } if(subst) my_free(_ALLOC_ID_, &subst); + if(old_name) my_free(_ALLOC_ID_, &old_name); set_inst_flags(&xctx->inst[inst]); hash_names(inst, XINSERT); if(!fast) { @@ -6215,6 +6224,14 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg Tcl_ResetResult(interp); } + /* unselect_attached_floaters + * Unselect objects (not symbol instances) attached to some instance with a + * non empty name=... attribute */ + else if(!strcmp(argv[1], "unselect_attached_floaters")) + { + if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;} + unselect_attached_floaters(); + } /* update_all_sym_bboxes * Update all symbol bounding boxes */ else if(!strcmp(argv[1], "update_all_sym_bboxes")) diff --git a/src/select.c b/src/select.c index c90d85f5..8386da34 100644 --- a/src/select.c +++ b/src/select.c @@ -1282,7 +1282,7 @@ Selected select_object(double mx,double my, unsigned short select_mode, break; case ELEMENT: if(xctx->inst[sel.n].sel) xctx->already_selected = 1; - select_element(sel.n,select_mode,0, override_lock); + select_element(sel.n, select_mode,0, override_lock); break; default: break; diff --git a/src/xschem.h b/src/xschem.h index 84e30e0e..d4e74449 100644 --- a/src/xschem.h +++ b/src/xschem.h @@ -1402,6 +1402,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 void unselect_attached_floaters(void); 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); @@ -1546,6 +1547,8 @@ extern void new_line(int what, double mx_snap, double my_snap); extern void new_arc(int what, double sweep, double mousex_snap, double mousey_snap); extern void arc_3_points(double x1, double y1, double x2, double y2, double x3, double y3, double *x, double *y, double *r, double *a, double *b); +/* sel: if set to 1 change references only on selected items, like in a copy operation */ +extern void update_attached_object_refs(const char *from_name, int inst, int sel); extern void move_objects(int what,int merge, double dx, double dy); extern void check_collapsing_objects(); extern void redraw_w_a_l_r_p_z_rubbers(int force); /* redraw wire, arcs, line, polygon rubbers */ diff --git a/src/xschem.tcl b/src/xschem.tcl index dd5d47cb..e35d90e6 100644 --- a/src/xschem.tcl +++ b/src/xschem.tcl @@ -8680,6 +8680,8 @@ proc build_widgets { {topwin {} } } { -command "xschem net_label 0" -accelerator Alt-Shift-L $topwin.menubar.sym add command -label "Change selected inst. texts to floaters" \ -command "xschem floaters_from_selected_inst" + $topwin.menubar.sym add command -label "Unselect attached floaters" \ + -command "xschem unselect_attached_floaters" $topwin.menubar.sym add command -label "Print list of highlight nets" \ -command "xschem print_hilight_net 1" -accelerator J $topwin.menubar.sym add command -label "Print list of highlight nets, with buses expanded" \