From 56b9b9a752e89913fa19001ab85dffa7f95ef307 Mon Sep 17 00:00:00 2001 From: simon Date: Thu, 10 Apr 2003 18:00:50 +0000 Subject: [PATCH] Implemented Change Settings under Unix. We are gradually getting there. git-svn-id: svn://svn.tartarus.org/sgt/putty@3092 cda61777-01e9-0310-a592-d414129be87e --- config.c | 12 ++- unix/gtkdlg.c | 6 +- unix/pterm.c | 273 ++++++++++++++++++++++++++++++++++++++++++--------------- unix/unix.h | 1 + unix/uxputty.c | 28 +----- 5 files changed, 218 insertions(+), 102 deletions(-) diff --git a/config.c b/config.c index 184023d0..e8b7c579 100644 --- a/config.c +++ b/config.c @@ -256,8 +256,12 @@ static void sessionsaver_handler(union control *ctrl, void *dlg, * allocate space to store the current contents of the saved * session edit box (since it must persist even when we switch * panels, but is not part of the Config). + * + * Of course, this doesn't need to be done mid-session. */ - if (!dlg_get_privdata(ssd->editbox, dlg)) { + if (!ssd->editbox) { + savedsession = NULL; + } else if (!dlg_get_privdata(ssd->editbox, dlg)) { savedsession = (char *) dlg_alloc_privdata(ssd->editbox, dlg, SAVEDSESSION_LEN); savedsession[0] = '\0'; @@ -333,6 +337,11 @@ static void sessionsaver_handler(union control *ctrl, void *dlg, dlg_refresh(ssd->listbox, dlg); } } else if (ctrl == ssd->okbutton) { + if (!savedsession) { + /* In a mid-session Change Settings, Apply is always OK. */ + dlg_end(dlg, 1); + return; + } /* * Annoying special case. If the `Open' button is * pressed while no host name is currently set, _and_ @@ -730,6 +739,7 @@ void setup_config_box(struct controlbox *b, struct sesslist *sesslist, ssd = (struct sessionsaver_data *) ctrl_alloc(b, sizeof(struct sessionsaver_data)); + memset(ssd, 0, sizeof(*ssd)); ssd->sesslist = (midsession ? NULL : sesslist); /* diff --git a/unix/gtkdlg.c b/unix/gtkdlg.c index 6115e49e..42998667 100644 --- a/unix/gtkdlg.c +++ b/unix/gtkdlg.c @@ -1935,7 +1935,7 @@ int get_listitemheight(void) return req.height; } -int do_config_box(const char *title, Config *cfg) +int do_config_box(const char *title, Config *cfg, int midsession) { GtkWidget *window, *hbox, *vbox, *cols, *label, *tree, *treescroll, *panels, *panelvbox; @@ -1964,8 +1964,8 @@ int do_config_box(const char *title, Config *cfg) window = gtk_dialog_new(); ctrlbox = ctrl_new_box(); - setup_config_box(ctrlbox, &sl, FALSE, 0); - unix_setup_config_box(ctrlbox, FALSE, window); + setup_config_box(ctrlbox, &sl, midsession, 0); + unix_setup_config_box(ctrlbox, midsession, window); gtk_window_set_title(GTK_WINDOW(window), title); hbox = gtk_hbox_new(FALSE, 4); diff --git a/unix/pterm.c b/unix/pterm.c index 1ae3c6c9..9f570183 100644 --- a/unix/pterm.c +++ b/unix/pterm.c @@ -55,6 +55,7 @@ struct gui_data { char *pasteout_data, *pasteout_data_utf8; int pasteout_data_len, pasteout_data_utf8_len; int font_width, font_height; + int width, height; int ignore_sbar; int mouseptr_visible; guint term_paste_idle_id; @@ -373,13 +374,13 @@ gint configure_area(GtkWidget *widget, GdkEventConfigure *event, gpointer data) w = (event->width - 2*inst->cfg.window_border) / inst->font_width; h = (event->height - 2*inst->cfg.window_border) / inst->font_height; - if (w != inst->cfg.width || h != inst->cfg.height) { + if (w != inst->width || h != inst->height) { if (inst->pixmap) { gdk_pixmap_unref(inst->pixmap); inst->pixmap = NULL; } - inst->cfg.width = w; - inst->cfg.height = h; + inst->cfg.width = inst->width = w; + inst->cfg.height = inst->height = h; need_size = 1; } if (!inst->pixmap) { @@ -1160,8 +1161,11 @@ void request_resize(void *frontend, int w, int h) gtk_widget_set_size_request(inst->area, area_x, area_y); #else gtk_widget_set_usize(inst->area, area_x, area_y); + gtk_drawing_area_size(GTK_DRAWING_AREA(inst->area), area_x, area_y); #endif + gtk_container_dequeue_resize_handler(GTK_CONTAINER(inst->window)); + #if GTK_CHECK_VERSION(2,0,0) gtk_window_resize(GTK_WINDOW(inst->window), area_x + offset_x, area_y + offset_y); @@ -1179,6 +1183,7 @@ static void real_palette_set(struct gui_data *inst, int n, int r, int g, int b) inst->cols[n].green = g * 0x0101; inst->cols[n].blue = b * 0x0101; + gdk_colormap_free_colors(inst->colmap, inst->cols + n, 1); gdk_colormap_alloc_colors(inst->colmap, inst->cols + n, 1, FALSE, FALSE, success); if (!success[0]) @@ -2294,6 +2299,80 @@ void uxsel_input_remove(int id) { gdk_input_remove(id); } +void setup_fonts_ucs(struct gui_data *inst) +{ + int font_charset; + + if (inst->fonts[0]) + gdk_font_unref(inst->fonts[0]); + if (inst->fonts[1]) + gdk_font_unref(inst->fonts[1]); + if (inst->fonts[2]) + gdk_font_unref(inst->fonts[2]); + if (inst->fonts[3]) + gdk_font_unref(inst->fonts[3]); + + inst->fonts[0] = gdk_font_load(inst->cfg.font.name); + if (!inst->fonts[0]) { + fprintf(stderr, "%s: unable to load font \"%s\"\n", appname, + inst->cfg.font.name); + exit(1); + } + font_charset = set_font_info(inst, 0); + if (inst->cfg.boldfont.name[0]) { + inst->fonts[1] = gdk_font_load(inst->cfg.boldfont.name); + if (!inst->fonts[1]) { + fprintf(stderr, "%s: unable to load bold font \"%s\"\n", appname, + inst->cfg.boldfont.name); + exit(1); + } + set_font_info(inst, 1); + } else + inst->fonts[1] = NULL; + if (inst->cfg.widefont.name[0]) { + inst->fonts[2] = gdk_font_load(inst->cfg.widefont.name); + if (!inst->fonts[2]) { + fprintf(stderr, "%s: unable to load wide font \"%s\"\n", appname, + inst->cfg.widefont.name); + exit(1); + } + set_font_info(inst, 2); + } else + inst->fonts[2] = NULL; + if (inst->cfg.wideboldfont.name[0]) { + inst->fonts[3] = gdk_font_load(inst->cfg.wideboldfont.name); + if (!inst->fonts[3]) { + fprintf(stderr, "%s: unable to load wide/bold font \"%s\"\n", + appname, inst->cfg.wideboldfont.name); + exit(1); + } + set_font_info(inst, 3); + } else + inst->fonts[3] = NULL; + + inst->font_width = gdk_char_width(inst->fonts[0], ' '); + inst->font_height = inst->fonts[0]->ascent + inst->fonts[0]->descent; + + inst->direct_to_font = init_ucs(&inst->ucsdata, + inst->cfg.line_codepage, font_charset); +} + +void set_geom_hints(struct gui_data *inst) +{ + GdkGeometry geom; + geom.min_width = inst->font_width + 2*inst->cfg.window_border; + geom.min_height = inst->font_height + 2*inst->cfg.window_border; + geom.max_width = geom.max_height = -1; + geom.base_width = 2*inst->cfg.window_border; + geom.base_height = 2*inst->cfg.window_border; + geom.width_inc = inst->font_width; + geom.height_inc = inst->font_height; + geom.min_aspect = geom.max_aspect = 0; + gtk_window_set_geometry_hints(GTK_WINDOW(inst->window), inst->area, &geom, + GDK_HINT_MIN_SIZE | GDK_HINT_BASE_SIZE | + GDK_HINT_RESIZE_INC); +} + void clear_scrollback_menuitem(GtkMenuItem *item, gpointer data) { struct gui_data *inst = (struct gui_data *)data; @@ -2327,6 +2406,106 @@ void event_log_menuitem(GtkMenuItem *item, gpointer data) showeventlog(inst->eventlogstuff, inst->window); } +void change_settings_menuitem(GtkMenuItem *item, gpointer data) +{ + /* This maps colour indices in inst->cfg to those used in inst->cols. */ + static const int ww[] = { + 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, + 0, 1, 2, 3, 4, 5 + }; + struct gui_data *inst = (struct gui_data *)data; + char *title = dupcat(appname, " Reconfiguration", NULL); + Config cfg2, oldcfg; + int i, need_size; + + cfg2 = inst->cfg; /* structure copy */ + + if (do_config_box(title, &cfg2, 1)) { + + oldcfg = inst->cfg; /* structure copy */ + inst->cfg = cfg2; /* structure copy */ + + /* Pass new config data to the logging module */ + log_reconfig(inst->logctx, &cfg2); + /* + * Flush the line discipline's edit buffer in the case + * where local editing has just been disabled. + */ + ldisc_send(inst->ldisc, NULL, 0, 0); + /* Pass new config data to the terminal */ + term_reconfig(inst->term, &cfg2); + /* Pass new config data to the back end */ + inst->back->reconfig(inst->backhandle, &cfg2); + + /* + * Just setting inst->cfg is sufficient to cause colour + * setting changes to appear on the next ESC]R palette + * reset. But we should also check whether any colour + * settings have been changed, and revert the ones that + * have to the new default, on the assumption that the user + * is most likely to want an immediate update. + */ + for (i = 0; i < NCOLOURS; i++) { + if (oldcfg.colours[ww[i]][0] != cfg2.colours[ww[i]][0] || + oldcfg.colours[ww[i]][1] != cfg2.colours[ww[i]][1] || + oldcfg.colours[ww[i]][2] != cfg2.colours[ww[i]][2]) + real_palette_set(inst, i, cfg2.colours[ww[i]][0], + cfg2.colours[ww[i]][1], + cfg2.colours[ww[i]][2]); + } + + /* + * If the scrollbar needs to be shown, hidden, or moved + * from one end to the other of the window, do so now. + */ + if (oldcfg.scrollbar != cfg2.scrollbar) { + if (cfg2.scrollbar) + gtk_widget_show(inst->sbar); + else + gtk_widget_hide(inst->sbar); + } + if (oldcfg.scrollbar_on_left != cfg2.scrollbar_on_left) { + gtk_box_reorder_child(inst->hbox, inst->sbar, + cfg2.scrollbar_on_left ? 0 : 1); + } + + /* + * Change the window title, if required. + */ + if (strcmp(oldcfg.wintitle, cfg2.wintitle)) + set_title(inst, cfg2.wintitle); + + /* + * Redo the whole tangled fonts and Unicode mess if + * necessary. + */ + if (strcmp(oldcfg.font.name, cfg2.font.name) || + strcmp(oldcfg.boldfont.name, cfg2.boldfont.name) || + strcmp(oldcfg.widefont.name, cfg2.widefont.name) || + strcmp(oldcfg.wideboldfont.name, cfg2.wideboldfont.name) || + strcmp(oldcfg.line_codepage, cfg2.line_codepage)) { + setup_fonts_ucs(inst); + need_size = 1; + } else + need_size = 0; + + /* + * Resize the window. + */ + if (oldcfg.width != cfg2.width || oldcfg.height != cfg2.height || + oldcfg.window_border != cfg2.window_border || need_size) { + set_geom_hints(inst); + request_resize(inst, cfg2.width, cfg2.height); + //term_size(inst->term, cfg2.height, cfg2.width, cfg2.savelines); + // where TF is our configure event going?! + } + + term_invalidate(inst->term); + } + sfree(title); +} + void update_specials_menu(void *frontend) { Terminal *term = (Terminal *)frontend; @@ -2365,7 +2544,6 @@ int pt_main(int argc, char **argv) extern Backend *select_backend(Config *cfg); extern int cfgbox(Config *cfg); struct gui_data *inst; - int font_charset; /* defer any child exit handling until we're ready to deal with * it */ @@ -2391,52 +2569,10 @@ int pt_main(int argc, char **argv) if (!*inst->cfg.host && !cfgbox(&inst->cfg)) exit(0); /* config box hit Cancel */ - inst->fonts[0] = gdk_font_load(inst->cfg.font.name); - if (!inst->fonts[0]) { - fprintf(stderr, "%s: unable to load font \"%s\"\n", appname, - inst->cfg.font.name); - exit(1); - } - font_charset = set_font_info(inst, 0); - if (inst->cfg.boldfont.name[0]) { - inst->fonts[1] = gdk_font_load(inst->cfg.boldfont.name); - if (!inst->fonts[1]) { - fprintf(stderr, "%s: unable to load bold font \"%s\"\n", appname, - inst->cfg.boldfont.name); - exit(1); - } - set_font_info(inst, 1); - } else - inst->fonts[1] = NULL; - if (inst->cfg.widefont.name[0]) { - inst->fonts[2] = gdk_font_load(inst->cfg.widefont.name); - if (!inst->fonts[2]) { - fprintf(stderr, "%s: unable to load wide font \"%s\"\n", appname, - inst->cfg.widefont.name); - exit(1); - } - set_font_info(inst, 2); - } else - inst->fonts[2] = NULL; - if (inst->cfg.wideboldfont.name[0]) { - inst->fonts[3] = gdk_font_load(inst->cfg.wideboldfont.name); - if (!inst->fonts[3]) { - fprintf(stderr, "%s: unable to load wide/bold font \"%s\"\n", - appname, inst->cfg.wideboldfont.name); - exit(1); - } - set_font_info(inst, 3); - } else - inst->fonts[3] = NULL; - - inst->font_width = gdk_char_width(inst->fonts[0], ' '); - inst->font_height = inst->fonts[0]->ascent + inst->fonts[0]->descent; - inst->compound_text_atom = gdk_atom_intern("COMPOUND_TEXT", FALSE); inst->utf8_string_atom = gdk_atom_intern("UTF8_STRING", FALSE); - inst->direct_to_font = init_ucs(&inst->ucsdata, - inst->cfg.line_codepage, font_charset); + setup_fonts_ucs(inst); inst->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); @@ -2445,43 +2581,36 @@ int pt_main(int argc, char **argv) */ palette_reset(inst); + inst->width = inst->cfg.width; + inst->height = inst->cfg.height; + inst->area = gtk_drawing_area_new(); gtk_drawing_area_size(GTK_DRAWING_AREA(inst->area), inst->font_width * inst->cfg.width + 2*inst->cfg.window_border, inst->font_height * inst->cfg.height + 2*inst->cfg.window_border); - if (inst->cfg.scrollbar) { - inst->sbar_adjust = GTK_ADJUSTMENT(gtk_adjustment_new(0,0,0,0,0,0)); - inst->sbar = gtk_vscrollbar_new(inst->sbar_adjust); - } + inst->sbar_adjust = GTK_ADJUSTMENT(gtk_adjustment_new(0,0,0,0,0,0)); + inst->sbar = gtk_vscrollbar_new(inst->sbar_adjust); inst->hbox = GTK_BOX(gtk_hbox_new(FALSE, 0)); - if (inst->cfg.scrollbar) { - if (inst->cfg.scrollbar_on_left) - gtk_box_pack_start(inst->hbox, inst->sbar, FALSE, FALSE, 0); - else - gtk_box_pack_end(inst->hbox, inst->sbar, FALSE, FALSE, 0); - } + /* + * We always create the scrollbar; it remains invisible if + * unwanted, so we can pop it up quickly if it suddenly becomes + * desirable. + */ + if (inst->cfg.scrollbar_on_left) + gtk_box_pack_start(inst->hbox, inst->sbar, FALSE, FALSE, 0); gtk_box_pack_start(inst->hbox, inst->area, TRUE, TRUE, 0); + if (!inst->cfg.scrollbar_on_left) + gtk_box_pack_start(inst->hbox, inst->sbar, FALSE, FALSE, 0); gtk_container_add(GTK_CONTAINER(inst->window), GTK_WIDGET(inst->hbox)); - { - GdkGeometry geom; - geom.min_width = inst->font_width + 2*inst->cfg.window_border; - geom.min_height = inst->font_height + 2*inst->cfg.window_border; - geom.max_width = geom.max_height = -1; - geom.base_width = 2*inst->cfg.window_border; - geom.base_height = 2*inst->cfg.window_border; - geom.width_inc = inst->font_width; - geom.height_inc = inst->font_height; - geom.min_aspect = geom.max_aspect = 0; - gtk_window_set_geometry_hints(GTK_WINDOW(inst->window), inst->area, &geom, - GDK_HINT_MIN_SIZE | GDK_HINT_BASE_SIZE | - GDK_HINT_RESIZE_INC); - } + set_geom_hints(inst); gtk_widget_show(inst->area); if (inst->cfg.scrollbar) gtk_widget_show(inst->sbar); + else + gtk_widget_hide(inst->sbar); gtk_widget_show(GTK_WIDGET(inst->hbox)); if (inst->gotpos) { @@ -2554,6 +2683,8 @@ int pt_main(int argc, char **argv) gtk_signal_connect(GTK_OBJECT(menuitem), "activate", \ GTK_SIGNAL_FUNC(func), inst); \ } while (0) + MKMENUITEM("Change Settings", change_settings_menuitem); + MKMENUITEM(NULL, NULL); if (use_event_log) MKMENUITEM("Event Log", event_log_menuitem); MKMENUITEM("Special Commands", NULL); diff --git a/unix/unix.h b/unix/unix.h index 3e126ea7..fca07999 100644 --- a/unix/unix.h +++ b/unix/unix.h @@ -59,6 +59,7 @@ long get_windowid(void *frontend); void *get_window(void *frontend); /* void * to avoid depending on gtk.h */ /* Things pterm.c needs from gtkdlg.c */ +int do_config_box(const char *title, Config *cfg, int midsession); void fatal_message_box(void *window, char *msg); void about_box(void *window); void *eventlogstuff_new(void); diff --git a/unix/uxputty.c b/unix/uxputty.c index 8f2fad1b..6507a2a9 100644 --- a/unix/uxputty.c +++ b/unix/uxputty.c @@ -45,31 +45,6 @@ * * - Saved Sessions submenu (not in pterm of course) * - * - Change Settings - * + we must also implement mid-session reconfig in pterm.c. - * + This will require some work. We have to throw the new - * config at the log module, the ldisc, the terminal, and - * the backend; that's the easy bit. But within pterm.c - * itself we must also: - * - redo the colour palette if necessary - * * might be nice to move this over into terminal.c. - * That way we could check which palette entries in - * cfg have actually been _changed_ during - * reconfiguration, and only update those ones in - * the currently visible palette. Also it'd save - * some of this hassle in the next port. - * - enable/disable/move the scroll bar if necessary - * - change the window title if necessary - * - reinitialise the fonts - * - resize the window if necessary (may be required - * either by terminal size change or font size change - * or both) - * - redraw everything, just to be safe. - * + In particular, among the above chaos, we must look into - * how the choice of font affects the choice of codepage - * since the Unix default is to derive the latter from the - * former. - * * - Copy All to Clipboard (for what that's worth) */ @@ -101,8 +76,7 @@ Backend *select_backend(Config *cfg) int cfgbox(Config *cfg) { - extern int do_config_box(const char *title, Config *cfg); - return do_config_box("PuTTY Configuration", cfg); + return do_config_box("PuTTY Configuration", cfg, 0); } static int got_host = 0; -- 2.11.0