]> asedeno.scripts.mit.edu Git - PuTTY.git/commitdiff
Add the ability to allocate extra per-dialog-instance private data
authorSimon Tatham <anakin@pobox.com>
Sat, 8 Mar 2003 11:46:42 +0000 (11:46 +0000)
committerSimon Tatham <anakin@pobox.com>
Sat, 8 Mar 2003 11:46:42 +0000 (11:46 +0000)
in the portable dialog interface. This has allowed me to remove
`ssd->savedsession' in config.c, which was (I believe) the only
out-of-place piece of per-instance data in the dialog template
stuff. Now we should actually be able to run more than one config
box in the same process at the same time (for platforms that'll find
that useful).

[originally from svn r2925]

config.c
dialog.h
winctrls.c
windlg.c
winstuff.h

index df8134bd8ea3441734f9f8cfa0de104fc537bd39..961dc7fc16a0a3ec8ceb44427b9344e1980ec6e4 100644 (file)
--- a/config.c
+++ b/config.c
@@ -198,10 +198,11 @@ 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;
-    char savedsession[2048];
     struct sesslist *sesslist;
 };
 
@@ -211,6 +212,7 @@ struct sessionsaver_data {
  * failure.
  */
 static int load_selected_session(struct sessionsaver_data *ssd,
+                                char *savedsession,
                                 void *dlg, Config *cfg)
 {
     int i = dlg_listbox_index(ssd->listbox, dlg);
@@ -222,11 +224,11 @@ static int load_selected_session(struct sessionsaver_data *ssd,
     isdef = !strcmp(ssd->sesslist->sessions[i], "Default Settings");
     load_settings(ssd->sesslist->sessions[i], !isdef, cfg);
     if (!isdef) {
-       strncpy(ssd->savedsession, ssd->sesslist->sessions[i],
-               sizeof(ssd->savedsession));
-       ssd->savedsession[sizeof(ssd->savedsession)-1] = '\0';
+       strncpy(savedsession, ssd->sesslist->sessions[i],
+               SAVEDSESSION_LEN);
+       savedsession[SAVEDSESSION_LEN-1] = '\0';
     } else {
-       ssd->savedsession[0] = '\0';
+       savedsession[0] = '\0';
     }
     dlg_refresh(NULL, dlg);
     /* Restore the selection, which might have been clobbered by
@@ -241,10 +243,25 @@ static void sessionsaver_handler(union control *ctrl, void *dlg,
     Config *cfg = (Config *)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 Config).
+     */
+    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, ssd->savedsession);
+           dlg_editbox_set(ctrl, dlg, savedsession);
        } else if (ctrl == ssd->listbox) {
            int i;
            dlg_update_start(ctrl, dlg);
@@ -255,8 +272,8 @@ static void sessionsaver_handler(union control *ctrl, void *dlg,
        }
     } else if (event == EVENT_VALCHANGE) {
        if (ctrl == ssd->editbox) {
-           dlg_editbox_get(ctrl, dlg, ssd->savedsession,
-                           sizeof(ssd->savedsession));
+           dlg_editbox_get(ctrl, dlg, savedsession,
+                           SAVEDSESSION_LEN);
        }
     } else if (event == EVENT_ACTION) {
        if (ctrl == ssd->listbox || ctrl == ssd->loadbutton) {
@@ -267,13 +284,13 @@ 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, dlg, cfg) &&
+           if (load_selected_session(ssd, savedsession, dlg, cfg) &&
                (ctrl == ssd->listbox && cfg->host[0])) {
                dlg_end(dlg, 1);       /* it's all over, and succeeded */
            }
        } else if (ctrl == ssd->savebutton) {
-           int isdef = !strcmp(ssd->savedsession, "Default Settings");
-           if (!ssd->savedsession[0]) {
+           int isdef = !strcmp(savedsession, "Default Settings");
+           if (!savedsession[0]) {
                int i = dlg_listbox_index(ssd->listbox, dlg);
                if (i < 0) {
                    dlg_beep(dlg);
@@ -281,14 +298,14 @@ static void sessionsaver_handler(union control *ctrl, void *dlg,
                }
                isdef = !strcmp(ssd->sesslist->sessions[i], "Default Settings");
                if (!isdef) {
-                   strncpy(ssd->savedsession, ssd->sesslist->sessions[i],
-                           sizeof(ssd->savedsession));
-                   ssd->savedsession[sizeof(ssd->savedsession)-1] = '\0';
+                   strncpy(savedsession, ssd->sesslist->sessions[i],
+                           SAVEDSESSION_LEN);
+                   savedsession[SAVEDSESSION_LEN-1] = '\0';
                } else {
-                   ssd->savedsession[0] = '\0';
+                   savedsession[0] = '\0';
                }
            }
-           save_settings(ssd->savedsession, !isdef, cfg);
+           save_settings(savedsession, !isdef, cfg);
            get_sesslist(ssd->sesslist, FALSE);
            get_sesslist(ssd->sesslist, TRUE);
            dlg_refresh(ssd->editbox, dlg);
@@ -313,7 +330,7 @@ static void sessionsaver_handler(union control *ctrl, void *dlg,
             */
            if (dlg_last_focused(dlg) == ssd->listbox && !*cfg->host) {
                Config cfg2;
-               if (!load_selected_session(ssd, dlg, &cfg2)) {
+               if (!load_selected_session(ssd, savedsession, dlg, &cfg2)) {
                    dlg_beep(dlg);
                    return;
                }
@@ -728,7 +745,6 @@ void setup_config_box(struct controlbox *b, struct sesslist *sesslist,
        s = ctrl_getset(b, "Session", "savedsessions",
                        "Load, save or delete a stored session");
        ctrl_columns(s, 2, 75, 25);
-       ssd->savedsession[0] = '\0';
        ssd->sesslist = sesslist;
        ssd->editbox = ctrl_editbox(s, "Saved Sessions", 'e', 100,
                                    HELPCTX(session_saved),
index 6b9f5e38bd5390719c821d502667757ce60f0c92..fc1dd4142c6c81ed54e16d6fe84e4df469b7654f 100644 (file)
--- a/dialog.h
+++ b/dialog.h
@@ -645,6 +645,21 @@ int dlg_coloursel_results(union control *ctrl, void *dlg,
  */
 void dlg_refresh(union control *ctrl, void *dlg);
 
+/*
+ * It's perfectly possible that individual controls might need to
+ * allocate or store per-dialog-instance data, so here's a
+ * mechanism.
+ * 
+ * `dlg_get_privdata' and `dlg_set_privdata' allow the user to get
+ * and set a void * pointer associated with the control in
+ * question. `dlg_alloc_privdata' will allocate memory, store a
+ * pointer to that memory in the private data field, and arrange
+ * for it to be automatically deallocated on dialog cleanup.
+ */
+void *dlg_get_privdata(union control *ctrl, void *dlg);
+void dlg_set_privdata(union control *ctrl, void *dlg, void *ptr);
+void *dlg_alloc_privdata(union control *ctrl, void *dlg, size_t size);
+
 /*
  * Standard helper functions for reading a controlbox structure.
  */
index dc931c88b27f607ad30bb62a5baa680b3c9f86b6..7e109b38851fa9b14a82ce0c9ed77a54d15f2f7d 100644 (file)
@@ -2424,3 +2424,99 @@ int dlg_coloursel_results(union control *ctrl, void *dlg,
     } else
        return 0;
 }
+
+struct perctrl_privdata {
+    union control *ctrl;
+    void *data;
+    int needs_free;
+};
+
+static int perctrl_privdata_cmp(void *av, void *bv)
+{
+    struct perctrl_privdata *a = (struct perctrl_privdata *)av;
+    struct perctrl_privdata *b = (struct perctrl_privdata *)bv;
+    if (a->ctrl < b->ctrl)
+       return -1;
+    else if (a->ctrl > b->ctrl)
+       return +1;
+    return 0;
+}
+
+void dp_init(struct dlgparam *dp)
+{
+    dp->nctrltrees = 0;
+    dp->data = NULL;
+    dp->ended = FALSE;
+    dp->focused = dp->lastfocused = NULL;
+    memset(dp->shortcuts, 0, sizeof(dp->shortcuts));
+    dp->hwnd = NULL;
+    dp->errtitle = NULL;
+    dp->privdata = newtree234(perctrl_privdata_cmp);
+}
+
+void dp_add_tree(struct dlgparam *dp, struct winctrls *wc)
+{
+    assert(dp->nctrltrees < lenof(dp->controltrees));
+    dp->controltrees[dp->nctrltrees++] = wc;
+}
+
+void dp_cleanup(struct dlgparam *dp)
+{
+    struct perctrl_privdata *p;
+
+    if (dp->privdata) {
+       while ( (p = index234(dp->privdata, 0)) != NULL ) {
+           del234(dp->privdata, p);
+           if (p->needs_free)
+               sfree(p->data);
+           sfree(p);
+       }
+       freetree234(dp->privdata);
+       dp->privdata = NULL;
+    }
+}
+
+void *dlg_get_privdata(union control *ctrl, void *dlg)
+{
+    struct dlgparam *dp = (struct dlgparam *)dlg;
+    struct perctrl_privdata tmp, *p;
+    tmp.ctrl = ctrl;
+    p = find234(dp->privdata, &tmp, NULL);
+    if (p)
+       return p->data;
+    else
+       return NULL;
+}
+
+void dlg_set_privdata(union control *ctrl, void *dlg, void *ptr)
+{
+    struct dlgparam *dp = (struct dlgparam *)dlg;
+    struct perctrl_privdata tmp, *p;
+    tmp.ctrl = ctrl;
+    p = find234(dp->privdata, &tmp, NULL);
+    if (!p) {
+       p = smalloc(sizeof(struct perctrl_privdata));
+       p->ctrl = ctrl;
+       p->needs_free = FALSE;
+       add234(dp->privdata, p);
+    }
+    p->data = ptr;
+}
+
+void *dlg_alloc_privdata(union control *ctrl, void *dlg, size_t size)
+{
+    struct dlgparam *dp = (struct dlgparam *)dlg;
+    struct perctrl_privdata tmp, *p;
+    tmp.ctrl = ctrl;
+    p = find234(dp->privdata, &tmp, NULL);
+    if (!p) {
+       p = smalloc(sizeof(struct perctrl_privdata));
+       p->ctrl = ctrl;
+       p->needs_free = FALSE;
+       add234(dp->privdata, p);
+    }
+    assert(!p->needs_free);
+    p->needs_free = TRUE;
+    p->data = smalloc(size);
+    return p->data;
+}
index ca1890c5162113532aeea2fa773a787cabb44883..ef2a2a4d9404ac3b5bf68a5cc84be4ba19f97b69 100644 (file)
--- a/windlg.c
+++ b/windlg.c
@@ -582,16 +582,13 @@ int do_config(void)
     ctrlbox = ctrl_new_box();
     setup_config_box(ctrlbox, &sesslist, FALSE, 0);
     win_setup_config_box(ctrlbox, &dp.hwnd, (help_path != NULL), FALSE);
+    dp_init(&dp);
     winctrl_init(&ctrls_base);
     winctrl_init(&ctrls_panel);
-    dp.controltrees[0] = &ctrls_base;
-    dp.controltrees[1] = &ctrls_panel;
-    dp.nctrltrees = 2;
+    dp_add_tree(&dp, &ctrls_base);
+    dp_add_tree(&dp, &ctrls_panel);
     dp.errtitle = "PuTTY Error";
     dp.data = &cfg;
-    dp.ended = FALSE;
-    dp.lastfocused = NULL;
-    memset(dp.shortcuts, 0, sizeof(dp.shortcuts));
     dp.shortcuts['g'] = TRUE;         /* the treeview: `Cate&gory' */
 
     get_sesslist(&sesslist, TRUE);
