Add the ability to allocate extra per-dialog-instance private data

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]
This commit is contained in:
Simon Tatham 2003-03-08 11:46:42 +00:00
Родитель e9cc328501
Коммит 43fe7d3c87
5 изменённых файлов: 160 добавлений и 32 удалений

Просмотреть файл

@ -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),

Просмотреть файл

@ -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.
*/

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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 */

Просмотреть файл

@ -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.
*/