diff options
author | George Hazan <ghazan@miranda.im> | 2021-03-06 17:46:30 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2021-03-06 17:46:30 +0300 |
commit | 975f5ad99a5e76c31da953602cc47e1003d0e152 (patch) | |
tree | 2caf8778db2b5bafdbef6527d9470fbb719e768a | |
parent | 4ac0593c310cc0e0af4e69bbbc5c6628647a5125 (diff) |
Clist_blind: last version that still works on ListBox
-rw-r--r-- | plugins/Clist_blind/Clist_blind.vcxproj | 2 | ||||
-rw-r--r-- | plugins/Clist_blind/Clist_blind.vcxproj.filters | 6 | ||||
-rw-r--r-- | plugins/Clist_blind/src/clc.cpp | 359 | ||||
-rw-r--r-- | plugins/Clist_blind/src/init.cpp | 514 | ||||
-rw-r--r-- | plugins/Clist_blind/src/stdafx.h | 11 | ||||
-rw-r--r-- | plugins/Clist_blind/src/utils.cpp | 41 |
6 files changed, 411 insertions, 522 deletions
diff --git a/plugins/Clist_blind/Clist_blind.vcxproj b/plugins/Clist_blind/Clist_blind.vcxproj index ed657001e8..6dd83304ae 100644 --- a/plugins/Clist_blind/Clist_blind.vcxproj +++ b/plugins/Clist_blind/Clist_blind.vcxproj @@ -30,6 +30,7 @@ <Import Project="$(ProjectDir)..\..\build\vc.common\plugin.props" />
</ImportGroup>
<ItemGroup>
+ <ClCompile Include="src\clc.cpp" />
<ClCompile Include="src\clcopts.cpp" />
<ClCompile Include="src\clcpaint.cpp" />
<ClCompile Include="src\clistmenus.cpp" />
@@ -40,6 +41,7 @@ <ClCompile Include="src\stdafx.cxx">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
+ <ClCompile Include="src\utils.cpp" />
<ClInclude Include="src\clc.h" />
<ClInclude Include="src\resource.h" />
<ClInclude Include="src\stdafx.h" />
diff --git a/plugins/Clist_blind/Clist_blind.vcxproj.filters b/plugins/Clist_blind/Clist_blind.vcxproj.filters index c44e8c2ff5..3c7308f11c 100644 --- a/plugins/Clist_blind/Clist_blind.vcxproj.filters +++ b/plugins/Clist_blind/Clist_blind.vcxproj.filters @@ -26,6 +26,12 @@ <ClCompile Include="src\stdafx.cxx">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="src\utils.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\clc.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\clc.h">
diff --git a/plugins/Clist_blind/src/clc.cpp b/plugins/Clist_blind/src/clc.cpp new file mode 100644 index 0000000000..49d68bd1a9 --- /dev/null +++ b/plugins/Clist_blind/src/clc.cpp @@ -0,0 +1,359 @@ +/* +Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org) + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation version 2 +of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "stdafx.h" + +void PaintClc(HWND hwnd, ClcData *dat, HDC hdc, RECT *rcPaint); + +///////////////////////////////////////////////////////////////////////////////////////// + +wchar_t status_name[128]; +static wchar_t* GetStatusName(struct ClcContact *item) +{ + status_name[0] = '\0'; + if (item->hContact == NULL || item->pce->szProto == nullptr) + return status_name; + + // Get XStatusName + MyDBGetContactSettingTString(item->hContact, item->pce->szProto, "XStatusName", status_name, _countof(status_name), nullptr); + if (status_name[0] != '\0') + return status_name; + + // Get status name + int status = db_get_w(item->hContact, item->pce->szProto, "Status", ID_STATUS_OFFLINE); + mir_wstrncpy(status_name, Clist_GetStatusModeDescription(status, 0), _countof(status_name)); + return status_name; +} + +wchar_t status_message[256]; +static wchar_t* GetStatusMessage(struct ClcContact *item) +{ + status_message[0] = '\0'; + if (item->hContact == NULL || item->pce->szProto == nullptr) + return status_message; + + // Get XStatusMsg + MyDBGetContactSettingTString(item->hContact, item->pce->szProto, "XStatusMsg", status_message, _countof(status_message), nullptr); + if (status_message[0] != '\0') + return status_message; + + // Get status message + MyDBGetContactSettingTString(item->hContact, "CList", "StatusMsg", status_message, _countof(status_message), nullptr); + return status_message; +} + +wchar_t proto_name[128]; +static wchar_t* GetProtoName(struct ClcContact *item) +{ + proto_name[0] = '\0'; + if (item->hContact == NULL || item->pce->szProto == nullptr) { + mir_wstrncpy(proto_name, TranslateT("Unknown protocol"), _countof(proto_name)); + return proto_name; + } + + PROTOACCOUNT *acc = Proto_GetAccount(item->pce->szProto); + if (acc == nullptr) { + char description[128]; + CallProtoService(item->pce->szProto, PS_GETNAME, sizeof(description), (LPARAM)description); + mir_snwprintf(proto_name, L"%S", description); + return proto_name; + } + + mir_wstrncpy(proto_name, acc->tszAccountName, _countof(proto_name)); + return proto_name; +} + +static void RebuildEntireListInternal(HWND hwnd, ClcData *tmp_dat, BOOL call_orig) +{ + ClcData *dat = (ClcData *)tmp_dat; + wchar_t tmp[1024]; + wchar_t template_contact[1024]; + wchar_t template_group[1024]; + wchar_t template_divider[1024]; + wchar_t template_info[1024]; + int selection = dat->selection; + BOOL has_focus = (GetFocus() == dat->hwnd_list || GetFocus() == hwnd); + + if (call_orig) + coreCli.pfnRebuildEntireList(hwnd, (ClcData *)dat); + + MyDBGetContactSettingTString(NULL, "CLC", "TemplateContact", template_contact, 1024, TranslateT("%name% [%status% %protocol%] %status_message%")); + MyDBGetContactSettingTString(NULL, "CLC", "TemplateGroup", template_group, 1024, TranslateT("Group: %name% %count% [%mode%]")); + MyDBGetContactSettingTString(NULL, "CLC", "TemplateDivider", template_divider, 1024, TranslateT("Divider: %s")); + MyDBGetContactSettingTString(NULL, "CLC", "TemplateInfo", template_info, 1024, TranslateT("Info: %s")); + + SendMessage(dat->hwnd_list, WM_SETREDRAW, FALSE, 0); + + // Reset content + SendMessage(dat->hwnd_list, LB_RESETCONTENT, 0, 0); + + // Set font + SendMessage(dat->hwnd_list, WM_SETFONT, (WPARAM)dat->fontInfo[FONTID_CONTACTS].hFont, 0); + + // Add all items to the list + ClcGroup *group = &dat->list; + group->scanIndex = 0; + + wchar_t *text = tmp; + size_t size = _countof(tmp); + while (true) { + if (group->scanIndex == group->cl.getCount()) { + if ((group = group->parent) == nullptr) + break; + text -= 2; + size += 2; + group->scanIndex++; + continue; + } + + ClcContact *item = group->cl[group->scanIndex]; + text[0] = '\0'; + switch (item->type) { + case CLCIT_GROUP: + { + CMStringW wszText(template_group); + wszText.Replace(L"%name%", item->szText); + wszText.Replace(L"%mode%", item->group->expanded ? TranslateT("Expanded") : TranslateT("Collapsed")); + + wchar_t *szCounts = Clist_GetGroupCountsText(dat, item); + wchar_t count[128]; + if (szCounts[0] != '\0') + mir_snwprintf(count, L"%s ", szCounts); + else + count[0] = '\0'; + wszText.Replace(L"%count%", count); + + if (!wszText.IsEmpty()) + mir_wstrncpy(text, wszText, size); + } + break; + + case CLCIT_CONTACT: + { + CMStringW wszText(template_contact); + wszText.Replace(L"%name%", item->szText); + wszText.Replace(L"%status%", GetStatusName(item)); + wszText.Replace(L"%protocol%", GetProtoName(item)); + wszText.Replace(L"%status_message%", GetStatusMessage(item)); + + if (!wszText.IsEmpty()) + mir_wstrncpy(text, wszText, size); + } + break; + + case CLCIT_DIVIDER: + mir_snwprintf(text, size, template_divider, item->szText); + break; + + case CLCIT_INFO: + mir_snwprintf(text, size, template_info, item->szText); + break; + } + + SendMessage(dat->hwnd_list, LB_ADDSTRING, 0, (LPARAM)tmp); + + if (item->type == CLCIT_GROUP && item->group->expanded) { + group = item->group; + text[0] = ' '; + text[1] = ' '; + text += 2; + size -= 2; + group->scanIndex = 0; + continue; + } + group->scanIndex++; + } + + SendMessage(dat->hwnd_list, WM_SETREDRAW, TRUE, 0); + InvalidateRect(dat->hwnd_list, nullptr, TRUE); + + dat->selection = selection; + SendMessage(dat->hwnd_list, LB_SETCURSEL, dat->selection, 0); + if (has_focus) + SetFocus(dat->hwnd_list); + + dat->need_rebuild = FALSE; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +static LRESULT CALLBACK ContactListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_NCCREATE: + return DefWindowProc(hwnd, msg, wParam, lParam); + + case WM_CREATE: + break; + + case WM_DRAWITEM: + return Menu_DrawItem(lParam); + } + return coreCli.pfnContactListWndProc(hwnd, msg, wParam, lParam); +} + +static LRESULT CALLBACK ContactListControlSubclass(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + if (msg == WM_CHAR) { + coreCli.pfnContactListControlWndProc(GetParent(hwnd), msg, wParam, lParam); + return 0; + } + + return mir_callNextSubclass(hwnd, ContactListControlSubclass, msg, wParam, lParam); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +static LRESULT CALLBACK ContactListControlWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + ClcData *dat = (ClcData *)GetWindowLongPtr(hwnd, 0); + RECT r; + + switch (msg) { + case WM_CREATE: + dat = new ClcData(); + SetWindowLongPtr(hwnd, 0, (LONG_PTR)dat); + + dat->hwnd_list = CreateWindowW(L"LISTBOX", L"", + (WS_VISIBLE | WS_CHILD | LBS_NOINTEGRALHEIGHT | LBS_NOTIFY | LBS_WANTKEYBOARDINPUT | WS_VSCROLL), + 0, 0, 0, 0, hwnd, nullptr, g_plugin.getInst(), nullptr); + dat->need_rebuild = FALSE; + mir_subclassWindow(dat->hwnd_list, ContactListControlSubclass); + + GetClientRect(hwnd, &r); + SetWindowPos(dat->hwnd_list, nullptr, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_NOZORDER | SWP_NOACTIVATE); + break; + + case WM_SIZE: + GetClientRect(hwnd, &r); + SetWindowPos(dat->hwnd_list, nullptr, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_NOZORDER | SWP_NOACTIVATE); + break; + + case WM_PRINTCLIENT: + case WM_PAINT: + if (dat->need_rebuild) + RebuildEntireListInternal(hwnd, (ClcData *)dat, FALSE); + __fallthrough; + + case WM_VSCROLL: + case WM_MOUSEWHEEL: + return DefWindowProc(hwnd, msg, wParam, lParam); + + case INTM_SCROLLBARCHANGED: + return TRUE; + + case WM_VKEYTOITEM: + { + WORD key = LOWORD(wParam); + if (key == VK_LEFT || key == VK_RIGHT || key == VK_RETURN || key == VK_DELETE || key == VK_F2) { + coreCli.pfnContactListControlWndProc(hwnd, WM_KEYDOWN, key, 0); + return dat->selection; + } + + NMKEY nmkey; + nmkey.hdr.hwndFrom = hwnd; + nmkey.hdr.idFrom = GetDlgCtrlID(hwnd); + nmkey.hdr.code = NM_KEYDOWN; + nmkey.nVKey = key; + nmkey.uFlags = 0; + if (SendMessage(GetParent(hwnd), WM_NOTIFY, 0, (LPARAM)&nmkey)) + return -2; + } + return -1; + + case WM_COMMAND: + if ((HANDLE)lParam != dat->hwnd_list || HIWORD(wParam) != LBN_SELCHANGE) + break; + + dat->selection = SendMessage(dat->hwnd_list, LB_GETCURSEL, 0, 0); + + KillTimer(hwnd, TIMERID_INFOTIP); + KillTimer(hwnd, TIMERID_RENAME); + dat->szQuickSearch[0] = 0; + g_clistApi.pfnInvalidateRect(hwnd, nullptr, FALSE); + Clist_EnsureVisible(hwnd, (ClcData *)dat, dat->selection, 0); + UpdateWindow(hwnd); + break; + + case WM_SETFOCUS: + case WM_ENABLE: + SetFocus(dat->hwnd_list); + break; + } + + return coreCli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); +} + +static void RebuildEntireList(HWND hwnd, ClcData *dat) +{ + RebuildEntireListInternal(hwnd, dat, TRUE); +} + +static void SetGroupExpand(HWND hwnd, ClcData *dat, struct ClcGroup *group, int newState) +{ + coreCli.pfnSetGroupExpand(hwnd, dat, group, newState); + dat->need_rebuild = TRUE; +} + +static void ScrollTo(HWND, ClcData *, int, int) +{ +} + +static void RecalcScrollBar(HWND, ClcData *) +{ +} + +static void LoadClcOptions(HWND hwnd, ClcData *dat, BOOL bFirst) +{ + coreCli.pfnLoadClcOptions(hwnd, dat, bFirst); + + dat->bFilterSearch = false; + dat->rowHeight = SendMessage(dat->hwnd_list, LB_GETITEMHEIGHT, 0, 0); +} + +static int GetRowHeight(ClcData *dat, int) +{ + dat->rowHeight = SendMessage(dat->hwnd_list, LB_GETITEMHEIGHT, 0, 0); + return dat->rowHeight; +} + +static void SortCLC(HWND hwnd, ClcData *dat, int useInsertionSort) +{ + if (dat->bNeedsResort) { + coreCli.pfnSortCLC(hwnd, dat, useInsertionSort); + dat->need_rebuild = TRUE; + } +} + +void InitClc() +{ + Clist_GetInterface(); + coreCli = g_clistApi; + g_clistApi.bOwnerDrawMenu = false; + g_clistApi.hInst = g_plugin.getInst(); + g_clistApi.pfnPaintClc = PaintClc; + g_clistApi.pfnContactListWndProc = ContactListWndProc; + g_clistApi.pfnContactListControlWndProc = ContactListControlWndProc; + g_clistApi.pfnRebuildEntireList = RebuildEntireList; + g_clistApi.pfnSetGroupExpand = SetGroupExpand; + g_clistApi.pfnRecalcScrollBar = RecalcScrollBar; + g_clistApi.pfnScrollTo = ScrollTo; + g_clistApi.pfnLoadClcOptions = LoadClcOptions; + g_clistApi.pfnGetRowHeight = GetRowHeight; + g_clistApi.pfnSortCLC = SortCLC; + g_clistApi.pfnCompareContacts = CompareContacts; +} diff --git a/plugins/Clist_blind/src/init.cpp b/plugins/Clist_blind/src/init.cpp index a360ad200e..87c7e9dd23 100644 --- a/plugins/Clist_blind/src/init.cpp +++ b/plugins/Clist_blind/src/init.cpp @@ -29,22 +29,11 @@ CLIST_INTERFACE coreCli; HIMAGELIST himlCListClc = nullptr;
-LRESULT CALLBACK ContactListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
-LRESULT CALLBACK ContactListControlWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
-void RebuildEntireList(HWND hwnd, ClcData *dat);
-void RebuildEntireListInternal(HWND hwnd, ClcData *dat, BOOL call_orig);
-void SetGroupExpand(HWND hwnd, ClcData *dat, struct ClcGroup *group, int newState);
-void ScrollTo(HWND hwnd, ClcData *dat, int desty, int noSmooth);
-void RecalcScrollBar(HWND hwnd, ClcData *dat);
-void LoadClcOptions(HWND hwnd, ClcData *dat, BOOL);
-int GetRowHeight(ClcData *dat, int item);
-void SortCLC(HWND hwnd, ClcData *dat, int useInsertionSort);
-
/////////////////////////////////////////////////////////////////////////////////////////
// external functions
+void InitClc();
void InitCustomMenus(void);
-void PaintClc(HWND hwnd, ClcData *dat, HDC hdc, RECT *rcPaint);
int ClcOptInit(WPARAM wParam, LPARAM lParam);
int CluiOptInit(WPARAM wParam, LPARAM lParam);
@@ -121,22 +110,7 @@ int CMPlugin::Load() g_bSortByStatus = g_plugin.getByte("SortByStatus", SETTING_SORTBYSTATUS_DEFAULT);
g_bSortByProto = g_plugin.getByte("SortByProto", SETTING_SORTBYPROTO_DEFAULT);
- Clist_GetInterface();
- coreCli = g_clistApi;
- g_clistApi.bOwnerDrawMenu = false;
- g_clistApi.hInst = g_plugin.getInst();
- g_clistApi.pfnPaintClc = PaintClc;
- g_clistApi.pfnContactListWndProc = ContactListWndProc;
- g_clistApi.pfnContactListControlWndProc = ContactListControlWndProc;
- g_clistApi.pfnRebuildEntireList = RebuildEntireList;
- g_clistApi.pfnSetGroupExpand = SetGroupExpand;
- g_clistApi.pfnRecalcScrollBar = RecalcScrollBar;
- g_clistApi.pfnScrollTo = ScrollTo;
- g_clistApi.pfnLoadClcOptions = LoadClcOptions;
- g_clistApi.pfnGetRowHeight = GetRowHeight;
- g_clistApi.pfnSortCLC = SortCLC;
- g_clistApi.pfnCompareContacts = CompareContacts;
-
+ InitClc();
CreateServiceFunction(MS_CLIST_GETSTATUSMODE, GetStatusMode);
HookEvent(ME_OPT_INITIALISE, OnOptsInit);
@@ -146,487 +120,3 @@ int CMPlugin::Load() InitCustomMenus();
return 0;
}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-wchar_t* MyDBGetContactSettingTString(MCONTACT hContact, char* module, char* setting, wchar_t* out, size_t len, wchar_t *def)
-{
- DBVARIANT dbv;
-
- out[0] = '\0';
-
- if (!db_get_ws(hContact, module, setting, &dbv)) {
- if (dbv.type == DBVT_ASCIIZ)
- MultiByteToWideChar(CP_ACP, 0, dbv.pszVal, -1, out, (int)len);
- else if (dbv.type == DBVT_UTF8)
- MultiByteToWideChar(CP_UTF8, 0, dbv.pszVal, -1, out, (int)len);
- else if (dbv.type == DBVT_WCHAR)
- mir_wstrncpy(out, dbv.pwszVal, (int)len);
- else if (def != nullptr)
- mir_wstrncpy(out, def, (int)len);
-
- db_free(&dbv);
- }
- else {
- if (def != nullptr)
- mir_wstrncpy(out, def, (int)len);
- }
-
- return out;
-}
-
-#define DATA_BLOCK 128
-
-typedef struct
-{
- wchar_t *text;
- size_t allocated;
- size_t used;
-
-} StringHelper;
-
-int CopyData(StringHelper *str, const wchar_t *text, size_t len)
-{
- size_t totalSize;
-
- if (len == 0)
- return 0;
-
- if (text == nullptr)
- return 0;
-
- totalSize = str->used + len + 1;
-
- if (totalSize > str->allocated) {
- totalSize += DATA_BLOCK - (totalSize % DATA_BLOCK);
-
- if (str->text != nullptr) {
- wchar_t *tmp = (wchar_t *)mir_realloc(str->text, sizeof(wchar_t) * totalSize);
-
- if (tmp == nullptr) {
- mir_free(str->text);
- return -1;
- }
-
- str->text = tmp;
- }
- else {
- str->text = (wchar_t *)mir_alloc(sizeof(wchar_t) * totalSize);
-
- if (str->text == nullptr) {
- return -2;
- }
- }
-
- str->allocated = totalSize;
- }
-
- memmove(&str->text[str->used], text, sizeof(wchar_t) * len);
- str->used += len;
- str->text[str->used] = '\0';
-
- return 0;
-}
-
-
-wchar_t *ParseText(const wchar_t *text,
- const wchar_t **variables, size_t variablesSize,
- const wchar_t **data, size_t dataSize)
-{
- size_t length = mir_wstrlen(text);
- size_t nextPos = 0;
- StringHelper ret = {};
- size_t i;
-
- // length - 1 because a % in last char will be a % and point
- for (i = 0; i < length - 1; i++) {
- if (text[i] == '%') {
- BOOL found = FALSE;
-
- if (CopyData(&ret, &text[nextPos], i - nextPos))
- return nullptr;
-
- if (text[i + 1] == '%') {
- if (CopyData(&ret, L"%", 1))
- return nullptr;
-
- i++;
-
- found = TRUE;
- }
- else {
- size_t size = min(variablesSize, dataSize);
- size_t j;
-
- // See if can find it
- for (j = 0; j < size; j++) {
- size_t vlen = mir_wstrlen(variables[j]);
-
- if (wcsnicmp(&text[i], variables[j], vlen) == 0) {
- if (CopyData(&ret, data[j], mir_wstrlen(data[j])))
- return nullptr;
-
- i += vlen - 1;
-
- found = TRUE;
-
- break;
- }
- }
- }
-
- if (found)
- nextPos = i + 1;
- else
- nextPos = i;
- }
- }
-
- if (nextPos < length)
- if (CopyData(&ret, &text[nextPos], length - nextPos))
- return nullptr;
-
- return ret.text;
-}
-
-LRESULT CALLBACK ContactListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- switch (msg) {
- case WM_NCCREATE:
- return DefWindowProc(hwnd, msg, wParam, lParam);
-
- case WM_CREATE:
- break;
-
- case WM_DRAWITEM:
- return Menu_DrawItem(lParam);
- }
- return coreCli.pfnContactListWndProc(hwnd, msg, wParam, lParam);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-LRESULT CALLBACK ContactListControlSubclass(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- if (msg == WM_CHAR) {
- coreCli.pfnContactListControlWndProc(GetParent(hwnd), msg, wParam, lParam);
- return 0;
- }
-
- return mir_callNextSubclass(hwnd, ContactListControlSubclass, msg, wParam, lParam);
-}
-
-LRESULT CALLBACK ContactListControlWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- ClcData *dat = (ClcData*)GetWindowLongPtr(hwnd, 0);
- RECT r;
-
- switch (msg) {
- case WM_CREATE:
- dat = new ClcData();
- SetWindowLongPtr(hwnd, 0, (LONG_PTR)dat);
-
- dat->hwnd_list = CreateWindow(L"LISTBOX", L"",
- (WS_VISIBLE | WS_CHILD | LBS_NOINTEGRALHEIGHT | LBS_NOTIFY | LBS_WANTKEYBOARDINPUT | WS_VSCROLL),
- 0, 0, 0, 0, hwnd, nullptr, g_plugin.getInst(), nullptr);
- dat->need_rebuild = FALSE;
- mir_subclassWindow(dat->hwnd_list, ContactListControlSubclass);
-
- GetClientRect(hwnd, &r);
- SetWindowPos(dat->hwnd_list, nullptr, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_NOZORDER | SWP_NOACTIVATE);
- break;
-
- case WM_SIZE:
- GetClientRect(hwnd, &r);
- SetWindowPos(dat->hwnd_list, nullptr, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_NOZORDER | SWP_NOACTIVATE);
- break;
-
- case WM_PRINTCLIENT:
- case WM_PAINT:
- if (dat->need_rebuild)
- RebuildEntireListInternal(hwnd, (ClcData *)dat, FALSE);
- __fallthrough;
-
- case WM_VSCROLL:
- case WM_MOUSEWHEEL:
- return DefWindowProc(hwnd, msg, wParam, lParam);
-
- case INTM_SCROLLBARCHANGED:
- return TRUE;
-
- case WM_VKEYTOITEM:
- {
- WORD key = LOWORD(wParam);
- if (key == VK_LEFT || key == VK_RIGHT || key == VK_RETURN || key == VK_DELETE || key == VK_F2) {
- coreCli.pfnContactListControlWndProc(hwnd, WM_KEYDOWN, key, 0);
- return dat->selection;
- }
-
- NMKEY nmkey;
- nmkey.hdr.hwndFrom = hwnd;
- nmkey.hdr.idFrom = GetDlgCtrlID(hwnd);
- nmkey.hdr.code = NM_KEYDOWN;
- nmkey.nVKey = key;
- nmkey.uFlags = 0;
- if (SendMessage(GetParent(hwnd), WM_NOTIFY, 0, (LPARAM)&nmkey))
- return -2;
- }
- return -1;
-
- case WM_COMMAND:
- if ((HANDLE)lParam != dat->hwnd_list || HIWORD(wParam) != LBN_SELCHANGE)
- break;
-
- dat->selection = SendMessage(dat->hwnd_list, LB_GETCURSEL, 0, 0);
-
- KillTimer(hwnd, TIMERID_INFOTIP);
- KillTimer(hwnd, TIMERID_RENAME);
- dat->szQuickSearch[0] = 0;
- g_clistApi.pfnInvalidateRect(hwnd, nullptr, FALSE);
- Clist_EnsureVisible(hwnd, (ClcData*)dat, dat->selection, 0);
- UpdateWindow(hwnd);
- break;
-
- case WM_SETFOCUS:
- case WM_ENABLE:
- SetFocus(dat->hwnd_list);
- break;
- }
-
- return coreCli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-wchar_t status_name[128];
-wchar_t* GetStatusName(struct ClcContact *item)
-{
- int status;
-
- status_name[0] = '\0';
- if (item->hContact == NULL || item->pce->szProto == nullptr)
- return status_name;
-
- // Get XStatusName
- MyDBGetContactSettingTString(item->hContact, item->pce->szProto, "XStatusName", status_name, _countof(status_name), nullptr);
- if (status_name[0] != '\0')
- return status_name;
-
- // Get status name
- status = db_get_w(item->hContact, item->pce->szProto, "Status", ID_STATUS_OFFLINE);
- mir_wstrncpy(status_name, Clist_GetStatusModeDescription(status, 0), _countof(status_name));
-
- return status_name;
-}
-
-wchar_t status_message[256];
-wchar_t* GetStatusMessage(struct ClcContact *item)
-{
- status_message[0] = '\0';
- if (item->hContact == NULL || item->pce->szProto == nullptr)
- return status_message;
-
- // Get XStatusMsg
- MyDBGetContactSettingTString(item->hContact, item->pce->szProto, "XStatusMsg", status_message, _countof(status_message), nullptr);
- if (status_message[0] != '\0')
- return status_message;
-
- // Get status message
- MyDBGetContactSettingTString(item->hContact, "CList", "StatusMsg", status_message, _countof(status_message), nullptr);
-
- return status_message;
-}
-
-
-wchar_t proto_name[128];
-wchar_t* GetProtoName(struct ClcContact *item)
-{
- char description[128];
-
- proto_name[0] = '\0';
- if (item->hContact == NULL || item->pce->szProto == nullptr) {
- mir_wstrncpy(proto_name, TranslateT("Unknown protocol"), _countof(proto_name));
- return proto_name;
- }
-
- PROTOACCOUNT *acc = Proto_GetAccount(item->pce->szProto);
- if (acc == nullptr) {
- CallProtoService(item->pce->szProto, PS_GETNAME, sizeof(description), (LPARAM)description);
- mir_snwprintf(proto_name, L"%S", description);
- return proto_name;
- }
-
- mir_wstrncpy(proto_name, acc->tszAccountName, _countof(proto_name));
-
- return proto_name;
-}
-
-void RebuildEntireListInternal(HWND hwnd, ClcData *tmp_dat, BOOL call_orig)
-{
- ClcData *dat = (ClcData*)tmp_dat;
- wchar_t tmp[1024];
- wchar_t count[128];
- wchar_t template_contact[1024];
- wchar_t template_group[1024];
- wchar_t template_divider[1024];
- wchar_t template_info[1024];
- int selection = dat->selection;
- BOOL has_focus = (GetFocus() == dat->hwnd_list || GetFocus() == hwnd);
-
- if (call_orig)
- coreCli.pfnRebuildEntireList(hwnd, (ClcData*)dat);
-
- MyDBGetContactSettingTString(NULL, "CLC", "TemplateContact", template_contact, 1024, TranslateT("%name% [%status% %protocol%] %status_message%"));
- MyDBGetContactSettingTString(NULL, "CLC", "TemplateGroup", template_group, 1024, TranslateT("Group: %name% %count% [%mode%]"));
- MyDBGetContactSettingTString(NULL, "CLC", "TemplateDivider", template_divider, 1024, TranslateT("Divider: %s"));
- MyDBGetContactSettingTString(NULL, "CLC", "TemplateInfo", template_info, 1024, TranslateT("Info: %s"));
-
- SendMessage(dat->hwnd_list, WM_SETREDRAW, FALSE, 0);
-
- // Reset content
- SendMessage(dat->hwnd_list, LB_RESETCONTENT, 0, 0);
-
- // Set font
- SendMessage(dat->hwnd_list, WM_SETFONT, (WPARAM)dat->fontInfo[FONTID_CONTACTS].hFont, 0);
-
- // Add all items to the list
- ClcGroup *group = &dat->list;
- group->scanIndex = 0;
-
- wchar_t *text = tmp;
- size_t size = _countof(tmp);
- while (true) {
- if (group->scanIndex == group->cl.getCount()) {
- if ((group = group->parent) == nullptr)
- break;
- text -= 2;
- size += 2;
- group->scanIndex++;
- continue;
- }
-
- ClcContact *item = group->cl[group->scanIndex];
- text[0] = '\0';
- switch (item->type) {
- case CLCIT_GROUP:
- {
- wchar_t *szCounts = Clist_GetGroupCountsText(dat, item);
- const wchar_t *t[] = {
- L"%name%",
- L"%count%",
- L"%mode%"
- };
- const wchar_t *v[] = {
- item->szText,
- count,
- item->group->expanded ? TranslateT("Expanded") : TranslateT("Collapsed")
- };
-
- if (szCounts[0] != '\0')
- mir_snwprintf(count, L"%s ", szCounts);
- else
- count[0] = '\0';
-
- wchar_t *txt = ParseText(template_group, t, _countof(t), v, _countof(v));
- if (txt != nullptr)
- mir_wstrncpy(text, txt, size);
- mir_free(txt);
- }
- break;
-
- case CLCIT_CONTACT:
- {
- const wchar_t *t[] = {
- L"%name%",
- L"%status%",
- L"%protocol%",
- L"%status_message%"
- };
- const wchar_t *v[] = {
- item->szText,
- GetStatusName(item),
- GetProtoName(item),
- GetStatusMessage(item)
- };
-
- wchar_t *txt = ParseText(template_contact, t, _countof(t), v, _countof(v));
- if (txt != nullptr)
- mir_wstrncpy(text, txt, size);
- mir_free(txt);
- }
- break;
-
- case CLCIT_DIVIDER:
- mir_snwprintf(text, size, template_divider, item->szText);
- break;
-
- case CLCIT_INFO:
- mir_snwprintf(text, size, template_info, item->szText);
- break;
- }
-
- SendMessage(dat->hwnd_list, LB_ADDSTRING, 0, (LPARAM)tmp);
-
- if (item->type == CLCIT_GROUP && item->group->expanded) {
- group = item->group;
- text[0] = ' ';
- text[1] = ' ';
- text += 2;
- size -= 2;
- group->scanIndex = 0;
- continue;
- }
- group->scanIndex++;
- }
-
- SendMessage(dat->hwnd_list, WM_SETREDRAW, TRUE, 0);
- InvalidateRect(dat->hwnd_list, nullptr, TRUE);
-
- dat->selection = selection;
- SendMessage(dat->hwnd_list, LB_SETCURSEL, dat->selection, 0);
- if (has_focus)
- SetFocus(dat->hwnd_list);
-
- dat->need_rebuild = FALSE;
-}
-
-void RebuildEntireList(HWND hwnd, ClcData *dat)
-{
- RebuildEntireListInternal(hwnd, dat, TRUE);
-}
-
-void SetGroupExpand(HWND hwnd, ClcData *dat, struct ClcGroup *group, int newState)
-{
- coreCli.pfnSetGroupExpand(hwnd, dat, group, newState);
- dat->need_rebuild = TRUE;
-}
-
-void ScrollTo(HWND, ClcData*, int, int)
-{
-}
-
-void RecalcScrollBar(HWND, ClcData*)
-{
-}
-
-void LoadClcOptions(HWND hwnd, ClcData *dat, BOOL bFirst)
-{
- coreCli.pfnLoadClcOptions(hwnd, dat, bFirst);
-
- dat->bFilterSearch = false;
- dat->rowHeight = SendMessage(dat->hwnd_list, LB_GETITEMHEIGHT, 0, 0);
-}
-
-int GetRowHeight(ClcData *dat, int)
-{
- dat->rowHeight = SendMessage(dat->hwnd_list, LB_GETITEMHEIGHT, 0, 0);
- return dat->rowHeight;
-}
-
-void SortCLC(HWND hwnd, ClcData *dat, int useInsertionSort)
-{
- if (dat->bNeedsResort) {
- coreCli.pfnSortCLC(hwnd, dat, useInsertionSort);
- dat->need_rebuild = TRUE;
- }
-}
diff --git a/plugins/Clist_blind/src/stdafx.h b/plugins/Clist_blind/src/stdafx.h index 95e56c9044..6738232f31 100644 --- a/plugins/Clist_blind/src/stdafx.h +++ b/plugins/Clist_blind/src/stdafx.h @@ -61,15 +61,6 @@ struct ClcData : public ClcDataBase extern CLIST_INTERFACE coreCli;
extern int g_bSortByStatus, g_bSortByProto;
+wchar_t* MyDBGetContactSettingTString(MCONTACT hContact, char *module, char *setting, wchar_t *out, size_t len, wchar_t *def);
int CompareContacts(const ClcContact *contact1, const ClcContact *contact2);
-
-/* most free()'s are invalid when the code is executed from a dll, so this changes
- all the bad free()'s to good ones, however it's still incorrect code. The reasons for not
- changing them include:
-
- * db_free has a CallService() lookup
- * free() is executed in some large loops to do with clist creation of group data
- * easy search and replace
-
-*/
diff --git a/plugins/Clist_blind/src/utils.cpp b/plugins/Clist_blind/src/utils.cpp new file mode 100644 index 0000000000..a13cfb407c --- /dev/null +++ b/plugins/Clist_blind/src/utils.cpp @@ -0,0 +1,41 @@ +/* +Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org) + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation version 2 +of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "stdafx.h" + +wchar_t* MyDBGetContactSettingTString(MCONTACT hContact, char *module, char *setting, wchar_t *out, size_t len, wchar_t *def) +{ + out[0] = '\0'; + + DBVARIANT dbv; + if (!db_get_ws(hContact, module, setting, &dbv)) { + if (dbv.type == DBVT_ASCIIZ) + MultiByteToWideChar(CP_ACP, 0, dbv.pszVal, -1, out, (int)len); + else if (dbv.type == DBVT_UTF8) + MultiByteToWideChar(CP_UTF8, 0, dbv.pszVal, -1, out, (int)len); + else if (dbv.type == DBVT_WCHAR) + mir_wstrncpy(out, dbv.pwszVal, len); + else if (def != nullptr) + mir_wstrncpy(out, def, len); + + db_free(&dbv); + } + else if (def != nullptr) + mir_wstrncpy(out, def, len); + + return out; +} |