When saving a schematic issue a warning if disk file has been changed since opening

This commit is contained in:
Stefan Frederik 2021-11-20 13:33:40 +01:00
parent 9ceb25716e
commit a495ada2ed
6 changed files with 52 additions and 27 deletions

View File

@ -373,6 +373,7 @@ char *strtoupper(char* s) {
return s; return s;
} }
/* call hash_all_names() (once) before (repeatedly) using this function */
void set_inst_prop(int i) void set_inst_prop(int i)
{ {
char *ptr; char *ptr;

View File

@ -928,8 +928,9 @@ void make_symbol(void)
void make_schematic(const char *schname) void make_schematic(const char *schname)
{ {
FILE *fd=NULL; FILE *fd=NULL;
rebuild_selected_array(); rebuild_selected_array();
if (!xctx->lastsel) return; if(!xctx->lastsel) return;
if (!(fd = fopen(schname, "w"))) if (!(fd = fopen(schname, "w")))
{ {
fprintf(errfp, "make_schematic(): problems opening file %s \n", schname); fprintf(errfp, "make_schematic(): problems opening file %s \n", schname);
@ -965,6 +966,7 @@ int save_schematic(const char *schname) /* 20171020 added return value */
FILE *fd; FILE *fd;
char name[PATH_MAX]; /* overflow safe 20161122 */ char name[PATH_MAX]; /* overflow safe 20161122 */
char *top_path; char *top_path;
struct stat buf;
top_path = xctx->top_path[0] ? xctx->top_path : "."; top_path = xctx->top_path[0] ? xctx->top_path : ".";
@ -978,6 +980,17 @@ int save_schematic(const char *schname) /* 20171020 added return value */
Tcl_VarEval(interp, "wm title ", top_path, " \"xschem - [file tail [xschem get schname]]\"", NULL); Tcl_VarEval(interp, "wm title ", top_path, " \"xschem - [file tail [xschem get schname]]\"", NULL);
Tcl_VarEval(interp, "wm iconname ", top_path, " \"xschem - [file tail [xschem get schname]]\"", NULL); Tcl_VarEval(interp, "wm iconname ", top_path, " \"xschem - [file tail [xschem get schname]]\"", NULL);
} }
if(!stat(name, &buf)) {
if(xctx->time_last_modify && xctx->time_last_modify != buf.st_mtime) {
Tcl_VarEval(interp, "ask_save \"Schematic file: ", name,
" has been changed since opening.\nSave anyway?\" 0", NULL);
if(strcmp(tclresult(), "yes") ) {
return -1;
}
}
}
if(!(fd=fopen(name,"w"))) if(!(fd=fopen(name,"w")))
{ {
fprintf(errfp, "save_schematic(): problems opening file %s \n",name); fprintf(errfp, "save_schematic(): problems opening file %s \n",name);
@ -987,6 +1000,10 @@ int save_schematic(const char *schname) /* 20171020 added return value */
unselect_all(); unselect_all();
write_xschem_file(fd); write_xschem_file(fd);
fclose(fd); fclose(fd);
/* update time stamp */
if(!stat(name)) {
xctx->time_last_modify = buf.st_mtime;
}
my_strncpy(xctx->current_name, rel_sym_path(name), S(xctx->current_name)); my_strncpy(xctx->current_name, rel_sym_path(name), S(xctx->current_name));
/* <<<<< >>>> why clear all these? */ /* <<<<< >>>> why clear all these? */
xctx->prep_hi_structs=0; xctx->prep_hi_structs=0;
@ -1058,6 +1075,12 @@ void load_schematic(int load_symbols, const char *filename, int reset_undo) /* 2
dbg(1, "load_schematic(): opening file for loading:%s, filename=%s\n", name, filename); dbg(1, "load_schematic(): opening file for loading:%s, filename=%s\n", name, filename);
dbg(1, "load_schematic(): sch[currsch]=%s\n", xctx->sch[xctx->currsch]); dbg(1, "load_schematic(): sch[currsch]=%s\n", xctx->sch[xctx->currsch]);
if(!name[0]) return; if(!name[0]) return;
if(!stat(name, &buf)) { /* file exists */
xctx->time_last_modify = buf.st_mtime;
} else {
xctx->time_last_modify = 0;
}
if( (fd=fopen(name,fopen_read_mode))== NULL) { if( (fd=fopen(name,fopen_read_mode))== NULL) {
fprintf(errfp, "load_schematic(): unable to open file: %s, filename=%s\n", fprintf(errfp, "load_schematic(): unable to open file: %s, filename=%s\n",
name, filename ? filename : "<NULL>"); name, filename ? filename : "<NULL>");
@ -2208,7 +2231,6 @@ void create_sch_from_sym(void)
char *dir = NULL; char *dir = NULL;
char *prop = NULL; char *prop = NULL;
char schname[PATH_MAX]; char schname[PATH_MAX];
char *savecmd=NULL;
char *sub_prop; char *sub_prop;
char *sub2_prop=NULL; char *sub2_prop=NULL;
char *str=NULL; char *str=NULL;
@ -2235,12 +2257,9 @@ void create_sch_from_sym(void)
my_strncpy(schname, add_ext(abs_sym_path(xctx->inst[xctx->sel_array[0].n].name, ""), ".sch"), S(schname)); my_strncpy(schname, add_ext(abs_sym_path(xctx->inst[xctx->sel_array[0].n].name, ""), ".sch"), S(schname));
} }
if( !stat(schname, &buf) ) { if( !stat(schname, &buf) ) {
my_strdup(353, &savecmd, "ask_save \" create schematic file: "); Tcl_VarEval(interp, "ask_save \"Create schematic file: ", schname,
my_strcat(354, &savecmd, schname); "?\nWARNING: This schematic file already exists, it will be overwritten\"", NULL);
my_strcat(355, &savecmd, " ?\nWARNING: This schematic file already exists, it will be overwritten\"");
tcleval(savecmd);
if(strcmp(tclresult(), "yes") ) { if(strcmp(tclresult(), "yes") ) {
my_free(914, &savecmd);
return; return;
} }
} }
@ -2248,7 +2267,6 @@ void create_sch_from_sym(void)
{ {
fprintf(errfp, "create_sch_from_sym(): problems opening file %s \n",schname); fprintf(errfp, "create_sch_from_sym(): problems opening file %s \n",schname);
tcleval("alert_ {file opening for write failed!} {}"); tcleval("alert_ {file opening for write failed!} {}");
my_free(915, &savecmd);
return; return;
} }
fprintf(fd, "v {xschem version=%s file_version=%s}\n", XSCHEM_VERSION, XSCHEM_FILE_VERSION); fprintf(fd, "v {xschem version=%s file_version=%s}\n", XSCHEM_VERSION, XSCHEM_FILE_VERSION);
@ -2311,7 +2329,6 @@ void create_sch_from_sym(void)
} /* if(xctx->lastsel...) */ } /* if(xctx->lastsel...) */
my_free(916, &dir); my_free(916, &dir);
my_free(917, &prop); my_free(917, &prop);
my_free(918, &savecmd);
my_free(919, &sub2_prop); my_free(919, &sub2_prop);
my_free(920, &str); my_free(920, &str);
} }

View File

@ -32,7 +32,7 @@ struct inst_hashentry {
}; };
static struct inst_hashentry *table[HASHSIZE]; static struct inst_hashentry *table[HASHSIZE]; /* safe with multiple schematics, hash rebuilt before usage */
enum status {TOK_BEGIN, TOK_TOKEN, TOK_SEP, TOK_VALUE, TOK_END, TOK_ENDTOK}; enum status {TOK_BEGIN, TOK_TOKEN, TOK_SEP, TOK_VALUE, TOK_END, TOK_ENDTOK};
@ -670,7 +670,7 @@ void new_prop_string(int i, const char *old_prop, int fast, int dis_uniq_names)
const char *tmp; const char *tmp;
const char *tmp2; const char *tmp2;
int q,qq; int q,qq;
static int last[256]; static int last[256]; /* safe to keep with multiple schematics, reset on 1st invocation */
int old_name_len; int old_name_len;
int new_name_len; int new_name_len;
int n; int n;
@ -1690,8 +1690,7 @@ int print_spice_element(FILE *fd, int inst)
/* fputs(value,fd); */ /* fputs(value,fd); */
} }
} }
else if (strcmp(token,"@symname")==0) /* of course symname must not be present */ else if (strcmp(token,"@symname")==0) /* of course symname must not be present in attributes */
/* in hash table */
{ {
const char *s = skip_dir(xctx->inst[inst].name); const char *s = skip_dir(xctx->inst[inst].name);
tmp = strlen(s) +100 ; /* always make room for some extra chars tmp = strlen(s) +100 ; /* always make room for some extra chars
@ -1700,8 +1699,7 @@ int print_spice_element(FILE *fd, int inst)
result_pos += my_snprintf(result + result_pos, tmp, "%s", s); result_pos += my_snprintf(result + result_pos, tmp, "%s", s);
/* fputs(s,fd); */ /* fputs(s,fd); */
} }
else if (strcmp(token,"@symname_ext")==0) /* of course symname must not be present */ else if (strcmp(token,"@symname_ext")==0) /* of course symname must not be present in attributes */
/* in hash table */
{ {
const char *s = get_cell_w_ext(xctx->inst[inst].name, 0); const char *s = get_cell_w_ext(xctx->inst[inst].name, 0);
tmp = strlen(s) +100 ; /* always make room for some extra chars tmp = strlen(s) +100 ; /* always make room for some extra chars
@ -1710,8 +1708,7 @@ int print_spice_element(FILE *fd, int inst)
result_pos += my_snprintf(result + result_pos, tmp, "%s", s); result_pos += my_snprintf(result + result_pos, tmp, "%s", s);
/* fputs(s,fd); */ /* fputs(s,fd); */
} }
else if(strcmp(token,"@schname")==0) /* of course schname must not be present */ else if(strcmp(token,"@schname")==0) /* of course schname must not be present in attributes */
/* in hash table */
{ {
tmp = strlen(xctx->current_name) +100 ; /* always make room for some extra chars tmp = strlen(xctx->current_name) +100 ; /* always make room for some extra chars
* so 1-char writes to result do not need reallocs */ * so 1-char writes to result do not need reallocs */
@ -1720,8 +1717,8 @@ int print_spice_element(FILE *fd, int inst)
/* fputs(xctx->current_name, fd); */ /* fputs(xctx->current_name, fd); */
} }
else if(strcmp(token,"@pinlist")==0) /* of course pinlist must not be present */ else if(strcmp(token,"@pinlist")==0) /* of course pinlist must not be present in attributes */
/* in hash table. print multiplicity */ /* print multiplicity */
{ /* and node number: m1 n1 m2 n2 .... */ { /* and node number: m1 n1 m2 n2 .... */
for(i=0;i<no_of_pins;i++) for(i=0;i<no_of_pins;i++)
{ {
@ -2758,7 +2755,7 @@ const char *find_nth(const char *str, char sep, int n)
const char *translate(int inst, const char* s) const char *translate(int inst, const char* s)
{ {
static const char empty[]=""; static const char empty[]="";
static char *result=NULL; static char *result=NULL; /* safe to keep even with multiple schematics */
int size=0, tmp; int size=0, tmp;
register int c, state=TOK_BEGIN, space; register int c, state=TOK_BEGIN, space;
char *token=NULL; char *token=NULL;

View File

@ -584,6 +584,7 @@ void alloc_xschem_data(const char *top_path)
#ifdef IN_MEMORY_UNDO #ifdef IN_MEMORY_UNDO
xctx->initialized = 0; /* in_memory_undo */ xctx->initialized = 0; /* in_memory_undo */
#endif #endif
xctx->time_last_modify = 0;
} }
void delete_schematic_data(void) void delete_schematic_data(void)

View File

@ -709,6 +709,7 @@ typedef struct {
int *fill_type; /* for every layer: 0: no fill, 1, solid fill, 2: stipple fill */ int *fill_type; /* for every layer: 0: no fill, 1, solid fill, 2: stipple fill */
int fill_pattern; int fill_pattern;
int draw_window; int draw_window;
time_t time_last_modify;
} Xschem_ctx; } Xschem_ctx;
struct Lcc { /* used for symbols containing schematics as instances (LCC, Local Custom Cell) */ struct Lcc { /* used for symbols containing schematics as instances (LCC, Local Custom Cell) */

View File

@ -2270,7 +2270,7 @@ proc attach_labels_to_inst {} {
return {} return {}
} }
proc ask_save { {ask {save file?}} } { proc ask_save { {ask {save file?}} {cancel 1}} {
global rcode wm_fix global rcode wm_fix
set rcode {} set rcode {}
if { [winfo exists .dialog] } return if { [winfo exists .dialog] } return
@ -2290,10 +2290,12 @@ proc ask_save { {ask {save file?}} } {
set rcode {yes} set rcode {yes}
destroy .dialog destroy .dialog
} }
button .dialog.f1.b2 -text {Cancel} -command\ if {$cancel} {
{ button .dialog.f1.b2 -text {Cancel} -command\
set rcode {} {
destroy .dialog set rcode {}
destroy .dialog
}
} }
button .dialog.f1.b3 -text {No} -command\ button .dialog.f1.b3 -text {No} -command\
{ {
@ -2301,8 +2303,14 @@ proc ask_save { {ask {save file?}} } {
destroy .dialog destroy .dialog
} }
pack .dialog.l1 .dialog.f1 -side top -fill x pack .dialog.l1 .dialog.f1 -side top -fill x
pack .dialog.f1.b1 .dialog.f1.b2 .dialog.f1.b3 -side left -fill x -expand yes pack .dialog.f1.b1 -side left -fill x -expand yes
bind .dialog <Escape> {.dialog.f1.b2 invoke} if { $cancel} {
pack .dialog.f1.b2 -side left -fill x -expand yes
}
pack .dialog.f1.b3 -side left -fill x -expand yes
if {$cancel} {
bind .dialog <Escape> {.dialog.f1.b2 invoke}
}
# needed, otherwise problems when descending with double clixk 23012004 # needed, otherwise problems when descending with double clixk 23012004
tkwait visibility .dialog tkwait visibility .dialog
grab set .dialog grab set .dialog