зеркало из https://github.com/github/putty.git
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:
Родитель
e9cc328501
Коммит
43fe7d3c87
52
config.c
52
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),
|
||||
|
|
15
dialog.h
15
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.
|
||||
*/
|
||||
|
|
96
winctrls.c
96
winctrls.c
|
@ -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;
|
||||
}
|
||||
|
|
22
windlg.c
22
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 */
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
Загрузка…
Ссылка в новой задаче