@@ -601,8 +598,9 @@ int do_config(void)
     get_sesslist(&sesslist, FALSE);
 
     ctrl_free_box(ctrlbox);
-    winctrl_cleanup(&ctrls_base);
     winctrl_cleanup(&ctrls_panel);
+    winctrl_cleanup(&ctrls_base);
+    dp_cleanup(&dp);
 
     return ret;
 }
@@ -617,16 +615,13 @@ int do_reconfig(HWND hwnd)
     ctrlbox = ctrl_new_box();
     setup_config_box(ctrlbox, NULL, TRUE, cfg.protocol);
     win_setup_config_box(ctrlbox, &dp.hwnd, (help_path != NULL), TRUE);
+    dp_init(&dp);
     winctrl_init(&ctrls_base);
     winctrl_init(&ctrls_panel);
-    dp.controltrees[0] = &ctrls_base;
-    dp.controltrees[1] = &ctrls_panel;
-    dp.nctrltrees = 2;
+    dp_add_tree(&dp, &ctrls_base);
+    dp_add_tree(&dp, &ctrls_panel);
     dp.errtitle = "PuTTY Error";
     dp.data = &cfg;
-    dp.ended = FALSE;
-    dp.lastfocused = NULL;
-    memset(dp.shortcuts, 0, sizeof(dp.shortcuts));
     dp.shortcuts['g'] = TRUE;         /* the treeview: `Cate&gory' */
 
     ret =
