From 17895ec37e6e958d9dec963484091f38a3329443 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Sun, 10 May 2020 12:39:41 +0300 Subject: mTextControl related code cleaning --- libs/mTextControl/src/services.cpp | 12 ++- libs/mTextControl/src/textcontrol.cpp | 3 +- plugins/ExternalAPI/m_text.h | 2 +- plugins/NewStory/src/history_array.cpp | 43 ++++++++++ plugins/NewStory/src/history_array.h | 23 +++--- plugins/NewStory/src/history_control.cpp | 132 +++++++++++++++---------------- 6 files changed, 132 insertions(+), 83 deletions(-) diff --git a/libs/mTextControl/src/services.cpp b/libs/mTextControl/src/services.cpp index 4e1ca40034..c457ba3156 100644 --- a/libs/mTextControl/src/services.cpp +++ b/libs/mTextControl/src/services.cpp @@ -158,10 +158,14 @@ MTEXTCONTROL_DLL(int) MTextDisplay(HDC dc, POINT pos, SIZE sz, HANDLE text) ///////////////////////////////////////////////////////////////////////////////////////// // set parent window for text object (this is required for mouse handling, etc) -MTEXTCONTROL_DLL(int) MTextSetParent(HANDLE text, HWND hwnd, RECT rect) +MTEXTCONTROL_DLL(int) MTextSetParent(HANDLE text, HWND hwnd) { - if (text) - ((TextObject *)text)->ftd->setParentWnd(hwnd, rect); + if (text) { + RECT rc; + GetClientRect(hwnd, &rc); + + ((TextObject *)text)->ftd->setParentWnd(hwnd, rc); + } return 0; } @@ -178,7 +182,7 @@ MTEXTCONTROL_DLL(int) MTextSendMessage(HWND hwnd, HANDLE text, UINT msg, WPARAM if (hwnd && (msg == WM_MOUSEMOVE)) { HDC hdc = GetDC(hwnd); - ((TextObject *)text)->ftd->getTextService()->OnTxSetCursor(DVASPECT_CONTENT, 0, nullptr, nullptr, hdc, nullptr, nullptr, LOWORD(0), HIWORD(0)); + ((TextObject *)text)->ftd->getTextService()->OnTxSetCursor(DVASPECT_CONTENT, 0, nullptr, nullptr, hdc, nullptr, nullptr, LOWORD(lParam), HIWORD(lParam)); ReleaseDC(hwnd, hdc); } diff --git a/libs/mTextControl/src/textcontrol.cpp b/libs/mTextControl/src/textcontrol.cpp index a7069ae88c..c62148269b 100644 --- a/libs/mTextControl/src/textcontrol.cpp +++ b/libs/mTextControl/src/textcontrol.cpp @@ -78,8 +78,7 @@ LRESULT CALLBACK MTextControlWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM GetWindowText(hwnd, data->text, textLength + 1); data->mtext = MTextCreateW(data->htu, data->text); - RECT rc; GetClientRect(hwnd, &rc); - MTextSetParent(data->mtext, hwnd, rc); + MTextSetParent(data->mtext, hwnd); InvalidateRect(hwnd, nullptr, TRUE); } diff --git a/plugins/ExternalAPI/m_text.h b/plugins/ExternalAPI/m_text.h index 30cdf466b9..5e10383bb5 100644 --- a/plugins/ExternalAPI/m_text.h +++ b/plugins/ExternalAPI/m_text.h @@ -66,7 +66,7 @@ MTEXTCONTROL_DLL(int) MTextMeasure(HDC dc, SIZE *sz, HANDLE text); MTEXTCONTROL_DLL(int) MTextDisplay(HDC dc, POINT pos, SIZE sz, HANDLE text); // set parent window for text object (this is required for mouse handling, etc) -MTEXTCONTROL_DLL(int) MTextSetParent(HANDLE text, HWND hwnd, RECT rect); +MTEXTCONTROL_DLL(int) MTextSetParent(HANDLE text, HWND hwnd); // send message to an object MTEXTCONTROL_DLL(int) MTextSendMessage(HWND hwnd, HANDLE text, UINT msg, WPARAM wParam, LPARAM lParam); diff --git a/plugins/NewStory/src/history_array.cpp b/plugins/NewStory/src/history_array.cpp index c8c5fc44a4..df39a0ef0f 100644 --- a/plugins/NewStory/src/history_array.cpp +++ b/plugins/NewStory/src/history_array.cpp @@ -1,5 +1,10 @@ #include "stdafx.h" +extern HANDLE htuLog; + +///////////////////////////////////////////////////////////////////////////////////////// +// Filters + bool Filter::check(ItemData *item) { if (!item) return false; @@ -41,6 +46,30 @@ bool Filter::check(ItemData *item) ///////////////////////////////////////////////////////////////////////////////////////// // Event +void ItemData::checkCreate(HWND hwnd) +{ + if (data == nullptr) { + data = MTextCreateW(htuLog, ptrW(TplFormatString(getTemplate(), hContact, this))); + MTextSetParent(data, hwnd); + } +} + +bool ItemData::isLink(POINT pt) const +{ + int cp = MTextSendMessage(0, data, EM_CHARFROMPOS, 0, LPARAM(&pt)); + if (cp == -1) + return false; + + CHARRANGE cr = { cp, cp + 1 }; + MTextSendMessage(0, data, EM_EXSETSEL, 0, LPARAM(&cr)); + + CHARFORMAT2 cf = {}; + cf.cbSize = sizeof(cf); + cf.dwMask = CFM_LINK; + DWORD res = MTextSendMessage(0, data, EM_GETCHARFORMAT, SCF_SELECTION, LPARAM(&cf)); + return ((res & CFM_LINK) && (cf.dwEffects & CFE_LINK)) || ((res & CFM_REVISED) && (cf.dwEffects & CFE_REVISED)); +} + void ItemData::load(bool bFullLoad) { if (!bFullLoad || bLoaded) @@ -107,6 +136,20 @@ int ItemData::getTemplate() const } } +int ItemData::getCopyTemplate() const +{ + switch (dbe.eventType) { + case EVENTTYPE_MESSAGE: return TPL_COPY_MESSAGE; + case EVENTTYPE_FILE: return TPL_COPY_FILE; + case EVENTTYPE_STATUSCHANGE: return TPL_COPY_SIGN; + case EVENTTYPE_AUTHREQUEST: return TPL_COPY_AUTH; + case EVENTTYPE_ADDED: return TPL_COPY_ADDED; + case EVENTTYPE_JABBER_PRESENCE: return TPL_COPY_PRESENCE; + default: + return TPL_COPY_OTHER; + } +} + void ItemData::getFontColor(int &fontId, int &colorId) const { switch (dbe.eventType) { diff --git a/plugins/NewStory/src/history_array.h b/plugins/NewStory/src/history_array.h index 07768f03dd..46e075c934 100644 --- a/plugins/NewStory/src/history_array.h +++ b/plugins/NewStory/src/history_array.h @@ -3,26 +3,31 @@ struct ItemData { - MCONTACT hContact = 0; - MEVENT hEvent = 0; + MCONTACT hContact; + MEVENT hEvent; - bool bSelected = false; - bool bLoaded = false; + bool bSelected; + bool bLoaded; + int savedTop; DBEVENTINFO dbe; - wchar_t *wtext = 0; - wchar_t *wszNick = 0; + wchar_t *wtext; + wchar_t *wszNick; - HANDLE data = 0; - ItemData *pPrev = 0; + HANDLE data; + ItemData *pPrev; - ItemData() { memset(&dbe, 0, sizeof(dbe)); } + ItemData() { memset(this, 0, sizeof(*this)); } ~ItemData(); + void checkCreate(HWND hwnd); + void load(bool bFullLoad); bool isGrouped() const; + bool isLink(POINT pt) const; int getTemplate() const; + int getCopyTemplate() const; void getFontColor(int &fontId, int &colorId) const; inline wchar_t *getWBuf() diff --git a/plugins/NewStory/src/history_control.cpp b/plugins/NewStory/src/history_control.cpp index c005d18728..b4b23cf808 100644 --- a/plugins/NewStory/src/history_control.cpp +++ b/plugins/NewStory/src/history_control.cpp @@ -112,19 +112,10 @@ struct NewstoryListData : public MZeroedObject if (idx == index) { ItemData *item = items[index]; - int tpl, fontid, colorid; + int fontid, colorid; item->getFontColor(fontid, colorid); - switch (item->dbe.eventType) { - case EVENTTYPE_MESSAGE: tpl = TPL_COPY_MESSAGE; break; - case EVENTTYPE_FILE: tpl = TPL_COPY_FILE; break; - case EVENTTYPE_STATUSCHANGE: tpl = TPL_COPY_SIGN; break; - case EVENTTYPE_AUTHREQUEST: tpl = TPL_COPY_AUTH; break; - case EVENTTYPE_ADDED: tpl = TPL_COPY_ADDED; break; - case EVENTTYPE_JABBER_PRESENCE: tpl = TPL_COPY_PRESENCE; break; - default: tpl = TPL_COPY_OTHER; break; - } - ptrW text(TplFormatString(tpl, item->hContact, item)); + ptrW text(TplFormatString(item->getCopyTemplate(), item->hContact, item)); hwndEditBox = CreateWindow(L"EDIT", text, WS_CHILD | WS_BORDER | ES_READONLY | ES_MULTILINE | ES_AUTOVSCROLL, 0, top, rc.right - rc.left, itemHeight, hwnd, NULL, g_plugin.getInst(), NULL); OldEditWndProc = (WNDPROC)SetWindowLongPtr(hwndEditBox, GWLP_WNDPROC, (LONG_PTR)HistoryEditWndProc); SendMessage(hwndEditBox, WM_SETFONT, (WPARAM)g_fontTable[fontid].hfnt, 0); @@ -225,10 +216,9 @@ struct NewstoryListData : public MZeroedObject int fontid, colorid; item->getFontColor(fontid, colorid); + item->checkCreate(hwnd); HFONT hfnt = (HFONT)SelectObject(hdc, g_fontTable[fontid].hfnt); - if (!item->data) - item->data = MTextCreateW(htuLog, ptrW(TplFormatString(item->getTemplate(), item->hContact, item))); SIZE sz; sz.cx = width - 6; @@ -243,6 +233,7 @@ struct NewstoryListData : public MZeroedObject int PaintItem(HDC hdc, int index, int top, int width) { auto *item = items[index]; + item->savedTop = top; // LOGFONT lfText; COLORREF clText, clBack, clLine; @@ -262,11 +253,7 @@ struct NewstoryListData : public MZeroedObject clBack = g_colorTable[colorid].cl; } - if (!item->data) { - item->data = MTextCreateW(htuLog, ptrW(TplFormatString(item->getTemplate(), item->hContact, item))); - if (!item->data) - return 0; - } + item->checkCreate(hwnd); SIZE sz; sz.cx = width - 6; @@ -386,6 +373,7 @@ static LRESULT CALLBACK HistoryEditWndProc(HWND hwnd, UINT msg, WPARAM wParam, L LRESULT CALLBACK NewstoryListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { + int idx; NewstoryListData *data = (NewstoryListData *)GetWindowLongPtr(hwnd, 0); switch (msg) { @@ -502,9 +490,9 @@ LRESULT CALLBACK NewstoryListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM return 0; case NSM_GETITEMFROMPIXEL: + RECT rc; + GetClientRect(hwnd, &rc); { - RECT rc; - GetClientRect(hwnd, &rc); int height = rc.bottom - rc.top; int count = data->items.getCount(); int current = data->scrollTopItem; @@ -518,8 +506,8 @@ LRESULT CALLBACK NewstoryListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM top = bottom; bottom = top + data->LayoutItem(current); } - return -1; } + return -1; case NSM_SETCARET: if (wParam < data->items.getCount()) { @@ -532,24 +520,20 @@ LRESULT CALLBACK NewstoryListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM return data->caret; case NSM_FINDNEXT: - { - int id = data->items.FindNext(SendMessage(hwnd, NSM_GETCARET, 0, 0), Filter(Filter::EVENTONLY, (wchar_t *)wParam)); - if (id >= 0) { - SendMessage(hwnd, NSM_SELECTITEMS2, id, id); - SendMessage(hwnd, NSM_SETCARET, id, TRUE); - } - return id; + idx = data->items.FindNext(data->caret, Filter(Filter::EVENTONLY, (wchar_t *)wParam)); + if (idx >= 0) { + SendMessage(hwnd, NSM_SELECTITEMS2, idx, idx); + SendMessage(hwnd, NSM_SETCARET, idx, TRUE); } + return idx; case NSM_FINDPREV: - { - int id = data->items.FindPrev(SendMessage(hwnd, NSM_GETCARET, 0, 0), Filter(Filter::EVENTONLY, (wchar_t *)wParam)); - if (id >= 0) { - SendMessage(hwnd, NSM_SELECTITEMS2, id, id); - SendMessage(hwnd, NSM_SETCARET, id, TRUE); - } - return id; + idx = data->items.FindPrev(data->caret, Filter(Filter::EVENTONLY, (wchar_t *)wParam)); + if (idx >= 0) { + SendMessage(hwnd, NSM_SELECTITEMS2, idx, idx); + SendMessage(hwnd, NSM_SETCARET, idx, TRUE); } + return idx; case NSM_SEEKTIME: { @@ -604,7 +588,7 @@ LRESULT CALLBACK NewstoryListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM for (int i = 0; i < eventCount; i++) { ItemData *p = data->items.get(i, false); if (p->bSelected) - res.Append(ptrW(TplFormatString(TPL_COPY_MESSAGE, p->hContact, p))); + res.Append(ptrW(TplFormatString(p->getCopyTemplate(), p->hContact, p))); } CopyText(hwnd, res); @@ -620,15 +604,14 @@ LRESULT CALLBACK NewstoryListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM return 1; case WM_PAINT: + PAINTSTRUCT ps; { - PAINTSTRUCT ps; HDC hdcWindow = BeginPaint(hwnd, &ps); /* we get so many InvalidateRect()'s that there is no point painting, Windows in theory shouldn't queue up WM_PAINTs in this case but it does so we'll just ignore them */ if (IsWindowVisible(hwnd)) { - RECT rc; GetClientRect(hwnd, &rc); HDC hdc = CreateCompatibleDC(hdcWindow); @@ -637,7 +620,7 @@ LRESULT CALLBACK NewstoryListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM int height = rc.bottom - rc.top; int width = rc.right - rc.left; int top = data->scrollTopPixel; - int idx = data->scrollTopItem; + idx = data->scrollTopItem; while ((top < height) && (idx < data->items.getCount())) top += data->PaintItem(hdc, idx++, top, width); @@ -657,12 +640,10 @@ LRESULT CALLBACK NewstoryListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM DeleteObject(SelectObject(hdc, hbmSave)); DeleteDC(hdc); } - - EndPaint(hwnd, &ps); } + EndPaint(hwnd, &ps); break; - case WM_CONTEXTMENU: { POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; @@ -700,36 +681,34 @@ LRESULT CALLBACK NewstoryListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM return DLGC_WANTMESSAGE; case WM_KEYDOWN: - { - switch (wParam) { - case VK_UP: - SendMessage(hwnd, NSM_SELECTITEMS2, data->caret - 1, data->caret - 1); - SendMessage(hwnd, NSM_SETCARET, data->caret - 1, TRUE); - break; + switch (wParam) { + case VK_UP: + SendMessage(hwnd, NSM_SELECTITEMS2, data->caret - 1, data->caret - 1); + SendMessage(hwnd, NSM_SETCARET, data->caret - 1, TRUE); + break; - case VK_DOWN: - SendMessage(hwnd, NSM_SELECTITEMS2, data->caret + 1, data->caret + 1); - SendMessage(hwnd, NSM_SETCARET, data->caret + 1, TRUE); - break; + case VK_DOWN: + SendMessage(hwnd, NSM_SELECTITEMS2, data->caret + 1, data->caret + 1); + SendMessage(hwnd, NSM_SETCARET, data->caret + 1, TRUE); + break; - case VK_PRIOR: - break; + case VK_PRIOR: + break; - case VK_NEXT: - break; + case VK_NEXT: + break; - case VK_HOME: - break; + case VK_HOME: + break; - case VK_END: - break; + case VK_END: + break; - case VK_F2: - data->BeginEditItem(data->caret); - break; - } + case VK_F2: + data->BeginEditItem(data->caret); break; } + break; case WM_SYSCHAR: case WM_CHAR: @@ -750,7 +729,8 @@ LRESULT CALLBACK NewstoryListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM case WM_LBUTTONDOWN: { - int item = SendMessage(hwnd, NSM_GETITEMFROMPIXEL, LOWORD(lParam), HIWORD(lParam)); + POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; + int item = SendMessage(hwnd, NSM_GETITEMFROMPIXEL, pt.x, pt.y); if (item >= 0) { if (data->caret != item) data->EndEditItem(); @@ -764,6 +744,13 @@ LRESULT CALLBACK NewstoryListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM SendMessage(hwnd, NSM_SETCARET, item, TRUE); } else { + auto *pItem = data->items[item]; + pt.y -= pItem->savedTop; + if (pItem->isLink(pt)) { + Utils_OpenUrlW(pItem->getWBuf()); + return 0; + } + if (data->caret == item) { data->BeginEditItem(item); return 0; @@ -777,6 +764,17 @@ LRESULT CALLBACK NewstoryListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM SetFocus(hwnd); return 0; + case WM_MOUSEMOVE: + { + POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; + int item = SendMessage(hwnd, NSM_GETITEMFROMPIXEL, pt.x, pt.y); + if (item >= 0) { + auto *pItem = data->items[item]; + MTextSendMessage(hwnd, pItem->data, msg, wParam, lParam); + } + } + break; + case WM_MOUSEWHEEL: { int s_scrollTopItem = data->scrollTopItem; @@ -787,7 +785,7 @@ LRESULT CALLBACK NewstoryListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM scrollLines = 3; data->ScrollListBy(0, (short)HIWORD(wParam) * 10 * (signed)scrollLines / WHEEL_DELTA); - if ((s_scrollTopItem != data->scrollTopItem) || (s_scrollTopPixel != data->scrollTopPixel)) + if (s_scrollTopItem != data->scrollTopItem || s_scrollTopPixel != data->scrollTopPixel) InvalidateRect(hwnd, 0, FALSE); } return TRUE; @@ -843,7 +841,7 @@ LRESULT CALLBACK NewstoryListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM return 0; } - if ((s_scrollTopItem != data->scrollTopItem) || (s_scrollTopPixel != data->scrollTopPixel)) + if (s_scrollTopItem != data->scrollTopItem || s_scrollTopPixel != data->scrollTopPixel) InvalidateRect(hwnd, 0, FALSE); break; } -- cgit v1.2.3