`xschem save` --> save_schematic(): added `fast` argument (do not update window/tab/sim button states for speed); `xschem select instance` --> select_element(): added `nodraw` argument in addition to existing `fast` (avoid drawing selected item for speed)

This commit is contained in:
stefan schippers 2025-01-05 13:27:49 +01:00
parent 4d76708534
commit 783fa04eb6
8 changed files with 48 additions and 30 deletions

View File

@ -1342,8 +1342,10 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
if x0, y0 not given use mouse coordinates </pre> if x0, y0 not given use mouse coordinates </pre>
<li><kbd> rotate_in_place</kbd></li><pre> <li><kbd> rotate_in_place</kbd></li><pre>
Rotate selected objects around their 0,0 coordinate point </pre> Rotate selected objects around their 0,0 coordinate point </pre>
<li><kbd> save</kbd></li><pre> <li><kbd> save [fast]</kbd></li><pre>
Save schematic if modified. Does not ask confirmation! </pre> Save schematic if modified. Does not ask confirmation!
if 'fast' is given it is passed to save_schematic() to avoid
updating window/tab/sim button states </pre>
<li><kbd> saveas [file] [type]</kbd></li><pre> <li><kbd> saveas [file] [type]</kbd></li><pre>
save current schematic as 'file' save current schematic as 'file'
if file is empty ({}) use current schematic name if file is empty ({}) use current schematic name
@ -1393,6 +1395,7 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
for all other objects 'id' is the position in the respective arrays for all other objects 'id' is the position in the respective arrays
if 'clear' is specified does an unselect operation if 'clear' is specified does an unselect operation
if 'fast' is specified avoid sending information to infowindow and status bar if 'fast' is specified avoid sending information to infowindow and status bar
if 'nodraw' is given on select instance do not draw selection
returns 1 if something selected, 0 otherwise </pre> returns 1 if something selected, 0 otherwise </pre>
<li><kbd> select_all</kbd></li><pre> <li><kbd> select_all</kbd></li><pre>
Selects all objects in schematic </pre> Selects all objects in schematic </pre>

View File

