Implemented Change Settings under Unix. We are gradually getting there.
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Thu, 10 Apr 2003 18:00:50 +0000 (18:00 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Thu, 10 Apr 2003 18:00:50 +0000 (18:00 +0000)
git-svn-id: svn://svn.tartarus.org/sgt/putty@3092 cda61777-01e9-0310-a592-d414129be87e

config.c
unix/gtkdlg.c
unix/pterm.c
unix/unix.h
unix/uxputty.c

index 184023d..e8b7c57 100644 (file)
--- 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);
 
     /*
index 6115e49..4299866 100644 (file)
@@ -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);
index 1ae3c6c..9f57018 100644 (file)
@@ -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);
index 3e126ea..fca0799 100644 (file)
@@ -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);
index 8f2fad1..6507a2a 100644 (file)
  * 
  *     - 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;