/* * Find the index of first controlset in a controlbox for a given * path. If that path doesn't exist, return the index where it * should be inserted. */ static int ctrl_find_set(struct controlbox *b, char *path, int start) { int i, last, thisone; last = 0; for (i = 0; i < b->nctrlsets; i++) { thisone = ctrl_path_compare(path, b->ctrlsets[i]->pathname); /* * If `start' is true and there exists a controlset with * exactly the path we've been given, we should return the * index of the first such controlset we find. Otherwise, * we should return the index of the first entry in which * _fewer_ path elements match than they did last time. */ if ((start && thisone == INT_MAX) || thisone < last) return i; last = thisone; } return b->nctrlsets; /* insert at end */ }
/* * This function is the configuration box. * (Being a dialog procedure, in general it returns 0 if the default * dialog processing should be performed, and 1 if it should not.) */ static INT_PTR CALLBACK config_dialog_proc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { when WM_INITDIALOG: { ctrlbox = ctrl_new_box(); setup_config_box(ctrlbox); windlg_init(); winctrl_init(&ctrls_base); winctrl_init(&ctrls_panel); windlg_add_tree(&ctrls_base); windlg_add_tree(&ctrls_panel); copy_config("dialog", &new_cfg, &file_cfg); RECT r; GetWindowRect(GetParent(wnd), &r); dlg.wnd = wnd; /* * Create the actual GUI widgets. */ // here we need the correct DIALOG_HEIGHT already create_controls(wnd, ""); /* Open and Cancel buttons etc */ SendMessage(wnd, WM_SETICON, (WPARAM) ICON_BIG, (LPARAM) LoadIcon(inst, MAKEINTRESOURCE(IDI_MAINICON))); /* * Create the tree view. */ r.left = 3; r.right = r.left + 64; r.top = 3; r.bottom = r.top + DIALOG_HEIGHT - 26; MapDialogRect(wnd, &r); HWND treeview = CreateWindowEx(WS_EX_CLIENTEDGE, WC_TREEVIEW, "", WS_CHILD | WS_VISIBLE | WS_TABSTOP | TVS_HASLINES | TVS_DISABLEDRAGDROP | TVS_HASBUTTONS | TVS_LINESATROOT | TVS_SHOWSELALWAYS, r.left, r.top, r.right - r.left, r.bottom - r.top, wnd, (HMENU) IDCX_TREEVIEW, inst, null); WPARAM font = SendMessage(wnd, WM_GETFONT, 0, 0); SendMessage(treeview, WM_SETFONT, font, MAKELPARAM(true, 0)); treeview_faff tvfaff; tvfaff.treeview = treeview; memset(tvfaff.lastat, 0, sizeof (tvfaff.lastat)); /* * Set up the tree view contents. */ HTREEITEM hfirst = null; char *path = null; for (int i = 0; i < ctrlbox->nctrlsets; i++) { controlset *s = ctrlbox->ctrlsets[i]; HTREEITEM item; int j; char *c; if (!s->pathname[0]) continue; j = path ? ctrl_path_compare(s->pathname, path) : 0; if (j == INT_MAX) continue; /* same path, nothing to add to tree */ /* * We expect never to find an implicit path * component. For example, we expect never to see * A/B/C followed by A/D/E, because that would * _implicitly_ create A/D. All our path prefixes * are expected to contain actual controls and be * selectable in the treeview; so we would expect * to see A/D _explicitly_ before encountering * A/D/E. */ c = strrchr(s->pathname, '/'); if (!c) c = s->pathname; else c++; item = treeview_insert(&tvfaff, j, c, s->pathname); if (!hfirst) hfirst = item; path = s->pathname; /* * Put the treeview selection on to the Session panel. * This should also cause creation of the relevant * controls. */ TreeView_SelectItem(treeview, hfirst); } /* * Set focus into the first available control. */ for (winctrl *c = ctrls_panel.first; c; c = c->next) { if (c->ctrl) { dlg_set_focus(c->ctrl); break; } } } when WM_DESTROY: winctrl_cleanup(&ctrls_base); winctrl_cleanup(&ctrls_panel); ctrl_free_box(ctrlbox); config_wnd = 0; when WM_NOTIFY: { if (LOWORD(wParam) == IDCX_TREEVIEW && ((LPNMHDR) lParam)->code == TVN_SELCHANGED) { HTREEITEM i = TreeView_GetSelection(((LPNMHDR) lParam)->hwndFrom); TVITEM item; char buffer[64]; item.hItem = i; item.pszText = buffer; item.cchTextMax = sizeof (buffer); item.mask = TVIF_TEXT | TVIF_PARAM; TreeView_GetItem(((LPNMHDR) lParam)->hwndFrom, &item); /* Destroy all controls in the currently visible panel. */ for (winctrl *c = ctrls_panel.first; c; c = c->next) { for (int k = 0; k < c->num_ids; k++) { HWND item = GetDlgItem(wnd, c->base_id + k); if (item) DestroyWindow(item); } } winctrl_cleanup(&ctrls_panel); // here we need the correct DIALOG_HEIGHT already create_controls(wnd, (char *) item.lParam); dlg_refresh(null); /* set up control values */ } } when WM_CLOSE: DestroyWindow(wnd); when WM_COMMAND or WM_DRAWITEM: { int ret = winctrl_handle_command(msg, wParam, lParam); if (dlg.ended) DestroyWindow(wnd); return ret; } when WM_USER: { HWND target = (HWND)wParam; // could delegate this to winctrls.c, like winctrl_handle_command; // but then we'd have to fiddle with the location of dragndrop /* * Look up the window handle in our data; find the control. (Hmm, apparently it works without looking for the widget entry that was particularly introduced for this purpose...) */ control * ctrl = null; for (winctrl *c = ctrls_panel.first; c && !ctrl; c = c->next) { if (c->ctrl) for (int k = 0; k < c->num_ids; k++) { #ifdef debug_dragndrop printf(" [->%8p] %8p\n", target, GetDlgItem(wnd, c->base_id + k)); #endif if (target == GetDlgItem(wnd, c->base_id + k)) { ctrl = c->ctrl; break; } } } if (ctrl) { //dlg_editbox_set_w(ctrl, L"Test"); // may hit unrelated items... // drop the drag-and-drop contents here dragndrop = (wstring)lParam; ctrl->handler(ctrl, EVENT_DROP); } } } return 0; }