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;
}
/* call hash_all_names() (once) before (repeatedly) using this function */
void set_inst_prop(int i)
{
char *ptr;

View File

@ -928,8 +928,9 @@ void make_symbol(void)
void make_schematic(const char *schname)
{
FILE *fd=NULL;
rebuild_selected_array();
if (!xctx->lastsel) return;
if(!xctx->lastsel) return;
if (!(fd = fopen(schname, "w")))
{
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;
char name[PATH_MAX]; /* overflow safe 20161122 */
char *top_path;
struct stat buf;
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 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")))
{
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();
write_xschem_file(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));
/* <<<<< >>>> why clear all these? */
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(): sch[currsch]=%s\n", xctx->sch[xctx->currsch]);
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) {
fprintf(errfp, "load_schematic(): unable to open file: %s, filename=%s\n",
name, filename ? filename : "<NULL>");
@ -2208,7 +2231,6 @@ void create_sch_from_sym(void)
char *dir = NULL;
char *prop = NULL;
char schname[PATH_MAX];
char *savecmd=NULL;
char *sub_prop;
char *sub2_prop=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));
}
if( !stat(schname, &buf) ) {
my_strdup(353, &savecmd, "ask_save \" create schematic file: ");
my_strcat(354, &savecmd, schname);
my_strcat(355, &savecmd, " ?\nWARNING: This schematic file already exists, it will be overwritten\"");
tcleval(savecmd);
Tcl_VarEval(interp, "ask_save \"Create schematic file: ", schname,
"?\nWARNING: This schematic file already exists, it will be overwritten\"", NULL);
if(strcmp(tclresult(), "yes") ) {
my_free(914, &savecmd);
return;
}
}
@ -2248,7 +2267,6 @@ void create_sch_from_sym(void)
{
fprintf(errfp, "create_sch_from_sym(): problems opening file %s \n",schname);
tcleval("alert_ {file opening for write failed!} {}");
my_free(915, &savecmd);
return;
}
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...) */
my_free(916, &dir);
my_free(917, &prop);
my_free(918, &savecmd);
my_free(919, &sub2_prop);
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};
@ -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 *tmp2;
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 new_name_len;
int n;
@ -1690,8 +1690,7 @@ int print_spice_element(FILE *fd, int inst)
/* fputs(value,fd); */
}
}
else if (strcmp(token,"@symname")==0) /* of course symname must not be present */
/* in hash table */
else if (strcmp(token,"@symname")==0) /* of course symname must not be present in attributes */
{
const char *s = skip_dir(xctx->inst[inst].name);
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);
/* fputs(s,fd); */
}
else if (strcmp(token,"@symname_ext")==0) /* of course symname must not be present */
/* in hash table */
else if (strcmp(token,"@symname_ext")==0) /* of course symname must not be present in attributes */
{
const char *s = get_cell_w_ext(xctx->inst[inst].name, 0);
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);
/* fputs(s,fd); */
}
else if(strcmp(token,"@schname")==0) /* of course schname must not be present */
/* in hash table */
else if(strcmp(token,"@schname")==0) /* of course schname must not be present in attributes */
{
tmp = strlen(xctx->current_name) +100 ; /* always make room for some extra chars
* 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); */
}
else if(strcmp(token,"@pinlist")==0) /* of course pinlist must not be present */
/* in hash table. print multiplicity */
else if(strcmp(token,"@pinlist")==0) /* of course pinlist must not be present in attributes */
/* print multiplicity */
{ /* and node number: m1 n1 m2 n2 .... */
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)
{
static const char empty[]="";
static char *result=NULL;
static char *result=NULL; /* safe to keep even with multiple schematics */
int size=0, tmp;
register int c, state=TOK_BEGIN, space;
char *token=NULL;

View File

@ -584,6 +584,7 @@ void alloc_xschem_data(const char *top_path)
#ifdef IN_MEMORY_UNDO
xctx->initialized = 0; /* in_memory_undo */
#endif
xctx->time_last_modify = 0;
}
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_pattern;
int draw_window;
time_t time_last_modify;
} Xschem_ctx;
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 {}
}
proc ask_save { {ask {save file?}} } {
proc ask_save { {ask {save file?}} {cancel 1}} {
global rcode wm_fix
set rcode {}
if { [winfo exists .dialog] } return
@ -2290,10 +2290,12 @@ proc ask_save { {ask {save file?}} } {
set rcode {yes}
destroy .dialog
}
button .dialog.f1.b2 -text {Cancel} -command\
{
set rcode {}
destroy .dialog
if {$cancel} {
button .dialog.f1.b2 -text {Cancel} -command\
{
set rcode {}
destroy .dialog
}
}
button .dialog.f1.b3 -text {No} -command\
{
@ -2301,8 +2303,14 @@ proc ask_save { {ask {save file?}} } {
destroy .dialog
}
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
bind .dialog <Escape> {.dialog.f1.b2 invoke}
pack .dialog.f1.b1 -side left -fill x -expand yes
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
tkwait visibility .dialog
grab set .dialog