#include <windows.h>
#include <commctrl.h>
#include <assert.h>
+#include <ctype.h>
#include "winstuff.h"
#include "misc.h"
SWP_NOACTIVATE | SWP_NOCOPYBITS |
SWP_NOMOVE | SWP_NOZORDER);
}
- }
+ } else
+ ctl = NULL;
return ctl;
}
*/
char *staticwrap(struct ctlpos *cp, HWND hwnd, char *text, int *lines)
{
- HFONT font = (HFONT) cp->font;
HDC hdc = GetDC(hwnd);
int lpx = GetDeviceCaps(hdc, LOGPIXELSX);
int width, nlines, j;
SIZE size;
char *ret, *p, *q;
RECT r;
+ HFONT oldfont, newfont;
ret = smalloc(1+strlen(text));
p = text;
* Work out the width the text will need to fit in, by doing
* the same adjustment that the `statictext' function itself
* will perform.
- *
- * We must first convert from dialog-box units into pixels, and
- * then from pixels into the `logical units' that Windows uses
- * within GDI. You can't make this stuff up.
*/
+ SetMapMode(hdc, MM_TEXT); /* ensure logical units == pixels */
r.left = r.top = r.bottom = 0;
r.right = cp->width;
MapDialogRect(hwnd, &r);
- width = MulDiv(r.right, lpx, 72);
+ width = r.right;
nlines = 1;
+ /*
+ * We must select the correct font into the HDC before calling
+ * GetTextExtent*, or silly things will happen.
+ */
+ newfont = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0);
+ oldfont = SelectObject(hdc, newfont);
+
while (*p) {
if (!GetTextExtentExPoint(hdc, p, strlen(p), width,
&nfit, pwidths, &size) ||
nlines++;
}
+ SelectObject(hdc, oldfont);
ReleaseDC(cp->hwnd, hdc);
if (lines) *lines = nlines;
if ((int)wParam == hdl->listid) {
DRAGLISTINFO *dlm = (DRAGLISTINFO *)lParam;
- int dest;
+ int dest = 0; /* initialise to placate gcc */
switch (dlm->uNotification) {
case DL_BEGINDRAG:
hdl->dummyitem =
struct ctlpos pos;
- char shortcuts[MAX_SHORTCUTS_PER_CTRL], nshortcuts;
+ char shortcuts[MAX_SHORTCUTS_PER_CTRL];
+ int nshortcuts;
char *escaped;
- int i, base_id, num_ids, orig_tabdelay;
+ int i, actual_base_id, base_id, num_ids;
void *data;
base_id = *id;
for (i = 0; i < s->ncontrols; i++) {
union control *ctrl = s->ctrls[i];
- orig_tabdelay = FALSE;
-
/*
* Generic processing that pertains to all control types.
* At the end of this if statement, we'll have produced
assert(!ctrl->generic.tabdelay);
ctrl = ctrl->tabdelay.ctrl;
- orig_tabdelay = TRUE;
for (i = 0; i < ntabdelays; i++)
if (tabdelayed[i] == ctrl)
pos = tabdelays[i]; /* structure copy */
+ colstart = colspan = -1; /* indicate this was tab-delayed */
+
} else {
/*
* If it wasn't one of those, it's a genuine control;
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.
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:
break;
default:
assert(!"Can't happen");
+ num_ids = 0; /* placate gcc */
break;
}
struct winctrl *c = smalloc(sizeof(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 (!orig_tabdelay) {
+ if (colstart >= 0) {
/*
* Update the ypos in all columns crossed by this
* control.
}
}
-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;
}
/*
/*
* Look up the control ID in our data.
*/
+ c = NULL;
for (i = 0; i < dp->nctrltrees; i++) {
c = winctrl_findbyid(dp->controltrees[i], LOWORD(wParam));
if (c)
RECT r = di->rcItem;
SIZE s;
+ SetMapMode(hdc, MM_TEXT); /* ensure logical units == pixels */
+
GetTextExtentPoint32(hdc, (char *)c->data,
strlen((char *)c->data), &s);
DrawEdge(hdc, &r, EDGE_ETCHED, BF_ADJUST | BF_RECT);
* checked before generating an event.
*/
if (msg == WM_COMMAND &&
- HIWORD(wParam) == BN_CLICKED ||
- HIWORD(wParam) == BN_DOUBLECLICKED &&
+ (HIWORD(wParam) == BN_CLICKED ||
+ HIWORD(wParam) == BN_DOUBLECLICKED) &&
IsDlgButtonChecked(dp->hwnd, LOWORD(wParam))) {
ctrl->generic.handler(ctrl, dp, dp->data, EVENT_VALCHANGE);
}
/*
* Look up the control ID in our data.
*/
+ c = NULL;
for (i = 0; i < dp->nctrltrees; i++) {
c = winctrl_findbyid(dp->controltrees[i], id);
if (c)
int msg;
assert(c &&
(c->ctrl->generic.type == CTRL_LISTBOX ||
- c->ctrl->generic.type == CTRL_EDITBOX &&
- c->ctrl->editbox.has_list));
+ (c->ctrl->generic.type == CTRL_EDITBOX &&
+ c->ctrl->editbox.has_list)));
msg = (c->ctrl->generic.type==CTRL_LISTBOX && c->ctrl->listbox.height!=0 ?
LB_RESETCONTENT : CB_RESETCONTENT);
SendDlgItemMessage(dp->hwnd, c->base_id+1, msg, 0, 0);
int msg;
assert(c &&
(c->ctrl->generic.type == CTRL_LISTBOX ||
- c->ctrl->generic.type == CTRL_EDITBOX &&
- c->ctrl->editbox.has_list));
+ (c->ctrl->generic.type == CTRL_EDITBOX &&
+ c->ctrl->editbox.has_list)));
msg = (c->ctrl->generic.type==CTRL_LISTBOX && c->ctrl->listbox.height!=0 ?
LB_DELETESTRING : CB_DELETESTRING);
SendDlgItemMessage(dp->hwnd, c->base_id+1, msg, index, 0);
int msg;
assert(c &&
(c->ctrl->generic.type == CTRL_LISTBOX ||
- c->ctrl->generic.type == CTRL_EDITBOX &&
- c->ctrl->editbox.has_list));
+ (c->ctrl->generic.type == CTRL_EDITBOX &&
+ c->ctrl->editbox.has_list)));
msg = (c->ctrl->generic.type==CTRL_LISTBOX && c->ctrl->listbox.height!=0 ?
LB_ADDSTRING : CB_ADDSTRING);
SendDlgItemMessage(dp->hwnd, c->base_id+1, msg, 0, (LPARAM)text);
int msg, msg2, index;
assert(c &&
(c->ctrl->generic.type == CTRL_LISTBOX ||
- c->ctrl->generic.type == CTRL_EDITBOX &&
- c->ctrl->editbox.has_list));
+ (c->ctrl->generic.type == CTRL_EDITBOX &&
+ c->ctrl->editbox.has_list)));
msg = (c->ctrl->generic.type==CTRL_LISTBOX && c->ctrl->listbox.height!=0 ?
LB_ADDSTRING : CB_ADDSTRING);
msg2 = (c->ctrl->generic.type==CTRL_LISTBOX && c->ctrl->listbox.height!=0 ?
} 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;
+}