X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/9733271975cb9be4a6d373517681760ce859b92c..7440fd4419acfc9c784f142fb9dee3e64c9a18c2:/winctrls.c diff --git a/winctrls.c b/winctrls.c index dc931c88..4a35cb6b 100644 --- a/winctrls.c +++ b/winctrls.c @@ -13,17 +13,14 @@ * button. */ -#include -#include #include #include -#include "winstuff.h" +#include "putty.h" #include "misc.h" #include "dialog.h" -#include "puttymem.h" -#include "putty.h" +#include #define GAPBETWEEN 3 #define GAPWITHIN 1 @@ -287,9 +284,10 @@ void radioline(struct ctlpos *cp, char *text, int id, int nacross, ...) if (!btext) break; bid = va_arg(ap, int); + nbuttons++; } va_end(ap); - buttons = smalloc(nbuttons * sizeof(struct radio)); + buttons = snewn(nbuttons, struct radio); va_start(ap, nacross); for (i = 0; i < nbuttons; i++) { buttons[i].text = va_arg(ap, char *); @@ -320,7 +318,7 @@ void bareradioline(struct ctlpos *cp, int nacross, ...) bid = va_arg(ap, int); } va_end(ap); - buttons = smalloc(nbuttons * sizeof(struct radio)); + buttons = snewn(nbuttons, struct radio); va_start(ap, nacross); for (i = 0; i < nbuttons; i++) { buttons[i].text = va_arg(ap, char *); @@ -351,7 +349,7 @@ void radiobig(struct ctlpos *cp, char *text, int id, ...) bid = va_arg(ap, int); } va_end(ap); - buttons = smalloc(nbuttons * sizeof(struct radio)); + buttons = snewn(nbuttons, struct radio); va_start(ap, id); for (i = 0; i < nbuttons; i++) { buttons[i].text = va_arg(ap, char *); @@ -395,10 +393,10 @@ char *staticwrap(struct ctlpos *cp, HWND hwnd, char *text, int *lines) RECT r; HFONT oldfont, newfont; - ret = smalloc(1+strlen(text)); + ret = snewn(1+strlen(text), char); p = text; q = ret; - pwidths = smalloc(sizeof(INT)*(1+strlen(text))); + pwidths = snewn(1+strlen(text), INT); /* * Work out the width the text will need to fit in, by doing @@ -973,7 +971,7 @@ static void pl_moveitem(HWND hwnd, int listid, int src, int dst) char *txt; /* Get the item's data. */ tlen = SendDlgItemMessage (hwnd, listid, LB_GETTEXTLEN, src, 0); - txt = smalloc(tlen+1); + txt = snewn(tlen+1, char); SendDlgItemMessage (hwnd, listid, LB_GETTEXT, src, (LPARAM) txt); val = SendDlgItemMessage (hwnd, listid, LB_GETITEMDATA, src, 0); /* Deselect old location. */ @@ -1176,7 +1174,7 @@ static char *shortcut_escape(char *text, char shortcut) if (!text) return NULL; /* sfree won't choke on this */ - ret = smalloc(2*strlen(text)+1); /* size potentially doubles! */ + ret = snewn(2*strlen(text)+1, char); /* size potentially doubles! */ shortcut = tolower((unsigned char)shortcut); p = text; @@ -1331,14 +1329,14 @@ void winctrl_layout(struct dlgparam *dp, struct winctrls *wc, char shortcuts[MAX_SHORTCUTS_PER_CTRL]; int nshortcuts; char *escaped; - int i, base_id, num_ids; + int i, actual_base_id, base_id, num_ids; void *data; base_id = *id; /* Start a containing box, if we have a boxname. */ if (s->boxname && *s->boxname) { - struct winctrl *c = smalloc(sizeof(struct winctrl)); + struct winctrl *c = snew(struct winctrl); c->ctrl = NULL; c->base_id = base_id; c->num_ids = 1; @@ -1351,7 +1349,7 @@ void winctrl_layout(struct dlgparam *dp, struct winctrls *wc, /* Draw a title, if we have one. */ if (!s->boxname && s->boxtitle) { - struct winctrl *c = smalloc(sizeof(struct winctrl)); + struct winctrl *c = snew(struct winctrl); c->ctrl = NULL; c->base_id = base_id; c->num_ids = 1; @@ -1479,6 +1477,9 @@ void winctrl_layout(struct dlgparam *dp, struct winctrls *wc, memset(shortcuts, NO_SHORTCUT, lenof(shortcuts)); nshortcuts = 0; + /* Almost all controls start at base_id. */ + actual_base_id = base_id; + /* * Now we're ready to actually create the control, by * switching on its type. @@ -1531,7 +1532,7 @@ void winctrl_layout(struct dlgparam *dp, struct winctrls *wc, ctrl->radio.shortcut); shortcuts[nshortcuts++] = ctrl->radio.shortcut; - buttons = smalloc(ctrl->radio.nbuttons * sizeof(struct radio)); + buttons = snewn(ctrl->radio.nbuttons, struct radio); for (i = 0; i < ctrl->radio.nbuttons; i++) { buttons[i].text = @@ -1569,8 +1570,10 @@ void winctrl_layout(struct dlgparam *dp, struct winctrls *wc, escaped = shortcut_escape(ctrl->button.label, ctrl->button.shortcut); shortcuts[nshortcuts++] = ctrl->button.shortcut; + if (ctrl->button.iscancel) + actual_base_id = IDCANCEL; num_ids = 1; - button(&pos, escaped, base_id, ctrl->button.isdefault); + button(&pos, escaped, actual_base_id, ctrl->button.isdefault); sfree(escaped); break; case CTRL_LISTBOX: @@ -1579,7 +1582,7 @@ void winctrl_layout(struct dlgparam *dp, struct winctrls *wc, ctrl->listbox.shortcut); shortcuts[nshortcuts++] = ctrl->listbox.shortcut; if (ctrl->listbox.draglist) { - data = smalloc(sizeof(struct prefslist)); + data = snew(struct prefslist); num_ids = 4; prefslist(data, &pos, ctrl->listbox.height, escaped, base_id, base_id+1, base_id+2, base_id+3); @@ -1611,7 +1614,7 @@ void winctrl_layout(struct dlgparam *dp, struct winctrls *wc, int *tabarray; int i, percent; - tabarray = smalloc((ctrl->listbox.ncols-1) * sizeof(int)); + tabarray = snewn(ctrl->listbox.ncols-1, int); percent = 0; for (i = 0; i < ctrl->listbox.ncols-1; i++) { percent += ctrl->listbox.percentages[i]; @@ -1641,7 +1644,7 @@ void winctrl_layout(struct dlgparam *dp, struct winctrls *wc, statictext(&pos, escaped, 1, base_id); staticbtn(&pos, "", base_id+1, "Change...", base_id+2); sfree(escaped); - data = smalloc(sizeof(FontSpec)); + data = snew(FontSpec); break; default: assert(!"Can't happen"); @@ -1655,16 +1658,17 @@ void winctrl_layout(struct dlgparam *dp, struct winctrls *wc, * (and isn't tabdelayed). */ if (pos.hwnd) { - struct winctrl *c = smalloc(sizeof(struct winctrl)); + struct winctrl *c = snew(struct winctrl); c->ctrl = ctrl; - c->base_id = base_id; + c->base_id = actual_base_id; c->num_ids = num_ids; c->data = data; memcpy(c->shortcuts, shortcuts, sizeof(shortcuts)); winctrl_add(wc, c); winctrl_add_shortcuts(dp, c); - base_id += num_ids; + if (actual_base_id == base_id) + base_id += num_ids; } if (colstart >= 0) { @@ -1705,10 +1709,10 @@ static void winctrl_set_focus(union control *ctrl, struct dlgparam *dp, } } -union control *dlg_last_focused(void *dlg) +union control *dlg_last_focused(union control *ctrl, void *dlg) { struct dlgparam *dp = (struct dlgparam *)dlg; - return dp->lastfocused; + return dp->focused == ctrl ? dp->lastfocused : dp->focused; } /* @@ -1808,7 +1812,7 @@ int winctrl_handle_command(struct dlgparam *dp, UINT msg, CB_GETCURSEL, 0, 0); len = SendDlgItemMessage(dp->hwnd, c->base_id+1, CB_GETLBTEXTLEN, index, 0); - text = smalloc(len+1); + text = snewn(len+1, char); SendDlgItemMessage(dp->hwnd, c->base_id+1, CB_GETLBTEXT, index, (LPARAM)text); SetDlgItemText(dp->hwnd, c->base_id+1, text); @@ -1893,6 +1897,8 @@ int winctrl_handle_command(struct dlgparam *dp, UINT msg, if (msg == WM_COMMAND && id == 2 && (HIWORD(wParam) == BN_SETFOCUS || HIWORD(wParam) == BN_KILLFOCUS)) winctrl_set_focus(ctrl, dp, HIWORD(wParam) == BN_SETFOCUS); + if (msg == WM_COMMAND && id == 1 && HIWORD(wParam) == EN_CHANGE) + ctrl->generic.handler(ctrl, dp, dp->data, EVENT_VALCHANGE); if (id == 2 && (msg == WM_COMMAND && (HIWORD(wParam) == BN_CLICKED || @@ -2171,8 +2177,8 @@ void dlg_listbox_add(union control *ctrl, void *dlg, char const *text) * strings in any listbox then you MUST not assign them different * IDs and expect to get meaningful results back. */ -void dlg_listbox_addwithindex(union control *ctrl, void *dlg, - char const *text, int id) +void dlg_listbox_addwithid(union control *ctrl, void *dlg, + char const *text, int id) { struct dlgparam *dp = (struct dlgparam *)dlg; struct winctrl *c = dlg_findbyctrl(dp, ctrl); @@ -2424,3 +2430,105 @@ 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->wintitle = 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; + } + sfree(dp->wintitle); + sfree(dp->errtitle); +} + +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 = snew(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 = snew(struct perctrl_privdata); + p->ctrl = ctrl; + p->needs_free = FALSE; + add234(dp->privdata, p); + } + assert(!p->needs_free); + p->needs_free = TRUE; + /* + * This is an internal allocation routine, so it's allowed to + * use smalloc directly. + */ + p->data = smalloc(size); + return p->data; +}