From 7aa6ecfbd69de1def2dea1e00347960b1b9d92d6 Mon Sep 17 00:00:00 2001 From: stefan schippers Date: Sun, 4 Jun 2023 15:37:35 +0200 Subject: [PATCH] make `xschem exit` (ctrl-w, close window) work in multi-window mode exactly as in tabbed interface, allowing to close the root window (will be swapped with subwindow and deleted) --- src/scheduler.c | 38 +++++++++++++-------- src/xinit.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++ src/xschem.h | 3 ++ src/xschem.tcl | 13 ++++---- 4 files changed, 123 insertions(+), 19 deletions(-) diff --git a/src/scheduler.c b/src/scheduler.c index 188f8748..5668bb6b 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -691,23 +691,35 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg if(!strcmp(xctx->current_win_path, ".drw")) { if(has_x) { int remaining; - if(!tclgetboolvar("tabbed_interface")) { /* non tabbed interface */ - if(closewindow) { - remaining = new_schematic("destroy_all", NULL, NULL); - if(!remaining) { - if(xctx->modified) { - tcleval("tk_messageBox -type okcancel -parent [xschem get topwindow] -message \"" + /* non tabbed interface */ + if(!tclgetboolvar("tabbed_interface")) { + int wc = get_window_count(); + dbg(1, "wc=%d\n", wc); + if(wc > 0 ) { + if(xctx->modified) { + tcleval("tk_messageBox -type okcancel -parent [xschem get topwindow] -message \"" "[get_cell [xschem get schname] 0]" ": UNSAVED data: want to exit?\""); - } - if(!xctx->modified || !strcmp(tclresult(), "ok")) { - tcleval("exit"); - } + } + if(!xctx->modified || !strcmp(tclresult(), "ok")) { + swap_windows(); + set_modify(0); + new_schematic("destroy", xctx->current_win_path, NULL); } } else { - clear_schematic(0, 0); + if(xctx->modified) { + tcleval("tk_messageBox -type okcancel -parent [xschem get topwindow] -message \"" + "[get_cell [xschem get schname] 0]" + ": UNSAVED data: want to exit?\""); + } + if(!xctx->modified || !strcmp(tclresult(), "ok")) { + if(closewindow) tcleval("exit"); + else clear_schematic(0, 0); + } } - } else { /* tabbed interface */ + } + /* tabbed interface */ + else { int wc = get_window_count(); dbg(1, "wc=%d\n", wc); if(wc > 0 ) { @@ -3743,7 +3755,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg * testmode */ else if(!strcmp(argv[1], "test")) { - swap_tabs(); + swap_windows(); Tcl_ResetResult(interp); } diff --git a/src/xinit.c b/src/xinit.c index 1f1ca80f..e5966ec2 100644 --- a/src/xinit.c +++ b/src/xinit.c @@ -1186,6 +1186,7 @@ void preview_window(const char *what, const char *win_path, const char *fname) void swap_tabs(void) { int wc = window_count; + if(!tclgetboolvar("tabbed_interface")) return; if(wc) { Xschem_ctx *ctx; char *tmp; @@ -1227,6 +1228,93 @@ void swap_tabs(void) } } +/* swap primary view (.drw) with first valid tab (x1.drw, x2.drw, ...) */ +void swap_windows(void) +{ + int wc = window_count; + if(tclgetboolvar("tabbed_interface")) return; + if(wc) { + Xschem_ctx *ctx; + char *tmp; + char wp_i[WINDOW_PATH_SIZE], wp_j[WINDOW_PATH_SIZE]; + Window window; + Pixmap save_pixmap; + GC gc, *gcptr; + int i = 0; + int j; + Tk_Window tkwin, mainwindow; + char geometry[80]; + + for(j = 1; j < MAX_NEW_WINDOWS; j++) { + if(save_xctx[j]) break; + } + if(j >= MAX_NEW_WINDOWS) { + dbg(0, "swap_windows(): no tab to swap to found\n"); + return; + } + if(!save_xctx[i]) { + dbg(0, "swap_windows(): no tab to swap from found\n"); + return; + } + dbg(1, "swap_windows(): i=%d, j=%d\n", i, j); + + my_snprintf(wp_i, S(wp_i), "%s", save_xctx[i]->current_win_path); + my_snprintf(wp_j, S(wp_j), "%s", save_xctx[j]->current_win_path); + + mainwindow = Tk_MainWindow(interp); + tkwin = Tk_Parent(Tk_NameToWindow(interp, wp_j, mainwindow)); + + dbg(1, "swap_windows(): %s: %dx%d+%d+%d\n", + wp_j, Tk_Width(tkwin), Tk_Height(tkwin), Tk_X(tkwin), Tk_Y(tkwin)); + my_snprintf(geometry, S(geometry), "%dx%d+%d+%d", + Tk_Width(tkwin), Tk_Height(tkwin), Tk_X(tkwin), Tk_Y(tkwin)); + + /* swap tcl contexts */ + tclvareval("save_ctx ", xctx->current_win_path, NULL); + tclvareval("restore_ctx ", wp_i, NULL); + tclvareval("save_ctx ", "_temp", NULL); + tclvareval("restore_ctx ", wp_j, NULL); + tclvareval("save_ctx ", wp_i, NULL); + tclvareval("restore_ctx ", "_temp", NULL); + tclvareval("save_ctx ", wp_j, NULL); + tclvareval("delete_ctx _temp", NULL); + + /* swap xschem xctx structs */ + ctx = save_xctx[i]; + save_xctx[i] = save_xctx[j]; + save_xctx[j] = ctx; + + /* swap window paths */ + SWAP(save_xctx[i]->top_path, save_xctx[j]->top_path, tmp); + SWAP(save_xctx[i]->current_win_path, save_xctx[j]->current_win_path, tmp); + + /* swap drawing stuff */ + SWAP(save_xctx[i]->save_pixmap, save_xctx[j]->save_pixmap, save_pixmap); + SWAP(save_xctx[i]->window, save_xctx[j]->window, window); + SWAP(save_xctx[i]->gctiled, save_xctx[j]->gctiled, gc); + SWAP(save_xctx[i]->gc, save_xctx[j]->gc, gcptr); + SWAP(save_xctx[i]->gcstipple, save_xctx[j]->gcstipple, gcptr); + + /* rebuld colors and pixmaps, redraw swapped schematics */ + tclvareval("restore_ctx ", wp_i, NULL); + new_schematic("switch_win", wp_i, ""); + tclvareval("housekeeping_ctx", NULL); + tclvareval("xschem build_colors", NULL); + resetwin(1, 1, 1, 0, 0); + draw(); + + tclvareval("restore_ctx ", wp_j, NULL); + new_schematic("switch_win", wp_j, ""); + tclvareval("housekeeping_ctx", NULL); + tclvareval("xschem build_colors", NULL); + resetwin(1, 1, 1, 0, 0); + draw(); + /* move primary window to location of deleted window */ + tclvareval("wm geometry . ", geometry, NULL); + } +} + + /* check if filename is already loaded into a tab or window */ /* caller should supply a win_path string for storing matching window path */ diff --git a/src/xschem.h b/src/xschem.h index 68d19ed2..31034775 100644 --- a/src/xschem.h +++ b/src/xschem.h @@ -385,6 +385,8 @@ do { \ } \ } while(0) +#define SWAP(a,b, tmp) do { tmp = a; a = b; b = tmp; } while(0) + #define INT_WIDTH(x) ( tclgetboolvar("change_lw") ? ( (int)(x) == 0 ? 1 : (int)(x) ) : (int)(x) ) #define INT_BUS_WIDTH(x) ( (int)( (BUS_WIDTH) * (x) ) == 0 ? 1 : (int)( (BUS_WIDTH) * (x) ) ) @@ -1333,6 +1335,7 @@ extern void mem_clear_undo(void); extern void load_schematic(int load_symbol, const char *fname, int reset_undo, int alert); /* check if filename already in an open window/tab */ extern void swap_tabs(void); +extern void swap_windows(void); extern int check_loaded(const char *f, char *win_path); extern char *get_window_path(int i); extern int get_window_count(void); diff --git a/src/xschem.tcl b/src/xschem.tcl index 31ed18ff..b9259b62 100644 --- a/src/xschem.tcl +++ b/src/xschem.tcl @@ -5708,10 +5708,11 @@ proc build_widgets { {topwin {} } } { global local_netlist_dir editor netlist_type netlist_dir spiceprefix initial_geometry set mbg {} set bbg {-highlightthickness 0} - if { $topwin ne {}} { - set mbg {-bg gray50} - set bbg {-bg gray50 -highlightthickness 0} - } + + # if { $topwin ne {}} { + # set mbg {-bg gray50} + # set bbg {-bg gray50 -highlightthickness 0} + # } eval frame $topwin.menubar -relief raised -bd 2 $mbg eval menubutton $topwin.menubar.file -text "File" -menu $topwin.menubar.file.menu \ -padx 3 -pady 0 $mbg @@ -5957,12 +5958,12 @@ proc build_widgets { {topwin {} } } { -command { xschem only_probes } $topwin.menubar.view.menu add command -label "Toggle colorscheme" -accelerator {Shift+O} -command { xschem toggle_colorscheme - xschem build_colors 1 + xschem build_colors xschem redraw } toolbar_add ViewToggleColors { xschem toggle_colorscheme - xschem build_colors 1 + xschem build_colors xschem redraw } "Toggle Color Scheme" $topwin $topwin.menubar.view.menu add command -label "Dim colors" -accelerator {} -command {