issue warning if opening same circuit in different tabs, if tabbed if is active edit sch/sym in new window will do in a new tab

This commit is contained in:
Stefan Frederik 2022-01-10 18:54:07 +01:00
parent b81ce64c0c
commit d6b513e1e2
9 changed files with 590 additions and 453 deletions

View File

@ -445,29 +445,39 @@ void saveas(const char *f, int type) /* changed name from ask_save_file to save
void ask_new_file(void)
{
char fullname[PATH_MAX]; /* overflow safe 20161125 */
char f[PATH_MAX]; /* overflow safe 20161125 */
if(!has_x) return;
if(xctx->modified) {
if(save(1) == -1 ) return; /* user cancels save, so do nothing. */
}
tcleval("load_file_dialog {Load file} .sch.sym INITIALLOADDIR");
my_snprintf(fullname, S(fullname),"%s", tclresult());
if( fullname[0] ) {
dbg(1, "ask_new_file(): load file: %s\n", fullname);
clear_all_hilights();
xctx->currsch = 0;
unselect_all();
remove_symbols();
load_schematic(1, fullname,1); /* 20180925.1 */
tclvareval("update_recent_file {", fullname, "}", NULL);
my_strdup(1, &xctx->sch_path[xctx->currsch],".");
xctx->sch_path_hash[xctx->currsch] = 0;
xctx->sch_inst_number[xctx->currsch] = 1;
zoom_full(1, 0, 1, 0.97);
my_snprintf(f, S(f),"%s", tclresult());
if(f[0]) {
char win_path[WINDOW_PATH_SIZE];
int skip = 0;
dbg(1, "ask_new_file(): load: f=%s\n", f);
if(check_loaded(f, win_path)) {
char msg[PATH_MAX + 100];
my_snprintf(msg, S(msg), "alert_ {xschem load: %s already open: %s}", f, win_path);
if(has_x) tcleval(msg);
else dbg(0, "ask_new_file: %s already open: %s\n", f, win_path);
skip = 1;
}
if(!skip) {
dbg(1, "ask_new_file(): load file: %s\n", f);
clear_all_hilights();
xctx->currsch = 0;
unselect_all();
remove_symbols();
load_schematic(1, f,1); /* 20180925.1 */
tclvareval("update_recent_file {", f, "}", NULL);
my_strdup(1, &xctx->sch_path[xctx->currsch],".");
xctx->sch_path_hash[xctx->currsch] = 0;
xctx->sch_inst_number[xctx->currsch] = 1;
zoom_full(1, 0, 1, 0.97);
}
}
}
@ -965,16 +975,32 @@ int place_symbol(int pos, const char *symbol_name, double x, double y, short rot
void symbol_in_new_window(void)
{
char filename[PATH_MAX];
char win_path[WINDOW_PATH_SIZE];
rebuild_selected_array();
if(xctx->lastsel !=1 || xctx->sel_array[0].type!=ELEMENT)
{
new_xschem_process(xctx->sch[xctx->currsch],1);
my_strncpy(filename, xctx->sch[xctx->currsch], S(filename));
if(tclgetvar("tabbed_interface")[0] == '1' && !check_loaded(filename, win_path)) {
tcleval("create_new_tab");
tclvareval("xschem load ", filename, NULL);
} else {
new_xschem_process(filename, 1);
}
}
else
{
new_xschem_process(abs_sym_path(xctx->inst[xctx->sel_array[0].n].name, ""),1);
my_strncpy(filename, abs_sym_path(xctx->inst[xctx->sel_array[0].n].name, ""), S(filename));
if(tclgetvar("tabbed_interface")[0] == '1') {
if(!check_loaded(filename, win_path)) {
tcleval("create_new_tab");
tclvareval("xschem load ", filename, NULL);
}
} else {
new_xschem_process(filename, 1);
}
}
}
@ -982,6 +1008,7 @@ void schematic_in_new_window(void)
{
char *sch = NULL;
char filename[PATH_MAX];
char win_path[WINDOW_PATH_SIZE];
rebuild_selected_array();
if(xctx->lastsel !=1 || xctx->sel_array[0].type!=ELEMENT)
{
@ -1011,7 +1038,14 @@ void schematic_in_new_window(void)
my_strncpy(filename, add_ext(abs_sym_path(xctx->inst[xctx->sel_array[0].n].name, ""), ".sch"), S(filename));
}
new_xschem_process(filename, 0);
if(tclgetvar("tabbed_interface")[0] == '1') {
if(!check_loaded(filename, win_path)) {
tcleval("create_new_tab");
tclvareval("xschem load ", filename, NULL);
}
} else {
new_xschem_process(filename, 0);
}
}
}

View File

@ -1455,12 +1455,18 @@ int callback(const char *winpath, int event, int mx, int my, KeySym key,
}
if(key=='e' && state == Mod1Mask) /* edit schematic in new window */
{
int save = xctx->semaphore;
xctx->semaphore--; /* so semaphore for current context wll be saved correctly */
schematic_in_new_window();
xctx->semaphore = save;
break;
}
if(key=='i' && state == Mod1Mask) /* edit symbol in new window */
{
int save = xctx->semaphore;
xctx->semaphore--; /* so semaphore for current context wll be saved correctly */
symbol_in_new_window();
xctx->semaphore = save;
break;
}
if( (key=='e' && state == ControlMask) || (key==XK_BackSpace)) /* back */

View File

@ -162,7 +162,6 @@ int help=0; /* help option set to global scope, printing help is deferred */
/* when configuration xschemrc has been read 20140406 */
FILE *errfp = NULL;
int no_readline=0;
char *filename=NULL; /* filename given on cmdline */
char home_dir[PATH_MAX]; /* home dir obtained via getpwuid */
char user_conf_dir[PATH_MAX];
char pwd_dir[PATH_MAX]; /* obtained via getcwd() */
@ -200,6 +199,7 @@ int cli_opt_netlist_type = 0;
int cli_opt_flat_netlist = 0;
char cli_opt_plotfile[PATH_MAX] = "";
char cli_opt_netlist_dir[PATH_MAX] = "";
char cli_opt_filename[PATH_MAX] = ""; /* filename given on cmdline */
/* --------------------------------------------------- */

View File

@ -230,9 +230,9 @@ int process_options(int argc, char *argv[])
}
if (arg_cnt>=2) {
dbg(1, "process_option(): file name given: %s\n",argv[1]);
my_strdup(291, &filename, argv[1]);
my_strncpy(cli_opt_filename, argv[1], S(cli_opt_filename));
#ifndef __unix__
change_to_unix_fn(filename);
change_to_unix_fn(cli_opt_filename);
#endif
}
return arg_cnt;

View File