@@ -636,6 +631,7 @@ int do_reconfig(HWND hwnd)
     ctrl_free_box(ctrlbox);
     winctrl_cleanup(&ctrls_base);
     winctrl_cleanup(&ctrls_panel);
+    dp_cleanup(&dp);
 
     if (!ret)
        cfg = backup_cfg;              /* structure copy */
index 411fe171494a88d38fa0b70dcbe4768a8694b7b6..fed920bd8b8bf65f85a609ac9d64dfc7d9a04fec 100644 (file)
@@ -166,10 +166,11 @@ struct dlgparam {
     char *errtitle;                   /* title of error sub-messageboxes */
     void *data;                               /* data to pass in refresh events */
     union control *focused, *lastfocused; /* which ctrl has focus now/before */
+    char shortcuts[128];              /* track which shortcuts in use */
     int coloursel_wanted;             /* has an event handler asked for
                                        * a colour selector? */
-    char shortcuts[128];              /* track which shortcuts in use */
     struct { unsigned char r, g, b, ok; } coloursel_result;   /* 0-255 */
+    tree234 *privdata;                /* stores per-control private data */
     int ended, endresult;             /* has the dialog been ended? */
 };
 
@@ -283,6 +284,10 @@ int winctrl_handle_command(struct dlgparam *dp, UINT msg,
 void winctrl_rem_shortcuts(struct dlgparam *dp, struct winctrl *c);
 int winctrl_context_help(struct dlgparam *dp, HWND hwnd, int id);
 
+void dp_init(struct dlgparam *dp);
+void dp_add_tree(struct dlgparam *dp, struct winctrls *tree);
+void dp_cleanup(struct dlgparam *dp);
+
 /*
  * Exports from wincfg.c.
  */