static BOOL cfgui_check_mod_state(khui_config_node node) { khm_int32 flags; khui_config_node c = NULL; BOOL rv = FALSE; flags = khui_cfg_get_flags(node); if (flags & KHUI_CNFLAG_MODIFIED) return TRUE; if (KHM_FAILED(khui_cfg_get_first_child(node, &c))) return FALSE; while(c) { rv = (rv || cfgui_check_mod_state(c)); khui_cfg_get_next_release(&c); } return rv; }
static void cfgui_apply_settings(khui_config_node node) { HWND hwnd; khui_config_node c; khm_int32 flags; hwnd = khui_cfg_get_hwnd(node); flags = khui_cfg_get_flags(node); if (hwnd && (flags & KHUI_CNFLAG_MODIFIED)) { SendMessage(hwnd, KHUI_WM_CFG_NOTIFY, MAKEWPARAM(0, WMCFG_APPLY), (LPARAM) node); } if (KHM_FAILED(khui_cfg_get_first_child(node, &c))) return; while (c) { cfgui_apply_settings(c); khui_cfg_get_next_release(&c); } }
static void refresh_identity_config_panels(void) { khm_handle ident = NULL; kcdb_enumeration e = NULL; khui_config_node cfg_iter = NULL; khui_config_node cfg_ids = NULL; if (KHM_FAILED(khui_cfg_open(NULL, L"KhmIdentities", &cfg_ids))) goto _cleanup; if (KHM_FAILED(kcdb_identity_begin_enum(KCDB_IDENT_FLAG_CONFIG, KCDB_IDENT_FLAG_CONFIG, &e, NULL))) goto _done_adding; while (KHM_SUCCEEDED(kcdb_enum_next(e, &ident))) { khui_config_node cfg_id; wchar_t cfgname[KCDB_MAXCCH_NAME]; khm_size cb; cb = sizeof(cfgname); if (KHM_FAILED(kcdb_identity_get_short_name(ident, FALSE, cfgname, &cb))) continue; if (KHM_SUCCEEDED(khui_cfg_open(cfg_ids, cfgname, &cfg_id))) { /* it's already there */ khui_cfg_release(cfg_id); continue; } else { khui_config_node_reg reg; wchar_t wshort[KHUI_MAXCCH_SHORT_DESC]; wchar_t wlong[KHUI_MAXCCH_LONG_DESC]; wchar_t wfmt[KHUI_MAXCCH_NAME]; wchar_t widname[KHUI_MAXCCH_SHORT_DESC]; khm_size cb; ZeroMemory(®, sizeof(reg)); reg.name = cfgname; reg.short_desc = wshort; reg.long_desc = wlong; reg.h_module = khm_hInstance; reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_IDENTITY); reg.dlg_proc = khm_cfg_identity_proc; reg.flags = 0; cb = sizeof(widname); kcdb_get_resource(ident, KCDB_RES_DISPLAYNAME, KCDB_RFS_SHORT, NULL, NULL, widname, &cb); LoadString(khm_hInstance, IDS_CFG_IDENTITY_SHORT, wfmt, ARRAYLENGTH(wfmt)); StringCbPrintf(wshort, sizeof(wshort), wfmt, widname); LoadString(khm_hInstance, IDS_CFG_IDENTITY_LONG, wfmt, ARRAYLENGTH(wfmt)); StringCbPrintf(wlong, sizeof(wlong), wfmt, widname); khui_cfg_register(cfg_ids, ®); if (KHM_SUCCEEDED(khui_cfg_open(cfg_ids, cfgname, &cfg_id))) { khui_cfg_set_data(cfg_id, ident); kcdb_identity_hold(ident); khui_cfg_release(cfg_id); } } } /* while enumerating through e */ kcdb_enum_end(e); _done_adding: for (khui_cfg_get_first_child(cfg_ids, &cfg_iter); cfg_iter; khui_cfg_get_next_release(&cfg_iter)) { khm_int32 flags = 0; ident = khui_cfg_get_data(cfg_iter); if (ident == NULL || KHM_FAILED(kcdb_identity_get_flags(ident, &flags)) || (flags & (KCDB_IDENT_FLAG_ACTIVE| KCDB_IDENT_FLAG_CONFIG)) != (KCDB_IDENT_FLAG_ACTIVE | KCDB_IDENT_FLAG_CONFIG)) { /* this configuration node needs to be removed */ if (ident) /* undo the hold done above for for configuration node data */ kcdb_identity_release(ident); khui_cfg_set_data(cfg_iter, NULL); khui_cfg_remove(cfg_iter); } } _cleanup: if (cfg_ids) { khui_cfg_release(cfg_ids); } }
static void cfgui_add_node(cfgui_wnd_data * d, HWND hwtv, khui_config_node node, khui_config_node parent, BOOL sorted) { khui_config_node_reg reg; khui_config_node c; wchar_t wbuf[256]; const wchar_t * short_desc; TVINSERTSTRUCT s; HTREEITEM hItem; if (node) { khui_cfg_get_reg(node, ®); short_desc = reg.short_desc; } else { short_desc = wbuf; LoadString(khm_hInstance, IDS_CFG_ROOT_NAME, wbuf, ARRAYLENGTH(wbuf)); reg.flags = 0; } ZeroMemory(&s, sizeof(s)); s.hParent = (node)? (HTREEITEM) khui_cfg_get_param(parent): TVI_ROOT; s.hInsertAfter = (sorted)? TVI_SORT: TVI_FIRST; s.itemex.mask = TVIF_CHILDREN | TVIF_PARAM | TVIF_TEXT | TVIF_STATE; { khui_config_node n; if (KHM_SUCCEEDED(khui_cfg_get_first_child(node, &n))) { s.itemex.cChildren = 1; s.itemex.state = TVIS_EXPANDED; s.itemex.stateMask = TVIS_EXPANDED; khui_cfg_release(n); } else { s.itemex.cChildren = 0; s.itemex.state = 0; s.itemex.stateMask = TVIS_EXPANDED; } s.itemex.state |= INDEXTOSTATEIMAGEMASK(d->idx_default); s.itemex.stateMask |= TVIS_STATEIMAGEMASK; } s.itemex.lParam = (LPARAM) node; khui_cfg_hold(node); s.itemex.pszText = (LPWSTR) short_desc; hItem = TreeView_InsertItem(hwtv, &s); khui_cfg_set_param(node, (LPARAM) hItem); if (KHM_SUCCEEDED(khui_cfg_get_first_child(node, &c))) { do { cfgui_add_node(d, hwtv, c, node, !!(reg.flags & KHUI_CNFLAG_SORT_CHILDREN)); } while (KHM_SUCCEEDED(khui_cfg_get_next_release(&c))); } }
static void cfgui_sync_node(cfgui_wnd_data * d, HWND hwtv, khui_config_node c, HTREEITEM hItem) { khui_config_node child; HTREEITEM hChild; struct cfgui_child_info * childinfo = NULL; khm_size n_childinfo = 0; khm_size nc_childinfo = 0; khm_size i; /* first, get the list of children from the treeview control */ for (hChild = TreeView_GetChild(hwtv, hItem); hChild; hChild = TreeView_GetNextSibling(hwtv, hChild)) { if (n_childinfo >= nc_childinfo) { nc_childinfo = UBOUNDSS(n_childinfo + 1, CI_ALLOC_INCR, CI_ALLOC_INCR); #ifdef DEBUG assert(nc_childinfo > n_childinfo); #endif childinfo = PREALLOC(childinfo, sizeof(*childinfo) * nc_childinfo); #ifdef DEBUG assert(childinfo); #endif } ZeroMemory(&childinfo[n_childinfo], sizeof(childinfo[n_childinfo])); childinfo[n_childinfo].hItem = hChild; childinfo[n_childinfo].checked = FALSE; n_childinfo++; } /* now, go through the list of actual nodes and make sure they match up */ child = NULL; for (khui_cfg_get_first_child(c, &child); child; khui_cfg_get_next_release(&child)) { hChild = (HTREEITEM) khui_cfg_get_param(child); for (i=0; i < n_childinfo; i++) { if (childinfo[i].hItem == hChild) break; } if (i < n_childinfo) { childinfo[i].checked = TRUE; } else { /* add it to the list, so we can create the node in the tree view control later. */ if (n_childinfo >= nc_childinfo) { nc_childinfo = UBOUNDSS(n_childinfo + 1, CI_ALLOC_INCR, CI_ALLOC_INCR); #ifdef DEBUG assert(nc_childinfo > n_childinfo); #endif childinfo = PREALLOC(childinfo, sizeof(*childinfo) * nc_childinfo); #ifdef DEBUG assert(childinfo); #endif } ZeroMemory(&childinfo[n_childinfo], sizeof(childinfo[n_childinfo])); childinfo[n_childinfo].node = child; khui_cfg_hold(child); n_childinfo++; } } /* by this point, the childinfo list contains items of the following forms: 1. childinfo[i].hItem != NULL && childinfo[i].checked == TRUE Corresponds to a tree view item that has a matching configuration node. Nothing to do here. 2. childinfo[i].hItem != NULL && childinfo[i].checked == FALSE Corresponds to a tree view item that has no matching configuration node. These should be removed. 3. childinfo[i].hItem == NULL && childinfo[i].node != NULL Corresponds to a configuration node that has no matching tree view item. These nodes should be added. */ /* first do the removals */ for (i=0; i < n_childinfo; i++) { if (childinfo[i].hItem == NULL) break; /* nothing more to see from this point on */ if (!childinfo[i].checked) { /* remove! */ cfgui_remove_item(hwtv, childinfo[i].hItem); } } /* continue from where the previous loop left off */ for (; i < n_childinfo; i++) { #ifdef DEBUG assert(childinfo[i].hItem == NULL); assert(childinfo[i].node != NULL); #endif cfgui_add_node(d, hwtv, childinfo[i].node, c, FALSE); khui_cfg_release(childinfo[i].node); childinfo[i].node = NULL; } if (childinfo) PFREE(childinfo); /* finally recurse through to the next level */ for (hChild = TreeView_GetChild(hwtv, hItem); hChild; hChild = TreeView_GetNextSibling(hwtv, hChild)) { TVITEMEX itemex; ZeroMemory(&itemex, sizeof(itemex)); itemex.mask = TVIF_PARAM; itemex.hItem = hChild; TreeView_GetItem(hwtv, &itemex); if (itemex.lParam) { child = (khui_config_node) itemex.lParam; cfgui_sync_node(d, hwtv, child, hChild); } } }
/* Makes sure that each top level configuration node has a corresponding menu item in the 'Options' menu.*/ static void refresh_config_menu_items(void) { khui_menu_def * omenu; khm_boolean refresh_menu = FALSE; khui_config_node cfg_r = NULL; omenu = khui_find_menu(KHUI_MENU_OPTIONS); if (omenu == NULL) { #ifdef DEBUG assert(FALSE); #endif return; } khui_action_lock(); for (khui_cfg_get_first_child(NULL, &cfg_r); cfg_r != NULL; khui_cfg_get_next_release(&cfg_r)) { khm_int32 flags; khui_action * paction; wchar_t cname[KHUI_MAXCCH_NAME]; khm_size cb; flags = khui_cfg_get_flags(cfg_r); if (flags & KHUI_CNFLAG_SYSTEM) continue; cb = sizeof(cname); if (KHM_FAILED(khui_cfg_get_name(cfg_r, cname, &cb))) { #ifdef DEBUG assert(FALSE); #endif continue; } paction = khui_find_named_action(cname); if (!paction) { khm_handle sub; khui_config_node_reg reg; wchar_t wshort[KHUI_MAXCCH_SHORT_DESC]; khm_int32 action; khui_cfg_get_reg(cfg_r, ®); kmq_create_hwnd_subscription(khm_hwnd_main, &sub); StringCbCopy(wshort, sizeof(wshort), reg.short_desc); StringCbCat(wshort, sizeof(wshort), L" ..."); action = khui_action_create(cname, wshort, reg.long_desc, (void *) CFGACTION_MAGIC, KHUI_ACTIONTYPE_TRIGGER, sub); if (action == 0) { #ifdef DEBUG assert(FALSE); #endif continue; } khui_menu_insert_action(omenu, (khm_size) -1, action, 0); refresh_menu = TRUE; } } khui_action_unlock(); if (refresh_menu) { khui_refresh_actions(); } }
static void add_subpanels(HWND hwnd, khui_config_node ctx_node, khui_config_node ref_node) { HWND hw_tab; HWND hw_target; khui_config_node sub; khui_config_node_reg reg; khui_config_init_data idata; int idx; hw_tab = GetDlgItem(hwnd, IDC_CFG_TAB); hw_target = GetDlgItem(hwnd, IDC_CFG_TARGET); #ifdef DEBUG assert(hw_tab); assert(hw_target); #endif if (KHM_FAILED(khui_cfg_get_first_subpanel(ref_node, &sub))) { #ifdef DEBUG assert(FALSE); #endif return; } idx = 0; while(sub) { HWND hwnd_panel; TCITEM tci; int iid; khui_cfg_get_reg(sub, ®); if ((ctx_node == ref_node && (reg.flags & KHUI_CNFLAG_PLURAL)) || (ctx_node != ref_node && !(reg.flags & KHUI_CNFLAG_PLURAL))) goto _next_node; idata.ctx_node = ctx_node; idata.this_node = sub; idata.ref_node = ref_node; hwnd_panel = CreateDialogParam(reg.h_module, reg.dlg_template, hwnd, reg.dlg_proc, (LPARAM) &idata); #ifdef DEBUG assert(hwnd_panel); #endif ShowWindow(hwnd_panel, SW_HIDE); ZeroMemory(&tci, sizeof(tci)); tci.mask = TCIF_PARAM | TCIF_TEXT; tci.lParam = (LPARAM) sub; tci.pszText = (LPWSTR) reg.short_desc; iid = TabCtrl_InsertItem(hw_tab, 0, &tci); idx++; if (reg.flags & KHUI_CNFLAG_PLURAL) { khui_cfg_set_param_inst(sub, ctx_node, iid); khui_cfg_set_hwnd_inst(sub, ctx_node, hwnd_panel); } else { khui_cfg_set_param(sub, iid); khui_cfg_set_hwnd(sub, hwnd_panel); } _next_node: khui_cfg_get_next_release(&sub); } TabCtrl_SetCurSel(hw_tab, 0); }