@ -1060,7 +1060,6 @@ void load_schematic(int load_symbols, const char *filename, int reset_undo) /* 2
char msg[PATH_MAX+100];
struct stat buf;
int i;
xctx->prep_hi_structs=0;
xctx->prep_net_structs=0;
xctx->prep_hash_inst=0;

View File

@ -165,7 +165,6 @@ void xschem_cmd_help(int argc, const char **argv)
"load\n",
"load_new_window\n",
"load_symbol\n",
"load_symbol\n",
"log\n",
"logic_set\n",
"make_sch\n",
@ -1548,17 +1547,31 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
cmd_found = 1;
if(argc==3) {
if(!has_x || !xctx->modified || save(1) != -1 ) { /* save(1)==-1 --> user cancel */
char f[PATH_MAX];
char win_path[WINDOW_PATH_SIZE];
int skip = 0;
dbg(1, "scheduler(): load: filename=%s\n", argv[2]);
clear_all_hilights();
xctx->currsch = 0;
unselect_all();
remove_symbols();
load_schematic(1, abs_sym_path(argv[2], ""), 1);
tclvareval("update_recent_file {", abs_sym_path(argv[2], ""), "}", NULL);
my_strdup(375, &xctx->sch_path[xctx->currsch],".");
xctx->sch_path_hash[xctx->currsch] = 0;
xctx->sch_inst_number[xctx->currsch] = 1;
zoom_full(1, 0, 1, 0.97);
my_strncpy(f, abs_sym_path(argv[2], ""), S(f));
if(f[0] && check_loaded(f, win_path)) {
char msg[PATH_MAX + 100];
my_snprintf(msg, S(msg), "alert_ {xschem load: %s already open: %s}", f, win_path);
if(has_x) tcleval(msg);
else dbg(0, "xschem load: %s already open: %s\n", f, win_path);
skip = 1;
}
if(!skip) {
clear_all_hilights();
xctx->currsch = 0;
unselect_all();
remove_symbols();
load_schematic(1, f, 1);
tclvareval("update_recent_file {", f, "}", NULL);
my_strdup(375, &xctx->sch_path[xctx->currsch],".");
xctx->sch_path_hash[xctx->currsch] = 0;
xctx->sch_inst_number[xctx->currsch] = 1;
zoom_full(1, 0, 1, 0.97);
}
}
}
else if(argc==2) {
@ -1582,32 +1595,18 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
}
}
else if(!strcmp(argv[1], "load_symbol"))
{
int save, missing = 0;
cmd_found = 1;
if(argc > 2) {
save = xctx->symbols;
match_symbol(argv[2]);
if( xctx->symbols != save && !strcmp( xctx->sym[xctx->symbols - 1].type, "missing") ) {
missing = 1;
remove_symbol( xctx->symbols - 1);
}
}
Tcl_SetResult(interp, missing ? "0" : "1", TCL_STATIC);
}
else if(!strcmp(argv[1],"load_symbol") )
{
cmd_found = 1;
if(argc==3) {
char f[PATH_MAX];
dbg(1, "scheduler(): load: filename=%s\n", argv[2]);
my_strncpy(f, abs_sym_path(argv[2], ""), S(f));
clear_all_hilights();
xctx->currsch = 0;
unselect_all();
remove_symbols();
/* load_symbol(argv[2]); */
load_schematic(0, abs_sym_path(argv[2], ""), 1);
load_schematic(0, f, 1);
my_strdup(374, &xctx->sch_path[xctx->currsch],".");
xctx->sch_path_hash[xctx->currsch] = 0;
xctx->sch_inst_number[xctx->currsch] = 1;
@ -1823,8 +1822,9 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
xctx->last_command = 0;
rebuild_selected_array();
if(xctx->lastsel && xctx->sel_array[0].type==ELEMENT) {
tclvareval("set INITIALINSTDIR [file dirname {",
abs_sym_path(xctx->inst[xctx->sel_array[0].n].name, ""), "}]", NULL);
char f[PATH_MAX];
my_strncpy(f, abs_sym_path(xctx->inst[xctx->sel_array[0].n].name, ""), S(f));
tclvareval("set INITIALINSTDIR [file dirname {", f, "}]", NULL);
}
ret = place_symbol(-1,NULL,xctx->mousex_snap, xctx->mousey_snap, 0, 0, NULL, 4, 1, 1/*to_push_undo*/);
}

View File

@ -24,8 +24,6 @@
#ifdef __unix__
#include <pwd.h> /* getpwuid */
#endif
/* max number of windows (including main) a single xschem process can handle */
#define MAX_NEW_WINDOWS 20
static int init_done=0; /* 20150409 to avoid double call by Xwindows close and TclExitHandler */
static XSetWindowAttributes winattr;
@ -39,6 +37,11 @@ typedef int myproc(
int argc,
const char *argv[]);
/* variables for handling multiple windows/tabs */
static Xschem_ctx *save_xctx[MAX_NEW_WINDOWS]; /* save pointer to current schematic context structure */
static char window_path[MAX_NEW_WINDOWS][WINDOW_PATH_SIZE];
static int window_count = 0;
/* ----------------------------------------------------------------------- */
/* EWMH message handling routines 20071027... borrowed from wmctrl code */
/* ----------------------------------------------------------------------- */
@ -373,7 +376,7 @@ static void free_xschem_data()
my_free(1123, &xctx->enable_layer);
my_free(1121, &xctx->active_layer);
my_free(1295, &xctx->top_path);
my_free(1295, &xctx->current_win_path);
my_free(1463, &xctx->current_win_path);
my_free(1120, &xctx->fill_type);
if(xctx->inst_redraw_table) my_free(604, &xctx->inst_redraw_table);
my_free(269, &xctx);
@ -412,12 +415,20 @@ static void alloc_xschem_data(const char *top_path, const char *win_path)
xctx->tail_undo_ptr = 0;
xctx->undo_dirname = NULL;
if(!strcmp(tclgetvar("undo_type"), "disk")) xctx->undo_type = 0;
else xctx->undo_type = 1; /* "memory" */
xctx->push_undo = &push_undo;
xctx->pop_undo = &pop_undo;
xctx->delete_undo = &delete_undo;
xctx->clear_undo = &clear_undo;
if(!strcmp(tclgetvar("undo_type"), "disk")) {
xctx->undo_type = 0;
xctx->push_undo = push_undo;
xctx->pop_undo = pop_undo;
xctx->delete_undo = delete_undo;
xctx->clear_undo = clear_undo;
} else {
xctx->undo_type = 1; /* "memory" */
xctx->push_undo = mem_push_undo;
xctx->pop_undo = mem_pop_undo;
xctx->delete_undo = mem_delete_undo;
xctx->clear_undo = mem_clear_undo;
}
xctx->undo_initialized = 0;
xctx->zoom=CADINITIALZOOM;
xctx->mooz=1/CADINITIALZOOM;
@ -678,7 +689,7 @@ void xwin_exit(void)
dbg(1, "xwin_exit(): removing font\n");
for(i=0;i<127;i++) my_free(1140, &character[i]);
dbg(1, "xwin_exit(): closed display\n");
my_free(1141, &filename);
my_strncpy(cli_opt_filename, "", S(cli_opt_filename));
my_free(1143, &xschem_executable);
record_global_node(2, NULL, NULL); /* delete global node array */
dbg(1, "xwin_exit(): deleted undo buffer\n");
@ -897,7 +908,7 @@ int source_tcl_file(char *s)
return TCL_OK;
}
void preview_window(const char *what, const char *win_path, const char *filename)
void preview_window(const char *what, const char *win_path, const char *fname)
{
static char *current_file = NULL;
static Xschem_ctx *save_xctx = NULL; /* save pointer to current schematic context structure */
@ -916,11 +927,11 @@ void preview_window(const char *what, const char *win_path, const char *filename
else if(!strcmp(what, "draw")) {
dbg(1, "preview_window() draw\n");
xctx = preview_xctx;
if(!current_file || strcmp(filename, current_file) ) {
if(!current_file || strcmp(fname, current_file) ) {
if(current_file) {
delete_schematic_data();
}
my_strdup(117, &current_file, filename);
my_strdup(117, &current_file, fname);
xctx = NULL; /* reset for preview */
alloc_xschem_data(".dialog", ".dialog.drw"); /* alloc data into xctx */
init_pixdata(); /* populate xctx->fill_type array that is used in create_gc() to set fill styles */
@ -931,7 +942,7 @@ void preview_window(const char *what, const char *win_path, const char *filename
build_colors(0.0, 0.0);
resetwin(1, 0, 1, 0, 0); /* create preview pixmap. resetwin(create_pixmap, clear_pixmap, force) */
dbg(1, "preview_window() draw, load schematic\n");
load_schematic(1,filename, 0);
load_schematic(1,fname, 0);
}
zoom_full(1, 0, 1, 0.97); /* draw */
xctx = save_xctx;
@ -952,6 +963,419 @@ void preview_window(const char *what, const char *win_path, const char *filename
}
}
/* check if filename is already loaded into a tab or window */
/* caller should supply a win_path string for storing matching window path */
int check_loaded(const char *f, char *win_path)
{
int i;
Xschem_ctx *ctx;
int found = 0;
for(i = 0; i < MAX_NEW_WINDOWS; i++) {
ctx = save_xctx[i];
if(ctx) {
if(!strcmp(ctx->sch[ctx->currsch], f)) {
found = 1;
my_strncpy(win_path, window_path[i], S(window_path[i]));
break;
}
}
}
return found;
}
static void switch_window(int *window_count, const char *win_path)
{
int i, n;
Tk_Window tkwin;
if(*window_count) {
dbg(1, "new_schematic() switch: %s\n", win_path);
tkwin = Tk_NameToWindow(interp, win_path, mainwindow); /* NULL if win_path not existing */
if(!tkwin) dbg(0, "new_schematic(\"switch\",...): Warning: %s has been destroyed\n", win_path);
n = -1;
if(tkwin) for(i = 0; i < MAX_NEW_WINDOWS; i++) {
if(!strcmp(win_path, window_path[i])) {
n = i;
break;
}
}
if(n == -1) {
dbg(0, "new_schematic(\"switch\"...): no window to switch to found: %s\n", win_path);
return;
}
/* if window was closed then tkwin == 0 --> do nothing */
if(tkwin && n >= 0 && n < MAX_NEW_WINDOWS) {
xctx = save_xctx[n];
set_modify(-1); /* sets window title */
}
}
}
static void switch_tab(int *window_count, const char *win_path)
{
int i, n;
if(*window_count) {
dbg(1, "new_schematic() switch_tab: %s\n", win_path);
n = -1;
for(i = 0; i < MAX_NEW_WINDOWS; i++) {
if(!strcmp(win_path, window_path[i])) {
n = i;
break;
}
}
if(n == -1) {
dbg(0, "new_schematic(\"switch_tab\"...): no tab to switch to found: %s\n", win_path);
return;
}
/* if window was closed then tkwin == 0 --> do nothing */
if(n >= 0 && n < MAX_NEW_WINDOWS) {
tclvareval("save_ctx ", xctx->current_win_path, NULL);
xctx = save_xctx[n];
tclvareval("restore_ctx ", win_path, NULL);
tclvareval("housekeeping_ctx", NULL);
tclvareval("reconfigure_layers_button {}", NULL);
xctx->window = save_xctx[0]->window;
resetwin(1, 1, 1, 0, 0);
set_modify(-1); /* sets window title */
draw();
}
}
}
static void create_new_window(int *window_count, const char *fname)
{
Window win_id;
char toppath[WINDOW_PATH_SIZE];
int i, n;
dbg(1, "new_schematic() create\n");
if(*window_count && fname && fname[0] && check_loaded(fname, toppath)) {
char msg[PATH_MAX+100];
my_snprintf(msg, S(msg), "alert_ {create_new_window: %s already open: %s}", fname, toppath);
if(has_x)
tcleval(msg);
else
dbg(0, "create_new_window: %s already open: %s\n", fname, toppath);
return;
}
if(*window_count == 0) {
for(i = 0; i < MAX_NEW_WINDOWS; i++) {
save_xctx[i] = NULL;
my_strncpy(window_path[i], "", S(window_path[i]));
}
tclvareval("save_ctx ", xctx->current_win_path, NULL);
save_xctx[0] = xctx; /* save current schematic */
/* window_path[0] = Tk_NameToWindow(interp, ".drw", mainwindow); */
my_strncpy(window_path[0], xctx->current_win_path, S(window_path[0]));
}
if(*window_count + 1 >= MAX_NEW_WINDOWS) {
dbg(0, "new_schematic(\"create\"...): no more free slots\n");
return; /* no more free slots */
}
(*window_count)++;
tcleval(".menubar.view.menu entryconfigure 21 -state disabled");
n = -1;
for(i = 1; i < MAX_NEW_WINDOWS; i++) { /* search 1st free slot */
if(save_xctx[i] == NULL) {
n = i;
break;
}
}
if(n == -1) {
dbg(0, "new_schematic(\"create\"...): no more free slots\n");
return;
}
my_snprintf(window_path[n], S(window_path[n]), ".x%d.drw", n);
my_snprintf(toppath, S(toppath), ".x%d", n);
tclvareval("toplevel ", toppath, " -bg {} -width 400 -height 400", NULL);
tclvareval("build_widgets ", toppath, NULL);
tclvareval("pack_widgets ", toppath, " ; update", NULL);
Tk_MakeWindowExist(Tk_NameToWindow(interp, window_path[n], mainwindow));
win_id = Tk_WindowId(Tk_NameToWindow(interp, window_path[n], mainwindow));
Tk_ChangeWindowAttributes(Tk_NameToWindow(interp, window_path[n], mainwindow), CWBackingStore, &winattr);
xctx = NULL;
alloc_xschem_data(toppath, window_path[n]); /* alloc data into xctx */
xctx->netlist_type = CAD_SPICE_NETLIST; /* for new windows start with spice netlist mode */
tclsetvar("netlist_type","spice");
init_pixdata();/* populate xctx->fill_type array that is used in create_gc() to set fill styles */
save_xctx[n] = xctx;
dbg(1, "new_schematic() draw, load schematic\n");
xctx->window = win_id;
set_snap(0); /* set default value specified in xschemrc as 'snap' else CADSNAP */
set_grid(0); /* set default value specified in xschemrc as 'grid' else CADGRID */
create_gc();
enable_layers();
build_colors(0.0, 0.0);
resetwin(1, 0, 1, 0, 0); /* create preview pixmap. resetwin(create_pixmap, clear_pixmap, force, w, h) */
/* draw empty window so if following load fails due to missing file window appears correctly drawn */
zoom_full(1, 0, 1, 0.97);
load_schematic(1, fname, 1);
zoom_full(1, 0, 1, 0.97); /* draw */
tclvareval("set_bindings ", window_path[n], NULL);
tclvareval("save_ctx ", window_path[n], NULL);
windowid(toppath);
}
static void create_new_tab(int *window_count, const char *win_path, const char *fname)
{
int i, n;
char open_path[WINDOW_PATH_SIZE];
dbg(1, "new_schematic() new_tab, creating...\n");
if(*window_count && fname && fname[0] && check_loaded(fname, open_path)) {
char msg[PATH_MAX+100];
my_snprintf(msg, S(msg), "alert_ {create_new_tab: %s already open: %s}", fname, open_path);
if(has_x)
tcleval(msg);
else
dbg(0, "create_new_tab: %s already open: %s\n", fname, open_path);
switch_tab(window_count, open_path);
return;
}
if(*window_count == 0) {
for(i = 0; i < MAX_NEW_WINDOWS; i++) {
save_xctx[i] = NULL;
my_strncpy(window_path[i], "", S(window_path[i]));
}
tclvareval("save_ctx ", xctx->current_win_path, NULL);
save_xctx[0] = xctx; /* save current schematic */
my_strncpy(window_path[0], xctx->current_win_path, S(window_path[0]));
}
if(*window_count + 1 >= MAX_NEW_WINDOWS) {
dbg(0, "new_schematic(\"new_tab\"...): no more free slots\n");
return; /* no more free slots */
}
(*window_count)++;
tcleval(".menubar.view.menu entryconfigure 21 -state disabled");
n = -1;
for(i = 1; i < MAX_NEW_WINDOWS; i++) { /* search 1st free slot */
if(save_xctx[i] == NULL) {
n = i;
break;
}
}
if(n == -1) {
dbg(0, "new_schematic(\"newtab\"...): no more free slots\n");
return;
}
my_strncpy(window_path[n], win_path, S(window_path[n]));
xctx = NULL;
alloc_xschem_data("", win_path); /* alloc data into xctx */
xctx->netlist_type = CAD_SPICE_NETLIST; /* for new windows start with spice netlist mode */
tclsetvar("netlist_type","spice");
init_pixdata();/* populate xctx->fill_type array that is used in create_gc() to set fill styles */
save_xctx[n] = xctx;
dbg(1, "new_schematic() draw, load schematic\n");
xctx->window = save_xctx[0]->window;
set_snap(0); /* set default value specified in xschemrc as 'snap' else CADSNAP */
set_grid(0); /* set default value specified in xschemrc as 'grid' else CADGRID */
create_gc();
enable_layers();
build_colors(0.0, 0.0);
resetwin(1, 0, 1, 0, 0); /* create pixmap. resetwin(create_pixmap, clear_pixmap, force, w, h) */
/* draw empty window so if following load fails due to missing file window appears correctly drawn */
zoom_full(1, 0, 1, 0.97);
load_schematic(1,fname, 1);
zoom_full(1, 0, 1, 0.97); /* draw */
}
static void destroy_window(int *window_count, const char *win_path)
{
int i, n;
Xschem_ctx *savectx;
Tk_Window tkwin;
savectx = xctx;
if(*window_count) {
int close = 0;
dbg(1, "new_schematic() destroy {%s}\n", win_path);
if(xctx->modified && has_x) {
tcleval("tk_messageBox -type okcancel -parent [xschem get topwindow] -message \""
"[get_cell [xschem get schname] 0]"
": UNSAVED data: want to exit?\"");
if(strcmp(tclresult(),"ok")==0) close = 1;
}
else close = 1;
Tcl_ResetResult(interp);
if(close) {
tkwin = Tk_NameToWindow(interp, win_path, mainwindow); /* NULL if win_path not existing */
if(!tkwin) dbg(0, "new_schematic(\"destroy\", ...): Warning: %s has been destroyed\n", win_path);
n = -1;
if(tkwin) for(i = 1; i < MAX_NEW_WINDOWS; i++) {
if(!strcmp(win_path, window_path[i])) {
n = i;
break;
}
}
if(n == -1) {
dbg(0, "new_schematic(\"destroy\"...): no window to destroy found: %s\n", win_path);
return;
}
if(tkwin && n >= 1 && n < MAX_NEW_WINDOWS) {
/* delete Tcl context of deleted schematic window */
tclvareval("delete_ctx ", win_path, NULL);
xctx = save_xctx[n];
/* set saved ctx to main window if current is to be destroyed */
if(savectx == xctx) savectx = save_xctx[0];
tclvareval("winfo toplevel ", win_path, NULL);
delete_schematic_data();
save_xctx[n] = NULL;
Tk_DestroyWindow(Tk_NameToWindow(interp, window_path[n], mainwindow));
tclvareval("destroy ", tclresult(), NULL);
my_strncpy(window_path[n], "", S(window_path[n]));
(*window_count)--;
if(*window_count == 0) tcleval(".menubar.view.menu entryconfigure 21 -state normal");
}
}
/* following 3 lines must be done also if window not closed */
xctx = savectx; /* restore previous schematic or main window if previous destroyed */
tclvareval("restore_ctx ", xctx->current_win_path, " ; housekeeping_ctx", NULL);
set_modify(-1); /* sets window title */
} else {
dbg(0, "new_schematic() destroy_tab: there are no additional tabs\n");
}
}
static void destroy_tab(int *window_count, const char *win_path)
{
int i, n;
if(*window_count) {
int close = 0;
dbg(1, "new_schematic() destroy_tab\n");
if(strcmp(win_path, xctx->current_win_path)) {
dbg(0, "new_schematic(\"destroy_tab\", %s): must be in this tab to destroy\n", win_path);
return;
}
if(xctx->modified && has_x) {
tcleval("tk_messageBox -type okcancel -parent [xschem get topwindow] -message \""
"[get_cell [xschem get schname] 0]"
": UNSAVED data: want to exit?\"");
if(strcmp(tclresult(),"ok")==0) close = 1;
}
else close = 1;
Tcl_ResetResult(interp);
if(close) {
n = -1;
for(i = 1; i < MAX_NEW_WINDOWS; i++) {
if(!strcmp(win_path, window_path[i])) {
n = i;
break;
}
}
if(n == -1) {
dbg(0, "new_schematic(\"destroy_tab\"...): no tab to destroy found: %s\n", win_path);
return;
}
if(n >= 1 && n < MAX_NEW_WINDOWS) {
tclvareval("delete_ctx ", win_path, NULL);
tclvareval("delete_tab ", win_path, NULL);
xctx = save_xctx[n];
delete_schematic_data();
save_xctx[n] = NULL;
my_strncpy(window_path[n], "", S(window_path[n]));
/* delete Tcl context of deleted schematic window */
(*window_count)--;
if(*window_count == 0) tcleval(".menubar.view.menu entryconfigure 21 -state normal");
}
xctx = save_xctx[0]; /* restore main (.drw) schematic */
tclvareval("restore_ctx ", xctx->current_win_path, " ; housekeeping_ctx", NULL);
set_modify(-1); /* sets window title */
draw();
}
} else {
dbg(0, "new_schematic() destroy_tab: there are no additional tabs\n");
}
}
static void destroy_all_windows(int *window_count)
{
int i;
Xschem_ctx *savectx;
Tk_Window tkwin;
savectx = xctx;
if(*window_count) {
int close;
dbg(1, "new_schematic() destroy_all\n");
for(i = 1; i < MAX_NEW_WINDOWS; i++) {
if(window_path[i][0]) {
tkwin = Tk_NameToWindow(interp, window_path[i], mainwindow); /* NULL if win_path not existing */
if(!tkwin) dbg(0, "new_schematic(\"switch\",...): Warning: %s has been destroyed\n", window_path[i]);
else {
xctx = save_xctx[i];
close = 0;
/* reset old focused window so callback() will force repaint on expose events */
if(xctx->modified && has_x) {
tcleval("tk_messageBox -type okcancel -parent [xschem get topwindow] -message \""
"[get_cell [xschem get schname] 0]"
": UNSAVED data: want to exit?\"");
if(strcmp(tclresult(),"ok")==0) close = 1;
}
else close = 1;
Tcl_ResetResult(interp);
if(close) {
tclvareval("winfo toplevel ", window_path[i], NULL);
delete_schematic_data();
/* set saved ctx to main window if previous is about to be destroyed */
if(savectx == save_xctx[i]) savectx = save_xctx[0];
save_xctx[i] = NULL;
Tk_DestroyWindow(Tk_NameToWindow(interp, window_path[i], mainwindow));
tclvareval("destroy ", tclresult(), NULL);
/* delete Tcl context of deleted schematic window */
tclvareval("delete_ctx ", window_path[i], NULL);
my_strncpy(window_path[i], "", S(window_path[i]));
(*window_count)--;
if(*window_count == 0) tcleval(".menubar.view.menu entryconfigure 21 -state normal");
}
}
}
}
/* following 3 lines must be done also if windows not closed */
xctx = savectx; /* restore previous schematic or main if old is destroyed */
tclvareval("restore_ctx ", xctx->current_win_path, " ; housekeeping_ctx", NULL);
set_modify(-1); /* sets window title */
}
}
static void destroy_all_tabs(int *window_count)
{
int i;
Xschem_ctx *savectx;
savectx = xctx;
if(*window_count) {
int close;
dbg(1, "new_schematic() destroy_all_tabs\n");
for(i = 1; i < MAX_NEW_WINDOWS; i++) {
if(window_path[i][0]) {
xctx = save_xctx[i];
close = 0;
/* reset old focused window so callback() will force repaint on expose events */
if(xctx->modified && has_x) {
tcleval("tk_messageBox -type okcancel -parent [xschem get topwindow] -message \""
"[get_cell [xschem get schname] 0]"
": UNSAVED data: want to exit?\"");
if(strcmp(tclresult(),"ok")==0) close = 1;
}
else close = 1;
Tcl_ResetResult(interp);
if(close) {
/* delete Tcl context of deleted schematic window */
tclvareval("delete_ctx ", window_path[i], NULL);
tclvareval("delete_tab ", window_path[i], NULL);
delete_schematic_data();
/* set saved ctx to main window if previous is about to be destroyed */
if(savectx == save_xctx[i]) savectx = save_xctx[0];
save_xctx[i] = NULL;
my_strncpy(window_path[i], "", S(window_path[i]));
(*window_count)--;
if(*window_count == 0) tcleval(".menubar.view.menu entryconfigure 21 -state normal");
}
}
}
/* following 3 lines must be done also if windows not closed */
xctx = savectx; /* restore previous schematic or main if old is destroyed */
tclvareval("restore_ctx ", xctx->current_win_path, " ; housekeeping_ctx", NULL);
set_modify(-1); /* sets window title */
}
}
/* top_path is the path prefix of win_path:
*
@ -959,15 +1383,8 @@ void preview_window(const char *what, const char *win_path, const char *filename
* ".drw" ""
* ".x1.drw" ".x1"
*/
int new_schematic(const char *what, const char *win_path, const char *filename)
int new_schematic(const char *what, const char *win_path, const char *fname)
{
static int cnt = 0;
static Xschem_ctx *save_xctx[MAX_NEW_WINDOWS]; /* save pointer to current schematic context structure */
/* static Tk_Window new_window[MAX_NEW_WINDOWS]; */
static char new_window[MAX_NEW_WINDOWS][30];
int i, n;
Tk_Window tkwin;
char toppath[30];
int tabbed_interface;
const char *tmp;
@ -976,364 +1393,34 @@ int new_schematic(const char *what, const char *win_path, const char *filename)
if(tmp[0] == '1') tabbed_interface = 1;
}
dbg(1, "new_schematic(): current_win_path=%s, what=%s, win_path=%s\n", xctx->current_win_path, what, win_path);
/********************** NTABS **********************/
if(!strcmp(what, "ntabs")) {
return cnt;
return window_count;
} else if(!strcmp(what, "create")) {
/********************** CREATE **********************/
if(!tabbed_interface) {
Window win_id;
dbg(1, "new_schematic() create\n");
if(cnt == 0) {
for(i = 0; i < MAX_NEW_WINDOWS; i++) {
save_xctx[i] = NULL;
my_strncpy(new_window[i], "", S(new_window[i]));
}
tclvareval("save_ctx ", xctx->current_win_path, NULL);
save_xctx[0] = xctx; /* save current schematic */
/* new_window[0] = Tk_NameToWindow(interp, ".drw", mainwindow); */
my_strncpy(new_window[0], xctx->current_win_path, S(new_window[0]));
}
if(cnt + 1 >= MAX_NEW_WINDOWS) {
dbg(0, "new_schematic(\"create\"...): no more free slots\n");
return cnt; /* no more free slots */
}
cnt++;
tcleval(".menubar.view.menu entryconfigure 21 -state disabled");
n = -1;
for(i = 1; i < MAX_NEW_WINDOWS; i++) { /* search 1st free slot */
if(save_xctx[i] == NULL) {
n = i;
break;
}
}
if(n == -1) {
dbg(0, "new_schematic(\"create\"...): no more free slots\n");
return cnt;
}
my_snprintf(new_window[n], S(new_window[n]), ".x%d.drw", n);
my_snprintf(toppath, S(toppath), ".x%d", n);
tclvareval("toplevel ", toppath, " -bg {} -width 400 -height 400", NULL);
tclvareval("build_widgets ", toppath, NULL);
tclvareval("pack_widgets ", toppath, " ; update", NULL);
Tk_MakeWindowExist(Tk_NameToWindow(interp, new_window[n], mainwindow));
win_id = Tk_WindowId(Tk_NameToWindow(interp, new_window[n], mainwindow));
Tk_ChangeWindowAttributes(Tk_NameToWindow(interp, new_window[n], mainwindow), CWBackingStore, &winattr);
dbg(1, "new_schematic() draw\n");
xctx = NULL; /* reset for preview */
alloc_xschem_data(toppath, new_window[n]); /* alloc data into xctx */
xctx->netlist_type = CAD_SPICE_NETLIST; /* for new windows start with spice netlist mode */
tclsetvar("netlist_type","spice");
init_pixdata();/* populate xctx->fill_type array that is used in create_gc() to set fill styles */
save_xctx[n] = xctx;
dbg(1, "new_schematic() draw, load schematic\n");
xctx->window = win_id;
set_snap(0); /* set default value specified in xschemrc as 'snap' else CADSNAP */
set_grid(0); /* set default value specified in xschemrc as 'grid' else CADGRID */
create_gc();
enable_layers();
build_colors(0.0, 0.0);
resetwin(1, 0, 1, 0, 0); /* create preview pixmap. resetwin(create_pixmap, clear_pixmap, force, w, h) */
/* draw empty window so if following load fails due to missing file window appears correctly drawn */
zoom_full(1, 0, 1, 0.97);
load_schematic(1,filename, 1);
zoom_full(1, 0, 1, 0.97); /* draw */
tclvareval("set_bindings ", new_window[n], NULL);
tclvareval("save_ctx ", new_window[n], NULL);
windowid(toppath);
/********************** CREATE_TAB **********************/
create_new_window(&window_count, fname);
} else {
dbg(1, "new_schematic() new_tab, creating...\n");
if(cnt == 0) {
for(i = 0; i < MAX_NEW_WINDOWS; i++) {
save_xctx[i] = NULL;
my_strncpy(new_window[i], "", S(new_window[i]));
}
tclvareval("save_ctx ", xctx->current_win_path, NULL);
save_xctx[0] = xctx; /* save current schematic */
my_strncpy(new_window[0], xctx->current_win_path, S(new_window[0]));
}
if(cnt + 1 >= MAX_NEW_WINDOWS) {
dbg(0, "new_schematic(\"new_tab\"...): no more free slots\n");
return cnt; /* no more free slots */
}
cnt++;
tcleval(".menubar.view.menu entryconfigure 21 -state disabled");
n = -1;
for(i = 1; i < MAX_NEW_WINDOWS; i++) { /* search 1st free slot */
if(save_xctx[i] == NULL) {
n = i;
break;
}
}
if(n == -1) {
dbg(0, "new_schematic(\"newtab\"...): no more free slots\n");
return cnt;
}
my_strncpy(new_window[n], win_path, S(new_window[n]));
xctx = NULL; /* reset for preview */
alloc_xschem_data("", win_path); /* alloc data into xctx */
xctx->netlist_type = CAD_SPICE_NETLIST; /* for new windows start with spice netlist mode */
tclsetvar("netlist_type","spice");
init_pixdata();/* populate xctx->fill_type array that is used in create_gc() to set fill styles */
save_xctx[n] = xctx;
dbg(1, "new_schematic() draw, load schematic\n");
xctx->window = save_xctx[0]->window;
set_snap(0); /* set default value specified in xschemrc as 'snap' else CADSNAP */
set_grid(0); /* set default value specified in xschemrc as 'grid' else CADGRID */
create_gc();
enable_layers();
build_colors(0.0, 0.0);
resetwin(1, 0, 1, 0, 0); /* create pixmap. resetwin(create_pixmap, clear_pixmap, force, w, h) */
/* draw empty window so if following load fails due to missing file window appears correctly drawn */
zoom_full(1, 0, 1, 0.97);
load_schematic(1,filename, 1);
zoom_full(1, 0, 1, 0.97); /* draw */
create_new_tab(&window_count, win_path, fname);
}
} else if(!strcmp(what, "destroy")) {
/********************** DESTROY **********************/
if(!tabbed_interface) {
Xschem_ctx *savectx;
savectx = xctx;
if(cnt) {
int close = 0;
dbg(1, "new_schematic() destroy {%s}\n", win_path);
if(xctx->modified && has_x) {
tcleval("tk_messageBox -type okcancel -parent [xschem get topwindow] -message \""
"[get_cell [xschem get schname] 0]"
": UNSAVED data: want to exit?\"");
if(strcmp(tclresult(),"ok")==0) close = 1;
}
else close = 1;
Tcl_ResetResult(interp);
if(close) {
tkwin = Tk_NameToWindow(interp, win_path, mainwindow); /* NULL if win_path not existing */
if(!tkwin) dbg(0, "new_schematic(\"destroy\", ...): Warning: %s has been destroyed\n", win_path);
n = -1;
if(tkwin) for(i = 1; i < MAX_NEW_WINDOWS; i++) {
if(!strcmp(win_path, new_window[i])) {
n = i;
break;
}
}
if(n == -1) {
dbg(0, "new_schematic(\"destroy\"...): no window to destroy found: %s\n", win_path);
return cnt;
}
if(tkwin && n >= 1 && n < MAX_NEW_WINDOWS) {
/* delete Tcl context of deleted schematic window */
tclvareval("delete_ctx ", win_path, NULL);
xctx = save_xctx[n];
/* set saved ctx to main window if current is to be destroyed */
if(savectx == xctx) savectx = save_xctx[0];
tclvareval("winfo toplevel ", win_path, NULL);
delete_schematic_data();
save_xctx[n] = NULL;
Tk_DestroyWindow(Tk_NameToWindow(interp, new_window[n], mainwindow));
tclvareval("destroy ", tclresult(), NULL);
my_strncpy(new_window[n], "", S(new_window[n]));
cnt--;
if(cnt == 0) tcleval(".menubar.view.menu entryconfigure 21 -state normal");
}
}
/* following 3 lines must be done also if window not closed */
xctx = savectx; /* restore previous schematic or main window if previous destroyed */
tclvareval("restore_ctx ", xctx->current_win_path, " ; housekeeping_ctx", NULL);
set_modify(-1); /* sets window title */
}
/********************** DESTROY_TAB **********************/
destroy_window(&window_count, win_path);
} else {
if(cnt) {
int close = 0;
dbg(1, "new_schematic() destroy_tab\n");
if(strcmp(win_path, xctx->current_win_path)) {
dbg(0, "new_schematic(\"destroy_tab\", %s): must be in this tab to destroy\n", win_path);
return cnt;
}
if(xctx->modified && has_x) {
tcleval("tk_messageBox -type okcancel -parent [xschem get topwindow] -message \""
"[get_cell [xschem get schname] 0]"
": UNSAVED data: want to exit?\"");
if(strcmp(tclresult(),"ok")==0) close = 1;
}
else close = 1;
Tcl_ResetResult(interp);
if(close) {
n = -1;
for(i = 1; i < MAX_NEW_WINDOWS; i++) {
if(!strcmp(win_path, new_window[i])) {
n = i;
break;
}
}
if(n == -1) {
dbg(0, "new_schematic(\"destroy_tab\"...): no tab to destroy found: %s\n", win_path);
return cnt;
}
if(n >= 1 && n < MAX_NEW_WINDOWS) {
tclvareval("delete_ctx ", win_path, NULL);
tclvareval("delete_tab ", win_path, NULL);
xctx = save_xctx[n];
delete_schematic_data();
save_xctx[n] = NULL;
my_strncpy(new_window[n], "", S(new_window[n]));
/* delete Tcl context of deleted schematic window */
cnt--;
if(cnt == 0) tcleval(".menubar.view.menu entryconfigure 21 -state normal");
}
xctx = save_xctx[0]; /* restore main (.drw) schematic */
tclvareval("restore_ctx ", xctx->current_win_path, " ; housekeeping_ctx", NULL);
set_modify(-1); /* sets window title */
draw();
}
} else {
dbg(0, "new_schematic() destroy_tab: there are no additional tabs\n");
}
destroy_tab(&window_count, win_path);
}
} else if(!strcmp(what, "destroy_all")) {
/********************** DESTROY_ALL **********************/
if(!tabbed_interface) {
Xschem_ctx *savectx;
savectx = xctx;
if(cnt) {
int close;
dbg(1, "new_schematic() destroy_all\n");
for(i = 1; i < MAX_NEW_WINDOWS; i++) {
if(new_window[i][0]) {
tkwin = Tk_NameToWindow(interp, new_window[i], mainwindow); /* NULL if win_path not existing */
if(!tkwin) dbg(0, "new_schematic(\"switch\",...): Warning: %s has been destroyed\n", new_window[i]);
else {
xctx = save_xctx[i];
close = 0;
/* reset old focused window so callback() will force repaint on expose events */
if(xctx->modified && has_x) {
tcleval("tk_messageBox -type okcancel -parent [xschem get topwindow] -message \""
"[get_cell [xschem get schname] 0]"
": UNSAVED data: want to exit?\"");
if(strcmp(tclresult(),"ok")==0) close = 1;
}
else close = 1;
Tcl_ResetResult(interp);
if(close) {
tclvareval("winfo toplevel ", new_window[i], NULL);
delete_schematic_data();
/* set saved ctx to main window if previous is about to be destroyed */
if(savectx == save_xctx[i]) savectx = save_xctx[0];
save_xctx[i] = NULL;
Tk_DestroyWindow(Tk_NameToWindow(interp, new_window[i], mainwindow));
tclvareval("destroy ", tclresult(), NULL);
/* delete Tcl context of deleted schematic window */
tclvareval("delete_ctx ", new_window[i], NULL);
my_strncpy(new_window[i], "", S(new_window[i]));
cnt--;
if(cnt == 0) tcleval(".menubar.view.menu entryconfigure 21 -state normal");
}
}
}
}
}
/* following 3 lines must be done also if windows not closed */
xctx = savectx; /* restore previous schematic or main if old is destroyed */
tclvareval("restore_ctx ", xctx->current_win_path, " ; housekeeping_ctx", NULL);
set_modify(-1); /* sets window title */
/********************* DESTROY_ALL_TABS ******************/
destroy_all_windows(&window_count);
} else {
Xschem_ctx *savectx;
savectx = xctx;
if(cnt) {
int close;
dbg(1, "new_schematic() destroy_all_tabs\n");
for(i = 1; i < MAX_NEW_WINDOWS; i++) {
if(new_window[i][0]) {
xctx = save_xctx[i];
close = 0;
/* reset old focused window so callback() will force repaint on expose events */
if(xctx->modified && has_x) {
tcleval("tk_messageBox -type okcancel -parent [xschem get topwindow] -message \""
"[get_cell [xschem get schname] 0]"
": UNSAVED data: want to exit?\"");
if(strcmp(tclresult(),"ok")==0) close = 1;
}
else close = 1;
Tcl_ResetResult(interp);
if(close) {
/* delete Tcl context of deleted schematic window */
tclvareval("delete_ctx ", new_window[i], NULL);
tclvareval("delete_tab ", new_window[i], NULL);
delete_schematic_data();
/* set saved ctx to main window if previous is about to be destroyed */
if(savectx == save_xctx[i]) savectx = save_xctx[0];
save_xctx[i] = NULL;
my_strncpy(new_window[i], "", S(new_window[i]));
cnt--;
if(cnt == 0) tcleval(".menubar.view.menu entryconfigure 21 -state normal");
}
}
}
}
/* following 3 lines must be done also if windows not closed */
xctx = savectx; /* restore previous schematic or main if old is destroyed */
tclvareval("restore_ctx ", xctx->current_win_path, " ; housekeeping_ctx", NULL);
set_modify(-1); /* sets window title */
destroy_all_tabs(&window_count);
}
} else if(!strcmp(what, "switch")) {
/********************** SWITCH **********************/
if(!tabbed_interface) {
if(cnt) {
dbg(1, "new_schematic() switch: %s\n", win_path);
tkwin = Tk_NameToWindow(interp, win_path, mainwindow); /* NULL if win_path not existing */
if(!tkwin) dbg(0, "new_schematic(\"switch\",...): Warning: %s has been destroyed\n", win_path);
n = -1;
if(tkwin) for(i = 0; i < MAX_NEW_WINDOWS; i++) {
if(!strcmp(win_path, new_window[i])) {
n = i;
break;
}
}
if(n == -1) {
dbg(0, "new_schematic(\"switch\"...): no window to switch to found: %s\n", win_path);
return cnt;
}
/* if window was closed then tkwin == 0 --> do nothing */
if(tkwin && n >= 0 && n < MAX_NEW_WINDOWS) {
xctx = save_xctx[n];
set_modify(-1); /* sets window title */
}
}
/********************** SWITCH_TAB **********************/
switch_window(&window_count, win_path);
} else {
if(cnt) {
dbg(1, "new_schematic() switch_tab: %s\n", win_path);
n = -1;
for(i = 0; i < MAX_NEW_WINDOWS; i++) {
if(!strcmp(win_path, new_window[i])) {
n = i;
break;
}
}
if(n == -1) {
dbg(0, "new_schematic(\"switch_tab\"...): no tab to switch to found: %s\n", win_path);
return cnt;
}
/* if window was closed then tkwin == 0 --> do nothing */
if(n >= 0 && n < MAX_NEW_WINDOWS) {
tclvareval("save_ctx ", xctx->current_win_path, NULL);
xctx = save_xctx[n];
tclvareval("restore_ctx ", win_path, NULL);
tclvareval("housekeeping_ctx", NULL);
tclvareval("reconfigure_layers_button {}", NULL);
xctx->window = save_xctx[0]->window;
resetwin(1, 1, 1, 0, 0);
set_modify(-1); /* sets window title */
draw();
}
}
switch_tab(&window_count, win_path);
}
}
return cnt;
return window_count;
}
void change_linewidth(double w)
@ -2080,23 +2167,23 @@ int Tcl_AppInit(Tcl_Interp *inter)
my_snprintf(pwd_dir, S(pwd_dir), "%s", tclgetvar("env(PWD)"));
}
if(filename) {
if(cli_opt_filename[0]) {
char f[PATH_MAX];
#ifdef __unix__
if(filename[0] == '~' && filename[1] == '/') {
my_snprintf(f, S(f), "%s%s", home_dir, filename + 1);
} else if(filename[0] == '.' && filename[1] == '/') {
my_snprintf(f, S(f), "%s%s", pwd_dir, filename + 1);
} else if(filename[0] !='/') {
my_snprintf(f, S(f), "%s/%s", pwd_dir, filename);
if(cli_opt_filename[0] == '~' && cli_opt_filename[1] == '/') {
my_snprintf(f, S(f), "%s%s", home_dir, cli_opt_filename + 1);
} else if(cli_opt_filename[0] == '.' && cli_opt_filename[1] == '/') {
my_snprintf(f, S(f), "%s%s", pwd_dir, cli_opt_filename + 1);
} else if(cli_opt_filename[0] !='/') {
my_snprintf(f, S(f), "%s/%s", pwd_dir, cli_opt_filename);
} else {
my_snprintf(f, S(f), "%s", filename);
my_snprintf(f, S(f), "%s", cli_opt_filename);
}
#else
my_strncpy(f, abs_sym_path(filename, ""), S(f));
my_strncpy(f, abs_sym_path(cli_opt_filename, ""), S(f));
#endif
dbg(1, "Tcl_AppInit(): filename %s given, removing symbols\n", filename);
dbg(1, "Tcl_AppInit(): cli_opt_filename %s given, removing symbols\n", cli_opt_filename);
remove_symbols();
/* if do_netlist=1 call load_schematic with 'reset_undo=0' avoiding call
to tcl is_xschem_file that could change xctx->netlist_type to symbol */
@ -2104,16 +2191,16 @@ int Tcl_AppInit(Tcl_Interp *inter)
tclvareval("update_recent_file {", f, "}", NULL);
} else if(!tcl_script[0]) {
char * tmp;
char filename[PATH_MAX];
char fname[PATH_MAX];
tmp = (char *) tclgetvar("XSCHEM_START_WINDOW");
#ifndef __unix__
change_to_unix_fn(tmp);
#endif
dbg(1, "Tcl_AppInit(): tmp=%s\n", tmp? tmp: "NULL");
my_strncpy(filename, abs_sym_path(tmp, ""), S(filename));
my_strncpy(fname, abs_sym_path(tmp, ""), S(fname));
/* if do_netlist=1 call load_schematic with 'reset_undo=0' avoiding call
to tcl is_xschem_file that could change xctx->netlist_type to symbol */
load_schematic(1, filename, !do_netlist);
load_schematic(1, fname, !do_netlist);
}
tclsetintvar("tctx::max_new_windows", MAX_NEW_WINDOWS);
@ -2125,7 +2212,7 @@ int Tcl_AppInit(Tcl_Interp *inter)
if(xctx->flat_netlist)
fprintf(errfp, "xschem: flat netlist requested\n");
}
if(!filename) {
if(!cli_opt_filename[0]) {
fprintf(errfp, "xschem: cant do a netlist without a filename\n");
tcleval("exit");
}
@ -2143,7 +2230,7 @@ int Tcl_AppInit(Tcl_Interp *inter)
}
}
if(do_print) {
if(!filename) {
if(!cli_opt_filename[0]) {
dbg(0, "xschem: can't do a print without a filename\n");
tcleval("exit");
}
@ -2173,7 +2260,7 @@ int Tcl_AppInit(Tcl_Interp *inter)
}
if(do_simulation) {
if(!filename) {
if(!cli_opt_filename[0]) {
fprintf(errfp, "xschem: can't do a simulation without a filename\n");
tcleval("exit");
}
@ -2181,7 +2268,7 @@ int Tcl_AppInit(Tcl_Interp *inter)
}
if(do_waves) {
if(!filename) {
if(!cli_opt_filename[0]) {
fprintf(errfp, "xschem: can't show simulation waves without a filename\n");
tcleval("exit");
}

View File

@ -125,6 +125,10 @@ extern char win_temp_dir[PATH_MAX];
#define CADHEIGHT 700 /* initial window size */
#define CADWIDTH 1000
/* max number of windows (including main) a single xschem process can handle */
#define MAX_NEW_WINDOWS 20
#define WINDOW_PATH_SIZE 30
#define BACKLAYER 0
#define WIRELAYER 1
#define GRIDLAYER 2
@ -904,7 +908,7 @@ typedef struct {
int netlist_count; /* netlist counter incremented at any cell being netlisted */
int hide_symbols;
int netlist_type;
char * top_path;
char *top_path;
/* top_path is the path prefix of drawing canvas (current_win_path):
*
* current_win_path
@ -966,7 +970,6 @@ extern char *cad_icon[];
extern int do_print;
extern FILE *errfp;
extern int no_readline;
extern char *filename;
extern char home_dir[PATH_MAX]; /* home dir obtained via getpwuid */
extern char user_conf_dir[PATH_MAX]; /* usually ~/.xschem */
extern char pwd_dir[PATH_MAX]; /* obtained via getcwd() */
@ -996,6 +999,7 @@ extern int cli_opt_netlist_type;
extern int cli_opt_flat_netlist;
extern char cli_opt_plotfile[PATH_MAX];
extern char cli_opt_netlist_dir[PATH_MAX];
extern char cli_opt_filename[PATH_MAX];
/*********** Following data is relative to the current schematic ***********/
extern Xschem_ctx *xctx;
@ -1021,7 +1025,7 @@ extern void here(double i);
extern void print_version(void);
extern int set_netlist_dir(int force, char *dir);
extern void netlist_options(int i);
extern int check_lib(int what, const char * s);
extern int check_lib(int what, const char *s);
extern void select_all(void);
extern void change_linewidth(double w);
extern void schematic_in_new_window(void);
@ -1200,6 +1204,8 @@ extern void mem_pop_undo(int redo, int set_modify_status);
extern void mem_delete_undo(void);
extern void mem_clear_undo(void);
extern void load_schematic(int load_symbol, const char *abs_name, int reset_undo);
/* check if filename already in an open window/tab */
extern int check_loaded(const char *f, char *win_path);
extern void link_symbols_to_instances(int from);
extern void load_ascii_string(char **ptr, FILE *fd);
extern void read_xschem_file(FILE *fd);
@ -1369,8 +1375,8 @@ extern void list_hilights(void);
extern void change_layer();
extern void launcher();
extern void windowid(const char *winpath);
extern void preview_window(const char *what, const char *tk_win_path, const char *filename);
extern int new_schematic(const char *what, const char *win_path, const char *filename);
extern void 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);
extern int window_state (Display *disp, Window win, char *arg);
extern void toggle_fullscreen(const char *topwin);
extern void toggle_only_probes();

View File

@ -3718,7 +3718,7 @@ proc toolbar_hide { { topwin {} } } {
proc setup_tabbed_interface {} {
global tabbed_interface
set top_path [xschem get top_path]
set top_path {}
if { $tabbed_interface } {
frame $top_path.tabs
button $top_path.tabs.x0 -padx 2 -pady 0 -text Main -command {xschem new_schematic switch .drw}
@ -3734,11 +3734,11 @@ proc setup_tabbed_interface {} {
if {$tabbed_interface} {
$top_path.menubar.file.menu entryconfigure 6 -state disabled
$top_path.menubar.file.menu entryconfigure 7 -state disabled
set_tab_names
} else {
$top_path.menubar.file.menu entryconfigure 6 -state normal
$top_path.menubar.file.menu entryconfigure 7 -state normal
}
set_tab_names
}
proc delete_tab {path} {
@ -3824,7 +3824,7 @@ proc set_tab_names {} {
set top_path [xschem get top_path]
if {$tabname eq {}} { set tabname .x0}
# puts "set_tab_names : currwin=$currwin"
${top_path}.tabs$tabname configure -text [file rootname [file tail [xschem get schname]]] -bg Palegreen
${top_path}.tabs$tabname configure -text [file tail [xschem get schname]] -bg Palegreen
for { set i 0} { $i < $tctx::max_new_windows} { incr i} {
if { [winfo exists ${top_path}.tabs.x$i] && ($tabname ne ".x$i")} {
${top_path}.tabs.x$i configure -bg $tctx::tab_bg
@ -3833,13 +3833,27 @@ proc set_tab_names {} {
}
}
proc test2 {} {
global tabbed_interface
set tabbed_interface 0
xschem load [abs_sym_path testbench.sch]
xschem load_new_window [abs_sym_path poweramp.sch]
xschem load_new_window [abs_sym_path mos_power_ampli.sch]
xschem load_new_window [abs_sym_path rom8k.sch]
xschem load_new_window [abs_sym_path autozero_comp.sch]
xschem load_new_window [abs_sym_path LCC_instances.sch]
xschem load_new_window [abs_sym_path simulate_ff.sch]
xschem load_new_window [abs_sym_path led_driver.sch]
xschem load_new_window [abs_sym_path solar_panel.sch]
}
proc test1 {} {
global tabbed_interface
set tabbed_interface 1
setup_tabbed_interface
xschem load [abs_sym_path rom8k.sch]
xschem load [abs_sym_path testbench.sch]
create_new_tab
xschem load [abs_sym_path poweramp.sch]
create_new_tab
@ -4144,16 +4158,6 @@ proc build_widgets { {topwin {} } } {
set mbg {-bg gray50}
set bbg {-bg gray50 -highlightthickness 0}
}
if { $tabbed_interface } {
frame $topwin.tabs
button $topwin.tabs.x0 -padx 2 -pady 0 -text Main -command {xschem new_schematic switch .drw}
# button $topwin.tabs.x1 -padx 2 -pady 0 -text Tab1 -command {xschem new_schematic switch .x1.drw}
# button $topwin.tabs.x2 -padx 2 -pady 0 -text Tab2 -command {xschem new_schematic switch .x2.drw}
button $topwin.tabs.add -padx 0 -pady 0 -text { + } -command create_new_tab
# pack $topwin.tabs.x0 $topwin.tabs.x1 $topwin.tabs.x2 $topwin.tabs.add -side left
pack $topwin.tabs.x0 $topwin.tabs.add -side left
}
eval frame $topwin.menubar -relief raised -bd 2 $mbg
toolbar_toolbar $topwin
eval menubutton $topwin.menubar.file -text "File" -menu $topwin.menubar.file.menu \
@ -4622,6 +4626,7 @@ proc build_widgets { {topwin {} } } {
focus $topwin.drw
if { $topwin == {} } {set rootwin .} else { set rootwin $topwin}
setup_tabbed_interface
wm title $rootwin "xschem - "
wm iconname $rootwin "xschem - "
$rootwin configure -background {}