@ -536,8 +536,9 @@ const char *get_file_path(char *f)
* 1 : file saved or not needed to save since no change * 1 : file saved or not needed to save since no change
* -1 : user cancel * -1 : user cancel
* 0 : file not saved due to errors or per user request * 0 : file not saved due to errors or per user request
* confirm:
*/ */
int save(int confirm) int save(int confirm, int fast)
{ {
struct stat buf; struct stat buf;
char *name = xctx->sch[xctx->currsch]; char *name = xctx->sch[xctx->currsch];
@ -556,10 +557,10 @@ int save(int confirm)
if(confirm) { if(confirm) {
tcleval("ask_save_optional"); tcleval("ask_save_optional");
if(!strcmp(tclresult(), "") ) return -1; /* user clicks "Cancel" */ if(!strcmp(tclresult(), "") ) return -1; /* user clicks "Cancel" */
else if(!strcmp(tclresult(), "yes") ) return save_schematic(xctx->sch[xctx->currsch]); else if(!strcmp(tclresult(), "yes") ) return save_schematic(xctx->sch[xctx->currsch], fast);
else return 0; /* user clicks "no" */ else return 0; /* user clicks "no" */
} else { } else {
return save_schematic(xctx->sch[xctx->currsch]); return save_schematic(xctx->sch[xctx->currsch], fast);
} }
} }
return 1; /* circuit not changed: always succeeed */ return 1; /* circuit not changed: always succeeed */
@ -592,7 +593,7 @@ void saveas(const char *f, int type) /* changed name from ask_save_file to save
if(!res[0]) return; if(!res[0]) return;
dbg(1, "saveas(): res = %s\n", res); dbg(1, "saveas(): res = %s\n", res);
save_schematic(res); save_schematic(res, 0);
tclvareval("update_recent_file {", res,"}", NULL); tclvareval("update_recent_file {", res,"}", NULL);
return; return;
} }
@ -603,7 +604,7 @@ void ask_new_file(void)
if(!has_x) return; if(!has_x) return;
if(xctx->modified) { if(xctx->modified) {
if(save(1) == -1 ) return; /* user cancels save, so do nothing. */ if(save(1, 0) == -1 ) return; /* user cancels save, so do nothing. */
} }
tcleval("load_file_dialog {Load file} *.\\{sch,sym,tcl\\} INITIALLOADDIR"); tcleval("load_file_dialog {Load file} *.\\{sch,sym,tcl\\} INITIALLOADDIR");
my_snprintf(f, S(f),"%s", tclresult()); my_snprintf(f, S(f),"%s", tclresult());
@ -2231,7 +2232,7 @@ int descend_schematic(int instnumber, int fallback, int alert, int set_title)
my_strncpy(res, tclresult(), S(res)); my_strncpy(res, tclresult(), S(res));
if(!res[0]) return 0; if(!res[0]) return 0;
dbg(1, "descend_schematic(): saving: %s\n",res); dbg(1, "descend_schematic(): saving: %s\n",res);
save_ok = save_schematic(res); save_ok = save_schematic(res, 0);
if(save_ok==0) return 0; if(save_ok==0) return 0;
} }
n = xctx->sel_array[0].n; n = xctx->sel_array[0].n;
@ -2248,7 +2249,7 @@ int descend_schematic(int instnumber, int fallback, int alert, int set_title)
if(xctx->modified) { if(xctx->modified) {
int ret; int ret;
ret = save(1); ret = save(1, 0);
/* if circuit is changed but not saved before descending /* if circuit is changed but not saved before descending
* state will be inconsistent when returning, can not propagare hilights * state will be inconsistent when returning, can not propagare hilights
* save() return value: * save() return value:
@ -2402,10 +2403,10 @@ void go_back(int confirm, int set_title) /* 20171006 add confirm */
{ {
if(confirm) { if(confirm) {
tcleval("ask_save_optional"); tcleval("ask_save_optional");
if(!strcmp(tclresult(), "yes") ) save_ok = save_schematic(xctx->sch[xctx->currsch]); if(!strcmp(tclresult(), "yes") ) save_ok = save_schematic(xctx->sch[xctx->currsch], 0);
else if(!strcmp(tclresult(), "") ) return; else if(!strcmp(tclresult(), "") ) return;
} else { } else {
save_ok = save_schematic(xctx->sch[xctx->currsch]); save_ok = save_schematic(xctx->sch[xctx->currsch], 0);
} }
} }
if(save_ok==0) { if(save_ok==0) {
@ -2458,7 +2459,7 @@ void go_back(int confirm, int set_title) /* 20171006 add confirm */
void clear_schematic(int cancel, int symbol) void clear_schematic(int cancel, int symbol)
{ {
if(cancel == 1) cancel=save(1); if(cancel == 1) cancel=save(1, 0);
if(cancel != -1) { /* -1 means user cancel save request */ if(cancel != -1) { /* -1 means user cancel save request */
char name[PATH_MAX]; char name[PATH_MAX];
struct stat buf; struct stat buf;

View File

@ -2831,7 +2831,7 @@ int rstate; /* (reduced state, without ShiftMask) */
if(!strcmp(xctx->sch[xctx->currsch],"") || strstr(xctx->sch[xctx->currsch], "untitled")) { if(!strcmp(xctx->sch[xctx->currsch],"") || strstr(xctx->sch[xctx->currsch], "untitled")) {
saveas(NULL, SCHEMATIC); saveas(NULL, SCHEMATIC);
} else { } else {
save(1); save(1, 0);
} }
break; break;
} }
@ -2907,7 +2907,7 @@ int rstate; /* (reduced state, without ShiftMask) */
"-message {do you want to make symbol view ?}"); "-message {do you want to make symbol view ?}");
if(strcmp(tclresult(),"ok")==0) if(strcmp(tclresult(),"ok")==0)
{ {
save_schematic(xctx->sch[xctx->currsch]); save_schematic(xctx->sch[xctx->currsch], 0);
make_symbol(); make_symbol();
} }
break; break;

View File

@ -3315,7 +3315,7 @@ Sch_pin_record *sort_schematic_pins(int *npins)
* 0 : did not save * 0 : did not save
* 1 : schematic saved * 1 : schematic saved
*/ */
int save_schematic(const char *schname) /* 20171020 added return value */ int save_schematic(const char *schname, int fast) /* 20171020 added return value */
{ {
FILE *fd; FILE *fd;
struct stat buf; struct stat buf;
@ -3372,7 +3372,8 @@ int save_schematic(const char *schname) /* 20171020 added return value */
* xctx->prep_hash_wires=0; * xctx->prep_hash_wires=0;
*/ */
if(!strstr(xctx->sch[xctx->currsch], ".xschem_embedded_")) { if(!strstr(xctx->sch[xctx->currsch], ".xschem_embedded_")) {
set_modify(0); if(fast) set_modify(2); /* only clear modified flag, no title/tab/sim buttons update */
else set_modify(0);
} }
tclvareval(xctx->top_path, ".menubar entryconfigure Simulate -background $simulate_bg", NULL); tclvareval(xctx->top_path, ".menubar entryconfigure Simulate -background $simulate_bg", NULL);
tclvareval("set tctx::", xctx->current_win_path, "_simulate $simulate_bg", NULL); tclvareval("set tctx::", xctx->current_win_path, "_simulate $simulate_bg", NULL);
@ -5067,7 +5068,7 @@ void descend_symbol(void)
if(xctx->modified) if(xctx->modified)
{ {
int ret; int ret;
ret = save(1); ret = save(1, 1);
/* if circuit is changed but not saved before descending /* if circuit is changed but not saved before descending
* state will be inconsistent when returning, can not propagare hilights * state will be inconsistent when returning, can not propagare hilights
* save() return value: * save() return value:

View File

@ -914,7 +914,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;} if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
rebuild_selected_array(); rebuild_selected_array();
if(xctx->lastsel==0 ) { if(xctx->lastsel==0 ) {
save_schematic(xctx->sch[xctx->currsch]); /* sync data with disk file before editing file */ save_schematic(xctx->sch[xctx->currsch], 0); /* sync data with disk file before editing file */
my_snprintf(name, S(name), "edit_file {%s}", my_snprintf(name, S(name), "edit_file {%s}",
abs_sym_path(xctx->sch[xctx->currsch], "")); abs_sym_path(xctx->sch[xctx->currsch], ""));
tcleval(name); tcleval(name);
@ -2815,7 +2815,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
my_snprintf(f, S(f),"regsub {^~/} {%s} {%s/}", argv[2], home_dir); my_snprintf(f, S(f),"regsub {^~/} {%s} {%s/}", argv[2], home_dir);
tcleval(f); tcleval(f);
my_strncpy(f, tclresult(), S(f)); my_strncpy(f, tclresult(), S(f));
if(force || !has_x || !xctx->modified || save(1) != -1 ) { /* save(1)==-1 --> user cancel */ if(force || !has_x || !xctx->modified || save(1, 0) != -1 ) { /* save(1)==-1 --> user cancel */
char win_path[WINDOW_PATH_SIZE]; char win_path[WINDOW_PATH_SIZE];
int skip = 0; int skip = 0;
dbg(1, "scheduler(): load: filename=%s\n", argv[2]); dbg(1, "scheduler(): load: filename=%s\n", argv[2]);
@ -3049,7 +3049,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
if(has_x) tcleval("tk_messageBox -type okcancel -parent [xschem get topwindow] " if(has_x) tcleval("tk_messageBox -type okcancel -parent [xschem get topwindow] "
"-message {do you want to make symbol view ?}"); "-message {do you want to make symbol view ?}");
if(!has_x || strcmp(tclresult(), "ok")==0) { if(!has_x || strcmp(tclresult(), "ok")==0) {
save_schematic(xctx->sch[xctx->currsch]); save_schematic(xctx->sch[xctx->currsch], 0);
make_symbol(); make_symbol();
} }
Tcl_ResetResult(interp); Tcl_ResetResult(interp);
@ -4590,16 +4590,23 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
else { cmd_found = 0;} else { cmd_found = 0;}
break; break;
case 's': /*----------------------------------------------*/ case 's': /*----------------------------------------------*/
/* save /* save [fast]
* Save schematic if modified. Does not ask confirmation! */ * Save schematic if modified. Does not ask confirmation!
* if 'fast' is given it is passed to save_schematic() to avoid
* updating window/tab/sim button states */
if(!strcmp(argv[1], "save")) if(!strcmp(argv[1], "save"))
{ {
int fast = 0;
if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;} if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
dbg(1, "scheduler(): saving: current schematic\n"); dbg(1, "scheduler(): saving: current schematic\n");
for(i = 2; i < argc; i++) {
if(!strcmp(argv[i], "fast")) fast |= 1;
}
if(!strcmp(xctx->sch[xctx->currsch], "")) { /* check if unnamed schematic, use saveas in this case... */ if(!strcmp(xctx->sch[xctx->currsch], "")) { /* check if unnamed schematic, use saveas in this case... */
saveas(NULL, SCHEMATIC); saveas(NULL, SCHEMATIC);
} else { } else {
save(0); save(0, fast);
} }
} }
@ -4745,6 +4752,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
* for all other objects 'id' is the position in the respective arrays * for all other objects 'id' is the position in the respective arrays
* if 'clear' is specified does an unselect operation * if 'clear' is specified does an unselect operation
* if 'fast' is specified avoid sending information to infowindow and status bar * if 'fast' is specified avoid sending information to infowindow and status bar
* if 'nodraw' is given on select instance do not draw selection
* returns 1 if something selected, 0 otherwise */ * returns 1 if something selected, 0 otherwise */
else if(!strcmp(argv[1], "select")) else if(!strcmp(argv[1], "select"))
{ {
@ -4766,7 +4774,8 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
int i; int i;
for(i = 4; i < argc; i++) { for(i = 4; i < argc; i++) {
if(!strcmp(argv[i], "clear")) sel = 0; if(!strcmp(argv[i], "clear")) sel = 0;
if(!strcmp(argv[i], "fast")) fast = 1; if(!strcmp(argv[i], "fast")) fast |= 1;
if(!strcmp(argv[i], "nodraw") && !strcmp(argv[2], "instance")) fast |= 2;
} }
} }
if(!strcmp(argv[2], "instance") && argc > 3) { if(!strcmp(argv[2], "instance") && argc > 3) {

View File

@ -937,6 +937,10 @@ void select_wire(int i,unsigned short select_mode, int fast)
xctx->need_reb_sel_arr=1; xctx->need_reb_sel_arr=1;
} }
/* fast == 1: do not update status line
* fast == 2: do not draw / undraw selected elements
* fast == 3: 1 + 2
*/
void select_element(int i,unsigned short select_mode, int fast, int override_lock) void select_element(int i,unsigned short select_mode, int fast, int override_lock)
{ {
int c, j; int c, j;
@ -946,7 +950,7 @@ void select_element(int i,unsigned short select_mode, int fast, int override_loc
if(!strboolcmp(get_tok_value(xctx->inst[i].prop_ptr, "lock", 0), "true") && if(!strboolcmp(get_tok_value(xctx->inst[i].prop_ptr, "lock", 0), "true") &&
select_mode == SELECTED && !override_lock) return; select_mode == SELECTED && !override_lock) return;
my_strncpy(s,xctx->inst[i].prop_ptr!=NULL?xctx->inst[i].prop_ptr:"<NULL>",S(s)); my_strncpy(s,xctx->inst[i].prop_ptr!=NULL?xctx->inst[i].prop_ptr:"<NULL>",S(s));
if( !fast ) if( !(fast & 1) )
{ {
my_snprintf(str, S(str), "Info: selected element %d: %s\nproperties:\n%s", i, my_snprintf(str, S(str), "Info: selected element %d: %s\nproperties:\n%s", i,
xctx->inst[i].name ? xctx->inst[i].name : "<NULL>" , s); xctx->inst[i].name ? xctx->inst[i].name : "<NULL>" , s);
@ -976,7 +980,7 @@ void select_element(int i,unsigned short select_mode, int fast, int override_loc
} }
xctx->inst[i].sel = select_mode; xctx->inst[i].sel = select_mode;
if(select_mode == SELECTED) set_first_sel(ELEMENT, i, 0); if(select_mode == SELECTED) set_first_sel(ELEMENT, i, 0);
if(!fast) { if(!(fast & 2) ) {
if(select_mode) { if(select_mode) {
for(c=0;c<cadlayers; ++c) { for(c=0;c<cadlayers; ++c) {
draw_temp_symbol(ADD, xctx->gc[SELLAYER], i,c,0,0,0.0,0.0); draw_temp_symbol(ADD, xctx->gc[SELLAYER], i,c,0,0,0.0,0.0);

View File

@ -1310,7 +1310,7 @@ extern void new_xschem_process(const char *cell, int symbol);
extern void ask_new_file(void); extern void ask_new_file(void);
extern void saveas(const char *f, int type); extern void saveas(const char *f, int type);
extern const char *get_file_path(char *f); extern const char *get_file_path(char *f);
extern int save(int confirm); extern int save(int confirm, int fast);
extern void save_ascii_string(const char *ptr, FILE *fd, int newline); extern void save_ascii_string(const char *ptr, FILE *fd, int newline);
extern Hilight_hashentry *bus_hilight_hash_lookup(const char *token, int value, int what) ; extern Hilight_hashentry *bus_hilight_hash_lookup(const char *token, int value, int what) ;
/* wrapper function to hash highlighted instances, avoid clash with net names */ /* wrapper function to hash highlighted instances, avoid clash with net names */
@ -1496,7 +1496,7 @@ extern int sym_vs_sch_pins(int all);
extern char *get_generator_command(const char *str); extern char *get_generator_command(const char *str);
extern int match_symbol(const char name[]); extern int match_symbol(const char name[]);
extern Sch_pin_record *sort_schematic_pins(int *npins); extern Sch_pin_record *sort_schematic_pins(int *npins);
extern int save_schematic(const char *); /* 20171020 added return value */ extern int save_schematic(const char *, int fast); /* 20171020 added return value */
extern void copy_symbol(xSymbol *dest_sym, xSymbol *src_sym); extern void copy_symbol(xSymbol *dest_sym, xSymbol *src_sym);
extern void push_undo(void); extern void push_undo(void);
extern void pop_undo(int redo, int set_modify_status); extern void pop_undo(int redo, int set_modify_status);

View File

@ -1904,7 +1904,7 @@ proc traversal_setlabels {w parent_sch instname inst_sch sym_sch default_sch ins
xschem setprop instance $instname schematic [$w get] fast ;# set schematic attr on instance xschem setprop instance $instname schematic [$w get] fast ;# set schematic attr on instance
} }
xschem set_modify 3 ;# set only modified flag to force a save, do not update window/tab titles xschem set_modify 3 ;# set only modified flag to force a save, do not update window/tab titles
xschem save xschem save fast
set inst_sch [$w get] set inst_sch [$w get]
# puts "inst_sch set to: $inst_sch" # puts "inst_sch set to: $inst_sch"
xschem load $current noundoreset nodraw xschem load $current noundoreset nodraw
@ -2083,7 +2083,7 @@ proc hier_traversal {{level 0} {only_subckts 0} {all_hierarchy 1}} {
set done_print 1 set done_print 1
if {$type eq {subcircuit} && $all_hierarchy} { if {$type eq {subcircuit} && $all_hierarchy} {
xschem select instance $i fast xschem select instance $i fast nodraw
set descended [xschem descend 1 6] set descended [xschem descend 1 6]
if {$descended} { if {$descended} {
incr level incr level