Use the new ctrl_alloc_with_free to clean up a long-standing FIXME in
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sun, 14 Jul 2013 10:46:34 +0000 (10:46 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sun, 14 Jul 2013 10:46:34 +0000 (10:46 +0000)
the session saving code, in which the contents of the edit box giving
the current saved session name was stored in a horrid place with a
fixed length. Now it's dangling off sessionsaver_data as it always
ought to have been, and it's dynamically reallocated to the
appropriate length, and there's a free function that cleans it up at
the end of the dialog's lifetime.

git-svn-id: svn://svn.tartarus.org/sgt/putty@9923 cda61777-01e9-0310-a592-d414129be87e

config.c

index b0b0092..1b9ac39 100644 (file)
--- a/config.c
+++ b/config.c
@@ -557,22 +557,27 @@ static void sshbug_handler(union control *ctrl, void *dlg,
     }
 }
 
-#define SAVEDSESSION_LEN 2048
-
 struct sessionsaver_data {
     union control *editbox, *listbox, *loadbutton, *savebutton, *delbutton;
     union control *okbutton, *cancelbutton;
     struct sesslist sesslist;
     int midsession;
+    char *savedsession;     /* the current contents of ssd->editbox */
 };
 
+static void sessionsaver_data_free(void *ssdv)
+{
+    struct sessionsaver_data *ssd = (struct sessionsaver_data *)ssdv;
+    sfree(ssd->savedsession);
+    sfree(ssd);
+}
+
 /* 
  * Helper function to load the session selected in the list box, if
  * any, as this is done in more than one place below. Returns 0 for
  * failure.
  */
 static int load_selected_session(struct sessionsaver_data *ssd,
-                                char *savedsession,
                                 void *dlg, Conf *conf, int *maybe_launch)
 {
     int i = dlg_listbox_index(ssd->listbox, dlg);
@@ -583,17 +588,10 @@ static int load_selected_session(struct sessionsaver_data *ssd,
     }
     isdef = !strcmp(ssd->sesslist.sessions[i], "Default Settings");
     load_settings(ssd->sesslist.sessions[i], conf);
-    if (!isdef) {
-       strncpy(savedsession, ssd->sesslist.sessions[i],
-               SAVEDSESSION_LEN);
-       savedsession[SAVEDSESSION_LEN-1] = '\0';
-       if (maybe_launch)
-           *maybe_launch = TRUE;
-    } else {
-       savedsession[0] = '\0';
-       if (maybe_launch)
-           *maybe_launch = FALSE;
-    }
+    sfree(ssd->savedsession);
+    ssd->savedsession = dupstr(isdef ? "" : ssd->sesslist.sessions[i]);
+    if (maybe_launch)
+        *maybe_launch = !isdef;
     dlg_refresh(NULL, dlg);
     /* Restore the selection, which might have been clobbered by
      * changing the value of the edit box. */
@@ -607,33 +605,10 @@ static void sessionsaver_handler(union control *ctrl, void *dlg,
     Conf *conf = (Conf *)data;
     struct sessionsaver_data *ssd =
        (struct sessionsaver_data *)ctrl->generic.context.p;
-    char *savedsession;
-
-    /*
-     * The first time we're called in a new dialog, we must
-     * 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 Conf).
-     *
-     * FIXME: this is disgusting, and we'd do much better to have
-     * the persistent storage be dynamically allocated and get rid
-     * of the arbitrary limit SAVEDSESSION_LEN. To do that would
-     * require a means of making sure the memory gets freed at the
-     * appropriate moment.
-     */
-    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';
-    } else {
-       savedsession = dlg_get_privdata(ssd->editbox, dlg);
-    }
 
     if (event == EVENT_REFRESH) {
        if (ctrl == ssd->editbox) {
-           dlg_editbox_set(ctrl, dlg, savedsession);
+           dlg_editbox_set(ctrl, dlg, ssd->savedsession);
        } else if (ctrl == ssd->listbox) {
            int i;
            dlg_update_start(ctrl, dlg);
@@ -645,14 +620,13 @@ static void sessionsaver_handler(union control *ctrl, void *dlg,
     } else if (event == EVENT_VALCHANGE) {
         int top, bottom, halfway, i;
        if (ctrl == ssd->editbox) {
-           char *tmp = dlg_editbox_get(ctrl, dlg);
-           strncpy(savedsession, tmp, SAVEDSESSION_LEN);
-           sfree(tmp);
+            sfree(ssd->savedsession);
+            ssd->savedsession = dlg_editbox_get(ctrl, dlg);
            top = ssd->sesslist.nsessions;
            bottom = -1;
            while (top-bottom > 1) {
                halfway = (top+bottom)/2;
-               i = strcmp(savedsession, ssd->sesslist.sessions[halfway]);
+               i = strcmp(ssd->savedsession, ssd->sesslist.sessions[halfway]);
                if (i <= 0 ) {
                    top = halfway;
                } else {
@@ -676,29 +650,25 @@ static void sessionsaver_handler(union control *ctrl, void *dlg,
             * double-click on the list box _and_ that session
             * contains a hostname.
             */
-           if (load_selected_session(ssd, savedsession, dlg, conf, &mbl) &&
+           if (load_selected_session(ssd, dlg, conf, &mbl) &&
                (mbl && ctrl == ssd->listbox && conf_launchable(conf))) {
                dlg_end(dlg, 1);       /* it's all over, and succeeded */
            }
        } else if (ctrl == ssd->savebutton) {
-           int isdef = !strcmp(savedsession, "Default Settings");
-           if (!savedsession[0]) {
+           int isdef = !strcmp(ssd->savedsession, "Default Settings");
+           if (!ssd->savedsession[0]) {
                int i = dlg_listbox_index(ssd->listbox, dlg);
                if (i < 0) {
                    dlg_beep(dlg);
                    return;
                }
                isdef = !strcmp(ssd->sesslist.sessions[i], "Default Settings");
-               if (!isdef) {
-                   strncpy(savedsession, ssd->sesslist.sessions[i],
-                           SAVEDSESSION_LEN);
-                   savedsession[SAVEDSESSION_LEN-1] = '\0';
-               } else {
-                   savedsession[0] = '\0';
-               }
+                sfree(ssd->savedsession);
+                ssd->savedsession = dupstr(isdef ? "" :
+                                           ssd->sesslist.sessions[i]);
            }
             {
-                char *errmsg = save_settings(savedsession, conf);
+                char *errmsg = save_settings(ssd->savedsession, conf);
                 if (errmsg) {
                     dlg_error_msg(dlg, errmsg);
                     sfree(errmsg);
@@ -736,8 +706,7 @@ static void sessionsaver_handler(union control *ctrl, void *dlg,
                !conf_launchable(conf)) {
                Conf *conf2 = conf_new();
                int mbl = FALSE;
-               if (!load_selected_session(ssd, savedsession, dlg,
-                                          conf2, &mbl)) {
+               if (!load_selected_session(ssd, dlg, conf2, &mbl)) {
                    dlg_beep(dlg);
                    conf_free(conf2);
                    return;
@@ -1256,8 +1225,10 @@ void setup_config_box(struct controlbox *b, int midsession,
     char *str;
 
     ssd = (struct sessionsaver_data *)
-       ctrl_alloc(b, sizeof(struct sessionsaver_data));
+       ctrl_alloc_with_free(b, sizeof(struct sessionsaver_data),
+                             sessionsaver_data_free);
     memset(ssd, 0, sizeof(*ssd));
+    ssd->savedsession = dupstr("");
     ssd->midsession = midsession;
 
     /*