}
}
+#define SAVEDSESSION_LEN 2048
+
struct sessionsaver_data {
union control *editbox, *listbox, *loadbutton, *savebutton, *delbutton;
union control *okbutton, *cancelbutton;
- char savedsession[2048];
struct sesslist *sesslist;
};
* failure.
*/
static int load_selected_session(struct sessionsaver_data *ssd,
+ char *savedsession,
void *dlg, Config *cfg)
{
int i = dlg_listbox_index(ssd->listbox, dlg);
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
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);
}
} 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) {
* 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);
}
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);
*/
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;
}
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),
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.
*/
} 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;
+}
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);
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;
}
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 =
ctrl_free_box(ctrlbox);
winctrl_cleanup(&ctrls_base);
winctrl_cleanup(&ctrls_panel);
+ dp_cleanup(&dp);
if (!ret)
cfg = backup_cfg; /* structure copy */
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? */
};
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.
*/