From 31a64b25521f2c96e88b7238343d9c05832d1eda Mon Sep 17 00:00:00 2001 From: George Hazan Date: Wed, 28 Apr 2021 19:48:34 +0300 Subject: Dbeditor++: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Search/Replace dialog -> UI classes; - fixes #2863 (DbEditor: невозможно перейти к результатам поиска без мыши); - version bump --- plugins/DbEditorPP/res/resource.rc | 2 +- plugins/DbEditorPP/src/findwindow.cpp | 879 +++++++++++++++++----------------- plugins/DbEditorPP/src/stdafx.h | 2 +- plugins/DbEditorPP/src/utils.cpp | 2 +- plugins/DbEditorPP/src/version.h | 2 +- 5 files changed, 435 insertions(+), 452 deletions(-) (limited to 'plugins') diff --git a/plugins/DbEditorPP/res/resource.rc b/plugins/DbEditorPP/res/resource.rc index 2a5154b7f8..947d3ad4d0 100644 --- a/plugins/DbEditorPP/res/resource.rc +++ b/plugins/DbEditorPP/res/resource.rc @@ -43,7 +43,7 @@ BEGIN CONTROL "Entirely",IDC_ENTIRELY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,249,58,69,10 PUSHBUTTON "&Replace",IDOK,325,56,60,14 CONTROL "List1",IDC_LIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SORTDESCENDING | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | WS_BORDER | WS_TABSTOP,4,80,387,152 - CONTROL "",IDC_SBAR,"msctls_statusbar32",WS_TABSTOP | 0x100,4,238,387,12 + CONTROL "",IDC_SBAR,"msctls_statusbar32",0x100,4,238,387,12 END IDD_OPTIONS DIALOGEX 0, 0, 314, 92 diff --git a/plugins/DbEditorPP/src/findwindow.cpp b/plugins/DbEditorPP/src/findwindow.cpp index 6615bc1405..eb52b401ad 100644 --- a/plugins/DbEditorPP/src/findwindow.cpp +++ b/plugins/DbEditorPP/src/findwindow.cpp @@ -1,249 +1,53 @@ #include "stdafx.h" -#define F_CASE 1 -#define F_EXACT 2 -#define F_MODNAME 4 -#define F_SETNAME 8 -#define F_SETVAL 0x10 - -#define F_ENTIRE 0x20 - -#define F_NUMSRCH 0x40 -#define F_NUMREPL 0x80 -#define F_UNICODE 0x100 - -#define F_REPLACED 0x200 -#define F_DELETED 0x400 - -static int lastColumn = -1; - -struct FindInfo +#define F_CASE 0x0001 +#define F_EXACT 0x0002 +#define F_MODNAME 0x0004 +#define F_SETNAME 0x0008 +#define F_SETVAL 0x0010 +#define F_ENTIRE 0x0020 +#define F_NUMSRCH 0x0040 +#define F_NUMREPL 0x0080 +#define F_UNICODE 0x0100 +#define F_REPLACED 0x0200 +#define F_DELETED 0x0400 + +///////////////////////////////////////////////////////////////////////////////////////// + +static int FindMatchA(const char *text, char *search, int options) { - HWND hwnd; // hwnd to item list - wchar_t* search; // text to find - wchar_t* replace; // text to replace - int options; // or'd about items -}; - -static ColumnsSettings csResultList[] = -{ - { LPGENW("Result"), 0, "Search0width", 100 }, - { LPGENW("Contact"), 1, "Search1width", 100 }, - { LPGENW("Module"), 2, "Search2width", 100 }, - { LPGENW("Setting"), 3, "Search3width", 100 }, - { LPGENW("Value"), 4, "Search4width", 150 }, - { nullptr } -}; - -void __cdecl FindSettings(LPVOID di); - -int FindDialogResize(HWND, LPARAM, UTILRESIZECONTROL *urc) -{ - switch (urc->wId) { - case IDC_LIST: - return RD_ANCHORX_WIDTH | RD_ANCHORY_HEIGHT; - case IDC_SBAR: - return RD_ANCHORX_WIDTH | RD_ANCHORY_BOTTOM; - default: - return RD_ANCHORX_LEFT | RD_ANCHORY_TOP; - } -} - -INT_PTR CALLBACK FindWindowDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - HWND hwndResults = GetDlgItem(hwnd, IDC_LIST); - - switch (msg) { - case WM_INITDIALOG: - SendDlgItemMessage(hwnd, IDC_SBAR, SB_SETTEXT, 0, (LPARAM)TranslateT("Enter a string to search the database for")); - CheckDlgButton(hwnd, IDC_MODNAME, BST_CHECKED); - CheckDlgButton(hwnd, IDC_SETTINGNAME, BST_CHECKED); - CheckDlgButton(hwnd, IDC_SETTINGVALUE, BST_CHECKED); - CheckDlgButton(hwnd, IDC_FOUND, BST_CHECKED); - SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)LoadIcon(g_plugin.getInst(), MAKEINTRESOURCE(ICO_REGEDIT))); - SetWindowLongPtr(GetDlgItem(hwnd, IDC_REPLACE), GWLP_USERDATA, 0); - SetWindowLongPtr(GetDlgItem(hwnd, IDC_SEARCH), GWLP_USERDATA, 0); - SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_APPWINDOW); // taskbar icon - TranslateDialogDefault(hwnd); - ListView_SetExtendedListViewStyle(hwndResults, 32 | LVS_EX_LABELTIP); // LVS_EX_GRIDLINES - loadListSettings(hwndResults, csResultList); - Utils_RestoreWindowPositionNoMove(hwnd, NULL, MODULENAME, "Search_"); - return TRUE; - - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDOK: - case IDC_SEARCH: - if (GetWindowLongPtr(GetDlgItem(hwnd, IDC_SEARCH), GWLP_USERDATA)) // stop the search - SetWindowLongPtr(GetDlgItem(hwnd, IDC_SEARCH), GWLP_USERDATA, 0); - else { - wchar_t text[FLD_SIZE]; - wchar_t replace[FLD_SIZE] = {}; - - if (!GetDlgItemText(hwnd, IDC_TEXT, text, _countof(text)) && !IsDlgButtonChecked(hwnd, IDC_EXACT)) break; - - // empty replace is done only for exact match or entire replace - if (LOWORD(wParam) == IDOK && - !GetDlgItemText(hwnd, IDC_REPLACE, replace, _countof(replace)) && - (!IsDlgButtonChecked(hwnd, IDC_ENTIRELY) && !IsDlgButtonChecked(hwnd, IDC_EXACT))) - break; - - if (BST_UNCHECKED == IsDlgButtonChecked(hwnd, IDC_MODNAME) && - BST_UNCHECKED == IsDlgButtonChecked(hwnd, IDC_SETTINGNAME) && - BST_UNCHECKED == IsDlgButtonChecked(hwnd, IDC_SETTINGVALUE)) - break; - - FindInfo *fi = (FindInfo *)mir_calloc(sizeof(FindInfo)); - if (!fi) - break; - - fi->hwnd = hwndResults; - fi->options = (IsDlgButtonChecked(hwnd, IDC_CASESENSITIVE) ? F_CASE : 0) | - (IsDlgButtonChecked(hwnd, IDC_EXACT) ? F_EXACT : 0) | - (IsDlgButtonChecked(hwnd, IDC_MODNAME) ? F_MODNAME : 0) | - (IsDlgButtonChecked(hwnd, IDC_SETTINGNAME) ? F_SETNAME : 0) | - (IsDlgButtonChecked(hwnd, IDC_SETTINGVALUE) ? F_SETVAL : 0); - - if (LOWORD(wParam) == IDOK) { - - if (IsDlgButtonChecked(hwnd, IDC_ENTIRELY)) - fi->options |= F_ENTIRE; - - fi->replace = mir_wstrdup(replace); - - SetDlgItemText(hwnd, IDOK, TranslateT("Stop")); - EnableWindow(GetDlgItem(hwnd, IDC_SEARCH), 0); - - } - else { - SetDlgItemText(hwnd, IDC_SEARCH, TranslateT("Stop")); - EnableWindow(GetDlgItem(hwnd, IDOK), 0); - } - - fi->search = mir_wstrdup(text); - - ListView_DeleteAllItems(fi->hwnd); - SetWindowLongPtr(GetDlgItem(hwnd, IDC_SEARCH), GWLP_USERDATA, 1); - - EnableWindow(GetDlgItem(hwnd, IDCANCEL), 0); - mir_forkthread(FindSettings, fi); - } - break; + if (!search[0] && (!(options & F_EXACT) || !text[0])) + return 1; - case IDCANCEL: - DestroyWindow(hwnd); - break; - } - break; + if (options & F_EXACT) + return (options & F_CASE) ? !strcmp(text, search) : !stricmp(text, search); - case WM_GETMINMAXINFO: - { - MINMAXINFO *mmi = (MINMAXINFO *)lParam; - mmi->ptMinTrackSize.x = 610; - mmi->ptMinTrackSize.y = 300; - } - return 0; - - case WM_SIZE: - Utils_ResizeDialog(hwnd, g_plugin.getInst(), MAKEINTRESOURCEA(IDD_FIND), FindDialogResize); - break; - - case WM_NOTIFY: - if (LOWORD(wParam) != IDC_LIST) break; - switch (((NMHDR *)lParam)->code) { - case NM_DBLCLK: - LVHITTESTINFO hti; - LVITEM lvi; - hti.pt = ((NMLISTVIEW *)lParam)->ptAction; - if (ListView_SubItemHitTest(hwndResults, &hti) > -1) { - if (hti.flags & LVHT_ONITEM) { - lvi.mask = LVIF_PARAM; - lvi.iItem = hti.iItem; - lvi.iSubItem = 0; - if (ListView_GetItem(hwndResults, &lvi)) { - ItemInfo ii = {}; - ii.hContact = (MCONTACT)lvi.lParam; - ListView_GetItemTextA(hwndResults, hti.iItem, 2, ii.module, _countof(ii.module)); - ListView_GetItemTextA(hwndResults, hti.iItem, 3, ii.setting, _countof(ii.setting)); - if (ii.setting[0]) - ii.type = FW_SETTINGNAME; - else if (ii.module[0]) - ii.type = FW_MODULE; - - SendMessage(hwnd2mainWindow, WM_FINDITEM, (WPARAM)&ii, 0); - } - } - } - break; - - case LVN_COLUMNCLICK: - LPNMLISTVIEW lv = (LPNMLISTVIEW)lParam; - ColumnsSortParams params; - params.hList = hwndResults; - params.column = lv->iSubItem; - params.last = lastColumn; - ListView_SortItemsEx(params.hList, ColumnsCompare, (LPARAM)¶ms); - lastColumn = (params.column == lastColumn) ? -1 : params.column; - break; - } // switch - break; - - case WM_DESTROY: - ListView_DeleteAllItems(hwndResults); - saveListSettings(hwndResults, csResultList); - Utils_SaveWindowPosition(hwnd, NULL, MODULENAME, "Search_"); - break; - } - return 0; + // on empty string strstr() returns full string while StrStrI() returns NULL + return (options & F_CASE) ? (INT_PTR)strstr(text, search) : (INT_PTR)StrStrIA(text, search); } -void newFindWindow() +static int FindMatchW(const wchar_t *text, wchar_t *search, int options) { - CreateDialog(g_plugin.getInst(), MAKEINTRESOURCE(IDD_FIND), hwnd2mainWindow, FindWindowDlgProc); -} - -void ItemFound(HWND hwnd, MCONTACT hContact, const char *module, const char *setting, wchar_t *value, int type) -{ - wchar_t name[NAME_SIZE]; - wchar_t *mode; - - if (type & F_REPLACED) - mode = TranslateT("Replaced"); - else if (type & F_DELETED) - mode = TranslateT("Deleted"); - else - mode = TranslateT("Found"); - - GetContactName(hContact, nullptr, name, _countof(name)); - - LVITEM lvi = {}; - lvi.mask = LVIF_PARAM; - lvi.lParam = (LPARAM)hContact; - - int index = ListView_InsertItem(hwnd, &lvi); - ListView_SetItemText(hwnd, index, 0, mode); - ListView_SetItemText(hwnd, index, 1, name); - - ListView_SetItemTextA(hwnd, index, 2, module); - - int F_type = type & 0xFF; + if (!search[0] && (!(options & F_EXACT) || !text[0])) + return 1; - if (F_type == F_SETNAME || F_type == F_SETVAL) - ListView_SetItemTextA(hwnd, index, 3, setting); + if (options & F_EXACT) + return (options & F_CASE) ? !wcscmp(text, search) : !wcsicmp(text, search); - if (F_type == F_SETVAL && value) - ListView_SetItemText(hwnd, index, 4, value); + // on empty string strstr() returns full string while StrStrI() returns NULL + return (options & F_CASE) ? (INT_PTR)wcsstr(text, search) : (INT_PTR)StrStrIW(text, search); } +///////////////////////////////////////////////////////////////////////////////////////// -char *multiReplaceA(const char *value, const char *search, const char *replace, int cs) +static char* multiReplaceA(const char *value, const char *search, const char *replace, int cs) { int slen = (int)mir_strlen(search); int rlen = (int)mir_strlen(replace); int vlen = (int)mir_strlen(value); int ci = slen ? cs : 1; // on empty string strstr() returns full string while StrStrI() returns NULL - // let's try to calculate maximum length for result string + // let's try to calculate maximum length for result string int newlen = (!slen) ? rlen + 1 : ((rlen <= slen) ? vlen + 1 : vlen * rlen / slen + 1); char *head; @@ -262,21 +66,20 @@ char *multiReplaceA(const char *value, const char *search, const char *replace, return out; } -WCHAR *multiReplaceW(const WCHAR *value, const WCHAR *search, const WCHAR *replace, int cs) +static wchar_t* multiReplaceW(const wchar_t *value, const wchar_t *search, const wchar_t *replace, int cs) { int slen = (int)mir_wstrlen(search); int rlen = (int)mir_wstrlen(replace); int vlen = (int)mir_wstrlen(value); int ci = slen ? cs : 1; // on empty string strstr() returns full string while StrStrI() returns NULL - // let's try to calculate maximum length for result string + // let's try to calculate maximum length for result string int newlen = (!slen) ? rlen + 1 : ((rlen <= slen) ? vlen + 1 : vlen * rlen / slen + 1); - WCHAR *head; - WCHAR *in = (WCHAR *)value; - WCHAR *out = (WCHAR *)mir_alloc(newlen * sizeof(WCHAR)); + wchar_t *in = (wchar_t *)value; + wchar_t *out = (wchar_t *)mir_alloc(newlen * sizeof(wchar_t)); out[0] = 0; - while (head = ci ? wcsstr(in, search) : StrStrIW(in, search)) { + while (wchar_t *head = ci ? wcsstr(in, search) : StrStrIW(in, search)) { if (head != in) mir_wstrncat(out, in, head - in + 1); in = head + slen; @@ -287,278 +90,458 @@ WCHAR *multiReplaceW(const WCHAR *value, const WCHAR *search, const WCHAR *repla return out; } +///////////////////////////////////////////////////////////////////////////////////////// -int FindMatchA(const char *text, char *search, int options) -{ - if (!search[0] && (!(options & F_EXACT) || !text[0])) - return 1; - - if (options & F_EXACT) - return (options & F_CASE) ? !strcmp(text, search) : !stricmp(text, search); - - // on empty string strstr() returns full string while StrStrI() returns NULL - return (options & F_CASE) ? (INT_PTR)strstr(text, search) : (INT_PTR)StrStrIA(text, search); -} - - -int FindMatchW(const WCHAR *text, WCHAR *search, int options) +static ColumnsSettings csResultList[] = { - if (!search[0] && (!(options & F_EXACT) || !text[0])) - return 1; - - if (options & F_EXACT) - return (options & F_CASE) ? !wcscmp(text, search) : !wcsicmp(text, search); - - // on empty string strstr() returns full string while StrStrI() returns NULL - return (options & F_CASE) ? (INT_PTR)wcsstr(text, search) : (INT_PTR)StrStrIW(text, search); -} - + { LPGENW("Result"), 0, "Search0width", 100 }, + { LPGENW("Contact"), 1, "Search1width", 100 }, + { LPGENW("Module"), 2, "Search2width", 100 }, + { LPGENW("Setting"), 3, "Search3width", 100 }, + { LPGENW("Value"), 4, "Search4width", 150 }, + { nullptr } +}; -void fi_free(FindInfo *fi) +class CFindWindowDlg : public CDlgBase { - mir_free(fi->search); - mir_free(fi->replace); - mir_free(fi); -} + struct FindInfo + { + CFindWindowDlg *pDlg; // hwnd to item list + int options; // or'd about items + ptrW search; // text to find + ptrW replace; // text to replace + }; + bool bSearchActive = false, bFirstMatch = false; + int lastColumn = -1; -void __cdecl FindSettings(LPVOID param) -{ - FindInfo *fi = (FindInfo *)param; - HWND hwndParent = GetParent(fi->hwnd); + static void __cdecl FindSettings(LPVOID param) + { + FindInfo *fi = (FindInfo *)param; + auto *pDlg = fi->pDlg; + pDlg->bSearchActive = pDlg->bFirstMatch = true; - ModuleSettingLL ModuleList, SettingList; - ModSetLinkLinkItem *module, *setting; + ModuleSettingLL ModuleList, SettingList; + ModSetLinkLinkItem *module, *setting; - MCONTACT hContact; - DBVARIANT dbv = {}; + MCONTACT hContact; + DBVARIANT dbv = {}; - int foundCount = 0, replaceCount = 0, deleteCount = 0; + int foundCount = 0, replaceCount = 0, deleteCount = 0; - DWORD numsearch = 0, numreplace = 0; - int NULLContactDone = 0; + DWORD numsearch = 0, numreplace = 0; + int NULLContactDone = 0; - if (!fi->search || !EnumModules(&ModuleList)) { - fi_free(fi); - return; - } + if (!fi->search || !EnumModules(&ModuleList)) { + delete fi; + return; + } - _T2A search(fi->search); - _T2A replace(fi->replace); + _T2A search(fi->search); + _T2A replace(fi->replace); - // skip modules and setting names on unicode search or replace - if (IsRealUnicode(fi->search) || IsRealUnicode(fi->replace)) { - fi->options &= ~(F_SETNAME | F_MODNAME); - fi->options |= F_UNICODE; - } + // skip modules and setting names on unicode search or replace + if (IsRealUnicode(fi->search) || IsRealUnicode(fi->replace)) { + fi->options &= ~(F_SETNAME | F_MODNAME); + fi->options |= F_UNICODE; + } - if (!(fi->options & F_UNICODE) && (fi->options & F_SETVAL)) { - char val[16]; - numsearch = strtoul(search, nullptr, 10); - _ultoa(numsearch, val, 10); - if (!mir_strcmp(search, val)) { - fi->options |= F_NUMSRCH; - // replace numeric values only entirely - if (replace && (fi->options & F_ENTIRE)) { - numreplace = strtoul(replace, nullptr, 10); - _ultoa(numreplace, val, 10); - if (!replace[0] || !mir_strcmp(replace, val)) - fi->options |= F_NUMREPL; + if (!(fi->options & F_UNICODE) && (fi->options & F_SETVAL)) { + char val[16]; + numsearch = strtoul(search, nullptr, 10); + _ultoa(numsearch, val, 10); + if (!mir_strcmp(search, val)) { + fi->options |= F_NUMSRCH; + // replace numeric values only entirely + if (replace && (fi->options & F_ENTIRE)) { + numreplace = strtoul(replace, nullptr, 10); + _ultoa(numreplace, val, 10); + if (!replace[0] || !mir_strcmp(replace, val)) + fi->options |= F_NUMREPL; + } } } - } - SendDlgItemMessage(hwndParent, IDC_SBAR, SB_SETTEXT, 0, (LPARAM)TranslateT("Searching...")); + pDlg->m_sb.SendMsg(SB_SETTEXT, 0, (LPARAM)TranslateT("Searching...")); - hContact = 0; + hContact = 0; - while (GetWindowLongPtr(GetDlgItem(hwndParent, IDC_SEARCH), GWLP_USERDATA)) { + while (pDlg->bSearchActive) { - if (!hContact) { - if (NULLContactDone) - break; - else { - NULLContactDone = 1; - hContact = db_find_first(); + if (!hContact) { + if (NULLContactDone) + break; + else { + NULLContactDone = 1; + hContact = db_find_first(); + } } - } - else hContact = db_find_next(hContact); - - for (module = ModuleList.first; module; module = module->next) { + else hContact = db_find_next(hContact); - if (IsModuleEmpty(hContact, module->name)) - continue; + for (module = ModuleList.first; module; module = module->next) { - if (fi->options & (F_SETVAL | F_SETNAME)) { + if (IsModuleEmpty(hContact, module->name)) + continue; - if (!EnumSettings(hContact, module->name, &SettingList)) { - fi_free(fi); - FreeModuleSettingLL(&ModuleList); - return; - } + if (fi->options & (F_SETVAL | F_SETNAME)) { - for (setting = SettingList.first; setting; setting = setting->next) { + if (!EnumSettings(hContact, module->name, &SettingList)) { + delete fi; + FreeModuleSettingLL(&ModuleList); + return; + } - dbv.type = 0; - if (db_get_s(hContact, module->name, setting->name, &dbv, 0)) - continue; + for (setting = SettingList.first; setting; setting = setting->next) { - // check in settings value - if (fi->options & F_SETVAL) { + dbv.type = 0; + if (db_get_s(hContact, module->name, setting->name, &dbv, 0)) + continue; - wchar_t *value = nullptr; + // check in settings value + if (fi->options & F_SETVAL) { - switch (dbv.type) { + wchar_t *value = nullptr; - case DBVT_BYTE: - case DBVT_WORD: - case DBVT_DWORD: - if ((fi->options & F_NUMSRCH) && numsearch == getNumericValue(&dbv)) { - wchar_t *val = fi->search; - int flag = F_SETVAL; + switch (dbv.type) { + case DBVT_BYTE: + case DBVT_WORD: + case DBVT_DWORD: + if ((fi->options & F_NUMSRCH) && numsearch == getNumericValue(&dbv)) { + wchar_t *val = fi->search; + int flag = F_SETVAL; - if (fi->options & F_NUMREPL) { - if (replace[0]) { - db_unset(hContact, module->name, setting->name); - flag |= F_DELETED; - deleteCount++; - } - else - if (setNumericValue(hContact, module->name, setting->name, numreplace, dbv.type)) { + if (fi->options & F_NUMREPL) { + if (replace[0]) { + db_unset(hContact, module->name, setting->name); + flag |= F_DELETED; + deleteCount++; + } + else if (setNumericValue(hContact, module->name, setting->name, numreplace, dbv.type)) { val = fi->replace; flag |= F_REPLACED; replaceCount++; } + } + + pDlg->ItemFound(hContact, module->name, setting->name, val, flag); } + break; + + case DBVT_WCHAR: + if (!value) value = mir_wstrdup(dbv.pwszVal); + __fallthrough; + case DBVT_UTF8: + if (!value) value = mir_utf8decodeW(dbv.pszVal); + __fallthrough; + case DBVT_ASCIIZ: + if (!value) value = mir_a2u(dbv.pszVal); + + if (FindMatchW(value, fi->search, fi->options)) { + foundCount++; + ptrW ptr; + wchar_t *newValue = value; + int flag = F_SETVAL; + + if (fi->replace) { + newValue = (fi->options & F_ENTIRE) ? fi->replace : ptr = multiReplaceW(value, fi->search, fi->replace, fi->options & F_CASE); + // !!!! delete or make empty ? + if (!newValue[0]) { + db_unset(hContact, module->name, setting->name); + flag |= F_DELETED; + newValue = value; + deleteCount++; + } + else { + // save as unicode if needed + if (dbv.type != DBVT_ASCIIZ || IsRealUnicode(newValue)) + db_set_ws(hContact, module->name, setting->name, newValue); + else + db_set_s(hContact, module->name, setting->name, _T2A(newValue)); + flag |= F_REPLACED; + replaceCount++; + } + } - ItemFound(fi->hwnd, hContact, module->name, setting->name, val, flag); - } - break; - - case DBVT_WCHAR: - if (!value) value = mir_wstrdup(dbv.pwszVal); - case DBVT_UTF8: - if (!value) value = mir_utf8decodeW(dbv.pszVal); - case DBVT_ASCIIZ: - if (!value) value = mir_a2u(dbv.pszVal); - - if (FindMatchW(value, fi->search, fi->options)) { - foundCount++; - ptrW ptr; - wchar_t *newValue = value; - int flag = F_SETVAL; - - if (fi->replace) { - newValue = (fi->options & F_ENTIRE) ? fi->replace : ptr = multiReplaceW(value, fi->search, fi->replace, fi->options & F_CASE); - // !!!! delete or make empty ? - if (!newValue[0]) { + pDlg->ItemFound(hContact, module->name, setting->name, newValue, flag); + } + mir_free(value); + break; + } // switch + } + + // check in setting name + if ((fi->options & F_SETNAME) && FindMatchA(setting->name, search, fi->options)) { + foundCount++; + ptrA ptr; + char *newSetting = setting->name; + int flag = F_SETNAME; + + if (replace) { + newSetting = (fi->options & F_ENTIRE) ? replace : ptr = multiReplaceA(setting->name, search, replace, fi->options & F_CASE); + if (!newSetting[0]) { + db_unset(hContact, module->name, setting->name); + flag |= F_DELETED; + newSetting = setting->name; + deleteCount++; + } + else { + DBVARIANT dbv2; + // skip if exist + if (!db_get_s(hContact, module->name, newSetting, &dbv2, 0)) + db_free(&dbv2); + else if (!db_set(hContact, module->name, newSetting, &dbv)) { db_unset(hContact, module->name, setting->name); - flag |= F_DELETED; - newValue = value; - deleteCount++; - } - else { - // save as unicode if needed - if (dbv.type != DBVT_ASCIIZ || IsRealUnicode(newValue)) - db_set_ws(hContact, module->name, setting->name, newValue); - else - db_set_s(hContact, module->name, setting->name, _T2A(newValue)); flag |= F_REPLACED; replaceCount++; } } - - ItemFound(fi->hwnd, hContact, module->name, setting->name, newValue, flag); } - mir_free(value); - break; - } // switch - } - // check in setting name - if ((fi->options & F_SETNAME) && FindMatchA(setting->name, search, fi->options)) { - foundCount++; - ptrA ptr; - char *newSetting = setting->name; - int flag = F_SETNAME; - - if (replace) { - newSetting = (fi->options & F_ENTIRE) ? replace : ptr = multiReplaceA(setting->name, search, replace, fi->options & F_CASE); - - if (!newSetting[0]) { - db_unset(hContact, module->name, setting->name); - flag |= F_DELETED; - newSetting = setting->name; - deleteCount++; - } - else { - DBVARIANT dbv2; - // skip if exist - if (!db_get_s(hContact, module->name, newSetting, &dbv2, 0)) - db_free(&dbv2); - else if (!db_set(hContact, module->name, newSetting, &dbv)) { - db_unset(hContact, module->name, setting->name); - flag |= F_REPLACED; - replaceCount++; - } - } + pDlg->ItemFound(hContact, module->name, newSetting, nullptr, flag); } - ItemFound(fi->hwnd, hContact, module->name, newSetting, nullptr, flag); - } - - db_free(&dbv); + db_free(&dbv); - } // for(setting) + } // for(setting) - FreeModuleSettingLL(&SettingList); - } + FreeModuleSettingLL(&SettingList); + } - // check in module name - if ((fi->options & F_MODNAME) && FindMatchA(module->name, search, fi->options)) { - foundCount++; - char *newModule = module->name; - int flag = F_MODNAME; - ptrA ptr; - - if (replace) { - newModule = (fi->options & F_ENTIRE) ? replace : ptr = multiReplaceA(module->name, search, replace, fi->options & F_CASE); - - if (!newModule[0]) { - deleteModule(hContact, module->name, 0); - replaceTreeItem(hContact, module->name, nullptr); - flag |= F_DELETED; - newModule = module->name; - deleteCount++; - } - else if (renameModule(hContact, module->name, newModule)) { - replaceTreeItem(hContact, module->name, nullptr); - flag |= F_REPLACED; - replaceCount++; + // check in module name + if ((fi->options & F_MODNAME) && FindMatchA(module->name, search, fi->options)) { + foundCount++; + char *newModule = module->name; + int flag = F_MODNAME; + ptrA ptr; + + if (replace) { + newModule = (fi->options & F_ENTIRE) ? replace : ptr = multiReplaceA(module->name, search, replace, fi->options & F_CASE); + if (!newModule[0]) { + deleteModule(hContact, module->name, 0); + replaceTreeItem(hContact, module->name, nullptr); + flag |= F_DELETED; + newModule = module->name; + deleteCount++; + } + else if (renameModule(hContact, module->name, newModule)) { + replaceTreeItem(hContact, module->name, nullptr); + flag |= F_REPLACED; + replaceCount++; + } } + + pDlg->ItemFound(hContact, newModule, nullptr, nullptr, flag); } + } // for(module) + } - ItemFound(fi->hwnd, hContact, newModule, nullptr, nullptr, flag); - } - } // for(module) + wchar_t msg[MSG_SIZE]; + mir_snwprintf(msg, TranslateT("Finished. Items found: %d / replaced: %d / deleted: %d"), foundCount, replaceCount, deleteCount); + pDlg->m_sb.SendMsg(SB_SETTEXT, 0, (LPARAM)msg); + + if (fi->replace) { + pDlg->btnReplace.SetText(TranslateT("&Replace")); + pDlg->btnSearch.Enable(1); + } + else { + pDlg->btnSearch.SetText(TranslateT("&Search")); + pDlg->btnReplace.Enable(); + } + + delete fi; + FreeModuleSettingLL(&ModuleList); + + pDlg->bSearchActive = false; + EnableWindow(GetDlgItem(pDlg->GetHwnd(), IDCANCEL), 1); } - wchar_t msg[MSG_SIZE]; - mir_snwprintf(msg, TranslateT("Finished. Items found: %d / replaced: %d / deleted: %d"), foundCount, replaceCount, deleteCount); - SendDlgItemMessage(hwndParent, IDC_SBAR, SB_SETTEXT, 0, (LPARAM)msg); + void ItemFound(MCONTACT hContact, const char *module, const char *setting, wchar_t *value, int type) + { + if (bFirstMatch) { + SetFocus(m_results.GetHwnd()); + bFirstMatch = false; + } + + wchar_t *mode; + if (type & F_REPLACED) + mode = TranslateT("Replaced"); + else if (type & F_DELETED) + mode = TranslateT("Deleted"); + else + mode = TranslateT("Found"); + + wchar_t name[NAME_SIZE]; + GetContactName(hContact, nullptr, name, _countof(name)); + + LVITEM lvi = {}; + lvi.mask = LVIF_PARAM; + lvi.lParam = (LPARAM)hContact; + + int index = m_results.InsertItem(&lvi); + m_results.SetItemText(index, 0, mode); + m_results.SetItemText(index, 1, name); + m_results.SetItemText(index, 2, _A2T(module)); + + int F_type = type & 0xFF; - if (fi->replace) { - EnableWindow(GetDlgItem(hwndParent, IDC_SEARCH), 1); - SetDlgItemText(hwndParent, IDOK, TranslateT("&Replace")); + if (F_type == F_SETNAME || F_type == F_SETVAL) + m_results.SetItemText(index, 3, _A2T(setting)); + + if (F_type == F_SETVAL && value) + m_results.SetItemText(index, 4, value); + } + + CCtrlBase m_sb; + CCtrlButton btnSearch, btnReplace; + CCtrlListView m_results; + +public: + CFindWindowDlg(HWND hwndParent) : + CDlgBase(g_plugin, IDD_FIND), + m_sb(this, IDC_SBAR), + m_results(this, IDC_LIST), + btnReplace(this, IDOK), + btnSearch(this, IDC_SEARCH) + { + SetParent(hwndParent); + SetMinSize(610, 300); + + btnSearch.OnClick = Callback(this, &CFindWindowDlg::onClick_Search); + } + + bool OnInitDialog() override + { + m_sb.SendMsg(SB_SETTEXT, 0, (LPARAM)TranslateT("Enter a string to search the database for")); + CheckDlgButton(m_hwnd, IDC_MODNAME, BST_CHECKED); + CheckDlgButton(m_hwnd, IDC_SETTINGNAME, BST_CHECKED); + CheckDlgButton(m_hwnd, IDC_SETTINGVALUE, BST_CHECKED); + CheckDlgButton(m_hwnd, IDC_FOUND, BST_CHECKED); + SendMessage(m_hwnd, WM_SETICON, ICON_BIG, (LPARAM)LoadIcon(g_plugin.getInst(), MAKEINTRESOURCE(ICO_REGEDIT))); + SetWindowLong(m_hwnd, GWL_EXSTYLE, GetWindowLong(m_hwnd, GWL_EXSTYLE) | WS_EX_APPWINDOW); // taskbar icon + m_results.SetExtendedListViewStyle(32 | LVS_EX_LABELTIP); // LVS_EX_GRIDLINES + loadListSettings(m_results.GetHwnd(), csResultList); + Utils_RestoreWindowPositionNoMove(m_hwnd, NULL, MODULENAME, "Search_"); + return true; + } + + bool OnApply() override + { + onClick_Search(0); + return false; } - else { - SetDlgItemText(hwndParent, IDC_SEARCH, TranslateT("&Search")); - EnableWindow(GetDlgItem(hwndParent, IDOK), 1); + + void OnDestroy() override + { + m_results.DeleteAllItems(); + saveListSettings(m_results.GetHwnd(), csResultList); + Utils_SaveWindowPosition(m_hwnd, NULL, MODULENAME, "Search_"); } - fi_free(fi); - FreeModuleSettingLL(&ModuleList); + int Resizer(UTILRESIZECONTROL *urc) override + { + switch (urc->wId) { + case IDC_LIST: + return RD_ANCHORX_WIDTH | RD_ANCHORY_HEIGHT; + case IDC_SBAR: + return RD_ANCHORX_WIDTH | RD_ANCHORY_BOTTOM; + } + return RD_ANCHORX_LEFT | RD_ANCHORY_TOP; + } - SetWindowLongPtr(GetDlgItem(hwndParent, IDC_SEARCH), GWLP_USERDATA, 0); - EnableWindow(GetDlgItem(hwndParent, IDCANCEL), 1); + void onClick_Search(CCtrlButton *pButton) + { + // stop the search, if it's active + if (bSearchActive) { + bSearchActive = false; + return; + } + + wchar_t text[FLD_SIZE]; + if (!GetDlgItemText(m_hwnd, IDC_TEXT, text, _countof(text)) && !IsDlgButtonChecked(m_hwnd, IDC_EXACT)) + return; + + // empty replace is done only for exact match or entire replace + wchar_t replace[FLD_SIZE] = {}; + if (pButton->GetCtrlId() == IDOK && + !GetDlgItemText(m_hwnd, IDC_REPLACE, replace, _countof(replace)) && + (!IsDlgButtonChecked(m_hwnd, IDC_ENTIRELY) && !IsDlgButtonChecked(m_hwnd, IDC_EXACT))) + return; + + if (BST_UNCHECKED == IsDlgButtonChecked(m_hwnd, IDC_MODNAME) && + BST_UNCHECKED == IsDlgButtonChecked(m_hwnd, IDC_SETTINGNAME) && + BST_UNCHECKED == IsDlgButtonChecked(m_hwnd, IDC_SETTINGVALUE)) + return; + + FindInfo *fi = new FindInfo(); + fi->pDlg = this; + fi->options = (IsDlgButtonChecked(m_hwnd, IDC_CASESENSITIVE) ? F_CASE : 0) | + (IsDlgButtonChecked(m_hwnd, IDC_EXACT) ? F_EXACT : 0) | + (IsDlgButtonChecked(m_hwnd, IDC_MODNAME) ? F_MODNAME : 0) | + (IsDlgButtonChecked(m_hwnd, IDC_SETTINGNAME) ? F_SETNAME : 0) | + (IsDlgButtonChecked(m_hwnd, IDC_SETTINGVALUE) ? F_SETVAL : 0); + + if (pButton->GetCtrlId() == IDOK) { + if (IsDlgButtonChecked(m_hwnd, IDC_ENTIRELY)) + fi->options |= F_ENTIRE; + + fi->replace = mir_wstrdup(replace); + + btnReplace.SetText(TranslateT("Stop")); + btnSearch.Disable(); + + } + else { + btnSearch.SetText(TranslateT("Stop")); + btnReplace.Disable(); + } + + fi->search = mir_wstrdup(text); + + m_results.DeleteAllItems(); + + EnableWindow(GetDlgItem(m_hwnd, IDCANCEL), 0); + mir_forkthread(FindSettings, fi); + } + + void onDblClick_List(CCtrlListView::TEventInfo *ev) + { + LVHITTESTINFO hti; + LVITEM lvi; + hti.pt = ev->nmlv->ptAction; + if (m_results.SubItemHitTest(&hti) == -1) + return; + + if (hti.flags & LVHT_ONITEM) { + lvi.mask = LVIF_PARAM; + lvi.iItem = hti.iItem; + lvi.iSubItem = 0; + if (m_results.GetItem(&lvi)) { + ItemInfo ii = {}; + ii.hContact = (MCONTACT)lvi.lParam; + ListView_GetItemTextA(m_results.GetHwnd(), hti.iItem, 2, ii.module, _countof(ii.module)); + ListView_GetItemTextA(m_results.GetHwnd(), hti.iItem, 3, ii.setting, _countof(ii.setting)); + if (ii.setting[0]) + ii.type = FW_SETTINGNAME; + else if (ii.module[0]) + ii.type = FW_MODULE; + + SendMessage(hwnd2mainWindow, WM_FINDITEM, (WPARAM)&ii, 0); + } + } + } + + void onColumnClick_List(CCtrlListView::TEventInfo *ev) + { + ColumnsSortParams params; + params.hList = m_results.GetHwnd(); + params.column = ev->nmlv->iSubItem; + params.last = lastColumn; + ListView_SortItemsEx(params.hList, ColumnsCompare, (LPARAM)¶ms); + lastColumn = (params.column == lastColumn) ? -1 : params.column; + } +}; + +void newFindWindow() +{ + (new CFindWindowDlg(hwnd2mainWindow))->Create(); } diff --git a/plugins/DbEditorPP/src/stdafx.h b/plugins/DbEditorPP/src/stdafx.h index afe1a23d68..0bdf7d8b05 100644 --- a/plugins/DbEditorPP/src/stdafx.h +++ b/plugins/DbEditorPP/src/stdafx.h @@ -212,7 +212,7 @@ int setNumericValue(MCONTACT hContact, const char *module, const char *setting, int IsRealUnicode(wchar_t *value); int setTextValue(MCONTACT hContact, const char *module, const char *setting, wchar_t *value, int type); int GetValueA(MCONTACT hContact, const char *module, const char *setting, char *value, int length); -int GetValueW(MCONTACT hContact, const char *module, const char *setting, WCHAR *value, int length); +int GetValueW(MCONTACT hContact, const char *module, const char *setting, wchar_t *value, int length); int GetContactName(MCONTACT hContact, const char *proto, wchar_t *value, int maxlen); int ApplyProtoFilter(MCONTACT hContact); void loadListSettings(HWND hwnd, ColumnsSettings *cs); diff --git a/plugins/DbEditorPP/src/utils.cpp b/plugins/DbEditorPP/src/utils.cpp index 7861e66266..f6d394c8bf 100644 --- a/plugins/DbEditorPP/src/utils.cpp +++ b/plugins/DbEditorPP/src/utils.cpp @@ -175,7 +175,7 @@ int GetValueA(MCONTACT hContact, const char *module, const char *setting, char * return 0; } -int GetValueW(MCONTACT hContact, const char *module, const char *setting, WCHAR *value, int length) +int GetValueW(MCONTACT hContact, const char *module, const char *setting, wchar_t *value, int length) { DBVARIANT dbv = {}; diff --git a/plugins/DbEditorPP/src/version.h b/plugins/DbEditorPP/src/version.h index 5d41638d3e..0c5cea7c4e 100644 --- a/plugins/DbEditorPP/src/version.h +++ b/plugins/DbEditorPP/src/version.h @@ -1,7 +1,7 @@ #define __MAJOR_VERSION 4 #define __MINOR_VERSION 0 #define __RELEASE_NUM 2 -#define __BUILD_NUM 2 +#define __BUILD_NUM 3 #include -- cgit v1.2.3