diff options
Diffstat (limited to 'plugins/NewStory')
-rw-r--r-- | plugins/NewStory/src/history.cpp | 46 | ||||
-rw-r--r-- | plugins/NewStory/src/history.h | 5 | ||||
-rw-r--r-- | plugins/NewStory/src/history_control.cpp | 810 | ||||
-rw-r--r-- | plugins/NewStory/src/history_control.h | 3 |
4 files changed, 423 insertions, 441 deletions
diff --git a/plugins/NewStory/src/history.cpp b/plugins/NewStory/src/history.cpp index 8cb8868891..143246d1be 100644 --- a/plugins/NewStory/src/history.cpp +++ b/plugins/NewStory/src/history.cpp @@ -220,7 +220,7 @@ class CHistoryDlg : public CDlgBase // main controls HWND m_hwndTimeTree; - HWND m_hwndLog; + // searchbar HWND m_hwndBtnCloseSearch; // statusbar @@ -386,7 +386,7 @@ class CHistoryDlg : public CDlgBase hSearch += WND_SPACING; } - hDwp = DeferWindowPos(hDwp, m_hwndLog, 0, + hDwp = DeferWindowPos(hDwp, m_histControl.GetHwnd(), 0, WND_SPACING, hToolBar + hFilterBar + WND_SPACING, w - WND_SPACING * 2, h - WND_SPACING * 2 - hFilterBar - hToolBar - hSearch - hStatus, SWP_NOZORDER); @@ -394,6 +394,7 @@ class CHistoryDlg : public CDlgBase EndDeferWindowPos(hDwp); } + CCtrlBase m_histControl; CCtrlEdit edtSearchText; CCtrlMButton btnUserInfo, btnSendMsg, btnUserMenu, btnCopy, btnOptions, btnFilter; CCtrlMButton btnCalendar, btnSearch, btnExport, btnClose, btnFindNext, btnFindPrev; @@ -404,6 +405,7 @@ public: CDlgBase(g_plugin, IDD_HISTORY), m_hContact(_hContact), m_timeTree(this, IDC_TIMETREE), + m_histControl(this, IDC_ITEMS2), edtSearchText(this, IDC_SEARCHTEXT), btnCopy(this, IDC_COPY, g_plugin.getIcon(ICO_COPY), LPGEN("Copy")), btnClose(this, IDC_CLOSE, g_plugin.getIcon(ICO_CLOSE), LPGEN("Close")), @@ -475,7 +477,6 @@ public: m_hwndBtnToolbar[TBTN_DATEPOPUP] = btnCalendar.GetHwnd(); m_hwndBtnToolbar[TBTN_CLOSE] = btnClose.GetHwnd(); - m_hwndLog = GetDlgItem(m_hwnd, IDC_ITEMS2); m_hwndBtnCloseSearch = GetDlgItem(m_hwnd, IDC_SEARCHICON); m_hwndStatus = CreateWindowEx(0, STATUSCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP, 0, 0, 0, 0, m_hwnd, NULL, g_plugin.getInst(), NULL); SendMessage(m_hwndStatus, SB_SETMINHEIGHT, GetSystemMetrics(SM_CYSMICON), 0); @@ -560,9 +561,9 @@ public: } if (m_hContact != INVALID_CONTACT_ID) - PostMessage(GetDlgItem(m_hwnd, IDC_ITEMS2), WM_USER, (WPARAM)m_hContact, 0); + PostMessage(m_histControl.GetHwnd(), WM_USER, m_hContact, 0); - SendMessage(m_hwnd, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)g_plugin.getIcon(ICO_NEWSTORY)); + Window_SetIcon_IcoLib(m_hwnd, g_plugin.getIconHandle(ICO_NEWSTORY)); SendMessage(GetDlgItem(m_hwnd, IDC_SEARCHICON), STM_SETICON, (WPARAM)g_plugin.getIcon(ICO_SEARCH), 0); @@ -582,7 +583,7 @@ public: SendMessage(ibTotal.hwndIcoIn, BM_SETIMAGE, IMAGE_ICON, (LPARAM)g_plugin.getIcon(ICO_MSGIN)); SendMessage(ibTotal.hwndIcoOut, BM_SETIMAGE, IMAGE_ICON, (LPARAM)g_plugin.getIcon(ICO_MSGOUT)); - SetFocus(GetDlgItem(m_hwnd, IDC_ITEMS2)); + SetFocus(m_histControl.GetHwnd()); ShowHideControls(); return true; @@ -590,11 +591,11 @@ public: void OnDestroy() override { - WindowList_Remove(hNewstoryWindows, m_hwnd); - g_plugin.setDword(m_hContact, "showFlags", showFlags); Utils_SaveWindowPosition(m_hwnd, m_hContact, MODULENAME, "wnd_"); + Window_FreeIcon_IcoLib(m_hwnd); + WindowList_Remove(hNewstoryWindows, m_hwnd); } void onClick_Calendar(CCtrlButton *pButton) @@ -604,7 +605,7 @@ public: time_t tm_jump = CalendarTool_Show(m_hwnd, rc.left, rc.bottom); if (tm_jump) - PostMessage(m_hwnd, UM_JUMP2TIME, tm_jump, 0); + m_histControl.SendMsg(NSM_SEEKTIME, tm_jump, 0); } void onClick_Close(CCtrlButton *) @@ -614,7 +615,7 @@ public: void onClick_Copy(CCtrlButton *) { - SendMessage(GetDlgItem(m_hwnd, IDC_ITEMS2), NSM_COPY, 0, 0); + m_histControl.SendMsg(NSM_COPY, 0, 0); } void onClick_Export(CCtrlButton *) @@ -636,12 +637,12 @@ public: void onClick_FindNext(CCtrlButton *) { - SendMessage(GetDlgItem(m_hwnd, IDC_ITEMS2), NSM_FINDNEXT, ptrW(edtSearchText.GetText()), 0); + m_histControl.SendMsg(NSM_FINDNEXT, ptrW(edtSearchText.GetText()), 0); } void onClick_FindPrev(CCtrlButton *) { - SendMessage(GetDlgItem(m_hwnd, IDC_ITEMS2), NSM_FINDPREV, ptrW(edtSearchText.GetText()), 0); + m_histControl.SendMsg(NSM_FINDPREV, ptrW(edtSearchText.GetText()), 0); } @@ -709,7 +710,7 @@ public: INT_PTR DlgProc(UINT msg, WPARAM wParam, LPARAM lParam) override { if ((msg >= NSM_FIRST) && (msg < NSM_LAST)) { - LPARAM result = SendMessage(GetDlgItem(m_hwnd, IDC_ITEMS2), msg, wParam, lParam); + LPARAM result = m_histControl.SendMsg(msg, wParam, lParam); SetWindowLongPtr(m_hwnd, DWLP_MSGRESULT, result); return result; } @@ -858,25 +859,6 @@ public: // ShowWindow(GetDlgItem(m_hwnd, IDC_TIMETREE), SW_SHOW); // ShowWindow(GetDlgItem(m_hwnd, IDC_ITEMS2), SW_SHOW); // ShowWindow(GetDlgItem(m_hwnd, IDC_SEARCHICON), SW_SHOW); - - /* - case UM_JUMP2TIME: - { - for (int i = 0; i < eventCount; i++) - { - ItemData *idata = (ItemData *)SendMessage(GetDlgItem(m_hwnd, IDC_ITEMS), LB_GETITEMDATA, i, 0); - if (idbe->timestamp >= wParam) - { - SendMessage(GetDlgItem(m_hwnd, IDC_ITEMS), LB_SETCARETINDEX, i, 0); - SendMessage(GetDlgItem(m_hwnd, IDC_ITEMS), LB_SETTOPINDEX, i, 0); - SendMessage(GetDlgItem(m_hwnd, IDC_ITEMS), LB_SELITEMRANGE, FALSE, MAKELPARAM(0,eventCount)); - SendMessage(GetDlgItem(m_hwnd, IDC_ITEMS), LB_SELITEMRANGE, TRUE, MAKELPARAM(i,i)); - break; - } - } - return TRUE; - } - */ }; INT_PTR svcShowNewstory(WPARAM hContact, LPARAM) diff --git a/plugins/NewStory/src/history.h b/plugins/NewStory/src/history.h index ff0104c790..00e9ccfded 100644 --- a/plugins/NewStory/src/history.h +++ b/plugins/NewStory/src/history.h @@ -24,10 +24,7 @@ enum UM_GETEVENT, UM_GETEVENTTEXT, UM_GETEVENTCONTACT, - UM_GETEVENTHANDLE, - // UM_GETEVENTDATA, - - UM_JUMP2TIME + UM_GETEVENTHANDLE }; extern MWindowList hNewstoryWindows; diff --git a/plugins/NewStory/src/history_control.cpp b/plugins/NewStory/src/history_control.cpp index d7fb75cc37..da8dcecd5b 100644 --- a/plugins/NewStory/src/history_control.cpp +++ b/plugins/NewStory/src/history_control.cpp @@ -1,23 +1,7 @@ #include "stdafx.h" -LRESULT CALLBACK NewstoryListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); - HANDLE htuLog = 0; -void InitNewstoryControl() -{ - htuLog = MTextRegister("Newstory", MTEXT_FANCY_DEFAULT | MTEXT_SYSTEM_HICONS); - - WNDCLASS wndclass = {}; - wndclass.style = /*CS_HREDRAW | CS_VREDRAW | */CS_DBLCLKS | CS_GLOBALCLASS; - wndclass.lpfnWndProc = NewstoryListWndProc; - wndclass.cbWndExtra = sizeof(void *); - wndclass.hInstance = g_plugin.getInst(); - wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); - wndclass.lpszClassName = _T(NEWSTORYLIST_CLASS); - RegisterClass(&wndclass); -} - ///////////////////////////////////////////////////////////////////////// // Control utilities, types and constants @@ -25,11 +9,11 @@ struct NewstoryListData : public MZeroedObject { HistoryArray items; - DWORD scrollTopItem; // topmost item + int scrollTopItem; // topmost item int scrollTopPixel; // y coord of topmost item, this should be negative or zero - DWORD caret; + int caret; int cachedWindowHeight; - DWORD cachedMaxTopItem; // the largest ID of top item to avoid empty space + int cachedMaxTopItem; // the largest ID of top item to avoid empty space int cachedMaxTopPixel; RECT rcLastPaint; @@ -40,13 +24,6 @@ struct NewstoryListData : public MZeroedObject #define AVERAGE_ITEM_HEIGHT 100 -//static HFONT CopyFont(HFONT hfnt) -//{ -// LOGFONT lf; -// GetObject(hfnt, sizeof(lf), &lf); -// return CreateFontIndirect(&lf); -//} - static void ScrollListBy(HWND hwnd, NewstoryListData *data, int scrollItems, int scrollPixels); static void EnsureVisible(HWND hwnd, NewstoryListData *data, int item); static void FixScrollPosition(HWND hwnd, NewstoryListData *data); @@ -56,7 +33,6 @@ static void EndEditItem(HWND hwnd, NewstoryListData *data); static int LayoutItem(HWND hwnd, HistoryArray *items, int index); static int PaintItem(HDC hdc, HistoryArray *items, int index, int top, int width); - // Edit box static WNDPROC OldEditWndProc; static LRESULT CALLBACK HistoryEditWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) @@ -94,7 +70,378 @@ static LRESULT CALLBACK HistoryEditWndProc(HWND hwnd, UINT msg, WPARAM wParam, L } ///////////////////////////////////////////////////////////////////////// +// Utilities + +static void ScrollListBy(HWND hwnd, NewstoryListData *data, int scrollItems, int scrollPixels) +{ + if (scrollItems) { + data->scrollTopItem += scrollItems; + data->scrollTopPixel = 0; + } + else if (scrollPixels) { + data->scrollTopPixel += scrollPixels; + if (data->scrollTopPixel > 0) { + while ((data->scrollTopPixel > 0) && data->scrollTopItem) { + data->scrollTopItem--; + int itemHeight = LayoutItem(hwnd, &data->items, data->scrollTopItem); + data->scrollTopPixel -= itemHeight; + } + + if (data->scrollTopPixel > 0) { + data->scrollTopPixel = 0; + } + } + else if (data->scrollTopPixel < 0) { + int maxItem = data->items.getCount(); + int itemHeight = LayoutItem(hwnd, &data->items, data->scrollTopItem); + while ((-data->scrollTopPixel > itemHeight) && (data->scrollTopItem < maxItem)) { + data->scrollTopPixel += itemHeight; + data->scrollTopItem++; + itemHeight = LayoutItem(hwnd, &data->items, data->scrollTopItem); + } + } + } + + FixScrollPosition(hwnd, data); +} + +static void EnsureVisible(HWND hwnd, NewstoryListData *data, int item) +{ + if (data->scrollTopItem >= item) { + data->scrollTopItem = item; + data->scrollTopPixel = 0; + } + else { + RECT rc; GetClientRect(hwnd, &rc); + int height = rc.bottom - rc.top; + int top = data->scrollTopPixel; + int idx = data->scrollTopItem; + int itemHeight = LayoutItem(hwnd, &data->items, idx); + bool found = false; + while (top < height) { + if (idx == item) { + itemHeight = LayoutItem(hwnd, &data->items, idx); + if (top + itemHeight > height) + ScrollListBy(hwnd, data, 0, height - top - itemHeight); + found = true; + break; + } + top += itemHeight; + idx++; + itemHeight = LayoutItem(hwnd, &data->items, idx); + } + if (!found) { + data->scrollTopItem = item; + data->scrollTopPixel = 0; + } + } + FixScrollPosition(hwnd, data); +} + +static void FixScrollPosition(HWND hwnd, NewstoryListData *data) +{ + EndEditItem(hwnd, data); + + RECT rc; + GetWindowRect(hwnd, &rc); + int windowHeight = rc.bottom - rc.top; + + if (windowHeight != data->cachedWindowHeight) { + int maxTopItem = 0; + int tmp = 0; + for (maxTopItem = data->items.getCount(); (maxTopItem > 0) && (tmp < windowHeight); maxTopItem--) + tmp += LayoutItem(hwnd, &data->items, maxTopItem - 1); + data->cachedMaxTopItem = maxTopItem; + data->cachedWindowHeight = windowHeight; + data->cachedMaxTopPixel = (windowHeight < tmp) ? windowHeight - tmp : 0; + } + + if (data->scrollTopItem < 0) { + data->scrollTopItem = 0; + } + + if ((data->scrollTopItem > data->cachedMaxTopItem) || + ((data->scrollTopItem == data->cachedMaxTopItem) && (data->scrollTopPixel < data->cachedMaxTopPixel))) { + data->scrollTopItem = data->cachedMaxTopItem; + data->scrollTopPixel = data->cachedMaxTopPixel; + } + RecalcScrollBar(hwnd, data); +} + +static void RecalcScrollBar(HWND hwnd, NewstoryListData *data) +{ + SCROLLINFO si = { 0 }; + RECT clRect; + GetClientRect(hwnd, &clRect); + si.cbSize = sizeof(si); + si.fMask = SIF_ALL; + si.nMin = 0; + si.nMax = data->items.getCount() * AVERAGE_ITEM_HEIGHT; + si.nPage = clRect.bottom; + si.nPos = data->scrollTopItem * AVERAGE_ITEM_HEIGHT; + SetScrollInfo(hwnd, SB_VERT, &si, TRUE); +} + +static void BeginEditItem(HWND hwnd, NewstoryListData *data, int index) +{ + if (data->hwndEditBox) + EndEditItem(hwnd, data); + + if (data->scrollTopItem > index) + return; + + RECT rc; GetClientRect(hwnd, &rc); + int height = rc.bottom - rc.top; + + int top = data->scrollTopPixel; + int idx = data->scrollTopItem; + int itemHeight = LayoutItem(hwnd, &data->items, idx); + while (top < height) { + if (idx == index) { + HistoryArray::ItemData *item = data->items.get(index, ELM_DATA); + + int tpl; + int fontid; + int colorid; + switch (item->dbe.eventType) { + case EVENTTYPE_MESSAGE: + tpl = TPL_COPY_MESSAGE; + fontid = !(item->dbe.flags & DBEF_SENT) ? FONT_INMSG : FONT_OUTMSG; + colorid = !(item->dbe.flags & DBEF_SENT) ? COLOR_INMSG : COLOR_OUTMSG; + break; + + case EVENTTYPE_FILE: + tpl = TPL_COPY_FILE; + fontid = !(item->dbe.flags & DBEF_SENT) ? FONT_INFILE : FONT_OUTFILE; + colorid = !(item->dbe.flags & DBEF_SENT) ? COLOR_INFILE : COLOR_OUTFILE; + break; + + case EVENTTYPE_STATUSCHANGE: + tpl = TPL_COPY_SIGN; + fontid = FONT_STATUS; + colorid = COLOR_STATUS; + break; + + case EVENTTYPE_AUTHREQUEST: + tpl = TPL_COPY_AUTH; + fontid = FONT_INOTHER; + colorid = COLOR_INOTHER; + break; + + case EVENTTYPE_ADDED: + tpl = TPL_COPY_ADDED; + fontid = FONT_INOTHER; + colorid = COLOR_INOTHER; + break; + + case EVENTTYPE_JABBER_PRESENCE: + tpl = TPL_COPY_PRESENCE; + fontid = !(item->dbe.flags & DBEF_SENT) ? FONT_INOTHER : FONT_OUTOTHER; + colorid = !(item->dbe.flags & DBEF_SENT) ? COLOR_INOTHER : COLOR_OUTOTHER; + break; + + default: + tpl = TPL_COPY_OTHER; + fontid = !(item->dbe.flags & DBEF_SENT) ? FONT_INOTHER : FONT_OUTOTHER; + colorid = !(item->dbe.flags & DBEF_SENT) ? COLOR_INOTHER : COLOR_OUTOTHER; + break; + } + + ptrW text(TplFormatString(tpl, item->hContact, item)); + data->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(data->hwndEditBox, GWLP_WNDPROC, (LONG_PTR)HistoryEditWndProc); + SendMessage(data->hwndEditBox, WM_SETFONT, (WPARAM)fonts[fontid].hfnt, 0); + SendMessage(data->hwndEditBox, EM_SETMARGINS, EC_RIGHTMARGIN, 100); + SendMessage(data->hwndEditBox, EM_SETSEL, 0, (LPARAM)(-1)); + ShowWindow(data->hwndEditBox, SW_SHOW); + SetFocus(data->hwndEditBox); + break; + } + top += itemHeight; + idx++; + itemHeight = LayoutItem(hwnd, &data->items, idx); + } +} + +static void EndEditItem(HWND, NewstoryListData *data) +{ + DestroyWindow(data->hwndEditBox); + data->hwndEditBox = 0; +} + +static int LayoutItem(HWND hwnd, HistoryArray *items, int index) +{ + HDC hdc = GetDC(hwnd); + RECT rc; GetClientRect(hwnd, &rc); + int width = rc.right - rc.left; + + HistoryArray::ItemData *item = items->get(index, ELM_DATA); + if (!item) return 0; + + int tpl; + int fontid; + switch (item->dbe.eventType) { + case EVENTTYPE_MESSAGE: + tpl = TPL_MESSAGE; + fontid = !(item->dbe.flags & DBEF_SENT) ? FONT_INMSG : FONT_OUTMSG; + break; + + case EVENTTYPE_FILE: + tpl = TPL_FILE; + fontid = !(item->dbe.flags & DBEF_SENT) ? FONT_INFILE : FONT_OUTFILE; + break; + + case EVENTTYPE_STATUSCHANGE: + tpl = TPL_SIGN; + fontid = FONT_STATUS; + break; + + case EVENTTYPE_AUTHREQUEST: + tpl = TPL_AUTH; + fontid = FONT_INOTHER; + break; + + case EVENTTYPE_ADDED: + tpl = TPL_ADDED; + fontid = FONT_INOTHER; + break; + + case EVENTTYPE_JABBER_PRESENCE: + tpl = TPL_PRESENCE; + fontid = !(item->dbe.flags & DBEF_SENT) ? FONT_INOTHER : FONT_OUTOTHER; + break; + + default: + tpl = TPL_OTHER; + fontid = !(item->dbe.flags & DBEF_SENT) ? FONT_INOTHER : FONT_OUTOTHER; + break; + } + + HFONT hfnt = (HFONT)SelectObject(hdc, fonts[fontid].hfnt); + if (!item->data) + item->data = MTextCreateW(htuLog, ptrW(TplFormatString(tpl, item->hContact, item))); + + SIZE sz; + sz.cx = width - 6; + MTextMeasure(hdc, &sz, (HANDLE)item->data); + + SelectObject(hdc, hfnt); + + ReleaseDC(hwnd, hdc); + return sz.cy + 5; +} + +static int PaintItem(HDC hdc, HistoryArray *items, int index, int top, int width) +{ + if (!items) return 0; + HistoryArray::ItemData *item = items->get(index, ELM_DATA); + + // LOGFONT lfText; + COLORREF clText, clBack, clLine; + int tpl; + int fontid; + int colorid; + switch (item->dbe.eventType) { + case EVENTTYPE_MESSAGE: + tpl = TPL_MESSAGE; + fontid = !(item->dbe.flags & DBEF_SENT) ? FONT_INMSG : FONT_OUTMSG; + colorid = !(item->dbe.flags & DBEF_SENT) ? COLOR_INMSG : COLOR_OUTMSG; + break; + + case EVENTTYPE_FILE: + tpl = TPL_FILE; + fontid = !(item->dbe.flags & DBEF_SENT) ? FONT_INFILE : FONT_OUTFILE; + colorid = !(item->dbe.flags & DBEF_SENT) ? COLOR_INFILE : COLOR_OUTFILE; + break; + + case EVENTTYPE_STATUSCHANGE: + tpl = TPL_SIGN; + fontid = FONT_STATUS; + colorid = COLOR_STATUS; + break; + + case EVENTTYPE_AUTHREQUEST: + tpl = TPL_AUTH; + fontid = FONT_INOTHER; + colorid = COLOR_INOTHER; + break; + + case EVENTTYPE_ADDED: + tpl = TPL_ADDED; + fontid = FONT_INOTHER; + colorid = COLOR_INOTHER; + break; + + case EVENTTYPE_JABBER_PRESENCE: + tpl = TPL_PRESENCE; + fontid = !(item->dbe.flags & DBEF_SENT) ? FONT_INOTHER : FONT_OUTOTHER; + colorid = !(item->dbe.flags & DBEF_SENT) ? COLOR_INOTHER : COLOR_OUTOTHER; + break; + + default: + tpl = TPL_OTHER; + fontid = !(item->dbe.flags & DBEF_SENT) ? FONT_INOTHER : FONT_OUTOTHER; + colorid = !(item->dbe.flags & DBEF_SENT) ? COLOR_INOTHER : COLOR_OUTOTHER; + break; + } + clText = fonts[fontid].cl; + if (item->flags & HIF_SELECTED) { + MTextSendMessage(0, item->data, EM_SETSEL, 0, -1); + clText = colors[COLOR_SELTEXT].cl; + clLine = GetSysColor(COLOR_HIGHLIGHTTEXT); + clBack = GetSysColor(COLOR_HIGHLIGHT); + } + else { + MTextSendMessage(0, item->data, EM_SETSEL, 0, 0); + clLine = colors[COLOR_SELECTED].cl; + clBack = colors[colorid].cl; + } + + if (!item->data) { + wchar_t *buf = TplFormatString(tpl, item->hContact, item); + item->data = MTextCreateW(htuLog, buf); + mir_free(buf); + if (!item->data) + return 0; + } + + SIZE sz; + sz.cx = width - 6; + HFONT hfnt = (HFONT)SelectObject(hdc, fonts[fontid].hfnt); + MTextMeasure(hdc, &sz, (HANDLE)item->data); + SelectObject(hdc, hfnt); + int height = sz.cy + 5; + + RECT rc; + SetRect(&rc, 0, top, width, top + height); + + HBRUSH hbr; + hbr = CreateSolidBrush(clBack); + FillRect(hdc, &rc, hbr); + + SetTextColor(hdc, clText); + SetBkMode(hdc, TRANSPARENT); + + POINT pos; + pos.x = 3; + pos.y = top + 2; + hfnt = (HFONT)SelectObject(hdc, fonts[fontid].hfnt); + MTextDisplay(hdc, pos, sz, (HANDLE)item->data); + SelectObject(hdc, hfnt); + + DeleteObject(hbr); + + HPEN hpn = (HPEN)SelectObject(hdc, CreatePen(PS_SOLID, 1, clLine)); + MoveToEx(hdc, rc.left, rc.bottom - 1, 0); + LineTo(hdc, rc.right, rc.bottom - 1); + DeleteObject(SelectObject(hdc, hpn)); + + return height; +} + +///////////////////////////////////////////////////////////////////////// // WndProc + LRESULT CALLBACK NewstoryListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { NewstoryListData *data = (NewstoryListData *)GetWindowLongPtr(hwnd, 0); @@ -114,7 +461,7 @@ LRESULT CALLBACK NewstoryListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM InvalidateRect(hwnd, 0, FALSE); break; - // History list control messages + // History list control messages case NSM_GETCOUNT: return data->items.getCount(); @@ -216,19 +563,14 @@ LRESULT CALLBACK NewstoryListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM } case NSM_SETCARET: - { - if ((wParam >= 0) && (wParam < data->items.getCount())) { - data->caret = wParam; - if (lParam) { - SendMessage(hwnd, NSM_ENSUREVISIBLE, data->caret, 0); - } - } + if ((wParam >= 0) && (wParam < data->items.getCount())) { + data->caret = wParam; + if (lParam) + SendMessage(hwnd, NSM_ENSUREVISIBLE, data->caret, 0); } case NSM_GETCARET: - { - return data->caret; - } + return data->caret; case NSM_FINDNEXT: { @@ -250,6 +592,19 @@ LRESULT CALLBACK NewstoryListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM return id; } + case NSM_SEEKTIME: + { + int eventCount = data->items.getCount(); + for (int i = 0; i < eventCount; i++) { + auto *item = data->items.get(i, ELM_NOTHING); + if (item->dbe.timestamp >= wParam) { + SendMessage(hwnd, NSM_SETCARET, i, TRUE); + break; + } + } + } + return TRUE; + case NSM_COPY: { CMStringW res; @@ -462,7 +817,7 @@ LRESULT CALLBACK NewstoryListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM case WM_MOUSEWHEEL: { - DWORD s_scrollTopItem = data->scrollTopItem; + int s_scrollTopItem = data->scrollTopItem; int s_scrollTopPixel = data->scrollTopPixel; UINT scrollLines; @@ -477,7 +832,7 @@ LRESULT CALLBACK NewstoryListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM case WM_VSCROLL: { - DWORD s_scrollTopItem = data->scrollTopItem; + int s_scrollTopItem = data->scrollTopItem; int s_scrollTopPixel = data->scrollTopPixel; switch (LOWORD(wParam)) { @@ -540,371 +895,16 @@ LRESULT CALLBACK NewstoryListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM return DefWindowProc(hwnd, msg, wParam, lParam); } -///////////////////////////////////////////////////////////////////////// -// Utilities -static void ScrollListBy(HWND hwnd, NewstoryListData *data, int scrollItems, int scrollPixels) -{ - if (scrollItems) { - data->scrollTopItem += scrollItems; - data->scrollTopPixel = 0; - } - else if (scrollPixels) { - data->scrollTopPixel += scrollPixels; - if (data->scrollTopPixel > 0) { - while ((data->scrollTopPixel > 0) && data->scrollTopItem) { - data->scrollTopItem--; - int itemHeight = LayoutItem(hwnd, &data->items, data->scrollTopItem); - data->scrollTopPixel -= itemHeight; - } - - if (data->scrollTopPixel > 0) { - data->scrollTopPixel = 0; - } - } - else if (data->scrollTopPixel < 0) { - int maxItem = data->items.getCount(); - int itemHeight = LayoutItem(hwnd, &data->items, data->scrollTopItem); - while ((-data->scrollTopPixel > itemHeight) && (data->scrollTopItem < maxItem)) { - data->scrollTopPixel += itemHeight; - data->scrollTopItem++; - itemHeight = LayoutItem(hwnd, &data->items, data->scrollTopItem); - } - } - } - - FixScrollPosition(hwnd, data); -} - -static void EnsureVisible(HWND hwnd, NewstoryListData *data, int item) -{ - if (data->scrollTopItem >= item) { - data->scrollTopItem = item; - data->scrollTopPixel = 0; - } - else { - RECT rc; GetClientRect(hwnd, &rc); - int height = rc.bottom - rc.top; - int top = data->scrollTopPixel; - int idx = data->scrollTopItem; - int itemHeight = LayoutItem(hwnd, &data->items, idx); - bool found = false; - while (top < height) { - if (idx == item) { - itemHeight = LayoutItem(hwnd, &data->items, idx); - if (top + itemHeight > height) - ScrollListBy(hwnd, data, 0, height - top - itemHeight); - found = true; - break; - } - top += itemHeight; - idx++; - itemHeight = LayoutItem(hwnd, &data->items, idx); - } - if (!found) { - data->scrollTopItem = item; - data->scrollTopPixel = 0; - } - } - FixScrollPosition(hwnd, data); -} - -static void FixScrollPosition(HWND hwnd, NewstoryListData *data) -{ - EndEditItem(hwnd, data); - - RECT rc; - GetWindowRect(hwnd, &rc); - int windowHeight = rc.bottom - rc.top; - - if (windowHeight != data->cachedWindowHeight) { - int maxTopItem = 0; - int tmp = 0; - for (maxTopItem = data->items.getCount(); (maxTopItem > 0) && (tmp < windowHeight); maxTopItem--) - tmp += LayoutItem(hwnd, &data->items, maxTopItem - 1); - data->cachedMaxTopItem = maxTopItem; - data->cachedWindowHeight = windowHeight; - data->cachedMaxTopPixel = (windowHeight < tmp) ? windowHeight - tmp : 0; - } - - if (data->scrollTopItem < 0) { - data->scrollTopItem = 0; - } - - if ((data->scrollTopItem > data->cachedMaxTopItem) || - ((data->scrollTopItem == data->cachedMaxTopItem) && (data->scrollTopPixel < data->cachedMaxTopPixel))) { - data->scrollTopItem = data->cachedMaxTopItem; - data->scrollTopPixel = data->cachedMaxTopPixel; - } - RecalcScrollBar(hwnd, data); -} - -static void RecalcScrollBar(HWND hwnd, NewstoryListData *data) -{ - SCROLLINFO si = { 0 }; - RECT clRect; - GetClientRect(hwnd, &clRect); - si.cbSize = sizeof(si); - si.fMask = SIF_ALL; - si.nMin = 0; - si.nMax = data->items.getCount() * AVERAGE_ITEM_HEIGHT; - si.nPage = clRect.bottom; - si.nPos = data->scrollTopItem * AVERAGE_ITEM_HEIGHT; - SetScrollInfo(hwnd, SB_VERT, &si, TRUE); -} - -static void BeginEditItem(HWND hwnd, NewstoryListData *data, int index) -{ - if (data->hwndEditBox) - EndEditItem(hwnd, data); - - if (data->scrollTopItem > index) - return; - - RECT rc; GetClientRect(hwnd, &rc); - int height = rc.bottom - rc.top; - - int top = data->scrollTopPixel; - int idx = data->scrollTopItem; - int itemHeight = LayoutItem(hwnd, &data->items, idx); - while (top < height) { - if (idx == index) { - HistoryArray::ItemData *item = data->items.get(index, ELM_DATA); - - int tpl; - int fontid; - int colorid; - switch (item->dbe.eventType) { - case EVENTTYPE_MESSAGE: - tpl = TPL_COPY_MESSAGE; - fontid = !(item->dbe.flags & DBEF_SENT) ? FONT_INMSG : FONT_OUTMSG; - colorid = !(item->dbe.flags & DBEF_SENT) ? COLOR_INMSG : COLOR_OUTMSG; - break; - - case EVENTTYPE_FILE: - tpl = TPL_COPY_FILE; - fontid = !(item->dbe.flags & DBEF_SENT) ? FONT_INFILE : FONT_OUTFILE; - colorid = !(item->dbe.flags & DBEF_SENT) ? COLOR_INFILE : COLOR_OUTFILE; - break; - - case EVENTTYPE_STATUSCHANGE: - tpl = TPL_COPY_SIGN; - fontid = FONT_STATUS; - colorid = COLOR_STATUS; - break; - - case EVENTTYPE_AUTHREQUEST: - tpl = TPL_COPY_AUTH; - fontid = FONT_INOTHER; - colorid = COLOR_INOTHER; - break; - - case EVENTTYPE_ADDED: - tpl = TPL_COPY_ADDED; - fontid = FONT_INOTHER; - colorid = COLOR_INOTHER; - break; - - case EVENTTYPE_JABBER_PRESENCE: - tpl = TPL_COPY_PRESENCE; - fontid = !(item->dbe.flags & DBEF_SENT) ? FONT_INOTHER : FONT_OUTOTHER; - colorid = !(item->dbe.flags & DBEF_SENT) ? COLOR_INOTHER : COLOR_OUTOTHER; - break; - - default: - tpl = TPL_COPY_OTHER; - fontid = !(item->dbe.flags & DBEF_SENT) ? FONT_INOTHER : FONT_OUTOTHER; - colorid = !(item->dbe.flags & DBEF_SENT) ? COLOR_INOTHER : COLOR_OUTOTHER; - break; - } - - ptrW text(TplFormatString(tpl, item->hContact, item)); - data->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(data->hwndEditBox, GWLP_WNDPROC, (LONG_PTR)HistoryEditWndProc); - SendMessage(data->hwndEditBox, WM_SETFONT, (WPARAM)fonts[fontid].hfnt, 0); - SendMessage(data->hwndEditBox, EM_SETMARGINS, EC_RIGHTMARGIN, 100); - SendMessage(data->hwndEditBox, EM_SETSEL, 0, (LPARAM)(-1)); - ShowWindow(data->hwndEditBox, SW_SHOW); - SetFocus(data->hwndEditBox); - break; - } - top += itemHeight; - idx++; - itemHeight = LayoutItem(hwnd, &data->items, idx); - } -} - -static void EndEditItem(HWND, NewstoryListData *data) -{ - DestroyWindow(data->hwndEditBox); - data->hwndEditBox = 0; -} - -static int LayoutItem(HWND hwnd, HistoryArray *items, int index) -{ - HDC hdc = GetDC(hwnd); - RECT rc; GetClientRect(hwnd, &rc); - int width = rc.right - rc.left; - - HistoryArray::ItemData *item = items->get(index, ELM_DATA); - if (!item) return 0; - - int tpl; - int fontid; - switch (item->dbe.eventType) { - case EVENTTYPE_MESSAGE: - tpl = TPL_MESSAGE; - fontid = !(item->dbe.flags & DBEF_SENT) ? FONT_INMSG : FONT_OUTMSG; - break; - - case EVENTTYPE_FILE: - tpl = TPL_FILE; - fontid = !(item->dbe.flags & DBEF_SENT) ? FONT_INFILE : FONT_OUTFILE; - break; - - case EVENTTYPE_STATUSCHANGE: - tpl = TPL_SIGN; - fontid = FONT_STATUS; - break; - - case EVENTTYPE_AUTHREQUEST: - tpl = TPL_AUTH; - fontid = FONT_INOTHER; - break; - - case EVENTTYPE_ADDED: - tpl = TPL_ADDED; - fontid = FONT_INOTHER; - break; - - case EVENTTYPE_JABBER_PRESENCE: - tpl = TPL_PRESENCE; - fontid = !(item->dbe.flags & DBEF_SENT) ? FONT_INOTHER : FONT_OUTOTHER; - break; - - default: - tpl = TPL_OTHER; - fontid = !(item->dbe.flags & DBEF_SENT) ? FONT_INOTHER : FONT_OUTOTHER; - break; - } - - HFONT hfnt = (HFONT)SelectObject(hdc, fonts[fontid].hfnt); - if (!item->data) - item->data = MTextCreateW(htuLog, ptrW(TplFormatString(tpl, item->hContact, item))); - - SIZE sz; - sz.cx = width - 6; - MTextMeasure(hdc, &sz, (HANDLE)item->data); - - SelectObject(hdc, hfnt); - - ReleaseDC(hwnd, hdc); - return sz.cy + 5; -} - -static int PaintItem(HDC hdc, HistoryArray *items, int index, int top, int width) +void InitNewstoryControl() { - if (!items) return 0; - HistoryArray::ItemData *item = items->get(index, ELM_DATA); - - // LOGFONT lfText; - COLORREF clText, clBack, clLine; - int tpl; - int fontid; - int colorid; - switch (item->dbe.eventType) { - case EVENTTYPE_MESSAGE: - tpl = TPL_MESSAGE; - fontid = !(item->dbe.flags & DBEF_SENT) ? FONT_INMSG : FONT_OUTMSG; - colorid = !(item->dbe.flags & DBEF_SENT) ? COLOR_INMSG : COLOR_OUTMSG; - break; - - case EVENTTYPE_FILE: - tpl = TPL_FILE; - fontid = !(item->dbe.flags & DBEF_SENT) ? FONT_INFILE : FONT_OUTFILE; - colorid = !(item->dbe.flags & DBEF_SENT) ? COLOR_INFILE : COLOR_OUTFILE; - break; - - case EVENTTYPE_STATUSCHANGE: - tpl = TPL_SIGN; - fontid = FONT_STATUS; - colorid = COLOR_STATUS; - break; - - case EVENTTYPE_AUTHREQUEST: - tpl = TPL_AUTH; - fontid = FONT_INOTHER; - colorid = COLOR_INOTHER; - break; - - case EVENTTYPE_ADDED: - tpl = TPL_ADDED; - fontid = FONT_INOTHER; - colorid = COLOR_INOTHER; - break; - - case EVENTTYPE_JABBER_PRESENCE: - tpl = TPL_PRESENCE; - fontid = !(item->dbe.flags & DBEF_SENT) ? FONT_INOTHER : FONT_OUTOTHER; - colorid = !(item->dbe.flags & DBEF_SENT) ? COLOR_INOTHER : COLOR_OUTOTHER; - break; - - default: - tpl = TPL_OTHER; - fontid = !(item->dbe.flags & DBEF_SENT) ? FONT_INOTHER : FONT_OUTOTHER; - colorid = !(item->dbe.flags & DBEF_SENT) ? COLOR_INOTHER : COLOR_OUTOTHER; - break; - } - clText = fonts[fontid].cl; - if (item->flags & HIF_SELECTED) { - MTextSendMessage(0, item->data, EM_SETSEL, 0, -1); - // clText = colors[COLOR_SELTEXT].cl; - clLine = GetSysColor(COLOR_HIGHLIGHTTEXT); - clBack = GetSysColor(COLOR_HIGHLIGHT); //colors[COLOR_SELECTED].cl; - } - else { - MTextSendMessage(0, item->data, EM_SETSEL, 0, 0); - clLine = colors[COLOR_SELECTED].cl; - clBack = colors[colorid].cl; - } - - if (!item->data) { - wchar_t *buf = TplFormatString(tpl, item->hContact, item); - item->data = MTextCreateW(htuLog, buf); - mir_free(buf); - if (!item->data) - return 0; - } - - SIZE sz; - sz.cx = width - 6; - HFONT hfnt = (HFONT)SelectObject(hdc, fonts[fontid].hfnt); - MTextMeasure(hdc, &sz, (HANDLE)item->data); - SelectObject(hdc, hfnt); - int height = sz.cy + 5; - - RECT rc; - SetRect(&rc, 0, top, width, top + height); - - HBRUSH hbr; - hbr = CreateSolidBrush(clBack); - FillRect(hdc, &rc, hbr); - - SetTextColor(hdc, clText); - SetBkMode(hdc, TRANSPARENT); - - POINT pos; - pos.x = 3; - pos.y = top + 2; - hfnt = (HFONT)SelectObject(hdc, fonts[fontid].hfnt); - MTextDisplay(hdc, pos, sz, (HANDLE)item->data); - SelectObject(hdc, hfnt); - - DeleteObject(hbr); - - HPEN hpn = (HPEN)SelectObject(hdc, CreatePen(PS_SOLID, 1, clLine)); - MoveToEx(hdc, rc.left, rc.bottom - 1, 0); - LineTo(hdc, rc.right, rc.bottom - 1); - DeleteObject(SelectObject(hdc, hpn)); + htuLog = MTextRegister("Newstory", MTEXT_FANCY_DEFAULT | MTEXT_SYSTEM_HICONS); - return height; + WNDCLASS wndclass = {}; + wndclass.style = /*CS_HREDRAW | CS_VREDRAW | */CS_DBLCLKS | CS_GLOBALCLASS; + wndclass.lpfnWndProc = NewstoryListWndProc; + wndclass.cbWndExtra = sizeof(void *); + wndclass.hInstance = g_plugin.getInst(); + wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); + wndclass.lpszClassName = _T(NEWSTORYLIST_CLASS); + RegisterClass(&wndclass); } diff --git a/plugins/NewStory/src/history_control.h b/plugins/NewStory/src/history_control.h index 3b857bac75..f17da39fdb 100644 --- a/plugins/NewStory/src/history_control.h +++ b/plugins/NewStory/src/history_control.h @@ -57,6 +57,9 @@ enum // NSM_GETCOUNT, + // + NSM_SEEKTIME, + NSM_LAST }; |