diff options
Diffstat (limited to 'plugins/NewStory/src')
28 files changed, 5178 insertions, 0 deletions
diff --git a/plugins/NewStory/src/calendartool.cpp b/plugins/NewStory/src/calendartool.cpp new file mode 100644 index 0000000000..3d1e118fe7 --- /dev/null +++ b/plugins/NewStory/src/calendartool.cpp @@ -0,0 +1,91 @@ +#include "headers.h" + +struct CalendarToolData +{ + int x, y; +}; + +int CALLBACK CalendarToolDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + CalendarToolData *data = (CalendarToolData *)GetWindowLong(hwnd, GWL_USERDATA); + switch (msg) + { + case WM_INITDIALOG: + { + data = (CalendarToolData *)lParam; + SetWindowLong(hwnd, GWL_USERDATA, (LONG)data); + +// This causes ALL miranda dialogs to have drop-shadow enabled. That's bad =( +// SetClassLong(hwnd, GCL_STYLE, GetClassLong(hwnd, GCL_STYLE)|CS_DROPSHADOW); + + SetWindowPos(hwnd, HWND_TOP, data->x, data->y, 0, 0, SWP_NOSIZE); + return TRUE; + } + + case WM_ACTIVATE: + if (wParam == WA_INACTIVE) + PostMessage(hwnd, WM_CLOSE, 0, 0); + break; + + case WM_COMMAND: + { + switch(LOWORD(wParam)) + { + case IDOK: + { + EndDialog(hwnd, 0); + return TRUE; + } + + case IDCANCEL: + { + EndDialog(hwnd, 0); + return TRUE; + } + } + break; + } + + case WM_NOTIFY: + { + LPNMHDR hdr = (LPNMHDR)lParam; + if ((hdr->idFrom = IDC_MONTHCALENDAR1) && (hdr->code == MCN_SELECT)) + { + LPNMSELCHANGE lpnmsc = (LPNMSELCHANGE)lParam; + struct tm tm_sel; + tm_sel.tm_hour = tm_sel.tm_min = tm_sel.tm_sec = 0; + tm_sel.tm_isdst = 1; + tm_sel.tm_mday = lpnmsc->stSelStart.wDay; + tm_sel.tm_mon = lpnmsc->stSelStart.wMonth - 1; + tm_sel.tm_year = lpnmsc->stSelStart.wYear - 1900; + EndDialog(hwnd, mktime(&tm_sel)); + } + return TRUE; + } + + case WM_CLOSE: + { + DestroyWindow(hwnd); + return TRUE; + } + + case WM_DESTROY: + { + delete data; + data = 0; + SetWindowLong(hwnd, GWL_USERDATA, 0); + } + } + return FALSE; +} + +time_t CalendarTool_Show(HWND hwnd, int x, int y) +{ + CalendarToolData *data = new CalendarToolData; + data->x = x; + data->y = y; + +// HWND hwndTool = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_CALENDARTOOL), 0, CalendarToolDlgProc, (LPARAM)data); +// ShowWindow(hwndTool, SW_SHOWNORMAL); + return DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_CALENDARTOOL), 0, CalendarToolDlgProc, (LPARAM)data); +}
\ No newline at end of file diff --git a/plugins/NewStory/src/calendartool.h b/plugins/NewStory/src/calendartool.h new file mode 100644 index 0000000000..85729ef92f --- /dev/null +++ b/plugins/NewStory/src/calendartool.h @@ -0,0 +1,6 @@ +#ifndef __calendartool_h__ +#define __calendartool_h__ + +time_t CalendarTool_Show(HWND hwnd, int x, int y); + +#endif // __calendartool_h__
\ No newline at end of file diff --git a/plugins/NewStory/src/fonts.cpp b/plugins/NewStory/src/fonts.cpp new file mode 100644 index 0000000000..f454fdc976 --- /dev/null +++ b/plugins/NewStory/src/fonts.cpp @@ -0,0 +1,120 @@ +#include "headers.h" + +MyColourID colors[] = +{ + {0, {sizeof(ColourID), MODULETITLE, "Incoming Messages", MODULENAME, "ColorMsgIn", 0, RGB(0xff, 0xff, 0xff), 0}}, + {0, {sizeof(ColourID), MODULETITLE, "Outgoing Messages", MODULENAME, "ColorMsgOut", 0, RGB(0xff, 0xff, 0xff), 1}}, + + {0, {sizeof(ColourID), MODULETITLE, "Incoming Files", MODULENAME, "ColorFileIn", 0, RGB(0xff, 0xff, 0xff), 2}}, + {0, {sizeof(ColourID), MODULETITLE, "Outgoing Files", MODULENAME, "ColorFileOut", 0, RGB(0xff, 0xff, 0xff), 3}}, + + {0, {sizeof(ColourID), MODULETITLE, "Incoming URLs", MODULENAME, "ColorURLIn", 0, RGB(0xff, 0xff, 0xff), 4}}, + {0, {sizeof(ColourID), MODULETITLE, "Outgoing URLs", MODULENAME, "ColorURLOut", 0, RGB(0xff, 0xff, 0xff), 5}}, + + {0, {sizeof(ColourID), MODULETITLE, "Status changes", MODULENAME, "ColorStatus", 0, RGB(0xff, 0xff, 0xff), 6}}, + + {0, {sizeof(ColourID), MODULETITLE, "Other Outgoing Events", MODULENAME, "ColorOut", 0, RGB(0xff, 0xff, 0xff), 7}}, + {0, {sizeof(ColourID), MODULETITLE, "Other Incoming Events", MODULENAME, "ColorIn", 0, RGB(0xff, 0xff, 0xff), 8}}, + + {0, {sizeof(ColourID), MODULETITLE, "Selected Items", MODULENAME, "ColorSel", 0, RGB(0x60, 0x60, 0x60), 9}}, + {0, {sizeof(ColourID), MODULETITLE, "Selected Items (Text)", MODULENAME, "ColorSelTxt", 0, RGB(0xff, 0xff, 0xff), 10}} +}; + +MyFontID fonts[] = +{ + {0, 0, 0, {sizeof(FontID), MODULETITLE, "Incoming Messages", MODULENAME, "FontMsgIn", 0, {0}, 0}}, + {0, 0, 0, {sizeof(FontID), MODULETITLE, "Outgoing Messages", MODULENAME, "FontMsgOut", 0, {0}, 1}}, + + {0, 0, 0, {sizeof(FontID), MODULETITLE, "Incoming Files", MODULENAME, "FontFileIn", 0, {0}, 2}}, + {0, 0, 0, {sizeof(FontID), MODULETITLE, "Outgoing Files", MODULENAME, "FontFileOut", 0, {0}, 3}}, + + {0, 0, 0, {sizeof(FontID), MODULETITLE, "Incoming URLs", MODULENAME, "FontURLIn", 0, {0}, 4}}, + {0, 0, 0, {sizeof(FontID), MODULETITLE, "Outgoing URLs", MODULENAME, "FontURLOut", 0, {0}, 5}}, + + {0, 0, 0, {sizeof(FontID), MODULETITLE, "Status changes", MODULENAME, "FontStatus", 0, {0}, 6}}, + + {0, 0, 0, {sizeof(FontID), MODULETITLE, "Other Outgoing Events", MODULENAME, "FontOut", 0, {0}, 7}}, + {0, 0, 0, {sizeof(FontID), MODULETITLE, "Other Incoming Events", MODULENAME, "FontIn", 0, {0}, 8}} + +// {sizeof(FontID), MODULETITLE, "Default Text", MODULENAME, "FontDef", FIDF_SAVEPOINTSIZE, {0}, 0}, +// {sizeof(FontID), MODULETITLE, "Selected Item", MODULENAME, "FontSel", FIDF_SAVEPOINTSIZE, {0}, 1} +}; + +int evtFontsChanged(WPARAM, LPARAM) +{ + int i; + for (i = 0; i < COLOR_COUNT; i++) + { + colors[i].cl = (COLORREF)CallService(MS_COLOUR_GET, (WPARAM)&colors[i].info, 0); + } + for (i = 0; i < FONT_COUNT; i++) + { + fonts[i].cl = (COLORREF)CallService(MS_FONT_GET, (WPARAM)&fonts[i].info, (LPARAM)fonts[i].lf); + DeleteObject(fonts[i].hfnt); + fonts[i].hfnt = CreateFontIndirectA(fonts[i].lf); + } +// WindowList_Broadcast(hNewstoryWindows, UM_REDRAWLISTH, 0, 0); + return 0; +} + +void InitFonts() +{ + bool isFSInstalled = ServiceExists(MS_FONT_GET) ? true : false; + + int i; // damn msvc can't handle for(int i...) correctly! =( + + HookEvent(ME_FONT_RELOAD, evtFontsChanged); + HookEvent(ME_COLOUR_RELOAD, evtFontsChanged); + + if (isFSInstalled) + { + for (i = 0; i < COLOR_COUNT; i++) + { + CallService(MS_COLOUR_REGISTER, (WPARAM)&colors[i].info, 0); + colors[i].cl = (COLORREF)CallService(MS_COLOUR_GET, (WPARAM)&colors[i].info, 0); + } + for (i = 0; i < FONT_COUNT; i++) + { + CallService(MS_FONT_REGISTER, (WPARAM)&fonts[i].info, 0); + fonts[i].lf = (LOGFONTA *)malloc(sizeof(LOGFONTA)); + fonts[i].cl = (COLORREF)CallService(MS_FONT_GET, (WPARAM)&fonts[i].info, (LPARAM)fonts[i].lf); + fonts[i].hfnt = CreateFontIndirectA(fonts[i].lf); + //MessageBox(0, fonts[i].lf->lfFaceName, _T(""), MB_OK); + } + } else + { + LOGFONTA lfText = {0}; + lfText.lfHeight = -11; + lfText.lfWidth = lfText.lfEscapement = lfText.lfOrientation = 0; + lfText.lfItalic = lfText.lfUnderline = lfText.lfStrikeOut = FALSE; + lfText.lfCharSet = DEFAULT_CHARSET; + lfText.lfOutPrecision = OUT_DEFAULT_PRECIS; + lfText.lfClipPrecision = CLIP_DEFAULT_PRECIS; + lfText.lfQuality = DEFAULT_QUALITY; + lfText.lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS; + lstrcpyA(lfText.lfFaceName, "MS Shell Dlg"); + lfText.lfWeight = FW_REGULAR; + + for (i = 0; i < COLOR_COUNT; i++) + { + colors[i].cl = colors[i].info.defcolour; + } + for (i = 0; i < FONT_COUNT; i++) + { + fonts[i].lf = (LOGFONTA *)malloc(sizeof(LOGFONTA)); + *fonts[i].lf = lfText; + fonts[i].cl = RGB(0,0,0); + fonts[i].hfnt = CreateFontIndirectA(fonts[i].lf); + } + } +} + +void DestroyFonts() +{ + int i; + for (i = 0; i < FONT_COUNT; i++) + { + DeleteObject(fonts[i].hfnt); + free(fonts[i].lf); + } +}
\ No newline at end of file diff --git a/plugins/NewStory/src/fonts.h b/plugins/NewStory/src/fonts.h new file mode 100644 index 0000000000..cdb7f426d5 --- /dev/null +++ b/plugins/NewStory/src/fonts.h @@ -0,0 +1,57 @@ +#ifndef __fonts_h__ +#define __fonts_h__ + +enum +{ + COLOR_INMSG, + COLOR_OUTMSG, + COLOR_INFILE, + COLOR_OUTFILE, + COLOR_INURL, + COLOR_OUTURL, + COLOR_STATUS, + COLOR_INOTHER, + COLOR_OUTOTHER, + COLOR_SELECTED, + COLOR_SELTEXT, + COLOR_COUNT +}; + +struct MyColourID +{ + COLORREF cl; + ColourID info; +}; + +extern MyColourID colors[]; + +enum +{ + FONT_INMSG, + FONT_OUTMSG, + FONT_INFILE, + FONT_OUTFILE, + FONT_INURL, + FONT_OUTURL, + FONT_STATUS, + FONT_INOTHER, + FONT_OUTOTHER, +// FONT_DEFAULT, +// FONT_SELECTED, + FONT_COUNT +}; + +struct MyFontID +{ + COLORREF cl; + LOGFONTA *lf; + HFONT hfnt; + FontID info; +}; + +extern MyFontID fonts[]; + +void InitFonts(); +void DestroyFonts(); + +#endif // __fonts_h__
\ No newline at end of file diff --git a/plugins/NewStory/src/history.cpp b/plugins/NewStory/src/history.cpp new file mode 100644 index 0000000000..0bc77cdaa4 --- /dev/null +++ b/plugins/NewStory/src/history.cpp @@ -0,0 +1,1074 @@ +//////////////////////////////////////////////////////////////////////// +// NewStory -- new history viewer for Miranda IM +// (c) 2005 Victor Pavlychko (nullbyte@sotline.net.ua) +// Visit http://miranda-im.org/ for details on Miranda Instant Messenger +//////////////////////////////////////////////////////////////////////// + +/* +for the date picker: + case WM_ACTIVATE: + if (wParam == WA_INACTIVE) PostMessage(m_hwndDialog, WM_CLOSE, 0, 0); + break; +*/ + +#include "headers.h" + +HANDLE hNewstoryWindows = 0; + +int evtEventAdded(WPARAM wParam, LPARAM lParam) +{ + HWND hwnd = WindowList_Find(hNewstoryWindows, (HANDLE)wParam); + SendMessage(hwnd, UM_ADDEVENT, wParam, lParam); + return 0; +} + +int evtEventDeleted(WPARAM wParam, LPARAM lParam) +{ + HWND hwnd = WindowList_Find(hNewstoryWindows, (HANDLE)wParam); + SendMessage(hwnd, UM_REMOVEEVENT, wParam, lParam); + return 0; +} + +void InitHistory() +{ + hNewstoryWindows = (HANDLE)CallService(MS_UTILS_ALLOCWINDOWLIST, 0, 0); + + HookEvent(ME_DB_EVENT_ADDED, evtEventAdded); + HookEvent(ME_DB_EVENT_DELETED, evtEventDeleted); +} + +void FreeHistory() +{ +} + +enum +{ + HIST_SHOW_IN = 0x001, + HIST_SHOW_OUT = 0x002, + HIST_SHOW_MSGS = 0x004, + HIST_SHOW_FILES = 0x008, + HIST_SHOW_URLS = 0x010, + HIST_SHOW_STATUS = 0x020, + HIST_SHOW_OTHER = 0x040, + HIST_AUTO_FILTER = 0x080, +}; + +enum +{ + WND_OPT_TIMETREE = 0x01, + WND_OPT_SEARCHBAR = 0x02, + WND_OPT_FILTERBAR = 0x04 +}; + +enum +{ + WND_SPACING = 4, + TBTN_SIZE = 25, + TBTN_SPACER = 10 +}; + +enum +{ + TBTN_USERINFO, TBTN_USERMENU, TBTN_MESSAGE, + TBTN_SEARCH, TBTN_FILTER, TBTN_DATEPOPUP, + TBTN_COPY, TBTN_EXPORT, + TBTN_LOGOPTIONS, TBTN_SECURITY, TBTN_CLOSE, + TBTN_COUNT +}; + +int tbtnSpacing[TBTN_COUNT] = {0, 0, TBTN_SPACER, 0, 0, TBTN_SPACER, 0, -1, 0, 0, 0}; + +struct InfoBarEvents +{ + HWND hwndIco, hwndIcoIn, hwndIcoOut; + HWND hwndTxt, hwndTxtIn, hwndTxtOut; +}; + +struct WindowData +{ + HMENU hMenu; + WORD showFlags; + bool gonnaRedraw; + bool isContactHistory; + HANDLE hContact; + int lastYear, lastMonth, lastDay; + HTREEITEM hLastYear, hLastMonth, hLastDay; + bool disableTimeTreeChange; + + // window flags + DWORD wndOptions; + + // toolbar buttons + HWND hwndBtnToolbar[TBTN_COUNT]; + // main controls + HWND hwndTimeTree; + HWND hwndLog; + // searchbar + HWND hwndBtnCloseSearch, hwndBtnFindNext, hwndBtnFindPrev; + HWND hwndSearchText; + // statusbar + HWND hwndStatus; + // filter bar + HWND hwndChkDateFrom, hwndChkDateTo; + HWND hwndDateFrom, hwndDateTo; + InfoBarEvents ibMessages, ibFiles, ibUrls, ibTotal; +}; + +void LayoutFilterBar(HDWP hDwp, HWND hwnd, int x, int y, int w, InfoBarEvents *ib) +{ + hDwp = DeferWindowPos(hDwp, ib->hwndIco, 0, + x, y, 16, 16, SWP_NOZORDER); + hDwp = DeferWindowPos(hDwp, ib->hwndTxt, 0, + x+16+WND_SPACING, y, w-16-WND_SPACING, 16, SWP_NOZORDER); + + hDwp = DeferWindowPos(hDwp, ib->hwndIcoIn, 0, + x+16, y+16+WND_SPACING, 16, 16, SWP_NOZORDER); + hDwp = DeferWindowPos(hDwp, ib->hwndTxtIn, 0, + x+32+WND_SPACING, y+16+WND_SPACING, w-WND_SPACING-32, 16, SWP_NOZORDER); + + hDwp = DeferWindowPos(hDwp, ib->hwndIcoOut, 0, + x+16, y+(16+WND_SPACING)*2, 16, 16, SWP_NOZORDER); + hDwp = DeferWindowPos(hDwp, ib->hwndTxtOut, 0, + x+32+WND_SPACING, y+(16+WND_SPACING)*2, w-WND_SPACING-32, 16, SWP_NOZORDER); + +} + +void ShowHideControls(HWND hwnd, WindowData *data) +{ + int cmd; + + cmd = (data->wndOptions & WND_OPT_FILTERBAR) ? SW_SHOW : SW_HIDE; + ShowWindow(data->ibMessages.hwndIco, cmd); + ShowWindow(data->ibMessages.hwndIcoIn, cmd); + ShowWindow(data->ibMessages.hwndIcoOut, cmd); + ShowWindow(data->ibMessages.hwndTxt, cmd); + ShowWindow(data->ibMessages.hwndTxtIn, cmd); + ShowWindow(data->ibMessages.hwndTxtOut, cmd); + ShowWindow(data->ibFiles.hwndIco, cmd); + ShowWindow(data->ibFiles.hwndIcoIn, cmd); + ShowWindow(data->ibFiles.hwndIcoOut, cmd); + ShowWindow(data->ibFiles.hwndTxt, cmd); + ShowWindow(data->ibFiles.hwndTxtIn, cmd); + ShowWindow(data->ibFiles.hwndTxtOut, cmd); + ShowWindow(data->ibUrls.hwndIco, cmd); + ShowWindow(data->ibUrls.hwndIcoIn, cmd); + ShowWindow(data->ibUrls.hwndIcoOut, cmd); + ShowWindow(data->ibUrls.hwndTxt, cmd); + ShowWindow(data->ibUrls.hwndTxtIn, cmd); + ShowWindow(data->ibUrls.hwndTxtOut, cmd); + ShowWindow(data->ibTotal.hwndIco, cmd); + ShowWindow(data->ibTotal.hwndIcoIn, cmd); + ShowWindow(data->ibTotal.hwndIcoOut, cmd); + ShowWindow(data->ibTotal.hwndTxt, cmd); + ShowWindow(data->ibTotal.hwndTxtIn, cmd); + ShowWindow(data->ibTotal.hwndTxtOut, cmd); + ShowWindow(data->hwndDateFrom, cmd); + ShowWindow(data->hwndDateTo, cmd); + ShowWindow(data->hwndChkDateFrom, cmd); + ShowWindow(data->hwndChkDateTo, cmd); + ShowWindow(GetDlgItem(hwnd, IDC_IB_SEPARATOR), cmd); + + cmd = (data->wndOptions & WND_OPT_SEARCHBAR) ? SW_SHOW : SW_HIDE; + ShowWindow(data->hwndBtnCloseSearch, cmd); + ShowWindow(data->hwndBtnFindNext, cmd); + ShowWindow(data->hwndBtnFindPrev, cmd); + ShowWindow(data->hwndSearchText, cmd); +} + +void LayoutHistoryWnd(HWND hwnd, WindowData *data) +{ + int i; + RECT rc; + GetClientRect(hwnd, &rc); + int x, y; // tmp vars + int w = rc.right - rc.left; + int h = rc.bottom - rc.top; + + HDWP hDwp = BeginDeferWindowPos(50); + + // toolbar + int hToolBar = TBTN_SIZE + WND_SPACING; + x = WND_SPACING; + int btnReverse = -1; + for (i = 0; i < TBTN_COUNT; ++i) + { + hDwp = DeferWindowPos(hDwp, data->hwndBtnToolbar[i], 0, + x, WND_SPACING, + TBTN_SIZE, TBTN_SIZE, + SWP_NOZORDER); + x += TBTN_SIZE + tbtnSpacing[i]; + if (tbtnSpacing[i] < 0) + { + btnReverse = i; + break; + } + } + x = w - WND_SPACING - TBTN_SIZE; + for (i = TBTN_COUNT-1; i > btnReverse; --i) + { + hDwp = DeferWindowPos(hDwp, data->hwndBtnToolbar[i], 0, + x, WND_SPACING, + TBTN_SIZE, TBTN_SIZE, + SWP_NOZORDER); + x -= TBTN_SIZE + tbtnSpacing[i-1]; + } + + // infobar +// hDwp = DeferWindowPos(hDwp, data->hwndIcoProtocol, 0, +// w-100+WND_SPACING, WND_SPACING, +// 16, 16, +// SWP_NOZORDER); +// hDwp = DeferWindowPos(hDwp, data->hwndTxtNickname, 0, +// w-100+WND_SPACING*2+16, WND_SPACING, +// 100, 16, +// SWP_NOZORDER); +// hDwp = DeferWindowPos(hDwp, data->hwndTxtUID, 0, +// w-100+WND_SPACING*2+16, WND_SPACING*2+16, +// 100, 16, +// SWP_NOZORDER); + + // filter bar + int hFilterBar = 0; + if (data->wndOptions & WND_OPT_FILTERBAR) + { + hFilterBar = WND_SPACING + (16 + WND_SPACING)*3; + LayoutFilterBar(hDwp, hwnd, WND_SPACING+(WND_SPACING+75)*0, WND_SPACING*2 + hToolBar, 75, &data->ibMessages); + LayoutFilterBar(hDwp, hwnd, WND_SPACING+(WND_SPACING+75)*1, WND_SPACING*2 + hToolBar, 75, &data->ibFiles); + LayoutFilterBar(hDwp, hwnd, WND_SPACING+(WND_SPACING+75)*2, WND_SPACING*2 + hToolBar, 75, &data->ibUrls); + LayoutFilterBar(hDwp, hwnd, WND_SPACING+(WND_SPACING+75)*3, WND_SPACING*2 + hToolBar, 75, &data->ibTotal); + + GetWindowRect(data->hwndChkDateFrom, &rc); + x = rc.right - rc.left; + GetWindowRect(data->hwndDateFrom, &rc); + y = hToolBar + WND_SPACING + (WND_SPACING + (16 + WND_SPACING)*3 - (rc.bottom-rc.top)*2 - WND_SPACING)/2; + hDwp = DeferWindowPos(hDwp, data->hwndChkDateFrom, 0, + w-x-(rc.right-rc.left)-WND_SPACING*2, y, + x, rc.bottom-rc.top, + SWP_NOZORDER); + hDwp = DeferWindowPos(hDwp, data->hwndDateFrom, 0, + w-(rc.right-rc.left)-WND_SPACING, y, + rc.right-rc.left, rc.bottom-rc.top, + SWP_NOZORDER); + + hDwp = DeferWindowPos(hDwp, data->hwndChkDateTo, 0, + w-x-(rc.right-rc.left)-WND_SPACING*2, y + (rc.bottom-rc.top) + WND_SPACING, + x, rc.bottom-rc.top, + SWP_NOZORDER); + hDwp = DeferWindowPos(hDwp, data->hwndDateTo, 0, + w-(rc.right-rc.left)-WND_SPACING, y + (rc.bottom-rc.top) + WND_SPACING, + rc.right-rc.left, rc.bottom-rc.top, + SWP_NOZORDER); + + hDwp = DeferWindowPos(hDwp, GetDlgItem(hwnd, IDC_IB_SEPARATOR), 0, + WND_SPACING, hToolBar + WND_SPACING, + w-WND_SPACING*2, 2, + SWP_NOZORDER); + } + + // general + GetWindowRect(data->hwndStatus, &rc); + int hStatus = rc.bottom - rc.top; + hDwp = DeferWindowPos(hDwp, data->hwndStatus, 0, + 0, h-hStatus, + w, hStatus, + SWP_NOZORDER); + + int hSearch = 0; + if (data->wndOptions & WND_OPT_SEARCHBAR) + { + GetWindowRect(data->hwndSearchText, &rc); + hSearch = rc.bottom - rc.top; + hDwp = DeferWindowPos(hDwp, data->hwndBtnCloseSearch, 0, + WND_SPACING, h-hSearch-hStatus-WND_SPACING, + TBTN_SIZE, hSearch, SWP_NOZORDER); + hDwp = DeferWindowPos(hDwp, data->hwndSearchText, 0, + TBTN_SIZE+WND_SPACING*2, h-hSearch-hStatus-WND_SPACING, + w-WND_SPACING*4-TBTN_SIZE*3, hSearch, + SWP_NOZORDER); + hDwp = DeferWindowPos(hDwp, data->hwndBtnFindPrev, 0, + w-WND_SPACING-TBTN_SIZE*2, h-hSearch-hStatus-WND_SPACING, + TBTN_SIZE, hSearch, + SWP_NOZORDER); + hDwp = DeferWindowPos(hDwp, data->hwndBtnFindNext, 0, + w-WND_SPACING-TBTN_SIZE*1, h-hSearch-hStatus-WND_SPACING, + TBTN_SIZE, hSearch, + SWP_NOZORDER); + hSearch += WND_SPACING; + } + + hDwp = DeferWindowPos(hDwp, data->hwndLog, 0, + WND_SPACING, hToolBar+hFilterBar+WND_SPACING, + w-WND_SPACING*2, h-WND_SPACING*2-hFilterBar-hToolBar-hSearch-hStatus, + SWP_NOZORDER); + + EndDeferWindowPos(hDwp); +// InvalidateRect(hwnd, 0, FALSE); +} + +/* +bool ExportHistoryDialog(HANDLE hContact, HWND hwndHistory) +{ + int filterIndex = 0; + char *filter = 0; + char filterSize = 0; + + char *templates[100] = {0}; + int nTemplates = 0; + + WIN32_FIND_DATA ffd; + HANDLE hFind = FindFirstFile("plugins\\newstory\\x_*.txt", &ffd); + while (hFind != INVALID_HANDLE_VALUE) + { + char *fn = (char *)malloc(MAX_PATH); + wsprintf(fn, "plugins\\newstory\\%s", ffd.cFileName); + + char *szSignature = "newstory export template"; + char line[1024]; + FILE *f = fopen(fn, "r"); + fgets(line, 1024, f); + if (*line) line[lstrlen(line)-1] = 0; + if (!lstrcmp(line, szSignature)) + { + fgets(line, 1024, f); + if (*line) line[lstrlen(line)-1] = 0; + + char *title = strdup(Translate(line)); + + fgets(line, 1024, f); + if (*line) line[lstrlen(line)-1] = 0; + char *ext = line; + + // <title> (*.<ext>)\0*.<ext>\0 + int newFilterSize = filterSize + lstrlen(title) + 2*lstrlen(ext) + 9; + char *newFilter = (char *)calloc(newFilterSize+1, 1); + + if (filterSize) + memcpy(newFilter, filter, filterSize); + + char buf[1024]; + wsprintf(buf, "%s (*.%s)%c*.%s%c", title, ext, '\0', ext, '\0'); + memcpy(newFilter+filterSize, buf, newFilterSize-filterSize); + + free(filter); + filter = newFilter; + filterSize = newFilterSize; + + templates[nTemplates++] = fn; + + free(title); + } else + { + free(fn); + } + fclose(f); + + if (!FindNextFile(hFind, &ffd)) + break; + } + + + char filename[MAX_PATH] = {0}; + + OPENFILENAME ofn = {0}; + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = hwndHistory; + ofn.hInstance = hInst; + ofn.lpstrFilter = filter; + ofn.lpstrCustomFilter = 0; + ofn.nMaxCustFilter = 0; + ofn.nFilterIndex = filterIndex; + ofn.lpstrFile = filename; + ofn.nMaxFile = MAX_PATH; + ofn.lpstrFileTitle = 0; + ofn.nMaxFileTitle = 0; + ofn.lpstrInitialDir = 0; + ofn.lpstrTitle = Translate("Export History..."); + ofn.Flags = OFN_ENABLESIZING|OFN_LONGNAMES|OFN_NOCHANGEDIR|OFN_NOREADONLYRETURN|OFN_OVERWRITEPROMPT|OFN_PATHMUSTEXIST; + ofn.lpstrDefExt = 0; + ofn.lCustData = 0; + ofn.lpfnHook = 0; + ofn.lpTemplateName = 0; + ofn.FlagsEx = 0; + + if (GetSaveFileName(&ofn)) + { +// ofn.nFilterIndex; + ExportHistory(hContact, templates[ofn.nFilterIndex-1], ofn.lpstrFile, hwndHistory); + } + + for (int i = 0; i < 100; i++) + if (templates[i]) + free(templates[i]); + + return false; +} +*/ + +int CALLBACK HistoryDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + CallSnappingWindowProc(hwnd, msg, wParam, lParam); + + WindowData *data = (WindowData *)GetWindowLong(hwnd, GWL_USERDATA); + + if ((msg >= NSM_FIRST) && (msg < NSM_LAST)) + { + int result = SendMessage(GetDlgItem(hwnd, IDC_ITEMS2), msg, wParam, lParam); + SetWindowLong(hwnd, DWL_MSGRESULT, result); + return result; + } + + switch (msg) + { + case WM_INITDIALOG: + { + data = new WindowData; + data->hContact = (HANDLE)lParam; + data->disableTimeTreeChange = false; + data->showFlags = DBGetContactSettingWord(data->hContact, MODULENAME, "showFlags", 0x7f); + data->lastYear = data->lastMonth = data->lastDay = -1; + data->hLastYear = data->hLastMonth = data->hLastDay = 0; + + data->wndOptions = 0; + + // get handles + data->hwndBtnToolbar[TBTN_USERINFO] = GetDlgItem(hwnd, IDC_USERINFO); + data->hwndBtnToolbar[TBTN_USERMENU] = GetDlgItem(hwnd, IDC_USERMENU); + data->hwndBtnToolbar[TBTN_MESSAGE] = GetDlgItem(hwnd, IDC_MESSAGE); + data->hwndBtnToolbar[TBTN_SEARCH] = GetDlgItem(hwnd, IDC_SEARCH); + data->hwndBtnToolbar[TBTN_COPY] = GetDlgItem(hwnd, IDC_COPY); + data->hwndBtnToolbar[TBTN_EXPORT] = GetDlgItem(hwnd, IDC_EXPORT); + data->hwndBtnToolbar[TBTN_LOGOPTIONS] = GetDlgItem(hwnd, IDC_LOGOPTIONS); + data->hwndBtnToolbar[TBTN_FILTER] = GetDlgItem(hwnd, IDC_FILTER); + data->hwndBtnToolbar[TBTN_DATEPOPUP] = GetDlgItem(hwnd, IDC_DATEPOPUP); + data->hwndBtnToolbar[TBTN_SECURITY] = GetDlgItem(hwnd, IDC_SECURITY); + data->hwndBtnToolbar[TBTN_CLOSE] = GetDlgItem(hwnd, IDC_CLOSE); + data->hwndLog = GetDlgItem(hwnd, IDC_ITEMS2); + data->hwndBtnCloseSearch = GetDlgItem(hwnd, IDC_SEARCHICON); + data->hwndBtnFindPrev = GetDlgItem(hwnd, IDC_FINDPREV); + data->hwndBtnFindNext = GetDlgItem(hwnd, IDC_FINDNEXT); + data->hwndSearchText = GetDlgItem(hwnd, IDC_SEARCHTEXT); + data->hwndStatus = CreateWindowEx(0, STATUSCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP, 0, 0, 0, 0, hwnd, NULL, hInst, NULL); + SendMessage(data->hwndStatus, SB_SETMINHEIGHT, GetSystemMetrics(SM_CYSMICON), 0); + + // filterbar + SendMessage(data->hwndBtnToolbar[TBTN_FILTER], BUTTONSETASPUSHBTN, 0, 0); + SendMessage(data->hwndBtnToolbar[TBTN_SEARCH], BUTTONSETASPUSHBTN, 0, 0); + + data->hwndChkDateFrom = GetDlgItem(hwnd, IDC_CHK_DATE_FROM); + data->hwndChkDateTo= GetDlgItem(hwnd, IDC_CHK_DATE_TO); + data->hwndDateFrom = GetDlgItem(hwnd, IDC_DATE_FROM); + data->hwndDateTo= GetDlgItem(hwnd, IDC_DATE_TO); + + data->ibMessages.hwndIco = GetDlgItem(hwnd, IDC_ICO_MESSAGES); + data->ibMessages.hwndTxt = GetDlgItem(hwnd, IDC_TXT_MESSAGES); + data->ibMessages.hwndIcoIn = GetDlgItem(hwnd, IDC_ICO_MESSAGES_IN); + SendMessage(data->ibMessages.hwndIcoIn, BUTTONSETASFLATBTN, 0, 0); + SendMessage(data->ibMessages.hwndIcoIn, BUTTONSETASPUSHBTN, 0, 0); + SendMessage(data->ibMessages.hwndIcoIn, BM_SETCHECK, BST_CHECKED, 0); + data->ibMessages.hwndTxtIn = GetDlgItem(hwnd, IDC_TXT_MESSAGES_IN); + data->ibMessages.hwndIcoOut = GetDlgItem(hwnd, IDC_ICO_MESSAGES_OUT); + SendMessage(data->ibMessages.hwndIcoOut, BUTTONSETASFLATBTN, 0, 0); + SendMessage(data->ibMessages.hwndIcoOut, BUTTONSETASPUSHBTN, 0, 0); + SendMessage(data->ibMessages.hwndIcoOut, BM_SETCHECK, BST_CHECKED, 0); + data->ibMessages.hwndTxtOut = GetDlgItem(hwnd, IDC_TXT_MESSAGES_OUT); + + data->ibFiles.hwndIco = GetDlgItem(hwnd, IDC_ICO_FILES); + data->ibFiles.hwndTxt = GetDlgItem(hwnd, IDC_TXT_FILES); + data->ibFiles.hwndIcoIn = GetDlgItem(hwnd, IDC_ICO_FILES_IN); + SendMessage(data->ibFiles.hwndIcoIn, BUTTONSETASFLATBTN, 0, 0); + SendMessage(data->ibFiles.hwndIcoIn, BUTTONSETASPUSHBTN, 0, 0); + SendMessage(data->ibFiles.hwndIcoIn, BM_SETCHECK, BST_CHECKED, 0); + data->ibFiles.hwndTxtIn = GetDlgItem(hwnd, IDC_TXT_FILES_IN); + data->ibFiles.hwndIcoOut = GetDlgItem(hwnd, IDC_ICO_FILES_OUT); + SendMessage(data->ibFiles.hwndIcoOut, BUTTONSETASFLATBTN, 0, 0); + SendMessage(data->ibFiles.hwndIcoOut, BUTTONSETASPUSHBTN, 0, 0); + SendMessage(data->ibFiles.hwndIcoOut, BM_SETCHECK, BST_CHECKED, 0); + data->ibFiles.hwndTxtOut = GetDlgItem(hwnd, IDC_TXT_FILES_OUT); + + data->ibUrls.hwndIco = GetDlgItem(hwnd, IDC_ICO_URLS); + data->ibUrls.hwndTxt = GetDlgItem(hwnd, IDC_TXT_URLS); + data->ibUrls.hwndIcoIn = GetDlgItem(hwnd, IDC_ICO_URLS_IN); + SendMessage(data->ibUrls.hwndIcoIn, BUTTONSETASFLATBTN, 0, 0); + SendMessage(data->ibUrls.hwndIcoIn, BUTTONSETASPUSHBTN, 0, 0); + SendMessage(data->ibUrls.hwndIcoIn, BM_SETCHECK, BST_CHECKED, 0); + data->ibUrls.hwndTxtIn = GetDlgItem(hwnd, IDC_TXT_URLS_IN); + data->ibUrls.hwndIcoOut = GetDlgItem(hwnd, IDC_ICO_URLS_OUT); + SendMessage(data->ibUrls.hwndIcoOut, BUTTONSETASFLATBTN, 0, 0); + SendMessage(data->ibUrls.hwndIcoOut, BUTTONSETASPUSHBTN, 0, 0); + SendMessage(data->ibUrls.hwndIcoOut, BM_SETCHECK, BST_CHECKED, 0); + data->ibUrls.hwndTxtOut = GetDlgItem(hwnd, IDC_TXT_URLS_OUT); + + data->ibTotal.hwndIco = GetDlgItem(hwnd, IDC_ICO_TOTAL); + data->ibTotal.hwndTxt = GetDlgItem(hwnd, IDC_TXT_TOTAL); + data->ibTotal.hwndIcoIn = GetDlgItem(hwnd, IDC_ICO_TOTAL_IN); + SendMessage(data->ibTotal.hwndIcoIn, BUTTONSETASFLATBTN, 0, 0); + SendMessage(data->ibTotal.hwndIcoIn, BUTTONSETASPUSHBTN, 0, 0); + SendMessage(data->ibTotal.hwndIcoIn, BM_SETCHECK, BST_CHECKED, 0); + data->ibTotal.hwndTxtIn = GetDlgItem(hwnd, IDC_TXT_TOTAL_IN); + data->ibTotal.hwndIcoOut = GetDlgItem(hwnd, IDC_ICO_TOTAL_OUT); + SendMessage(data->ibTotal.hwndIcoOut, BUTTONSETASFLATBTN, 0, 0); + SendMessage(data->ibTotal.hwndIcoOut, BUTTONSETASPUSHBTN, 0, 0); + SendMessage(data->ibTotal.hwndIcoOut, BM_SETCHECK, BST_CHECKED, 0); + data->ibTotal.hwndTxtOut = GetDlgItem(hwnd, IDC_TXT_TOTAL_OUT); + + SetWindowLong(hwnd, GWL_USERDATA, (LONG)data); + + data->hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_POPUPS)); + CallService(MS_LANGPACK_TRANSLATEMENU, (WPARAM)data->hMenu, 0); + CheckMenuItem(GetSubMenu(data->hMenu, 1), IDD_FILTER_INCOMING, + data->showFlags&HIST_SHOW_IN ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(GetSubMenu(data->hMenu, 1), IDD_FILTER_OUTGOING, + data->showFlags&HIST_SHOW_OUT ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(GetSubMenu(data->hMenu, 1), IDD_FILTER_MESSAGES, + data->showFlags&HIST_SHOW_MSGS ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(GetSubMenu(data->hMenu, 1), IDD_FILTER_FILES, + data->showFlags&HIST_SHOW_FILES ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(GetSubMenu(data->hMenu, 1), IDD_FILTER_URLS, + data->showFlags&HIST_SHOW_URLS ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(GetSubMenu(data->hMenu, 1), IDD_FILTER_STATUS, + data->showFlags&HIST_SHOW_STATUS ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(GetSubMenu(data->hMenu, 1), IDD_FILTER_OTHER, + data->showFlags&HIST_SHOW_OTHER ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(GetSubMenu(data->hMenu, 1), IDD_FILTER_AUTO, + data->showFlags&HIST_AUTO_FILTER ? MF_CHECKED : MF_UNCHECKED); + +// CheckMenuItem(GetSubMenu(data->hMenu, 1), ID_LOGOPTIONS_SHOWTIMETREE, +// data->showFlags&HIST_TIMETREE ? MF_CHECKED : MF_UNCHECKED); +// ShowWindow(GetDlgItem(hwnd, IDC_TIMETREE), data->showFlags&HIST_TIMETREE ? SW_SHOW : SW_HIDE); + + // Ask for layout + PostMessage(hwnd, WM_SIZE, 0, 0); + + SendMessage(GetDlgItem(hwnd, IDC_USERINFO), BUTTONSETASFLATBTN, 0, 0); + SendMessage(GetDlgItem(hwnd, IDC_MESSAGE), BUTTONSETASFLATBTN, 0, 0); + SendMessage(GetDlgItem(hwnd, IDC_USERMENU), BUTTONSETASFLATBTN, 0, 0); + SendMessage(GetDlgItem(hwnd, IDC_COPY), BUTTONSETASFLATBTN, 0, 0); + SendMessage(GetDlgItem(hwnd, IDC_LOGOPTIONS),BUTTONSETASFLATBTN, 0, 0); + SendMessage(GetDlgItem(hwnd, IDC_FILTER), BUTTONSETASFLATBTN, 0, 0); + SendMessage(GetDlgItem(hwnd, IDC_DATEPOPUP), BUTTONSETASFLATBTN, 0, 0); + SendMessage(GetDlgItem(hwnd, IDC_SEARCH), BUTTONSETASFLATBTN, 0, 0); + SendMessage(GetDlgItem(hwnd, IDC_EXPORT), BUTTONSETASFLATBTN, 0, 0); + SendMessage(GetDlgItem(hwnd, IDC_CLOSE), BUTTONSETASFLATBTN, 0, 0); + SendMessage(GetDlgItem(hwnd, IDC_SECURITY), BUTTONSETASFLATBTN, 0, 0); + SendMessage(GetDlgItem(hwnd, IDC_FINDPREV), BUTTONSETASFLATBTN, 0, 0); + SendMessage(GetDlgItem(hwnd, IDC_FINDNEXT), BUTTONSETASFLATBTN, 0, 0); + + SendMessage(GetDlgItem(hwnd, IDC_USERINFO), BUTTONADDTOOLTIP, (WPARAM)Translate("User Info"), 0); + SendMessage(GetDlgItem(hwnd, IDC_MESSAGE), BUTTONADDTOOLTIP, (WPARAM)Translate("Send Message"), 0); + SendMessage(GetDlgItem(hwnd, IDC_USERMENU), BUTTONADDTOOLTIP, (WPARAM)Translate("User Menu"), 0); + SendMessage(GetDlgItem(hwnd, IDC_COPY), BUTTONADDTOOLTIP, (WPARAM)Translate("Copy"), 0); + SendMessage(GetDlgItem(hwnd, IDC_LOGOPTIONS),BUTTONADDTOOLTIP, (WPARAM)Translate("Options"), 0); + SendMessage(GetDlgItem(hwnd, IDC_FILTER), BUTTONADDTOOLTIP, (WPARAM)Translate("Filter"), 0); + SendMessage(GetDlgItem(hwnd, IDC_DATEPOPUP), BUTTONADDTOOLTIP, (WPARAM)Translate("Jump2Date"), 0); + SendMessage(GetDlgItem(hwnd, IDC_SEARCH), BUTTONADDTOOLTIP, (WPARAM)Translate("Search..."), 0); + SendMessage(GetDlgItem(hwnd, IDC_EXPORT), BUTTONADDTOOLTIP, (WPARAM)Translate("Export..."), 0); + SendMessage(GetDlgItem(hwnd, IDC_CLOSE), BUTTONADDTOOLTIP, (WPARAM)Translate("Close"), 0); + SendMessage(GetDlgItem(hwnd, IDC_SECURITY), BUTTONADDTOOLTIP, (WPARAM)Translate("Security Options"), 0); + SendMessage(GetDlgItem(hwnd, IDC_FINDPREV), BUTTONADDTOOLTIP, (WPARAM)Translate("Find Previous"), 0); + SendMessage(GetDlgItem(hwnd, IDC_FINDNEXT), BUTTONADDTOOLTIP, (WPARAM)Translate("Find Next"), 0); + + WindowList_Add(hNewstoryWindows, hwnd, data->hContact); + + if (data->hContact && (data->hContact != INVALID_HANDLE_VALUE)) + { + TCHAR *title = TplFormatString(TPL_TITLE, data->hContact, 0); + SetWindowText(hwnd, title); + free(title); + } else + if (data->hContact == INVALID_HANDLE_VALUE) + { + SetWindowText(hwnd, TranslateT("Newstory Search Results")); + } else + { + SetWindowText(hwnd, TranslateT("System Newstory")); + } + + if (data->hContact != INVALID_HANDLE_VALUE) + { +// ShowWindow(GetDlgItem(hwnd, IDC_TIMETREE), SW_HIDE); +// ShowWindow(GetDlgItem(hwnd, IDC_ITEMS), SW_HIDE); +// ShowWindow(GetDlgItem(hwnd, IDC_ITEMS2), SW_HIDE); +// ShowWindow(GetDlgItem(hwnd, IDC_SEARCHICON), SW_HIDE); + PostMessage(GetDlgItem(hwnd, IDC_ITEMS2), WM_USER, (WPARAM)data->hContact, 0); + } + + SendMessage(hwnd, UM_UPDATEICONS, 0, 0); + SetFocus(GetDlgItem(hwnd, IDC_ITEMS2)); + + RECT rc; + rc.left = (int)DBGetContactSettingDword(data->hContact, MODULENAME, "left", 0); + rc.top = (int)DBGetContactSettingDword(data->hContact, MODULENAME, "top", 0); + rc.right = (int)DBGetContactSettingDword(data->hContact, MODULENAME, "right", 0); + rc.bottom = (int)DBGetContactSettingDword(data->hContact, MODULENAME, "bottom", 0); + if ((rc.left-rc.right) && (rc.top-rc.bottom)) + MoveWindow(hwnd, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, TRUE); + + ShowHideControls(hwnd, data); + + return TRUE; + } + + case WM_MOUSEWHEEL: + SendMessage(GetDlgItem(hwnd, IDC_CUSTOM1), msg, wParam, lParam); + return TRUE; + + case WM_SETFOCUS: + SetFocus(GetDlgItem(hwnd, IDC_CUSTOM1)); + return TRUE; + + case UM_UPDATEICONS: + { + SendMessage(hwnd, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)icons[ICO_NEWSTORY].hIcon); + + SendMessage(GetDlgItem(hwnd, IDC_SEARCHICON), STM_SETICON, (WPARAM)icons[ICO_SEARCH].hIcon, 0); + + SendMessage(GetDlgItem(hwnd, IDC_USERINFO), BM_SETIMAGE, IMAGE_ICON, (LPARAM)icons[ICO_USERINFO].hIcon); + SendMessage(GetDlgItem(hwnd, IDC_MESSAGE), BM_SETIMAGE, IMAGE_ICON, (LPARAM)icons[ICO_SENDMSG].hIcon); + SendMessage(GetDlgItem(hwnd, IDC_USERMENU), BM_SETIMAGE, IMAGE_ICON, (LPARAM)icons[ICO_USERMENU].hIcon); + SendMessage(GetDlgItem(hwnd, IDC_COPY), BM_SETIMAGE, IMAGE_ICON, (LPARAM)icons[ICO_COPY].hIcon); + SendMessage(GetDlgItem(hwnd, IDC_LOGOPTIONS),BM_SETIMAGE, IMAGE_ICON, (LPARAM)icons[ICO_OPTIONS].hIcon); + SendMessage(GetDlgItem(hwnd, IDC_FILTER), BM_SETIMAGE, IMAGE_ICON, (LPARAM)icons[ICO_FILTER].hIcon); + SendMessage(GetDlgItem(hwnd, IDC_DATEPOPUP), BM_SETIMAGE, IMAGE_ICON, (LPARAM)icons[ICO_CALENDAR].hIcon); + SendMessage(GetDlgItem(hwnd, IDC_SEARCH), BM_SETIMAGE, IMAGE_ICON, (LPARAM)icons[ICO_SEARCH].hIcon); + SendMessage(GetDlgItem(hwnd, IDC_EXPORT), BM_SETIMAGE, IMAGE_ICON, (LPARAM)icons[ICO_EXPORT].hIcon); + SendMessage(GetDlgItem(hwnd, IDC_CLOSE), BM_SETIMAGE, IMAGE_ICON, (LPARAM)icons[ICO_CLOSE].hIcon); + SendMessage(GetDlgItem(hwnd, IDC_FINDPREV), BM_SETIMAGE, IMAGE_ICON, (LPARAM)icons[ICO_FINDPREV].hIcon); + SendMessage(GetDlgItem(hwnd, IDC_FINDNEXT), BM_SETIMAGE, IMAGE_ICON, (LPARAM)icons[ICO_FINDNEXT].hIcon); + + SendMessage(data->ibMessages.hwndIco, STM_SETICON, (LPARAM)icons[ICO_SENDMSG].hIcon, 0); + SendMessage(data->ibMessages.hwndIcoIn, BM_SETIMAGE, IMAGE_ICON, (LPARAM)icons[ICO_MSGIN].hIcon); + SendMessage(data->ibMessages.hwndIcoOut, BM_SETIMAGE, IMAGE_ICON, (LPARAM)icons[ICO_MSGOUT].hIcon); + SendMessage(data->ibFiles.hwndIco, STM_SETICON, (LPARAM)icons[ICO_FILE].hIcon, 0); + SendMessage(data->ibFiles.hwndIcoIn, BM_SETIMAGE, IMAGE_ICON, (LPARAM)icons[ICO_MSGIN].hIcon); + SendMessage(data->ibFiles.hwndIcoOut, BM_SETIMAGE, IMAGE_ICON, (LPARAM)icons[ICO_MSGOUT].hIcon); + SendMessage(data->ibUrls.hwndIco, STM_SETICON, (LPARAM)icons[ICO_URL].hIcon, 0); + SendMessage(data->ibUrls.hwndIcoIn, BM_SETIMAGE, IMAGE_ICON, (LPARAM)icons[ICO_MSGIN].hIcon); + SendMessage(data->ibUrls.hwndIcoOut, BM_SETIMAGE, IMAGE_ICON, (LPARAM)icons[ICO_MSGOUT].hIcon); + SendMessage(data->ibTotal.hwndIco, STM_SETICON, (LPARAM)icons[ICO_UNKNOWN].hIcon, 0); + SendMessage(data->ibTotal.hwndIcoIn, BM_SETIMAGE, IMAGE_ICON, (LPARAM)icons[ICO_MSGIN].hIcon); + SendMessage(data->ibTotal.hwndIcoOut, BM_SETIMAGE, IMAGE_ICON, (LPARAM)icons[ICO_MSGOUT].hIcon); + + if (CheckPassword(data->hContact, "")) + SendMessage(GetDlgItem(hwnd, IDC_SECURITY), BM_SETIMAGE, IMAGE_ICON, (LPARAM)icons[ICO_NOPASSWORD].hIcon); + else + SendMessage(GetDlgItem(hwnd, IDC_SECURITY), BM_SETIMAGE, IMAGE_ICON, (LPARAM)icons[ICO_PASSWORD].hIcon); + + break; + } + + case UM_REBUILDLIST: + { +// if (data->showFlags & HIST_TIMETREE) +// ShowWindow(GetDlgItem(hwnd, IDC_TIMETREE), SW_SHOW); +// ShowWindow(GetDlgItem(hwnd, IDC_ITEMS2), SW_SHOW); +// ShowWindow(GetDlgItem(hwnd, IDC_SEARCHICON), SW_SHOW); + + return TRUE; + } + +/* + case UM_JUMP2TIME: + { + for (int i = 0; i < data->eventCount; i++) + { + ItemData *idata = (ItemData *)SendMessage(GetDlgItem(hwnd, IDC_ITEMS), LB_GETITEMDATA, i, 0); + if (idata->dbe->timestamp >= wParam) + { + SendMessage(GetDlgItem(hwnd, IDC_ITEMS), LB_SETCARETINDEX, i, 0); + SendMessage(GetDlgItem(hwnd, IDC_ITEMS), LB_SETTOPINDEX, i, 0); + SendMessage(GetDlgItem(hwnd, IDC_ITEMS), LB_SELITEMRANGE, FALSE, MAKELPARAM(0,data->eventCount)); + SendMessage(GetDlgItem(hwnd, IDC_ITEMS), LB_SELITEMRANGE, TRUE, MAKELPARAM(i,i)); + break; + } + } + return TRUE; + } +*/ + case WM_MEASUREITEM: + { + LPMEASUREITEMSTRUCT lpmis; + lpmis = (LPMEASUREITEMSTRUCT) lParam; + + if (lpmis->CtlType == ODT_MENU) + return CallService(MS_CLIST_MENUMEASUREITEM, wParam, lParam); + + lpmis->itemHeight = 25; + return TRUE; + } + + case WM_SIZE: + { + LayoutHistoryWnd(hwnd, data); + return TRUE; + } + + case WM_CHARTOITEM: + { + if (!((GetKeyState(VK_CONTROL)&0x80) || (GetKeyState(VK_MENU)&0x80))) + { + TCHAR s[] = { LOWORD(wParam), 0 }; + SetWindowText(GetDlgItem(hwnd, IDC_SEARCHTEXT), s); + SendMessage(GetDlgItem(hwnd, IDC_SEARCHTEXT), EM_SETSEL, 1, 1); + SetFocus(GetDlgItem(hwnd, IDC_SEARCHTEXT)); + } + return -1; + } + + case WM_CLOSE: + { + WindowList_Remove(hNewstoryWindows, hwnd); + + DBWriteContactSettingWord(data->hContact, MODULENAME, "showFlags", data->showFlags); + RECT rc; + GetWindowRect(hwnd, &rc); + DBWriteContactSettingDword(data->hContact, MODULENAME, "left", rc.left); + DBWriteContactSettingDword(data->hContact, MODULENAME, "top", rc.top); + DBWriteContactSettingDword(data->hContact, MODULENAME, "right", rc.right); + DBWriteContactSettingDword(data->hContact, MODULENAME, "bottom", rc.bottom); + +// CLCombo_Cleanup(GetDlgItem(hwnd, IDC_USERLIST)); + + DestroyMenu(data->hMenu); + delete data; + DestroyWindow(hwnd); + return TRUE; + } + + case WM_DRAWITEM: + { + LPDRAWITEMSTRUCT lpdis; + lpdis = (LPDRAWITEMSTRUCT) lParam; + + if (lpdis->CtlType == ODT_MENU) + return CallService(MS_CLIST_MENUDRAWITEM, wParam, lParam); + + if (lpdis->itemID == -1) + return FALSE; + + return TRUE; + } + + case WM_NOTIFY: + { + LPNMHDR hdr = (LPNMHDR)lParam; + switch (hdr->idFrom) + { + case IDC_TIMETREE: + { + switch (hdr->code) + { + case TVN_SELCHANGED: + { + if (data->disableTimeTreeChange) + { + data->disableTimeTreeChange = false; + } else + { + LPNMTREEVIEW pnmtv = (LPNMTREEVIEW)lParam; + int id = pnmtv->itemNew.lParam; +// SendMessage(GetDlgItem(hwnd, IDC_ITEMS), LB_SETCARETINDEX, id, 0); +// SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDC_ITEMS, LBN_SELCHANGE), (LPARAM)GetDlgItem(hwnd, IDC_ITEMS)); +// SendMessage(GetDlgItem(hwnd, IDC_ITEMS), LB_SETTOPINDEX, id, 0); +// SendMessage(GetDlgItem(hwnd, IDC_ITEMS), LB_SELITEMRANGE, FALSE, MAKELPARAM(0,data->eventCount)); +// SendMessage(GetDlgItem(hwnd, IDC_ITEMS), LB_SELITEMRANGE, TRUE, MAKELPARAM(id,id)); + } + break; + } + } + break; + } + } + return TRUE; + } + + case WM_COMMAND: + { + if (CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(wParam), MPCF_CONTACTMENU), (LPARAM) data->hContact)) + return TRUE; + switch(LOWORD(wParam)) + { + case IDCANCEL: + case IDC_CLOSE: + SendMessage(hwnd, WM_CLOSE, 0, 0); + break; + + case IDC_MESSAGE: + CallService(MS_MSG_SENDMESSAGE, (WPARAM)data->hContact, 0); + break; + + case IDC_USERINFO: + CallService(MS_USERINFO_SHOWDIALOG, (WPARAM)data->hContact, 0); + break; + + case IDC_DATEPOPUP: + { + RECT rc; + GetWindowRect(GetDlgItem(hwnd, LOWORD(wParam)), &rc); + time_t tm_jump = CalendarTool_Show(hwnd, rc.left, rc.bottom); + if (tm_jump) PostMessage(hwnd, UM_JUMP2TIME, tm_jump, 0); + break; + } + + case IDC_USERMENU: + { + RECT rc; + HMENU hMenu = (HMENU) CallService(MS_CLIST_MENUBUILDCONTACT, (WPARAM)data->hContact, 0); + GetWindowRect(GetDlgItem(hwnd, LOWORD(wParam)), &rc); + TrackPopupMenu(hMenu, 0, rc.left, rc.bottom, 0, hwnd, NULL); + DestroyMenu(hMenu); + break; + } + + case IDC_LOGOPTIONS: + { + RECT rc; + GetWindowRect(GetDlgItem(hwnd, LOWORD(wParam)), &rc); + DWORD itemID = 0; + switch (TrackPopupMenu(GetSubMenu(data->hMenu, 2), TPM_RETURNCMD, rc.left, rc.bottom, 0, hwnd, NULL)) + { +// case ID_LOGOPTIONS_SHOWTIMETREE: +// { +// data->showFlags = toggleBit(data->showFlags, HIST_TIMETREE); +// CheckMenuItem(GetSubMenu(data->hMenu, 1), ID_LOGOPTIONS_SHOWTIMETREE, +// data->showFlags&HIST_TIMETREE ? MF_CHECKED : MF_UNCHECKED); +// ShowWindow(GetDlgItem(hwnd, IDC_TIMETREE), data->showFlags&HIST_TIMETREE ? SW_SHOW : SW_HIDE); +// break; +// } + + case ID_LOGOPTIONS_OPTIONS: + { + OptShowPage = 0; + OPENOPTIONSDIALOG ood; + ood.cbSize = sizeof(ood); + ood.pszGroup = 0; + ood.pszPage = "Newstory"; + CallService(MS_OPT_OPENOPTIONS, 0, (LPARAM)&ood); + break; + } + case ID_LOGOPTIONS_TEMPLATES: + { + OptShowPage = 1; + OPENOPTIONSDIALOG ood; + ood.cbSize = sizeof(ood); + ood.pszGroup = 0; + ood.pszPage = "Newstory"; + CallService(MS_OPT_OPENOPTIONS, 0, (LPARAM)&ood); + break; + } + case ID_LOGOPTIONS_PASSWORDS: + { + OptShowPage = 2; + OPENOPTIONSDIALOG ood; + ood.cbSize = sizeof(ood); + ood.pszGroup = 0; + ood.pszPage = "Newstory"; + CallService(MS_OPT_OPENOPTIONS, 0, (LPARAM)&ood); + break; + } + } + PostMessage(hwnd, WM_SIZE, 0, 0); + break; + } + + case IDC_SEARCH: + { + if (data->wndOptions & WND_OPT_SEARCHBAR) + { + data->wndOptions &= ~WND_OPT_SEARCHBAR; + } else + { + data->wndOptions |= WND_OPT_SEARCHBAR; + } + ShowHideControls(hwnd, data); + LayoutHistoryWnd(hwnd, data); + break; + } + + case IDC_FILTER: + { + if (data->wndOptions & WND_OPT_FILTERBAR) + { + data->wndOptions &= ~WND_OPT_FILTERBAR; + } else + { + data->wndOptions |= WND_OPT_FILTERBAR; + } + ShowHideControls(hwnd, data); + LayoutHistoryWnd(hwnd, data); + break; + + RECT rc; + GetWindowRect(GetDlgItem(hwnd, LOWORD(wParam)), &rc); + DWORD itemID = 0; + bool doFilter = true; + switch (TrackPopupMenu(GetSubMenu(data->hMenu, 1), TPM_RETURNCMD, rc.left, rc.bottom, 0, hwnd, NULL)) + { + case ID_FILTER_INCOMING: + { + data->showFlags = toggleBit(data->showFlags, HIST_SHOW_IN); + CheckMenuItem(GetSubMenu(data->hMenu, 1), ID_FILTER_INCOMING, + data->showFlags&HIST_SHOW_IN ? MF_CHECKED : MF_UNCHECKED); + break; + } + case ID_FILTER_OUTGOING: + { + data->showFlags = toggleBit(data->showFlags, HIST_SHOW_OUT); + CheckMenuItem(GetSubMenu(data->hMenu, 1), ID_FILTER_OUTGOING, + data->showFlags&HIST_SHOW_OUT ? MF_CHECKED : MF_UNCHECKED); + break; + } + case ID_FILTER_MESSAGES: + { + data->showFlags = toggleBit(data->showFlags, HIST_SHOW_MSGS); + CheckMenuItem(GetSubMenu(data->hMenu, 1), ID_FILTER_MESSAGES, + data->showFlags&HIST_SHOW_MSGS ? MF_CHECKED : MF_UNCHECKED); + break; + } + case ID_FILTER_FILES: + { + data->showFlags = toggleBit(data->showFlags, HIST_SHOW_FILES); + CheckMenuItem(GetSubMenu(data->hMenu, 1), ID_FILTER_FILES, + data->showFlags&HIST_SHOW_FILES ? MF_CHECKED : MF_UNCHECKED); + break; + } + case ID_FILTER_URLS: + { + data->showFlags = toggleBit(data->showFlags, HIST_SHOW_URLS); + CheckMenuItem(GetSubMenu(data->hMenu, 1), ID_FILTER_URLS, + data->showFlags&HIST_SHOW_URLS ? MF_CHECKED : MF_UNCHECKED); + break; + } + case ID_FILTER_STATUS: + { + data->showFlags = toggleBit(data->showFlags, HIST_SHOW_STATUS); + CheckMenuItem(GetSubMenu(data->hMenu, 1), ID_FILTER_STATUS, + data->showFlags&HIST_SHOW_STATUS ? MF_CHECKED : MF_UNCHECKED); + break; + } + case ID_FILTER_OTHER: + { + data->showFlags = toggleBit(data->showFlags, HIST_SHOW_OTHER); + CheckMenuItem(GetSubMenu(data->hMenu, 1), ID_FILTER_OTHER, + data->showFlags&HIST_SHOW_OTHER ? MF_CHECKED : MF_UNCHECKED); + break; + } + case ID_FILTER_AUTO: + { + data->showFlags = toggleBit(data->showFlags, HIST_AUTO_FILTER); + CheckMenuItem(GetSubMenu(data->hMenu, 1), ID_FILTER_AUTO, + data->showFlags&HIST_AUTO_FILTER ? MF_CHECKED : MF_UNCHECKED); + break; + } + default: + { + doFilter = false; + break; + } + } + if (doFilter) + PostMessage(hwnd, UM_REBUILDLIST, 0, 0); + break; + } + + case IDC_SECURITY: + { + ChangePassword(hwnd, data->hContact); + PostMessage(hwnd, UM_UPDATEICONS, 0, 0); + break; + } + + case IDC_EXPORT: + { +// ExportHistoryDialog(data->hContact, hwnd); +// DialogBox(hInst, MAKEINTRESOURCE(IDD_EXPORT), hwnd, ExportWndProc); + break; + } + + case IDC_SEARCHTEXT: + if ((data->showFlags&HIST_AUTO_FILTER) && (HIWORD(wParam) == EN_CHANGE)) + PostMessage(hwnd, UM_REBUILDLIST, 0, 0); + break; +/* + case IDC_EXPORT: + { + RECT rc; + GetWindowRect(GetDlgItem(hwnd, LOWORD(wParam)), &rc); + TrackPopupMenu(GetSubMenu(data->hMenu, 0), TPM_RETURNCMD, rc.left, rc.bottom, 0, hwnd, NULL); + break; + } +*/ +/* + case IDC_SEARCH: + { + int id = DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SEARCH), 0, SearchDlgProc, (LPARAM)GetDlgItem(hwnd, IDC_ITEMS)); + SendMessage(GetDlgItem(hwnd, IDC_ITEMS), LB_SETCARETINDEX, id, 0); + SendMessage(GetDlgItem(hwnd, IDC_ITEMS), LB_SETTOPINDEX, id, 0); + SendMessage(GetDlgItem(hwnd, IDC_ITEMS), LB_SELITEMRANGE, FALSE, MAKELPARAM(0,data->eventCount)); + SendMessage(GetDlgItem(hwnd, IDC_ITEMS), LB_SELITEMRANGE, TRUE, MAKELPARAM(id,id)); + break; + } +*/ + case IDC_FINDPREV: + { + int bufSize = GetWindowTextLength(GetDlgItem(hwnd, IDC_SEARCHTEXT))+1; + TCHAR *buf = new TCHAR[bufSize]; + GetWindowText(GetDlgItem(hwnd, IDC_SEARCHTEXT), buf, GetWindowTextLength(GetDlgItem(hwnd, IDC_SEARCHTEXT))+1); + SendMessage(GetDlgItem(hwnd, IDC_ITEMS2), NSM_FINDPREV, (WPARAM)buf, 0); + delete [] buf; + break; + } + + case IDOK: + case IDC_FINDNEXT: + { + int bufSize = GetWindowTextLength(GetDlgItem(hwnd, IDC_SEARCHTEXT))+1; + TCHAR *buf = new TCHAR[bufSize]; + GetWindowText(GetDlgItem(hwnd, IDC_SEARCHTEXT), buf, GetWindowTextLength(GetDlgItem(hwnd, IDC_SEARCHTEXT))+1); + SendMessage(GetDlgItem(hwnd, IDC_ITEMS2), NSM_FINDNEXT, (WPARAM)buf, 0); + delete [] buf; + break; + } + + case IDC_COPY: + { + SendMessage(GetDlgItem(hwnd, IDC_ITEMS2), NSM_COPY, 0, 0); + } + break; + } + return TRUE; + } + } + return FALSE; //DefWindowProc(hwnd, msg, wParam, lParam); +} + +int svcShowNewstory(WPARAM wParam, LPARAM lParam) +{ + HWND hwnd = (HWND)WindowList_Find(hNewstoryWindows, (HANDLE)wParam); + if (hwnd && IsWindow(hwnd)) + { + SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); + SetFocus(hwnd); + } else + if (AskPassword((HANDLE)wParam)) + { + HWND hwnd = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_HISTORY), 0, HistoryDlgProc, wParam); + ShowWindow(hwnd, SW_SHOWNORMAL); + } + return 0; +} + +int svcShowSystemNewstory(WPARAM wParam, LPARAM lParam) +{ + HWND hwnd = (HWND)WindowList_Find(hNewstoryWindows, 0); + if (hwnd && IsWindow(hwnd)) + { + SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); + SetFocus(hwnd); + } else + if (AskPassword(0)) + { + HWND hwnd = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_HISTORY), 0, HistoryDlgProc, 0); + ShowWindow(hwnd, SW_SHOWNORMAL); + } + return 0; +} diff --git a/plugins/NewStory/src/history.h b/plugins/NewStory/src/history.h new file mode 100644 index 0000000000..c070d3e4d3 --- /dev/null +++ b/plugins/NewStory/src/history.h @@ -0,0 +1,40 @@ +#ifndef __history_h__ +#define __history_h__ + +#define EVENTTYPE_STATUSCHANGE 25368 + +enum +{ + UM_LOADCONTACT = WM_USER+1, + + UM_REBUILDLIST, + UM_FILTERLIST, + UM_REDRAWLIST, + UM_REDRAWLISTH, + UM_UPDATEICONS, + + UM_ADDEVENT, + UM_ADDEVENTFILTER, + UM_REMOVEEVENT, + + UM_SELECTED, + + UM_GETEVENTCOUNT, + UM_GETEVENT, + UM_GETEVENTTEXT, + UM_GETEVENTCONTACT, + UM_GETEVENTHANDLE, +// UM_GETEVENTDATA, + + UM_JUMP2TIME +}; + +extern HANDLE hNewstoryWindows; + +void InitHistory(); +void FreeHistory(); + +int svcShowNewstory(WPARAM wParam, LPARAM lParam); +int svcShowSystemNewstory(WPARAM wParam, LPARAM lParam); + +#endif // __history_h__
\ No newline at end of file diff --git a/plugins/NewStory/src/history_array.cpp b/plugins/NewStory/src/history_array.cpp new file mode 100644 index 0000000000..81758eab48 --- /dev/null +++ b/plugins/NewStory/src/history_array.cpp @@ -0,0 +1,256 @@ +#include "headers.h" + +void CacheThreadFunc(void *arg); + +// Event +bool HistoryArray::ItemData::load(EventLoadMode mode) +{ + if (mode == ELM_NOTHING) + return true; + + if ((mode == ELM_INFO) && (!dbeOk || !dbe.cbSize)) + { + dbeOk = true; + dbe.cbSize = sizeof(dbe); + dbe.cbBlob = 0; + dbe.pBlob = 0; + CallService(MS_DB_EVENT_GET, (WPARAM)hEvent, (LPARAM)&dbe); + return true; + } + + if ((mode == ELM_DATA) && (!dbeOk || !dbe.cbBlob)) + { + dbeOk = true; + dbe.cbSize = sizeof(dbe); + dbe.cbBlob = CallService(MS_DB_EVENT_GETBLOBSIZE, (WPARAM)hEvent, 0); + dbe.pBlob = (PBYTE)calloc(dbe.cbBlob+1, 1); + CallService(MS_DB_EVENT_GET, (WPARAM)hEvent, (LPARAM)&dbe); + + int aLength = 0; + atext = 0; + wtext = 0; + + switch (dbe.eventType) + { + case EVENTTYPE_STATUSCHANGE: + case EVENTTYPE_MESSAGE: + { + atext = (char *)dbe.pBlob; + atext_del = false; + aLength = lstrlenA(atext); + if (dbe.cbBlob > aLength+1) + { + wtext = (WCHAR *)(dbe.pBlob + aLength + 1); + wtext_del = false; + } + break; + } + + case EVENTTYPE_AUTHREQUEST: + { + atext = new char[512]; + atext_del = true; + if ((dbe.cbBlob>8) && *(dbe.pBlob+8)) + { + mir_snprintf(atext, 512, ("%s requested authorization"), dbe.pBlob + 8); + } else + { + mir_snprintf(atext, 512, ("%d requested authorization"), *(DWORD*)(dbe.pBlob)); + } + aLength = lstrlenA(atext); + break; + } + + case EVENTTYPE_ADDED: + { + atext = new char[512]; + atext_del = true; + if ((dbe.cbBlob>8) && *(dbe.pBlob+8)) + { + mir_snprintf(atext, 512, ("%s added you to the contact list"), dbe.pBlob + 8); + } else + { + mir_snprintf(atext, 512, ("%d added you to the contact list"), *(DWORD*)(dbe.pBlob)); + } + aLength = lstrlenA(atext); + break; + } + } + + if (atext && !wtext) + { + #ifdef UNICODE + int bufSize = MultiByteToWideChar(CP_ACP, 0, atext, aLength+1, 0, 0); + wtext = new WCHAR[bufSize+1]; + MultiByteToWideChar(CP_ACP, 0, atext, aLength+1, wtext, bufSize); + wtext_del = true; + #else + this->wtext = 0; + wtext_del = false; + #endif + } else + if (!atext && wtext) + { + // strange situation, really :) I'll fix this later + } else + if (!atext && !wtext) + { + atext = ""; + atext_del = false; + wtext = L""; + wtext_del = false; + } + + return true; + } + + return false; +} + +HistoryArray::ItemData::~ItemData() +{ + if (dbeOk && dbe.pBlob) + { + free(dbe.pBlob); + dbe.pBlob = 0; + } + if (wtext && wtext_del) delete [] wtext; + if (atext && atext_del) delete [] atext; + if (data) MTextDestroy(data); +} + +// Array +HistoryArray::HistoryArray() +{ + head = tail = 0; + caching = false; + caching_complete = true; + InitializeCriticalSection(&csItems); +} + +HistoryArray::~HistoryArray() +{ + DeleteCriticalSection(&csItems); + clear(); +} + +bool HistoryArray::allocateBlock(int count) +{ + ItemBlock *newBlock = new ItemBlock; + newBlock->items = new ItemData[count]; + newBlock->count = count; + newBlock->prev = tail; + newBlock->next = 0; + + if (tail) + { + tail->next = newBlock; + } else + { + head = newBlock; + } + tail = newBlock; + + return true; +} + +void HistoryArray::clear() +{ + while (head) + { + ItemBlock *next = head->next; +// for (int i = 0; i < head->count; ++i) +// destroyEvent(head->items[i]); + delete [] head->items; + head = next; + } + + head = tail = 0; + preBlock = 0; + preIndex = 0; +} + +bool HistoryArray::addHistory(HANDLE hContact, EventLoadMode mode) +{ + int count = CallService(MS_DB_EVENT_GETCOUNT, (WPARAM)hContact, 0); + allocateBlock(count); + + int i = 0; + HANDLE hEvent = (HANDLE)CallService(MS_DB_EVENT_FINDFIRST, (WPARAM)hContact, 0); + while (hEvent) + { + tail->items[i].hContact = hContact; + tail->items[i].hEvent = hEvent; + + ++i; + hEvent = (HANDLE)CallService(MS_DB_EVENT_FINDNEXT, (WPARAM)hEvent, 0); + } + char buf[666]; + + return true; +} + +bool HistoryArray::addEvent(HANDLE hContact, HANDLE hEvent, EventLoadMode mode) +{ + allocateBlock(1); + tail->items[0].hContact = hContact; + tail->items[0].hEvent = hEvent; + if (mode != ELM_NOTHING) + tail->items[0].load(mode); + + return true; +} +/* +bool HistoryArray::preloadEvents(int count) +{ + for (int i = 0; i < count; ++i) + { + preBlock->items[preIndex].load(ELM_DATA); + if (++preIndex == preBlock->count) + { + preBlock = preBlock->next; + if (!preBlock) + return false; + preIndex = 0; + } + } + return true; +} +*/ +HistoryArray::ItemData *HistoryArray::get(int id, EventLoadMode mode) +{ + caching = false; + if (caching) EnterCriticalSection(&csItems); + int offset = 0; + for (ItemBlock *p = head; p; p = p->next) + { + if (id < offset + p->count) + { + if (mode != ELM_NOTHING) + p->items[id - offset].load(mode); + + if (caching) + { + if (caching_complete) caching = false; + LeaveCriticalSection(&csItems); + } + return p->items + id - offset; + } + offset += p->count; + } + if (caching) + { + if (caching_complete) caching = false; + LeaveCriticalSection(&csItems); + } + return 0; +} + +/////////////////////////////////////////////////////////// +// Cache data +void HistoryArray::CacheThreadFunc(void *arg) +{ + HistoryArray *_this = (HistoryArray *)arg; + _this->caching_complete = true; + _endthread(); +}
\ No newline at end of file diff --git a/plugins/NewStory/src/history_array.h b/plugins/NewStory/src/history_array.h new file mode 100644 index 0000000000..88dc551d65 --- /dev/null +++ b/plugins/NewStory/src/history_array.h @@ -0,0 +1,226 @@ +#ifndef __history_array__ +#define __history_array__ + +enum EventLoadMode +{ + ELM_NOTHING, + ELM_INFO, + ELM_DATA +}; + +enum +{ + HIF_SELECTED = 0x01, + + FILTER_TIME = 0x01, + FILTER_TYPE = 0x02, + FILTER_DIRECTION = 0x04, + FILTER_TEXT = 0x08, + FILTER_UNICODE = 0x10, + + FTYPE_MESSAGE = 0x01, + FTYPE_FILE = 0x02, + FTYPE_URL = 0x04, + FTYPE_STATUS = 0x08, + FTYPE_OTHER = 0x10, + FTYPE_INCOMING = 0x20, + FTYPE_OUTGOING = 0x40 +}; + +class HistoryArray +{ +public: + struct ItemData + { + BYTE flags; + + HANDLE hContact; + HANDLE hEvent; + + bool dbeOk; + DBEVENTINFO dbe; + + bool atext_del, wtext_del; + char *atext; + WCHAR *wtext; + + HANDLE data; + + ItemData(): flags(0), hContact(0), hEvent(0), atext(0), wtext(0), atext_del(false), wtext_del(false), data(0), dbeOk(false) {} + ~ItemData(); + bool load(EventLoadMode mode); + inline bool loadInline(EventLoadMode mode) + { + if (((mode >= ELM_INFO) && !dbeOk) || ((mode == ELM_DATA) && !dbe.pBlob)) + return load(mode); + return true; + } + inline TCHAR *getTBuf() + { + loadInline(ELM_DATA); + #ifdef UNICODE + return wtext; + #else + return atext; + #endif + } + inline char *getBuf() + { + loadInline(ELM_DATA); + return atext; + } + inline WCHAR *getWBuf() + { + loadInline(ELM_DATA); + return wtext; + } + }; + + struct ItemBlock + { + ItemData *items; + int count; + ItemBlock *prev, *next; + }; + + class Filter + { + public: + enum + { + INCOMING = 0x001, + OUTGOING = 0x002, + MESSAGES = 0x004, + FILES = 0x008, + URLS = 0x010, + STATUS = 0x020, + OTHER = 0x040, + EVENTTEXT = 0x080, + EVENTONLY = 0x100, + }; + Filter(WORD aFlags, TCHAR *aText) + { + refCount = new int(0); + flags = aFlags; + text = new TCHAR[lstrlen(aText)+1]; + lstrcpy(text, aText); + } + Filter(const Filter &other) + { + flags = other.flags; + refCount = other.refCount; + text = other.text; + ++*refCount; + } + Filter &operator=(const Filter &other) + { + flags = other.flags; + refCount = other.refCount; + text = other.text; + ++*refCount; + } + ~Filter() + { + if (!--*refCount) + { + delete refCount; + if (text) delete [] text; + } + } + inline bool check(ItemData *item) + { + if (!item) return false; + if (!(flags & EVENTONLY)) + { + if (item->dbe.flags & DBEF_SENT) + { + if (!(flags & OUTGOING)) + return false; + } else + { + if (!(flags & INCOMING)) + return false; + } + switch (item->dbe.eventType) + { + case EVENTTYPE_MESSAGE: + if (!(flags & MESSAGES)) + return false; + break; + case EVENTTYPE_FILE: + if (!(flags & FILES)) + return false; + break; + case EVENTTYPE_URL: + if (!(flags & URLS)) + return false; + break; + case EVENTTYPE_STATUSCHANGE: + if (!(flags & STATUS)) + return false; + break; + default: + if (!(flags & OTHER)) + return false; + } + } + if (flags & (EVENTTEXT|EVENTONLY)) + { + item->loadInline(ELM_DATA); + return CheckFilter(item->getTBuf(), text); + } + return true; + }; + + private: + WORD flags; + int *refCount; + TCHAR *text; + }; + +private: + ItemBlock *head, *tail; + ItemBlock *preBlock; + int preIndex; + bool allocateBlock(int count); + + bool caching; + bool caching_complete; + CRITICAL_SECTION csItems; + static void CacheThreadFunc(void *arg); + +public: + HistoryArray(); + ~HistoryArray(); + + void clear(); + bool addHistory(HANDLE hContact, EventLoadMode mode = ELM_NOTHING); + bool addEvent(HANDLE hContact, HANDLE hEvent, EventLoadMode mode = ELM_NOTHING); + +// bool preloadEvents(int count = 10); + + ItemData *get(int id, EventLoadMode mode = ELM_NOTHING); + ItemData *operator[] (int id) { return get(id, ELM_DATA); } + ItemData *operator() (int id) { return get(id, ELM_INFO); } + + int FindRel(int id, int dir, Filter filter) + { + int count = getCount(); + for (int i = id+dir; (i >= 0) && (i < count); i += dir) + if (filter.check(get(i))) + return i; + return -1; + } + int FindNext(int id, Filter filter) { return FindRel(id, +1, filter); } + int FindPrev(int id, Filter filter) { return FindRel(id, -1, filter); } + + int getCount() + { + int res = 0; + for (ItemBlock *p = head; p; p = p->next) + res += p->count; + return res; + } +}; + +#endif // __history_array__ diff --git a/plugins/NewStory/src/history_control.cpp b/plugins/NewStory/src/history_control.cpp new file mode 100644 index 0000000000..f433a3e1a7 --- /dev/null +++ b/plugins/NewStory/src/history_control.cpp @@ -0,0 +1,1009 @@ +#include "headers.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 = {0}; + wndclass.style = /*CS_HREDRAW | CS_VREDRAW | */CS_DBLCLKS | CS_GLOBALCLASS; + wndclass.lpfnWndProc = NewstoryListWndProc; + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = sizeof(void *); + wndclass.hInstance = hInst; + wndclass.hIcon = NULL; + wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); + wndclass.hbrBackground = NULL; + wndclass.lpszMenuName = NULL; + wndclass.lpszClassName = _T(NEWSTORYLIST_CLASS); + RegisterClass(&wndclass); +} + +///////////////////////////////////////////////////////////////////////// +// Control utilities, types and constants +struct NewstoryListData +{ + HistoryArray items; + + DWORD scrollTopItem; // topmost item + int scrollTopPixel; // y coord of topmost item, this should be negative or zero + DWORD caret; + int cachedWindowHeight; + DWORD cachedMaxTopItem; // the largest ID of top item to avoid empty space + int cachedMaxTopPixel; + + RECT rcLastPaint; + bool repaint; + + HWND hwndEditBox; +}; + +#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); +static void RecalcScrollBar(HWND hwnd, NewstoryListData *data); +static void BeginEditItem(HWND hwnd, NewstoryListData *data, int index); +static void EndEditItem(HWND hwnd, NewstoryListData *data); +static int LayoutItem(HWND hwnd, HistoryArray *items, int index, bool force); +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) +{ + switch (msg) + { + case WM_KEYDOWN: + { + switch (wParam) + { + case VK_ESCAPE: + { + EndEditItem(GetParent(hwnd), (NewstoryListData *)GetWindowLong(GetParent(hwnd), 0)); + return 0; + } + } + break; + } + case WM_GETDLGCODE: + { + if (lParam) + { + MSG *msg = (MSG *)lParam; + if (msg->message == WM_KEYDOWN && msg->wParam == VK_TAB) + return 0; + if (msg->message == WM_CHAR && msg->wParam == '\t') + return 0; + } + return DLGC_WANTMESSAGE; + } +// case WM_KILLFOCUS: +// { +// EndEditItem(GetParent(hwnd), (NewstoryListData *)GetWindowLong(GetParent(hwnd), 0)); +// return 0; +// } + } + return CallWindowProc(OldEditWndProc, hwnd, msg, wParam, lParam); +} + +///////////////////////////////////////////////////////////////////////// +// WndProc +LRESULT CALLBACK NewstoryListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + NewstoryListData *data = (NewstoryListData *)GetWindowLong(hwnd, 0); + + switch (msg) + { + case WM_CREATE: + { + data = new NewstoryListData; + data->scrollTopItem = 0; + data->scrollTopPixel = 0; + data->cachedMaxTopItem = 0; + data->cachedMaxTopPixel = 0; + data->hwndEditBox = 0; + SetWindowLong(hwnd, 0, (int)data); + RecalcScrollBar(hwnd, data); + + break; + } + + case WM_USER: + { + data->items.addHistory((HANDLE)wParam); + RecalcScrollBar(hwnd, data); + data->scrollTopItem = data->items.getCount(); + FixScrollPosition(hwnd, data); + InvalidateRect(hwnd, 0, FALSE); + break; + } + + // History list control messages + case NSM_GETCOUNT: + { + return data->items.getCount(); + } + + case NSM_SELECTITEMS: + { + DWORD start = min(data->items.getCount()-1, max(0, wParam)); + DWORD end = min(data->items.getCount()-1, max(0, lParam)); + if (start > end) + { + start ^= end; + end ^= start; + start ^= end; + } + for (int i = start; i <= end; ++i) + data->items.get(i, ELM_NOTHING)->flags |= HIF_SELECTED; + InvalidateRect(hwnd, 0, FALSE); + return 0; + } + + case NSM_TOGGLEITEMS: + { + DWORD start = min(data->items.getCount()-1, max(0, wParam)); + DWORD end = min(data->items.getCount()-1, max(0, lParam)); + if (start > end) + { + start ^= end; + end ^= start; + start ^= end; + } + for (int i = start; i <= end; ++i) + { + if (data->items.get(i, ELM_NOTHING)->flags & HIF_SELECTED) + { + data->items.get(i, ELM_NOTHING)->flags &= ~HIF_SELECTED; + } else + { + data->items.get(i, ELM_NOTHING)->flags |= HIF_SELECTED; + } + } + InvalidateRect(hwnd, 0, FALSE); + return 0; + } + + case NSM_SELECTITEMS2: + { + DWORD start = min(data->items.getCount()-1, max(0, wParam)); + DWORD end = min(data->items.getCount()-1, max(0, lParam)); + if (start > end) + { + start ^= end; + end ^= start; + start ^= end; + } + DWORD count = data->items.getCount(); + for (int i = 0; i < count; ++i) + { + if ((i >= start) && (i <= end)) + { + data->items.get(i, ELM_NOTHING)->flags |= HIF_SELECTED; + } else + { + data->items.get(i, ELM_NOTHING)->flags &= ~((DWORD)HIF_SELECTED); + } + } + InvalidateRect(hwnd, 0, FALSE); + return 0; + } + + case NSM_DESELECTITEMS: + { + DWORD start = min(data->items.getCount()-1, max(0, wParam)); + DWORD end = min(data->items.getCount()-1, max(0, lParam)); + if (start > end) + { + start ^= end; + end ^= start; + start ^= end; + } + for (int i = start; i <= end; ++i) + data->items.get(i, ELM_NOTHING)->flags &= ~((DWORD)HIF_SELECTED); + InvalidateRect(hwnd, 0, FALSE); + return 0; + } + + case NSM_ENSUREVISIBLE: + { + EnsureVisible(hwnd, data, wParam); + return 0; + } + + case NSM_GETITEMFROMPIXEL: + { + RECT rc; + GetClientRect(hwnd, &rc); + int height = rc.bottom - rc.top; + DWORD count = data->items.getCount(); + DWORD current = data->scrollTopItem; + int top = data->scrollTopPixel; + int bottom = top + LayoutItem(hwnd, &data->items, current, false); + while (top <= height) + { + if ((lParam >= top) && (lParam <= bottom)) + return current; + if (++current >= count) + return -1; + top = bottom; + bottom = top + LayoutItem(hwnd, &data->items, current, false); + } + return -1; + } + + case NSM_SETCARET: + { + 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; + } + + case NSM_FINDNEXT: + { + int id = data->items.FindNext(SendMessage(hwnd, NSM_GETCARET, 0, 0), HistoryArray::Filter(HistoryArray::Filter::EVENTONLY, (TCHAR *)wParam)); + if (id >= 0) + { + SendMessage(hwnd, NSM_SELECTITEMS2, id, id); + SendMessage(hwnd, NSM_SETCARET, id, TRUE); + } + return id; + } + + case NSM_FINDPREV: + { + int id = data->items.FindPrev(SendMessage(hwnd, NSM_GETCARET, 0, 0), HistoryArray::Filter(HistoryArray::Filter::EVENTONLY, (TCHAR *)wParam)); + if (id >= 0) + { + SendMessage(hwnd, NSM_SELECTITEMS2, id, id); + SendMessage(hwnd, NSM_SETCARET, id, TRUE); + } + return id; + } + + case NSM_COPY: + { + TCHAR *res = 0; + TCHAR *buf; + int size = 0; + + int eventCount = data->items.getCount(); + for (int i = 0; i < eventCount; i++) + { + HistoryArray::ItemData *item = data->items.get(i, ELM_NOTHING); + if (item->flags&HIF_SELECTED) + { + buf = TplFormatString(TPL_COPY_MESSAGE, item->hContact, item); + res = appendString(res, buf); + free(buf); + } + } + + CopyText(hwnd, res); + free(res); + } + // End of history list control messages + case WM_SIZE: + InvalidateRect(hwnd, 0, FALSE); + break; + + case WM_ERASEBKGND: + return 1; + + case WM_PRINTCLIENT: + { +// PaintClc(hwnd, dat, (HDC) wParam, NULL); + break; + } +/* + case WM_NCPAINT: + { + RECT rc; + GetWindowRect(hwnd, &rc); + + HDC hdc; + hdc = GetDCEx(hwnd, (HRGN)wParam, DCX_WINDOW|DCX_INTERSECTRGN); + FrameRect(hdc, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH)); + ReleaseDC(hwnd, hdc); + } +*/ +/* + case WM_NCPAINT: + { + if (wParam == 1) + break; + { + POINT ptTopLeft = { 0, 0 }; + HRGN hClientRgn; + ClientToScreen(hwnd, &ptTopLeft); + hClientRgn = CreateRectRgn(0, 0, 1, 1); + CombineRgn(hClientRgn, (HRGN) wParam, NULL, RGN_COPY); + OffsetRgn(hClientRgn, -ptTopLeft.x, -ptTopLeft.y); + InvalidateRgn(hwnd, hClientRgn, FALSE); + DeleteObject(hClientRgn); + UpdateWindow(hwnd); + } + break; + } +*/ + case WM_PAINT: + { + HDC hdcWindow; + PAINTSTRUCT ps; + 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 = hdcWindow; + HDC hdc = CreateCompatibleDC(hdcWindow); + HBITMAP hbmSave = (HBITMAP)SelectObject(hdc, CreateCompatibleBitmap(hdcWindow, rc.right-rc.left, rc.bottom-rc.top)); + + GetClientRect(hwnd, &rc); + int height = rc.bottom - rc.top; + int width = rc.right - rc.left; + int top = data->scrollTopPixel; + int idx = data->scrollTopItem; + while ((top < height) && (idx < data->items.getCount())) + top += PaintItem(hdc, &data->items, idx++, top, width); + + if (top <= height) + { + RECT rc; + SetRect(&rc, 0, top, width, height); + + HBRUSH hbr; + hbr = CreateSolidBrush(RGB(0xff,0xff,0xff)); + FillRect(hdc, &rc, hbr); + DeleteObject(hbr); + } + + GetWindowRect(hwnd, &rc); + rc.right -= rc.left; rc.left = 0; + rc.bottom -= rc.top; rc.top = 0; + DrawEdge(hdc, &rc, BDR_SUNKENOUTER, BF_RECT); + + BitBlt(hdcWindow, 0, 0, rc.right, rc.bottom, hdc, 0, 0, SRCCOPY); + DeleteObject(SelectObject(hdc, hbmSave)); + DeleteDC(hdc); + } + + EndPaint(hwnd, &ps); + break; + } + + case WM_SETFOCUS: + { + return 0; + } + + case WM_GETDLGCODE: + { + if (lParam) + { + MSG *msg = (MSG *) lParam; + if (msg->message == WM_KEYDOWN) + { + if (msg->wParam == VK_TAB) + return 0; + if (msg->wParam == VK_ESCAPE && !data->hwndEditBox) + return 0; + } else + if (msg->message == WM_CHAR) + { + if (msg->wParam == '\t') + return 0; + if (msg->wParam == 27 && !data->hwndEditBox) + return 0; + } + } + 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; + } + 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_NEXT: + { + break; + } + case VK_HOME: + { + break; + } + case VK_END: + { + break; + } + case VK_F2: + { + BeginEditItem(hwnd, data, data->caret); + break; + } + } + break; + } + + case WM_SYSCHAR: + case WM_CHAR: + { + if (wParam == 27) + { + if (data->hwndEditBox) + EndEditItem(hwnd, data); + } else + { + char ch = MapVirtualKey((lParam>>16)&0xff, 1); + if (((ch == 'C') || (ch == VK_INSERT)) && (GetKeyState(VK_CONTROL)&0x80)) + { + PostMessage(hwnd, NSM_COPY, 0, 0); + } else + if ((ch == 'A') && (GetKeyState(VK_CONTROL)&0x80)) + { + SendMessage(hwnd, NSM_SELECTITEMS, 0, data->items.getCount()); +// } else +// if (ch == VK_ESCAPE) +// { +// PostMessage(GetParent(hwnd), WM_CLOSE, 0, 0); + } + } + break; + } + + case WM_LBUTTONDOWN: + { + int item = SendMessage(hwnd, NSM_GETITEMFROMPIXEL, LOWORD(lParam), HIWORD(lParam)); + if (item >= 0) + { + if (data->caret != item) + EndEditItem(hwnd, data); + + if (wParam & MK_CONTROL) + { + SendMessage(hwnd, NSM_TOGGLEITEMS, item, item); + SendMessage(hwnd, NSM_SETCARET, item, TRUE); + } else + if (wParam & MK_SHIFT) + { + SendMessage(hwnd, NSM_SELECTITEMS, data->caret, item); + SendMessage(hwnd, NSM_SETCARET, item, TRUE); + } else + { + if (data->caret == item) + { + BeginEditItem(hwnd, data, item); + } else + { + SendMessage(hwnd, NSM_SELECTITEMS2, item, item); + SendMessage(hwnd, NSM_SETCARET, item, TRUE); + } + } + } + SetFocus(hwnd); + return 0; + } + + case WM_MOUSEWHEEL: + { + DWORD s_scrollTopItem = data->scrollTopItem; + int s_scrollTopPixel = data->scrollTopPixel; + + UINT scrollLines; + if (!SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &scrollLines, FALSE)) + scrollLines = 3; + ScrollListBy(hwnd, data, 0, (short)HIWORD(wParam) * 10 * (signed)scrollLines / WHEEL_DELTA); + + if ((s_scrollTopItem != data->scrollTopItem) || (s_scrollTopPixel != data->scrollTopPixel)) + InvalidateRect(hwnd, 0, FALSE); + + return TRUE; + } + + case WM_VSCROLL: + { + DWORD s_scrollTopItem = data->scrollTopItem; + int s_scrollTopPixel = data->scrollTopPixel; + + switch (LOWORD(wParam)) + { + case SB_LINEUP: + ScrollListBy(hwnd, data, 0, 10); + break; + case SB_LINEDOWN: + ScrollListBy(hwnd, data, 0, -10); + break; + case SB_PAGEUP: + ScrollListBy(hwnd, data, -10, 0); + break; + case SB_PAGEDOWN: + ScrollListBy(hwnd, data, 10, 0); + break; + case SB_BOTTOM: + data->scrollTopItem = data->items.getCount()-1; + data->scrollTopPixel = 0; + break; + case SB_TOP: + data->scrollTopItem = 0; + data->scrollTopPixel = 0; + break; + case SB_THUMBTRACK: + { + SCROLLINFO si; + si.cbSize = sizeof(si); + si.fMask = SIF_TRACKPOS|SIF_RANGE; + GetScrollInfo(hwnd, SB_VERT, &si); + int pos = si.nTrackPos; + + if (pos == si.nMax) + { + data->scrollTopItem = data->items.getCount(); + data->scrollTopPixel = -1000; + } else + { + data->scrollTopItem = pos/AVERAGE_ITEM_HEIGHT; + int itemHeight = LayoutItem(hwnd, &data->items, data->scrollTopItem, false); + data->scrollTopPixel = -pos%AVERAGE_ITEM_HEIGHT * itemHeight / AVERAGE_ITEM_HEIGHT; + } + FixScrollPosition(hwnd, data); + break; + } + + default: + return 0; + } + + if ((s_scrollTopItem != data->scrollTopItem) || (s_scrollTopPixel != data->scrollTopPixel)) + InvalidateRect(hwnd, 0, FALSE); + break; + } + + case WM_DESTROY: + { + delete data; + SetWindowLong(hwnd, 0, 0); + break; + } + } + + 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, false); + 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, false); + while ((-data->scrollTopPixel > itemHeight) && (data->scrollTopItem < maxItem)) + { + data->scrollTopPixel += itemHeight; + data->scrollTopItem++; + itemHeight = LayoutItem(hwnd, &data->items, data->scrollTopItem, false); + } + } + } + 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, false); + bool found = false; + while (top < height) + { + if (idx == item) + { + itemHeight = LayoutItem(hwnd, &data->items, idx, false); + if (top + itemHeight > height) + ScrollListBy(hwnd, data, 0, height-top-itemHeight); + found = true; + break; + } + top += itemHeight; + idx++; + itemHeight = LayoutItem(hwnd, &data->items, idx, false); + } + 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, false); + 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, false); + 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_URL: + tpl = TPL_COPY_URL; + fontid = !(item->dbe.flags&DBEF_SENT) ? FONT_INURL : FONT_OUTURL; + colorid = !(item->dbe.flags&DBEF_SENT) ? COLOR_INURL : COLOR_OUTURL; + 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; + + 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; + } + + TCHAR *text = TplFormatString(tpl, item->hContact, item); + data->hwndEditBox = CreateWindow(_T("EDIT"), text, WS_CHILD|WS_BORDER|ES_READONLY|ES_MULTILINE|ES_AUTOVSCROLL, 0, top, rc.right-rc.left, itemHeight, hwnd, NULL, hInst, NULL); + OldEditWndProc = (WNDPROC)SetWindowLong(data->hwndEditBox, GWL_WNDPROC, (LONG)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); + free(text); + break; + } + top += itemHeight; + idx++; + itemHeight = LayoutItem(hwnd, &data->items, idx, false); + } +} + +static void EndEditItem(HWND hwnd, NewstoryListData *data) +{ + DestroyWindow(data->hwndEditBox); + data->hwndEditBox = 0; +} + +static int LayoutItem(HWND hwnd, HistoryArray *items, int index, bool force) +{ + 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_URL: + tpl = TPL_URL; + fontid = !(item->dbe.flags&DBEF_SENT) ? FONT_INURL : FONT_OUTURL; + 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; + + default: + tpl = TPL_OTHER; + fontid = !(item->dbe.flags&DBEF_SENT) ? FONT_INOTHER : FONT_OUTOTHER; + break; + } + HFONT hfnt = (HFONT)SelectObject(hdc, fonts[fontid].hfnt); + +// HANDLE hText = (HANDLE)item->data; + if (!item->data) + { + TCHAR *buf = TplFormatString(tpl, item->hContact, item); + item->data = MTextCreateT(htuLog, buf); + free(buf); + } + + 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_URL: + tpl = TPL_URL; + fontid = !(item->dbe.flags&DBEF_SENT) ? FONT_INURL : FONT_OUTURL; + colorid = !(item->dbe.flags&DBEF_SENT) ? COLOR_INURL : COLOR_OUTURL; + 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; + + 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) + { + TCHAR *buf = TplFormatString(tpl, item->hContact, item); + item->data = MTextCreateT(htuLog, buf); + 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; +} diff --git a/plugins/NewStory/src/history_control.h b/plugins/NewStory/src/history_control.h new file mode 100644 index 0000000000..01ca695ddd --- /dev/null +++ b/plugins/NewStory/src/history_control.h @@ -0,0 +1,66 @@ +#ifndef __history_control_h__ +#define __history_control_h__ + +#define NEWSTORYLIST_CLASS "NewstoryList" + +enum +{ + NSM_FIRST = WM_USER+100, + + // wParam = fist item + // lParam = last item + // result = number of total selected items + NSM_SELECTITEMS = NSM_FIRST, + + // wParam = fist item + // lParam = last item + // result = number of total selected items + NSM_TOGGLEITEMS, + + // wParam = fist item + // lParam = last item + // result = number of total selected items + // select items wParam - lParam and deselect all other + NSM_SELECTITEMS2, + + // wParam = fist item + // lParam = last item + // result = number of total selected items + NSM_DESELECTITEMS, + + // wParam = item id + NSM_ENSUREVISIBLE, + + // wParam = x in control + // lParam = y in control + // result = id + NSM_GETITEMFROMPIXEL, + + // wParam = id + NSM_SETCARET, + + // result = id + NSM_GETCARET, + + // wParam = text + NSM_FINDNEXT, + NSM_FINDPREV, + + // wParam = wtext + NSM_FINDNEXTW, + NSM_FINDPREVW, + + // + NSM_COPY, + NSM_EXPORT, + + // + NSM_GETCOUNT, + + NSM_LAST +}; + +void InitNewstoryControl(); +//void DestroyNewstoryControl(); + +#endif // __history_control_h__
\ No newline at end of file diff --git a/plugins/NewStory/src/icons.cpp b/plugins/NewStory/src/icons.cpp new file mode 100644 index 0000000000..8572678804 --- /dev/null +++ b/plugins/NewStory/src/icons.cpp @@ -0,0 +1,74 @@ +#include "headers.h" + +MyIconDesriptor icons[] = +{ + {ICO_NEWSTORY, MODULENAME"/main", MODULETITLE, "Main Icon", 0}, + {ICO_USERINFO, MODULENAME"/userinfo", MODULETITLE, "User Info", 0}, + {ICO_USERMENU, MODULENAME"/usermenu", MODULETITLE, "User Menu", 0}, + {ICO_SEARCH, MODULENAME"/search", MODULETITLE, "Search", 0}, + {ICO_OPTIONS, MODULENAME"/options", MODULETITLE, "Options", 0}, + {ICO_FILTER, MODULENAME"/filter", MODULETITLE, "Filter", 0}, + {ICO_EXPORT, MODULENAME"/export", MODULETITLE, "Export", 0}, + {ICO_COPY, MODULENAME"/copy", MODULETITLE, "Copy", 0}, + {ICO_SENDMSG, MODULENAME"/message", MODULETITLE, "Send Message", 0}, + {ICO_CLOSE, MODULENAME"/close", MODULETITLE, "Close", 0}, + + {ICO_MSGIN, MODULENAME"/msgin", MODULETITLE, "Incoming Message", 0}, + {ICO_MSGOUT, MODULENAME"/msgout", MODULETITLE, "Outgoing Message", 0}, + {ICO_SIGNIN, MODULENAME"/signin", MODULETITLE, "User Signed In", 0}, + {ICO_FILE, MODULENAME"/file", MODULETITLE, "File", 0}, + {ICO_URL, MODULENAME"/url", MODULETITLE, "URL", 0}, + {ICO_UNKNOWN, MODULENAME"/unknown", MODULETITLE, "Unknown Event", 0}, + + {ICO_FINDPREV, MODULENAME"/findprev", MODULETITLE, "Find Previous", 0}, + {ICO_FINDNEXT, MODULENAME"/findnext", MODULETITLE, "Find Next", 0}, + {ICO_NOPASSWORD,MODULENAME"/nopassword",MODULETITLE, "Password disabled", 0}, + {ICO_PASSWORD, MODULENAME"/password", MODULETITLE, "Password enabled", 0}, + {ICO_CALENDAR, MODULENAME"/calendar", MODULETITLE, "Jump to Date", 0}, + + {ICO_TPLGROUP, MODULENAME"/tplgroup", MODULETITLE, "Template Group", 0}, + {ICO_RESET, MODULENAME"/reset", MODULETITLE, "Reset", 0}, + {ICO_PREVIEW, MODULENAME"/preview", MODULETITLE, "Update Preview", 0}, + {ICO_VARHELP, MODULENAME"/varhelp", MODULETITLE, "Help", 0}, + {ICO_SAVEPASS, MODULENAME"/savepass", MODULETITLE, "Save Password", 0} +}; + +int iconCount = sizeof(icons) / sizeof(icons[0]); + +int evtIconsChanged(WPARAM, LPARAM) +{ + RefreshIcons(icons, ICO_COUNT); + WindowList_Broadcast(hNewstoryWindows, UM_UPDATEICONS, 0, 0); + return 0; +} + +void InitIcons(MyIconDesriptor *icons, LPSTR szFilename, int count) +{ + for (int i = 0; i < count; i++) + { + if (ServiceExists(MS_SKIN2_ADDICON)) + { + SKINICONDESC sid; + sid.cbSize = sizeof(sid); + sid.pszName = icons[i].szId; + sid.pszSection = icons[i].szGroup; + sid.pszDescription = icons[i].szTitle; + sid.pszDefaultFile = szFilename; + sid.iDefaultIndex = -icons[i].dwIndex-1; + CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid); + icons[i].hIcon = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)icons[i].szId); + } else + { + ExtractIconExA(szFilename, icons[i].dwIndex, 0, &icons[i].hIcon, 1); + } + } + + HookEvent(ME_SKIN2_ICONSCHANGED, evtIconsChanged); +} + +void RefreshIcons(MyIconDesriptor *icons, int count) +{ + if (ServiceExists(MS_SKIN2_ADDICON)) + for (int i = 0; i < count; i++) + icons[i].hIcon = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)icons[i].szId); +}
\ No newline at end of file diff --git a/plugins/NewStory/src/icons.h b/plugins/NewStory/src/icons.h new file mode 100644 index 0000000000..e041c648e5 --- /dev/null +++ b/plugins/NewStory/src/icons.h @@ -0,0 +1,47 @@ +struct MyIconDesriptor +{ + DWORD dwIndex; + + LPSTR szId; + LPSTR szGroup; + LPSTR szTitle; + + HICON hIcon; +}; + +enum +{ + ICO_NEWSTORY, // 0 + ICO_USERINFO, // 1 + ICO_USERMENU, // 2 + ICO_SEARCH, // 3 + ICO_OPTIONS, // 4 + ICO_FILTER, // 5 + ICO_EXPORT, // 6 + ICO_COPY, // 7 + ICO_SENDMSG, // 8 + ICO_CLOSE, // 9 + ICO_MSGIN, // 10 + ICO_MSGOUT, // 11 + ICO_SIGNIN, // 12 + ICO_FILE, // 13 + ICO_URL, // 14 + ICO_UNKNOWN, // 15 + ICO_FINDPREV, // 16 + ICO_FINDNEXT, // 17 + ICO_NOPASSWORD, // 18 + ICO_PASSWORD, // 19 + ICO_CALENDAR, // 20 + ICO_TPLGROUP, // 21 + ICO_RESET, // 22 + ICO_PREVIEW, // 23 + ICO_VARHELP, // 24 + ICO_SAVEPASS, // 25 + ICO_COUNT // 26 +}; + +extern MyIconDesriptor icons[]; +extern int iconCount; + +void InitIcons(MyIconDesriptor *icons, LPSTR szFilename, int count); +void RefreshIcons(MyIconDesriptor *icons, int count);
\ No newline at end of file diff --git a/plugins/NewStory/src/main.cpp b/plugins/NewStory/src/main.cpp new file mode 100644 index 0000000000..885c53393c --- /dev/null +++ b/plugins/NewStory/src/main.cpp @@ -0,0 +1,103 @@ +//////////////////////////////////////////////////////////////////////// +// NewStory -- new history viewer for Miranda IM +// (c) 2005 Victor Pavlychko (nullbyte@sotline.net.ua) +// Visit http://miranda-im.org/ for details on Miranda Instant Messenger +//////////////////////////////////////////////////////////////////////// +// File: main.cpp +// Created by: Victor Pavlychko +// Description: +// Main module. Responsible for startup/cleanup and Miranda bindings +//////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" + +HANDLE hhkModulesLoaded=0, hhkOptInitialise=0, hhkTTBLoaded=0; + +CMPlugin g_plugin; + +///////////////////////////////////////////////////////////////////////////////////////// + +PLUGININFOEX pluginInfoEx = { + sizeof(PLUGININFOEX), + __PLUGIN_NAME, + PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM), + __DESCRIPTION, + __AUTHOR, + __COPYRIGHT, + __AUTHORWEB, + UNICODE_AWARE, + // {1AD11C86-CAAB-4372-A0A4-8B1168D51B9E} + { 0x1ad11c86, 0xcaab, 0x4372, { 0xa0, 0xa4, 0x8b, 0x11, 0x68, 0xd5, 0x1b, 0x9e } } +}; + +CMPlugin::CMPlugin() : + PLUGIN<CMPlugin>(MODULENAME, pluginInfoEx) +{} + +///////////////////////////////////////////////////////////////////////////////////////// + +extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = { MIID_UIHISTORY, MIID_LAST }; + +///////////////////////////////////////////////////////////////////////////////////////// + +int evtModulesLoaded(WPARAM, LPARAM) +{ + InitIcons(icons, "plugins\\newstory_icons.dll", iconCount); + InitFonts(); + InitNewstoryControl(); + InitHistory(); + InitOptions(); + LoadTemplates(); + + CLISTMENUITEM mi; + ZeroMemory(&mi, sizeof(mi)); + mi.cbSize = sizeof(mi); + mi.pszService = MS_HISTORY_SHOWCONTACTHISTORY; + mi.pszName = "User Newstory"; + mi.popupPosition = 1999990000; + mi.hIcon = icons[ICO_NEWSTORY].hIcon; + CallService(MS_CLIST_ADDCONTACTMENUITEM, (WPARAM)0, (LPARAM)&mi); + + ZeroMemory(&mi, sizeof(mi)); + mi.cbSize = sizeof(mi); + mi.pszService = "Newstory/System"; + mi.pszName = "System Newstory"; + mi.popupPosition = 1999990000; + mi.hIcon = icons[ICO_NEWSTORY].hIcon; + CallService(MS_CLIST_ADDMAINMENUITEM, (WPARAM)0, (LPARAM)&mi); + + return 0; +} + +int CMPlugin::Load() +{ + + CreateServiceFunction(MS_HISTORY_SHOWCONTACTHISTORY, svcShowNewstory); + CreateServiceFunction("Newstory/System", svcShowSystemNewstory); + + hhkModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED, evtModulesLoaded); +/* + hhkOptInitialise = HookEvent(ME_OPT_INITIALISE, OptInitialise); + + options.fnup = options.fndown = 0; + options.flags = 0; + LoadOptions(); +*/ + return 0; +} + +//void DoCleanup(); + +int CMPlugin::Unload() +{ + UnhookEvent(hhkModulesLoaded); +/* + UnhookEvent(hhkOptInitialise); + if (hhkTTBLoaded) + UnhookEvent(hhkTTBLoaded); + + DoCleanup(); +*/ + FreeHistory(); + return 0; +} diff --git a/plugins/NewStory/src/opt_passwords.cpp b/plugins/NewStory/src/opt_passwords.cpp new file mode 100644 index 0000000000..ac81dc01bc --- /dev/null +++ b/plugins/NewStory/src/opt_passwords.cpp @@ -0,0 +1,174 @@ +#include "stdafx.h" + +int icoidNoPassword, icoidPassword; + +void SetAllContactIcons(HWND hwndList) +{ + HANDLE hContact,hItem; + hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0); + while (hContact) + { + hItem=(HANDLE)SendMessage(hwndList,CLM_FINDCONTACT,(WPARAM)hContact,0); + SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(0, CheckPassword(hContact,"")?icoidNoPassword:icoidPassword)); + hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0); + } +} + +static void ResetListOptions(HWND hwndList) +{ + SendMessage(hwndList,CLM_SETBKBITMAP,0,(LPARAM)(HBITMAP)NULL); + SendMessage(hwndList,CLM_SETBKCOLOR,GetSysColor(COLOR_WINDOW),0); + SendMessage(hwndList,CLM_SETGREYOUTFLAGS,0,0); + SendMessage(hwndList,CLM_SETLEFTMARGIN,2,0); + SendMessage(hwndList,CLM_SETINDENT,10,0); + for(int i=0;i<=FONTID_MAX;i++) + SendMessage(hwndList,CLM_SETTEXTCOLOR,i,GetSysColor(COLOR_WINDOWTEXT)); + SetWindowLong(hwndList,GWL_STYLE,GetWindowLong(hwndList,GWL_STYLE)|CLS_SHOWHIDDEN); +} + +BOOL CALLBACK OptPasswordsDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + HTREEITEM hitmGlobal, hitmMaster; + switch (msg) + { + case WM_INITDIALOG: + { + HIMAGELIST himg; + himg = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), (IsWinVerXPPlus()?ILC_COLOR32:ILC_COLOR16)|ILC_MASK, 3, 3); + icoidNoPassword = ImageList_AddIcon(himg, icons[ICO_NOPASSWORD].hIcon); + icoidPassword = ImageList_AddIcon(himg, icons[ICO_PASSWORD].hIcon); + SendDlgItemMessage(hwnd, IDC_LIST, CLM_SETEXTRAIMAGELIST, 0, (LPARAM)himg); + + SendDlgItemMessage(hwnd,IDC_LIST,CLM_SETEXTRACOLUMNS,1,0); + + CLCINFOITEM cii={0}; + cii.cbSize=sizeof(cii); + cii.flags=CLCIIF_GROUPFONT; + + cii.pszText=TranslateT("** Global **"); + hitmGlobal = (HTREEITEM)SendDlgItemMessage(hwnd,IDC_LIST,CLM_ADDINFOITEM,0,(LPARAM)&cii); + SendMessage(GetDlgItem(hwnd, IDC_LIST),CLM_SETEXTRAIMAGE,(WPARAM)hitmGlobal,MAKELPARAM(0, icoidNoPassword)); + + cii.pszText=TranslateT("** Master **"); + hitmMaster = (HTREEITEM)SendDlgItemMessage(hwnd,IDC_LIST,CLM_ADDINFOITEM,0,(LPARAM)&cii); + SendMessage(GetDlgItem(hwnd, IDC_LIST),CLM_SETEXTRAIMAGE,(WPARAM)hitmMaster,MAKELPARAM(0, icoidNoPassword)); + + HWND hwndList = GetDlgItem(hwnd, IDC_LIST); + + SetAllContactIcons(GetDlgItem(hwnd, IDC_LIST)); + ResetListOptions(GetDlgItem(hwnd, IDC_LIST)); + + SendMessage(GetDlgItem(hwnd, IDC_ICO_NOPASSWORD), STM_SETICON, (WPARAM)icons[ICO_NOPASSWORD].hIcon, 0); + SendMessage(GetDlgItem(hwnd, IDC_ICO_PASSWORD), STM_SETICON, (WPARAM)icons[ICO_PASSWORD].hIcon, 0); + + SendMessage(GetDlgItem(hwnd, IDC_SAVEPASSWORD), BUTTONSETASFLATBTN, 0, 0); + SendMessage(GetDlgItem(hwnd, IDC_SAVEPASSWORD), BUTTONADDTOOLTIP, (WPARAM)Translate("Save Password"), 0); + SendMessage(GetDlgItem(hwnd, IDC_SAVEPASSWORD), BM_SETIMAGE, IMAGE_ICON, (LPARAM)icons[ICO_SAVEPASS].hIcon); + +// hVisibleIcon=ImageList_GetIcon(hIml,1,ILD_NORMAL); +// SendDlgItemMessage(hwndDlg,IDC_VISIBLEICON,STM_SETICON,(WPARAM)hVisibleIcon,0); +// hInvisibleIcon=ImageList_GetIcon(hIml,2,ILD_NORMAL); +// SendDlgItemMessage(hwndDlg,IDC_INVISIBLEICON,STM_SETICON,(WPARAM)hInvisibleIcon,0); + + return TRUE; + } + + case WM_NOTIFY: + switch(((LPNMHDR)lParam)->idFrom) + { + case 0: + { + switch (((LPNMHDR)lParam)->code) + { + case PSN_RESET: + { + return TRUE; + } + + case PSN_APPLY: + { + return TRUE; + } + } + break; + } + + case IDC_LIST: + { + switch (((LPNMHDR)lParam)->code) + { + case CLN_NEWCONTACT: + case CLN_LISTREBUILT: + SetAllContactIcons(GetDlgItem(hwnd,IDC_LIST)); + //fall through +// case CLN_CONTACTMOVED: +// SetListGroupIcons(GetDlgItem(hwndDlg,IDC_LIST),(HANDLE)SendDlgItemMessage(hwndDlg,IDC_LIST,CLM_GETNEXTITEM,CLGN_ROOT,0),hItemAll,NULL); +// break; +// case CLN_OPTIONSCHANGED: + ResetListOptions(GetDlgItem(hwnd,IDC_LIST)); + break; +/* + case NM_CLICK: + { HANDLE hItem; + NMCLISTCONTROL *nm=(NMCLISTCONTROL*)lParam; + DWORD hitFlags; + int iImage; + int itemType; + + // Make sure we have an extra column + if (nm->iColumn == -1) + break; + + // Find clicked item + hItem = (HANDLE)SendDlgItemMessage(hwndDlg, IDC_LIST, CLM_HITTEST, (WPARAM)&hitFlags, MAKELPARAM(nm->pt.x,nm->pt.y)); + // Nothing was clicked + if (hItem == NULL) break; + // It was not a visbility icon + if (!(hitFlags & CLCHT_ONITEMEXTRA)) break; + + // Get image in clicked column (0=none, 1=visible, 2=invisible) + iImage = SendDlgItemMessage(hwndDlg, IDC_LIST, CLM_GETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(nm->iColumn, 0)); + if (iImage == 0) + iImage=nm->iColumn + 1; + else + if (iImage == 1 || iImage == 2) + iImage = 0; + + // Get item type (contact, group, etc...) + itemType = SendDlgItemMessage(hwndDlg, IDC_LIST, CLM_GETITEMTYPE, (WPARAM)hItem, 0); + + // Update list, making sure that the options are mutually exclusive + if (itemType == CLCIT_CONTACT) { // A contact + SendDlgItemMessage(hwndDlg, IDC_LIST, CLM_SETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(nm->iColumn, iImage)); + if (iImage && SendDlgItemMessage(hwndDlg,IDC_LIST,CLM_GETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(nm->iColumn?0:1,0))!=0xFF) + SendDlgItemMessage(hwndDlg, IDC_LIST, CLM_SETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(nm->iColumn?0:1, 0)); + } + else if (itemType == CLCIT_INFO) { // All Contacts + SetAllChildIcons(GetDlgItem(hwndDlg, IDC_LIST), hItem, nm->iColumn, iImage); + if (iImage) + SetAllChildIcons(GetDlgItem(hwndDlg, IDC_LIST), hItem, nm->iColumn?0:1, 0); + } + else if (itemType == CLCIT_GROUP) { // A group + hItem = (HANDLE)SendDlgItemMessage(hwndDlg, IDC_LIST, CLM_GETNEXTITEM, CLGN_CHILD, (LPARAM)hItem); + if (hItem) { + SetAllChildIcons(GetDlgItem(hwndDlg, IDC_LIST), hItem, nm->iColumn, iImage); + if (iImage) + SetAllChildIcons(GetDlgItem(hwndDlg, IDC_LIST), hItem, nm->iColumn?0:1, 0); + } + } + // Update the all/none icons + SetListGroupIcons(GetDlgItem(hwndDlg, IDC_LIST), (HANDLE)SendDlgItemMessage(hwndDlg, IDC_LIST, CLM_GETNEXTITEM, CLGN_ROOT, 0), hItemAll, NULL); + + // Activate Apply button + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + } +*/ + } + return TRUE; + } + } + break; + } + return FALSE; +} diff --git a/plugins/NewStory/src/opt_passwords.h b/plugins/NewStory/src/opt_passwords.h new file mode 100644 index 0000000000..f9583c266d --- /dev/null +++ b/plugins/NewStory/src/opt_passwords.h @@ -0,0 +1,6 @@ +#ifndef __opt_passwords_h__ +#define __opt_passwords_h__ + +BOOL CALLBACK OptPasswordsDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); + +#endif // __opt_passwords_h__
\ No newline at end of file diff --git a/plugins/NewStory/src/options.cpp b/plugins/NewStory/src/options.cpp new file mode 100644 index 0000000000..fb5283223a --- /dev/null +++ b/plugins/NewStory/src/options.cpp @@ -0,0 +1,161 @@ +#include "stdafx.h" + +Options options; +int OptShowPage = 0; + +#undef MODULENAME +#define MODULENAME "PopUp" + +void LoadOptions() +{ + return; +} + +static int OptionsInitialize(WPARAM wParam, LPARAM lParam); + +void InitOptions() +{ + HookEvent(ME_OPT_INITIALISE, OptionsInitialize); +} + +BOOL CALLBACK OptionsDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); + +static int OptionsInitialize(WPARAM wParam, LPARAM lParam) +{ + OPTIONSDIALOGPAGE odp = { 0 }; + odp.cbSize = sizeof(odp); + odp.position = 100000000; + odp.hInstance = hInst; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS); + odp.pszTitle = Translate("Newstory"); +// odp.pszGroup = Translate("PopUps"); + odp.groupPosition = 910000000; + odp.flags=ODPF_BOLDGROUPS; + odp.pfnDlgProc = OptionsDlgProc; + CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp); + return 0; +} + +static void ThemeDialogBackground(HWND hwnd) { + if (IsWinVerXPPlus()) { + static HMODULE hThemeAPI = NULL; + if (!hThemeAPI) hThemeAPI = GetModuleHandle(_T("uxtheme")); + if (hThemeAPI) { + HRESULT (STDAPICALLTYPE *MyEnableThemeDialogTexture)(HWND,DWORD) = (HRESULT (STDAPICALLTYPE*)(HWND,DWORD))GetProcAddress(hThemeAPI,"EnableThemeDialogTexture"); + if (MyEnableThemeDialogTexture) + MyEnableThemeDialogTexture(hwnd,0x00000002|0x00000004); //0x00000002|0x00000004=ETDT_ENABLETAB + } + } +} + +BOOL CALLBACK OptionsDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch(msg) + { + case WM_INITDIALOG: + { + TCITEM tci; + RECT rc; + + tci.mask = TCIF_PARAM|TCIF_TEXT; + tci.lParam = (LPARAM)CreateDialog(hInst,MAKEINTRESOURCE(IDD_OPT_PASSWORDS),GetDlgItem(hwnd, IDC_TAB),OptPasswordsDlgProc); + tci.pszText = TranslateT("Passwords (not ready yet)"); + if (tci.lParam) TabCtrl_InsertItem(GetDlgItem(hwnd,IDC_TAB),0,&tci); + GetClientRect(GetDlgItem(hwnd, IDC_TAB), &rc); + TabCtrl_AdjustRect(GetDlgItem(hwnd, IDC_TAB), FALSE, &rc); + ThemeDialogBackground((HWND)tci.lParam); + MoveWindow((HWND)tci.lParam, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, TRUE); + ShowWindow((HWND)tci.lParam,(OptShowPage==2)?SW_SHOW:SW_HIDE); + + tci.mask = TCIF_PARAM|TCIF_TEXT; + tci.lParam = (LPARAM)CreateDialog(hInst,MAKEINTRESOURCE(IDD_OPT_TEMPLATES),GetDlgItem(hwnd, IDC_TAB),OptTemplatesDlgProc); + tci.pszText = TranslateT("Templates"); + if (tci.lParam) TabCtrl_InsertItem(GetDlgItem(hwnd,IDC_TAB),0,&tci); + GetClientRect(GetDlgItem(hwnd, IDC_TAB), &rc); + TabCtrl_AdjustRect(GetDlgItem(hwnd, IDC_TAB), FALSE, &rc); + ThemeDialogBackground((HWND)tci.lParam); + MoveWindow((HWND)tci.lParam, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, TRUE); + ShowWindow((HWND)tci.lParam,(OptShowPage==1)?SW_SHOW:SW_HIDE); + + tci.mask = TCIF_PARAM|TCIF_TEXT; + tci.lParam = (LPARAM)CreateDialog(hInst,MAKEINTRESOURCE(IDD_OPT_GENERAL),GetDlgItem(hwnd, IDC_TAB), 0); + tci.pszText = TranslateT("General"); + if (tci.lParam) TabCtrl_InsertItem(GetDlgItem(hwnd,IDC_TAB),0,&tci); + GetClientRect(GetDlgItem(hwnd, IDC_TAB), &rc); + TabCtrl_AdjustRect(GetDlgItem(hwnd, IDC_TAB), FALSE, &rc); + ThemeDialogBackground((HWND)tci.lParam); + MoveWindow((HWND)tci.lParam, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, TRUE); + ShowWindow((HWND)tci.lParam,(OptShowPage==0)?SW_SHOW:SW_HIDE); + + TabCtrl_SetCurSel(GetDlgItem(hwnd, IDC_TAB), OptShowPage); + OptShowPage = 0; + return FALSE; + } + + case PSM_CHANGED: + { + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + break; + } + + case WM_DESTROY: + { + OptShowPage = 0; + break; + } + + case WM_NOTIFY: + { + switch(((LPNMHDR)lParam)->idFrom) + { + case 0: + { + switch (((LPNMHDR)lParam)->code) + { + case PSN_RESET: + case PSN_APPLY: + { + TCITEM tci; + int i,count; + tci.mask = TCIF_PARAM; + count = TabCtrl_GetItemCount(GetDlgItem(hwnd,IDC_TAB)); + for (i=0;i<count;i++) + { + TabCtrl_GetItem(GetDlgItem(hwnd,IDC_TAB),i,&tci); + SendMessage((HWND)tci.lParam,WM_NOTIFY,wParam,lParam); + } + break; + } + } + break; + } + + case IDC_TAB: + { + switch (((LPNMHDR)lParam)->code) + { + case TCN_SELCHANGING: + { + TCITEM tci; + tci.mask = TCIF_PARAM; + TabCtrl_GetItem(GetDlgItem(hwnd,IDC_TAB),TabCtrl_GetCurSel(GetDlgItem(hwnd,IDC_TAB)),&tci); + ShowWindow((HWND)tci.lParam,SW_HIDE); + break; + } + case TCN_SELCHANGE: + { + TCITEM tci; + tci.mask = TCIF_PARAM; + TabCtrl_GetItem(GetDlgItem(hwnd,IDC_TAB),TabCtrl_GetCurSel(GetDlgItem(hwnd,IDC_TAB)),&tci); + ShowWindow((HWND)tci.lParam,SW_SHOW); + break; + } + } + break; + } + } + break; + } + } + return FALSE; +} diff --git a/plugins/NewStory/src/options.h b/plugins/NewStory/src/options.h new file mode 100644 index 0000000000..4912e12a02 --- /dev/null +++ b/plugins/NewStory/src/options.h @@ -0,0 +1,15 @@ +#ifndef __options_h__ +#define __options_h__ + +struct Options +{ + int dummy; +}; + +extern Options options; +extern int OptShowPage; + +void LoadOptions(); +void InitOptions(); + +#endif // __options_h__
\ No newline at end of file diff --git a/plugins/NewStory/src/password.cpp b/plugins/NewStory/src/password.cpp new file mode 100644 index 0000000000..bd49cbf653 --- /dev/null +++ b/plugins/NewStory/src/password.cpp @@ -0,0 +1,258 @@ +#include "stdafx.h" + +struct PasswordData +{ + HANDLE hContact; + int attempt; +}; + +bool CheckPassword(HANDLE hContact, char *password) +{ + md5_state_t ms; + md5_byte_t digest[16]; + md5_init(&ms); + md5_append(&ms, (const unsigned char *)password, lstrlenA(password)); + md5_finish(&ms, digest); + + DBVARIANT dbv; + DBCONTACTGETSETTING dbcgs; + dbcgs.szModule = MODULENAME; + dbcgs.szSetting = "password"; + dbcgs.pValue = &dbv; + CallService(MS_DB_CONTACT_GETSETTING, (WPARAM)hContact, (LPARAM)&dbcgs); + if (dbv.type != DBVT_BLOB) + { + CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); + return true; + } else + { + if (dbv.cpbVal != 16) + { + CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); + return false; + } + for (int i = 0; i < 16; i++) + if (dbv.pbVal[i] != digest[i]) + { + CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); + return false; + } + + CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); + return true; + } +} + +void SetPassword(HANDLE hContact, char *password) +{ + if (!password || !*password) + { + DBCONTACTGETSETTING dbcgs; + dbcgs.szModule = MODULENAME; + dbcgs.szSetting = "password"; + CallService(MS_DB_CONTACT_DELETESETTING, (WPARAM)hContact, (LPARAM)&dbcgs); + return; + } + + md5_state_t ms; + md5_byte_t digest[16]; + md5_init(&ms); + md5_append(&ms, (const unsigned char *)password, lstrlenA(password)); + md5_finish(&ms, digest); + + DBCONTACTWRITESETTING dbcws; + dbcws.szModule = MODULENAME; + dbcws.szSetting = "password"; + dbcws.value.type = DBVT_BLOB; + dbcws.value.cpbVal = 16; + dbcws.value.pbVal = (PBYTE)digest; + CallService(MS_DB_CONTACT_WRITESETTING, (WPARAM)hContact, (LPARAM)&dbcws); +} + +int CALLBACK PasswordDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + PasswordData *data = (PasswordData *)GetWindowLong(hwnd, GWL_USERDATA); + switch (msg) + { + case WM_INITDIALOG: + { + data = new PasswordData; + data->attempt = 0; + data->hContact = (HANDLE)lParam; + SetWindowLong(hwnd, GWL_USERDATA, (LONG)data); + + RECT rc, rcMe; + SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, 0); + GetWindowRect(hwnd, &rcMe); + SetWindowPos(hwnd, hwnd, + rc.left+((rc.right-rc.left) - (rcMe.right-rcMe.left))/2, + rc.top+((rc.bottom-rc.top) - (rcMe.bottom-rcMe.top))/2, + 0, 0, SWP_NOSIZE|SWP_NOZORDER); + + SetFocus(GetDlgItem(hwnd, IDC_PASSWORD)); + return TRUE; + } + + case WM_COMMAND: + { + switch(LOWORD(wParam)) + { + case IDOK: + { + data->attempt++; + int length = GetWindowTextLengthA(GetDlgItem(hwnd, IDC_PASSWORD)); + char *input = new char[length+1]; + GetWindowTextA(GetDlgItem(hwnd, IDC_PASSWORD), input, length+1); + if (CheckPassword(data->hContact, input)) + { + MessageBeep(MB_OK); + EndDialog(hwnd, 1); + } else + { + if (data->attempt >= 3) + { + MessageBoxA(hwnd, "Sorry, but you've not managed to type\r\nthe correct password in 3 attempts.", "Newstory", MB_ICONHAND|MB_OK); + EndDialog(hwnd, 0); + } else + { + MessageBeep(MB_ICONHAND); + SetWindowTextA(GetDlgItem(hwnd, IDC_PASSWORD), ""); + } + } + delete [] input; + return TRUE; + } + + case IDCANCEL: + { + EndDialog(hwnd, 0); + return TRUE; + } + } + break; + } + + case WM_CLOSE: + { + DestroyWindow(hwnd); + return TRUE; + } + + case WM_DESTROY: + { + delete data; + data = 0; + SetWindowLong(hwnd, GWL_USERDATA, 0); + } + } + return FALSE; +} + +bool AskPassword(HANDLE hContact) +{ + DBVARIANT dbv; + DBCONTACTGETSETTING dbcgs; + dbcgs.szModule = MODULENAME; + dbcgs.szSetting = "password"; + dbcgs.pValue = &dbv; + CallService(MS_DB_CONTACT_GETSETTING, (WPARAM)hContact, (LPARAM)&dbcgs); + if (dbv.type != DBVT_BLOB) + { + CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); + return true; + } + CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); + + if (DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_PASSWORD), 0, PasswordDlgProc, (LPARAM)hContact)) + return true; + return false; +} + + +int CALLBACK ChangePasswordDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + HANDLE hContact = (HANDLE)GetWindowLong(hwnd, GWL_USERDATA); + switch (msg) + { + case WM_INITDIALOG: + { + hContact = (HANDLE)lParam; + SetWindowLong(hwnd, GWL_USERDATA, (LONG)hContact); + +// RECT rc, rcMe; +// SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, 0); +// GetWindowRect(hwnd, &rcMe); +// SetWindowPos(hwnd, hwnd, +// rc.left+((rc.right-rc.left) - (rcMe.right-rcMe.left))/2, +// rc.top+((rc.bottom-rc.top) - (rcMe.bottom-rcMe.top))/2, +// 0, 0, SWP_NOSIZE|SWP_NOZORDER); + + SetFocus(GetDlgItem(hwnd, IDC_PASSWORD)); + return TRUE; + } + + case WM_COMMAND: + { + switch(LOWORD(wParam)) + { + case IDOK: + { + int length = GetWindowTextLengthA(GetDlgItem(hwnd, IDC_PASSWORD)); + char *input = new char[length+1]; + GetWindowTextA(GetDlgItem(hwnd, IDC_PASSWORD), input, length+1); + + length = GetWindowTextLengthA(GetDlgItem(hwnd, IDC_PASSWORD2)); + char *input2 = new char[length+1]; + GetWindowTextA(GetDlgItem(hwnd, IDC_PASSWORD2), input2, length+1); + + length = GetWindowTextLengthA(GetDlgItem(hwnd, IDC_PASSWORD3)); + char *input3 = new char[length+1]; + GetWindowTextA(GetDlgItem(hwnd, IDC_PASSWORD3), input3, length+1); + + if (lstrcmpA(input2, input3) || !CheckPassword(hContact, input)) + { + MessageBeep(MB_ICONHAND); + SetWindowTextA(GetDlgItem(hwnd, IDC_PASSWORD), ""); + SetWindowTextA(GetDlgItem(hwnd, IDC_PASSWORD2), ""); + SetWindowTextA(GetDlgItem(hwnd, IDC_PASSWORD3), ""); + } else + { + SetPassword(hContact, input2); + EndDialog(hwnd, 0); + } + + delete [] input; + delete [] input2; + delete [] input3; + + return TRUE; + } + + case IDCANCEL: + { + EndDialog(hwnd, 0); + return TRUE; + } + } + break; + } + + case WM_CLOSE: + { + EndDialog(hwnd, 0); + DestroyWindow(hwnd); + return TRUE; + } + + case WM_DESTROY: + { + SetWindowLong(hwnd, GWL_USERDATA, 0); + } + } + return FALSE; +} + +void ChangePassword(HWND hwnd, HANDLE hContact) +{ + DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_CHANGEPASSWORD), hwnd, ChangePasswordDlgProc, (LPARAM)hContact); +} diff --git a/plugins/NewStory/src/password.h b/plugins/NewStory/src/password.h new file mode 100644 index 0000000000..592cf137ec --- /dev/null +++ b/plugins/NewStory/src/password.h @@ -0,0 +1,8 @@ +#ifndef __password_h__ +#define __password_h__ + +bool CheckPassword(HANDLE hContact, char *password); +bool AskPassword(HANDLE hContact); +void ChangePassword(HWND hwnd, HANDLE hContact); + +#endif // __password_h__
\ No newline at end of file diff --git a/plugins/NewStory/src/quicklist.h b/plugins/NewStory/src/quicklist.h new file mode 100644 index 0000000000..66bb070c6c --- /dev/null +++ b/plugins/NewStory/src/quicklist.h @@ -0,0 +1,34 @@ +template <class T> +class QuickList +{ +private: + struct Item + { + T data; + Item *prev, *next; + }; + struct CacheItem + { + CacheItem(): item(0), no(0) {} + Item *item; + int no; + }; + Item *head, *tail; + int cacheSize, cacheStep, cacheUsed; + CacheItem *cache; + CacheItem last; + +public: + QuickList(int theCacheSize = 100, int theCacheStep = ) + { + head = tail = 0; + cacheSize = theCacheSize; + cacheStep = theCacheStep; + cacheUsed = 0; + cache = new CacheItem[cacheSize]; + } + ~QuickList() + { + delete [] cache; + } +};
\ No newline at end of file diff --git a/plugins/NewStory/src/resource.h b/plugins/NewStory/src/resource.h new file mode 100644 index 0000000000..6d29c53451 --- /dev/null +++ b/plugins/NewStory/src/resource.h @@ -0,0 +1,182 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by resource.rc +// +#define IDD_HISTORY 101 +#define IDI_NEWSTORY 102 +#define IDD_SEARCH 105 +#define IDD_OPTIONS 107 +#define IDR_CONTEXT 109 +#define IDR_EXPORT 110 +#define IDR_FILTER 111 +#define IDD_MESSAGE 112 +#define IDR_POPUPS 113 +#define IDR_ACCEL 114 +#define IDD_PASSWORD 116 +#define IDD_CALENDARTOOL 118 +#define IDD_CHANGEPASSWORD 119 +#define IDD_OPT_TEMPLATES 121 +#define IDD_FILTERMODE 123 +#define IDD_OPT_GENERAL 124 +#define IDI_FOLDER 125 +#define IDD_OPT_PASSWORDS 126 +#define IDC_CUSTOM1 1000 +#define IDC_GPREVIEW 1000 +#define IDC_LIST 1000 +#define IDC_ITEMS2 1000 +#define IDC_PROGRESS 1002 +#define IDC_EDIT1 1003 +#define IDC_SEARCHTEXT 1003 +#define IDC_CUSTOM3 1009 +#define IDC_CLOSE 1009 +#define IDC_MESSAGE 1010 +#define IDC_USERINFO 1011 +#define IDC_USERMENU 1012 +#define IDC_TEXT 1012 +#define IDC_SEARCH 1013 +#define IDC_USER 1013 +#define IDC_USERNICK 1013 +#define IDC_EXPORT 1014 +#define IDC_COPY 1015 +#define IDC_FILTER 1016 +#define IDC_FINDNEXT 1017 +#define IDC_LOGOPTIONS 1018 +#define IDC_FINDPREV 1019 +#define IDC_SEARCHICON 1020 +#define IDC_SECURITY 1021 +#define IDC_MSGICON 1022 +#define IDC_DATEPOPUP 1022 +#define IDC_ICO_MESSAGES_IN 1023 +#define IDC_ICO_MESSAGES_OUT 1024 +#define IDC_ICO_FILES_IN 1025 +#define IDC_ICO_FILES_OUT 1026 +#define IDC_ICO_TOTAL_IN 1027 +#define IDC_EDIT2 1028 +#define IDC_PASSWORD 1028 +#define IDC_TPL_LOGTEXT 1028 +#define IDC_PREVIEW 1028 +#define IDC_CHANGEPASS2 1028 +#define IDC_ICO_TOTAL_OUT 1028 +#define IDC_PASSWORD2 1029 +#define IDC_ICO_URLS_IN 1029 +#define IDC_PASSWORD3 1030 +#define IDC_ICO_URLS_OUT 1030 +#define IDC_TABS 1032 +#define IDC_TAB 1032 +#define IDC_TIMETREE 1035 +#define IDC_LOADING 1036 +#define IDC_PROGRESS1 1037 +#define IDC_COMBO1 1038 +#define IDC_CHECK2 1040 +#define IDC_CHECK3 1041 +#define IDC_MONTHCALENDAR1 1044 +#define IDC_USERLIST 1049 +#define IDC_TPL_WINDOW 1050 +#define IDC_UNLOCK 1055 +#define IDC_TEMPLATES 1057 +#define IDC_VARHELP 1058 +#define IDC_CHK_IN 1059 +#define IDC_VARHELP2 1059 +#define IDC_SAVEPASSWORD 1059 +#define IDC_DISCARD 1060 +#define IDC_CHK_FILE 1060 +#define IDC_CHK_URL 1061 +#define IDC_SAVE 1061 +#define IDC_UPDATEPREVIEW 1061 +#define IDC_CHK_STATUS 1062 +#define IDC_CHK_OTHER 1063 +#define IDC_CHK_AUTOFILTER 1064 +#define IDC_DATETIMEPICKER1 1065 +#define IDC_DATETIMEPICKER2 1066 +#define IDC_CHK_OUT 1067 +#define IDC_CHK_MESSAGES 1068 +#define IDC_EDITTEMPLATE 1069 +#define IDC_EDIT3 1071 +#define IDC_CHANGEPASS3 1071 +#define IDC_ICO_NOPASSWORD 1072 +#define IDC_ICO_PASSWORD 1073 +#define IDC_CHANGEPASS 1074 +#define IDC_BUTTON1 1076 +#define IDC_ICO_MESSAGES 1078 +#define IDC_ICO_FILES 1079 +#define IDC_ICO_URLS 1080 +#define IDC_ICO_TOTAL 1081 +#define IDC_TXT_MESSAGES 1090 +#define IDC_TXT_FILES 1091 +#define IDC_TXT_TOTAL 1092 +#define IDC_IB_SEPARATOR 1093 +#define IDC_TXT_URLS 1094 +#define IDC_TXT_MESSAGES_IN 1095 +#define IDC_TXT_FILES_IN 1096 +#define IDC_TXT_TOTAL_IN 1097 +#define IDC_TXT_MESSAGES_OUT 1098 +#define IDC_TXT_FILES_OUT 1099 +#define IDC_TXT_TOTAL_OUT 1100 +#define IDC_TXT_URLS_IN 1101 +#define IDC_TXT_URLS_OUT 1102 +#define IDC_DATE_FROM 1103 +#define IDC_DATE_TO 1104 +#define IDC_CHK_DATE_FROM 1105 +#define IDC_CHK_DATE_TO 1106 +#define ID_EXPOTASHTML 40001 +#define ID_EXPORTASXML 40002 +#define ID_INCOMINGONLY 40003 +#define IDD_FILTER_INCOMING 40003 +#define ID_FILTER_INCOMING 40003 +#define ID_OUTGOINGONLY 40004 +#define IDD_FILTER_OUTGOING 40004 +#define ID_FILTER_OUTGOING 40004 +#define ID_SHOWMESSAGES 40006 +#define IDD_FILTER_MESSAGES 40006 +#define ID_FILTER_MESSAGES 40006 +#define ID_SHOWFILES 40008 +#define IDD_FILTER_FILES 40008 +#define ID_FILTER_FILES 40008 +#define ID_SHOWURLS 40009 +#define IDD_FILTER_URLS 40009 +#define ID_FILTER_URLS 40009 +#define ID_SHOWSIGININOUTMESSAGES 40010 +#define IDD_FILTER_STATUS 40010 +#define ID_FILTER_STATUS 40010 +#define ID_SHOWOTHEREVENTS 40011 +#define IDD_FILTER_OTHER 40011 +#define ID_FILTER_OTHER 40011 +#define ID_CONTEXT_COPY 40012 +#define ID_EXPORT_EXPORTASTEXT 40013 +#define ID_EXPORT_EXPORTASHTML 40014 +#define ID_EXPORT_EXPORTASXML 40015 +#define ID_EXPORT_EXPORTALLASTEXT 40017 +#define ID_EXPORT_EXPORTALLASHTML 40018 +#define ID_EXPORT_EXPORTALLASXML 40019 +#define IDA_COPY 40020 +#define IDA_SEARCH 40021 +#define IDD_FILTER_AUTO 40022 +#define ID_FILTER_AUTO 40022 +#define ID_LOGOPTIONS_TEMPLATES 40023 +#define ID_LOGOPTIONS_NEWSTORYOPTIONS 40024 +#define ID_LOGOPTIONS_OPTIONS 40024 +#define ID_CONTEXT_DELETE 40026 +#define ID_CONTEXT_SELECTALL 40027 +#define ID_CONTEXT_CANCEL 40028 +#define ID_EXPORT_SAVEAS 40029 +#define ID_EXPORT_SAVESELECTEDAS 40031 +#define ID_LOGOPTIONS_SHOWTIMETREE 40032 +#define ID_SECURITY_LOCK 40033 +#define ID_SECURITY_CHANGEPASSWORD 40034 +#define ID_FILTER_SHOWALLEVENTS 40036 +#define ID_FILTER_SHOWINCOMINGEVENTSONLY 40037 +#define ID_FILTER_SHOWOUTGOINGEVENTSONLY 40038 +#define ID_FILTER_USECUSTOMFILTER 40039 +#define ID_LOGOPTIONS_PASSWORDS 40040 +#define IDC_CONTEXT_EXPORT 65535 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 127 +#define _APS_NEXT_COMMAND_VALUE 40041 +#define _APS_NEXT_CONTROL_VALUE 1107 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/plugins/NewStory/src/stdafx.cxx b/plugins/NewStory/src/stdafx.cxx new file mode 100644 index 0000000000..18ec0f9dc4 --- /dev/null +++ b/plugins/NewStory/src/stdafx.cxx @@ -0,0 +1,18 @@ +/* +Copyright (C) 2012-18 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"
\ No newline at end of file diff --git a/plugins/NewStory/src/stdafx.h b/plugins/NewStory/src/stdafx.h new file mode 100644 index 0000000000..c5e790b543 --- /dev/null +++ b/plugins/NewStory/src/stdafx.h @@ -0,0 +1,86 @@ +/* +Copyright (C) 2012 Mataes + +This is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this file; see the file license.txt. If +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. +*/ + +#pragma once + +//Windows headers +#include <windows.h> +#include <process.h> +#include <tchar.h> +#include <commctrl.h> +#include <stdio.h> +#include <time.h> + +//Miranda headers +#include "newpluginapi.h" +#include "win2k.h" +#include "m_system.h" +//#include "m_plugins.h" +#include "m_clc.h" +//#include "m_clui.h" +#include "m_clist.h" +#include "m_options.h" +#include "m_skin.h" +#include "m_langpack.h" +#include "m_database.h" +#include "m_protocols.h" +#include "m_protosvc.h" +#include "m_utils.h" +#include "m_history.h" +#include "m_button.h" +#include "m_message.h" +#include "m_userinfo.h" +#include "m_icolib.h" +#include "m_fontservice.h" + +#include "m_smileyadd.h" +//#include "m_nconvers.h" +//#include "m_MathModule.h" +//#include "m_Snapping_windows.h" +#ifndef MTEXT_NOHELPERS +#define MTEXT_NOHELPERS +#endif // MTEXT_NOHELPERS +#include "m_text.h" + +#include "resource.h" +#include "version.h" + +#define MODULENAME "NewStory" +#define MODULETITLE "NewStory" + +#include "utils.h" +#include "opt_passwords.h" +#include "options.h" +#include "icons.h" +#include "fonts.h" +#include "password.h" +#include "calendartool.h" +#include "history.h" +#include "history_array.h" +#include "history_control.h" +#include "templates.h" + +struct CMPlugin : public PLUGIN<CMPlugin> +{ + CMPlugin(); + + int Load() override; + int Unload() override; +}; + diff --git a/plugins/NewStory/src/templates.cpp b/plugins/NewStory/src/templates.cpp new file mode 100644 index 0000000000..998b48f5ea --- /dev/null +++ b/plugins/NewStory/src/templates.cpp @@ -0,0 +1,713 @@ +#include "stdafx.h" + +void TplInitVars(TemplateVars *vars); +void TplCleanVars(TemplateVars *vars); +__forceinline TCHAR *TplGetVar(TemplateVars *vars, char id); +__forceinline void TplSetVar(TemplateVars *vars, char id, TCHAR *v, bool d); +int TplMeasureVars(TemplateVars *vars, TCHAR *str); + +void vfGlobal(int mode, TemplateVars *vars, HANDLE hContact, HistoryArray::ItemData *item); +void vfContact(int mode, TemplateVars *vars, HANDLE hContact, HistoryArray::ItemData *item); +void vfSystem(int mode, TemplateVars *vars, HANDLE hContact, HistoryArray::ItemData *item); +void vfEvent(int mode, TemplateVars *vars, HANDLE hContact, HistoryArray::ItemData *item); +void vfMessage(int mode, TemplateVars *vars, HANDLE hContact, HistoryArray::ItemData *item); +void vfFile(int mode, TemplateVars *vars, HANDLE hContact, HistoryArray::ItemData *item); +void vfUrl(int mode, TemplateVars *vars, HANDLE hContact, HistoryArray::ItemData *item); +void vfSign(int mode, TemplateVars *vars, HANDLE hContact, HistoryArray::ItemData *item); +void vfAuth(int mode, TemplateVars *vars, HANDLE hContact, HistoryArray::ItemData *item); +void vfAdded(int mode, TemplateVars *vars, HANDLE hContact, HistoryArray::ItemData *item); +void vfDeleted(int mode, TemplateVars *vars, HANDLE hContact, HistoryArray::ItemData *item); +void vfOther(int mode, TemplateVars *vars, HANDLE hContact, HistoryArray::ItemData *item); + +TemplateInfo templates[TPL_COUNT] = +{ + { "tpl/interface/title", _T("Interface"), ICO_NEWSTORY, _T("Window Title"), + _T("%N's Newstory [%c messages total]"), 0, 0, + { vfGlobal, vfContact, 0, 0, 0 } }, + { "tpl/interface/passwordq", _T("Interface"), ICO_NOPASSWORD, _T("Password Query"), + _T("Ooops, %N's history seems to be password protected, so type your password here:"), 0, 0, + { vfGlobal, vfContact, 0, 0, 0 } }, + + { "tpl/msglog/msg", _T("Message Log"), ICO_SENDMSG, _T("Messages"), + _T("%I%i[b]%N, %t:[/b]\x0d\x0a%M"), 0, 0, + { vfGlobal, vfContact, vfEvent, vfMessage, 0 } }, + { "tpl/msglog/file", _T("Message Log"), ICO_FILE, _T("Files"), + _T("%I%i[b]%N, %t:[/b]%n%M"), 0, 0, + { vfGlobal, vfContact, vfEvent, vfFile, 0 } }, + { "tpl/msglog/url", _T("Message Log"), ICO_URL, _T("URLs"), + _T("%I%i[b]%N, %t:[/b]%n%M"), 0, 0, + { vfGlobal, vfContact, vfEvent, vfUrl, 0 } }, + { "tpl/msglog/status", _T("Message Log"), ICO_SIGNIN, _T("Status Changes"), + _T("%I%i[b]%N, %t:[/b]%n%M"), 0, 0, + { vfGlobal, vfContact, vfEvent, vfSign, 0 } }, + { "tpl/msglog/other", _T("Message Log"), ICO_UNKNOWN, _T("Other Events"), + _T("%I%i[b]%N, %t:[/b]%n%M"), 0, 0, + { vfGlobal, vfContact, vfEvent, vfOther, 0 } }, + + { "tpl/msglog/authrq", _T("Message Log"), ICO_UNKNOWN, _T("Authorization Requests"), + _T("%I%i[b]%N, %t:[/b]%n%M"), 0, 0, + { vfGlobal, vfEvent, vfSystem, vfAuth, 0 } }, + { "tpl/msglog/added", _T("Message Log"), ICO_UNKNOWN, _T("'You were added' events"), + _T("%I%i[b]%N, %t:[/b]%n%M"), 0, 0, + { vfGlobal, vfEvent, vfSystem, vfAdded, 0 } }, + { "tpl/msglog/deleted", _T("Message Log"), ICO_UNKNOWN, _T("'You were deleted' events"), + _T("%I%i[b]%N, %t:[/b]%n%M"), 0, 0, + { vfGlobal, vfEvent, vfSystem, vfDeleted, 0 } }, + + { "tpl/copy/msg", _T("Clipboard"), ICO_SENDMSG, _T("Messages"), + _T("%N, %t:\x0d\x0a%M%n"), 0, 0, + { vfGlobal, vfContact, vfEvent, vfMessage, 0 } }, + { "tpl/copy/file", _T("Clipboard"), ICO_FILE, _T("Files"), + _T("%N, %t:\x0d\x0a%M%n"), 0, 0, + { vfGlobal, vfContact, vfEvent, vfFile, 0 } }, + { "tpl/copy/url", _T("Clipboard"), ICO_URL, _T("URLs"), + _T("%N, %t:\x0d\x0a%M%n"), 0, 0, + { vfGlobal, vfContact, vfEvent, vfUrl, 0 } }, + { "tpl/copy/status", _T("Clipboard"), ICO_SIGNIN, _T("Status Changes"), + _T("%N, %t:\x0d\x0a%M%n"), 0, 0, + { vfGlobal, vfContact, vfEvent, vfSign, 0 } }, + { "tpl/copy/other", _T("Clipboard"), ICO_UNKNOWN, _T("Other Events"), + _T("%N, %t:\x0d\x0a%M%n"), 0, 0, + { vfGlobal, vfContact, vfEvent, vfOther, 0 } }, + + { "tpl/copy/authrq", _T("Clipboard"), ICO_UNKNOWN, _T("Authorization Requests"), + _T("%N, %t:\x0d\x0a%M%n"), 0, 0, + { vfGlobal, vfEvent, vfSystem, vfAuth, 0 } }, + { "tpl/copy/added", _T("Clipboard"), ICO_UNKNOWN, _T("'You were added' events"), + _T("%N, %t:\x0d\x0a%M%n"), 0, 0, + { vfGlobal, vfEvent, vfSystem, vfAdded, 0 } }, + { "tpl/copy/deleted", _T("Clipboard"), ICO_UNKNOWN, _T("'You were deleted' events"), + _T("%N, %t:\x0d\x0a%M%n"), 0, 0, + { vfGlobal, vfEvent, vfSystem, vfDeleted, 0 } } +}; + +void LoadTemplates() +{ + for (int i = 0; i < TPL_COUNT; i++) + { + DBVARIANT dbv = {0}; + db_get_ws(0, MODULENAME, templates[i].setting, &dbv); + if (templates[i].value) + free(templates[i].value); + if (dbv.pwszVal) + { + templates[i].value = _tcsdup(dbv.pwszVal); + } else + { + templates[i].value = 0; + } + db_free(&dbv); + } +} + +void SaveTemplates() +{ + for (int i = 0; i < TPL_COUNT; i++) + if (templates[i].value) + db_set_ws(0, MODULENAME, templates[i].setting, templates[i].value); +} + +TCHAR *TplFormatStringEx(int tpl, TCHAR *sztpl, HANDLE hContact, HistoryArray::ItemData *item) +{ + if ((tpl < 0) || (tpl >= TPL_COUNT) || !sztpl) + return _tcsdup(_T("")); + + int i; + TemplateVars vars; + for (i = 0; i < 256; i++) + { + vars.del[i] = false; + vars.val[i] = 0; + } + for (i = 0; i < TemplateInfo::VF_COUNT; i++) + if (templates[tpl].vf[i]) + templates[tpl].vf[i](VFM_VARS, &vars, hContact, item); + + TCHAR *buf = (TCHAR *)malloc(sizeof(TCHAR)*(TplMeasureVars(&vars, sztpl)+1)); + TCHAR *bufptr = buf; + for (TCHAR *p = sztpl; *p; p++) + { + if (*p == '%') + { + TCHAR *var = TplGetVar(&vars, (char)(p[1]&0xff)); + if (var) + { + lstrcpy(bufptr, var); + bufptr += lstrlen(var); + } + p++; + } else + { + *bufptr++ = *p; + } + } + *bufptr = 0; + return buf; +} + +TCHAR *TplFormatString(int tpl, HANDLE hContact, HistoryArray::ItemData *item) +{ + if ((tpl < 0) || (tpl >= TPL_COUNT)) + return _tcsdup(_T("")); + + if (!templates[tpl].value) + templates[tpl].value = _tcsdup(templates[tpl].defvalue); + + int i; + TemplateVars vars; + for (i = 0; i < 256; i++) + { + vars.del[i] = false; + vars.val[i] = 0; + } + for (i = 0; i < TemplateInfo::VF_COUNT; i++) + if (templates[tpl].vf[i]) + templates[tpl].vf[i](VFM_VARS, &vars, hContact, item); + + TCHAR *buf = (TCHAR *)malloc(sizeof(TCHAR)*(TplMeasureVars(&vars, templates[tpl].value)+1)); + TCHAR *bufptr = buf; + for (TCHAR *p = templates[tpl].value; *p; p++) + { + if (*p == '%') + { + TCHAR *var = TplGetVar(&vars, (char)(p[1]&0xff)); + if (var) + { + lstrcpy(bufptr, var); + bufptr += lstrlen(var); + } + p++; + } else + { + *bufptr++ = *p; + } + } + *bufptr = 0; + return buf; +} + +// Variable management +void TplInitVars(TemplateVars *vars) +{ + for(int i = 0; i < 256; i++) + { + vars->val[i] = 0; + vars->del[i] = false; + } +} + +void TplCleanVars(TemplateVars *vars) +{ + for(int i = 0; i < 256; i++) + if (vars->val[i] && vars->del[i]) + { + free(vars->val[i]); + vars->val[i] = 0; + vars->del[i] = false; + } +} + +__forceinline TCHAR *TplGetVar(TemplateVars *vars, char id) +{ + return vars->val[id]; +} + +__forceinline void TplSetVar(TemplateVars *vars, char id, TCHAR *v, bool d) +{ + if (vars->val[id] && vars->del[id]) + free(vars->val[id]); + vars->val[id] = v; + vars->del[id] = d; +} + +int TplMeasureVars(TemplateVars *vars, TCHAR *str) +{ + int res = 0; + for (TCHAR *p = str; *p; p++) + { + if (*p == '%') + { + TCHAR *var = TplGetVar(vars, (char)(p[1]&0xff)); + if (var) res += lstrlen(var); + p++; + } else + { + res++; + } + } + return res; +} + +// Loading variables +void vfGlobal(int mode, TemplateVars *vars, HANDLE hContact, HistoryArray::ItemData *item) +{ +// %%: simply % character + TplSetVar(vars, '%', _T("%"), false); + +// %n: line break + TplSetVar(vars, 'n', _T("\x0d\x0a"), false); + +// %M: my nick (not for messages) + wchar_t *buf = Clist_GetContactDisplayName(0, 0); + TplSetVar(vars, 'M', buf, false); +} + +void vfContact(int mode, TemplateVars *vars, HANDLE hContact, HistoryArray::ItemData *item) +{ +// %N: buddy's nick (not for messages) + DWORD a = GCDNF_TCHAR; + TplSetVar(vars, 'N', (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR), false); + +// %c: event count + TCHAR *buf = new TCHAR[20]; + wsprintf(buf, _T("%d"), CallService(MS_DB_EVENT_GETCOUNT, (WPARAM)hContact, 0)); + TplSetVar(vars, 'c', buf, false); +} + +void vfSystem(int mode, TemplateVars *vars, HANDLE hContact, HistoryArray::ItemData *item) +{ +// %N: buddy's nick (not for messages) + TplSetVar(vars, 'N', /*TranslateTS*/_T("System Event"), false); + +// %c: event count + TCHAR *buf = new TCHAR[20]; + wsprintf(buf, _T("%d"), CallService(MS_DB_EVENT_GETCOUNT, (WPARAM)hContact, 0)); + TplSetVar(vars, 'c', buf, false); +} + +void vfEvent(int mode, TemplateVars *vars, HANDLE hContact, HistoryArray::ItemData *item) +{ + HICON hIcon; + TCHAR *s; + +// %U: UIN (contextual, own uin for sent, buddys UIN for received messages) + +// %N: Nickname + TplSetVar(vars, 'N', (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, item->dbe.flags&DBEF_SENT ? 0 : (WPARAM)item->hContact, GCDNF_TCHAR), false); + +// %I: Icon + switch (item->dbe.eventType) + { + case EVENTTYPE_MESSAGE: + hIcon = icons[ICO_SENDMSG].hIcon; + break; + case EVENTTYPE_FILE: + hIcon = icons[ICO_FILE].hIcon; + break; + case EVENTTYPE_URL: + hIcon = icons[ICO_URL].hIcon; + break; + case EVENTTYPE_STATUSCHANGE: + hIcon = icons[ICO_SIGNIN].hIcon; + break; + default: + hIcon = icons[ICO_UNKNOWN].hIcon; + break; + } + s = (TCHAR *)calloc(64,sizeof(TCHAR)); + wsprintf(s, _T("[$hicon=%d$]"), hIcon); + TplSetVar(vars, 'I', s, true); + +// %i: Direction icon + if (item->dbe.flags & DBEF_SENT) + { + hIcon = icons[ICO_MSGOUT].hIcon; + } else + { + hIcon = icons[ICO_MSGIN].hIcon; + } + s = (TCHAR *)calloc(64,sizeof(TCHAR)); + wsprintf(s, _T("[$hicon=%d$]"), hIcon); + TplSetVar(vars, 'i', s, true); + +// %D: direction symbol + if (item->dbe.flags & DBEF_SENT) + { + TplSetVar(vars, 'D', _T("<<"), false); + } else + { + TplSetVar(vars, 'D', _T(">>"), false); + } + +// %t: timestamp + TCHAR *buf = (TCHAR *)calloc(100, sizeof(TCHAR)); + _tcsftime(buf, 100, _T("%d.%m.%Y, %H:%M"), localtime((time_t *)&item->dbe.timestamp)); + TplSetVar(vars, 't', buf, true); + +// DBTIMETOSTRING tts; +// tts.cbDest = 100; +// tts.szFormat = "d, t"; +// tts.szDest = (char *)calloc(100, 1); +// CallService(MS_DB_TIME_TIMESTAMPTOSTRING, item->dbe.timestamp, (LPARAM)&tts); +// TplSetVar(vars, 't', tts.szDest, true); + +// tts.szFormat = ""; +// tts.szDest = (char *)calloc(100, 1); +// CallService(MS_DB_TIME_TIMESTAMPTOSTRING, item->dbe.timestamp, (LPARAM)&tts); +// TplSetVar(vars, 't', tts.szDest, true); + +// %h: hour (24 hour format, 0-23) + buf = (TCHAR *)calloc(5, sizeof(TCHAR)); + _tcsftime(buf, 5, _T("%H"), localtime((time_t *)&item->dbe.timestamp)); + TplSetVar(vars, 'h', buf, true); + +// %a: hour (12 hour format) + buf = (TCHAR *)calloc(5, sizeof(TCHAR)); + _tcsftime(buf, 5, _T("%h"), localtime((time_t *)&item->dbe.timestamp)); + TplSetVar(vars, 'a', buf, true); + +// %m: minute + buf = (TCHAR *)calloc(5, sizeof(TCHAR)); + _tcsftime(buf, 5, _T("%M"), localtime((time_t *)&item->dbe.timestamp)); + TplSetVar(vars, 'm', buf, true); + +// %s: second + buf = (TCHAR *)calloc(5, sizeof(TCHAR)); + _tcsftime(buf, 5, _T("%S"), localtime((time_t *)&item->dbe.timestamp)); + TplSetVar(vars, 's', buf, true); + +// %o: month + buf = (TCHAR *)calloc(5, sizeof(TCHAR)); + _tcsftime(buf, 5, _T("%m"), localtime((time_t *)&item->dbe.timestamp)); + TplSetVar(vars, 'o', buf, true); + +// %d: day of month + buf = (TCHAR *)calloc(5, sizeof(TCHAR)); + _tcsftime(buf, 5, _T("%d"), localtime((time_t *)&item->dbe.timestamp)); + TplSetVar(vars, 'd', buf, true); + +// %y: year + buf = (TCHAR *)calloc(5, sizeof(TCHAR)); + _tcsftime(buf, 5, _T("%Y"), localtime((time_t *)&item->dbe.timestamp)); + TplSetVar(vars, 'y', buf, true); + +// %w: day of week (Sunday, Monday.. translateable) + buf = (TCHAR *)calloc(25, sizeof(TCHAR)); + _tcsftime(buf, 25, _T("%A"), localtime((time_t *)&item->dbe.timestamp)); + TplSetVar(vars, 'w', TranslateTS(buf), false); + +// %p: AM/PM symbol + buf = (TCHAR *)calloc(5, sizeof(TCHAR)); + _tcsftime(buf, 5, _T("%p"), localtime((time_t *)&item->dbe.timestamp)); + TplSetVar(vars, 'p', buf, true); + +// %O: Name of month, translateable + buf = (TCHAR *)calloc(25, sizeof(TCHAR)); + _tcsftime(buf, 25, _T("%B"), localtime((time_t *)&item->dbe.timestamp)); + TplSetVar(vars, 'O', TranslateTS(buf), false); +} + +void vfMessage(int mode, TemplateVars *vars, HANDLE hContact, HistoryArray::ItemData *item) +{ +// %M: the message string itself + TplSetVar(vars, 'M', item->getTBuf(), false); +} + +void vfFile(int mode, TemplateVars *vars, HANDLE hContact, HistoryArray::ItemData *item) +{ +// %M: the message string itself + TplSetVar(vars, 'M', item->getTBuf(), false); +// TplSetVar(vars, 'M', _T("File event"), false); +} + +void vfUrl(int mode, TemplateVars *vars, HANDLE hContact, HistoryArray::ItemData *item) +{ +// %M: the message string itself + TplSetVar(vars, 'M', item->getTBuf(), false); +// TplSetVar(vars, 'M', _T("URL Event"), false); +} + +void vfSign(int mode, TemplateVars *vars, HANDLE hContact, HistoryArray::ItemData *item) +{ +// %M: the message string itself + TplSetVar(vars, 'M', item->getTBuf(), false); +} + +void vfAuth(int mode, TemplateVars *vars, HANDLE hContact, HistoryArray::ItemData *item) +{ +// %M: the message string itself + TplSetVar(vars, 'M', item->getTBuf(), false); +// TplSetVar(vars, 'M', _T("Auth Rq"), false); +} + +void vfAdded(int mode, TemplateVars *vars, HANDLE hContact, HistoryArray::ItemData *item) +{ +// %M: the message string itself + TplSetVar(vars, 'M', item->getTBuf(), false); +// TplSetVar(vars, 'M', _T("Added"), false); +} + +void vfDeleted(int mode, TemplateVars *vars, HANDLE hContact, HistoryArray::ItemData *item) +{ +// %M: the message string itself + TplSetVar(vars, 'M', item->getTBuf(), false); +// TplSetVar(vars, 'M', _T("Deleted"), false); +} + +void vfOther(int mode, TemplateVars *vars, HANDLE hContact, HistoryArray::ItemData *item) +{ +// %M: the message string itself + TplSetVar(vars, 'M', _T("Unknown Event"), false); +} + +// Option dialog + +BOOL CALLBACK OptTemplatesDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static int CurrentTemplate; + switch (msg) + { + case WM_INITDIALOG: + { + CurrentTemplate = -1; + + HTREEITEM hGroup = 0; + HTREEITEM hFirst = 0; + + HIMAGELIST himgTree = ImageList_Create(GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),(IsWinVerXPPlus()?ILC_COLOR32:ILC_COLOR16)|ILC_MASK,1,1); + TreeView_SetImageList(GetDlgItem(hwnd, IDC_TEMPLATES), himgTree, TVSIL_NORMAL); + + ImageList_AddIcon(himgTree, icons[ICO_TPLGROUP].hIcon); + + for (int i = 0; i < TPL_COUNT; i++) + { + if (!i || lstrcmp(templates[i].group, templates[i-1].group)) + { + if (hGroup) + TreeView_Expand(GetDlgItem(hwnd, IDC_TEMPLATES), hGroup, TVE_EXPAND); + + TVINSERTSTRUCT tvis; + tvis.hParent = 0; + tvis.hInsertAfter = TVI_LAST; + tvis.item.mask = TVIF_TEXT|TVIF_STATE|TVIF_PARAM|TVIF_IMAGE|TVIF_SELECTEDIMAGE; + tvis.item.state = tvis.item.stateMask = TVIS_BOLD; + tvis.item.iSelectedImage = tvis.item.iImage = 0; + tvis.item.pszText = templates[i].group; + tvis.item.lParam = -1; + hGroup = TreeView_InsertItem(GetDlgItem(hwnd, IDC_TEMPLATES), &tvis); + + if (!hFirst) hFirst = hGroup; + } + + TVINSERTSTRUCT tvis; + tvis.hParent = hGroup; + tvis.hInsertAfter = TVI_LAST; + tvis.item.mask = TVIF_TEXT|TVIF_PARAM|TVIF_IMAGE|TVIF_SELECTEDIMAGE; + tvis.item.pszText = templates[i].title; + tvis.item.iSelectedImage = tvis.item.iImage = + ImageList_AddIcon(himgTree, icons[templates[i].icon].hIcon); + tvis.item.lParam = i; + TreeView_InsertItem(GetDlgItem(hwnd, IDC_TEMPLATES), &tvis); + } + + if (hGroup) + TreeView_Expand(GetDlgItem(hwnd, IDC_TEMPLATES), hGroup, TVE_EXPAND); + + TreeView_SelectItem(GetDlgItem(hwnd, IDC_TEMPLATES), hFirst); + TreeView_EnsureVisible(GetDlgItem(hwnd, IDC_TEMPLATES), hFirst); + + SendMessage(GetDlgItem(hwnd, IDC_DISCARD), BUTTONSETASFLATBTN, 0, 0); + SendMessage(GetDlgItem(hwnd, IDC_UPDATEPREVIEW), BUTTONSETASFLATBTN, 0, 0); + SendMessage(GetDlgItem(hwnd, IDC_VARHELP), BUTTONSETASFLATBTN, 0, 0); + + SendMessage(GetDlgItem(hwnd, IDC_DISCARD), BUTTONADDTOOLTIP, (WPARAM)Translate("Cancel Edit"), 0); + SendMessage(GetDlgItem(hwnd, IDC_UPDATEPREVIEW), BUTTONADDTOOLTIP, (WPARAM)Translate("Update Preview"), 0); + SendMessage(GetDlgItem(hwnd, IDC_VARHELP), BUTTONADDTOOLTIP, (WPARAM)Translate("Help on Variables"), 0); + + SendMessage(GetDlgItem(hwnd, IDC_DISCARD), BM_SETIMAGE, IMAGE_ICON, (LPARAM)icons[ICO_RESET].hIcon); + SendMessage(GetDlgItem(hwnd, IDC_UPDATEPREVIEW), BM_SETIMAGE, IMAGE_ICON, (LPARAM)icons[ICO_PREVIEW].hIcon); + SendMessage(GetDlgItem(hwnd, IDC_VARHELP), BM_SETIMAGE, IMAGE_ICON, (LPARAM)icons[ICO_VARHELP].hIcon); + + return TRUE; + } + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDC_EDITTEMPLATE: + { + SendMessage(GetParent(GetParent(hwnd)), PSM_CHANGED, 0, 0); + } + + case IDC_UPDATEPREVIEW: + { + if (templates[CurrentTemplate].tmpValue) + free(templates[CurrentTemplate].tmpValue); + int length = GetWindowTextLength(GetDlgItem(hwnd, IDC_EDITTEMPLATE))+1; + templates[CurrentTemplate].tmpValue = (TCHAR *)malloc(length*sizeof(TCHAR)); + GetWindowText(GetDlgItem(hwnd, IDC_EDITTEMPLATE), templates[CurrentTemplate].tmpValue, length); + + HistoryArray::ItemData item; + item.hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + while (item.hContact && !item.hEvent) + { + item.hEvent = (HANDLE)CallService(MS_DB_EVENT_FINDFIRST, (WPARAM)item.hContact, 0); + if (!item.hEvent) + item.hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)item.hContact, 0); + } + if (item.hContact && item.hEvent) + { + item.load(ELM_DATA); + TCHAR *preview = TplFormatStringEx(CurrentTemplate, templates[CurrentTemplate].tmpValue, item.hContact, &item); + SetWindowText(GetDlgItem(hwnd, IDC_PREVIEW), preview); +// SetWindowText(GetDlgItem(hwnd, IDC_GPREVIEW), preview); + SetWindowText(GetDlgItem(hwnd, IDC_GPREVIEW), _T("$hit :)")); + free(preview); + } else + { + SetWindowText(GetDlgItem(hwnd, IDC_PREVIEW), _T("")); + SetWindowText(GetDlgItem(hwnd, IDC_GPREVIEW), _T("")); + } + break; + } + + case IDC_DISCARD: + { + if (templates[CurrentTemplate].tmpValue) + free(templates[CurrentTemplate].tmpValue); + templates[CurrentTemplate].tmpValue = 0; + if (templates[CurrentTemplate].value) + { + SetWindowText(GetDlgItem(hwnd, IDC_EDITTEMPLATE), templates[CurrentTemplate].value); + } else + { + SetWindowText(GetDlgItem(hwnd, IDC_EDITTEMPLATE), templates[CurrentTemplate].defvalue); + } + PostMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDC_UPDATEPREVIEW,0), 0); + break; + } + } + break; + + case WM_NOTIFY: + switch(((LPNMHDR)lParam)->idFrom) + { + case 0: + { + switch (((LPNMHDR)lParam)->code) + { + case PSN_RESET: + { + for (int i = 0; i < TPL_COUNT; i++) + { + if (templates[i].tmpValue) + { + if (templates[i].tmpValue) + free(templates[i].tmpValue); + } + } + return TRUE; + } + + case PSN_APPLY: + { + for (int i = 0; i < TPL_COUNT; i++) + { + if (templates[i].tmpValue) + { + if (templates[i].value) + free(templates[i].value); + templates[i].value = templates[i].tmpValue; + templates[i].tmpValue = 0; + } + } + SaveTemplates(); + return TRUE; + } + } + break; + } + + case IDC_TEMPLATES: + { + switch (((LPNMHDR)lParam)->code) + { + case TVN_SELCHANGED: + case TVN_SELCHANGING: + { + LPNMTREEVIEW lpnmtv = (LPNMTREEVIEW)lParam; + + TVITEM tvi; + tvi.hItem = TreeView_GetSelection(GetDlgItem(hwnd, IDC_TEMPLATES)); + tvi.mask = TVIF_PARAM; + TreeView_GetItem(GetDlgItem(hwnd, IDC_TEMPLATES), &tvi); + + if ((tvi.lParam < 0) || (tvi.lParam >= TPL_COUNT)) + { + EnableWindow(GetDlgItem(hwnd, IDC_EDITTEMPLATE), FALSE); + EnableWindow(GetDlgItem(hwnd, IDC_GPREVIEW), FALSE); + EnableWindow(GetDlgItem(hwnd, IDC_PREVIEW), FALSE); + EnableWindow(GetDlgItem(hwnd, IDC_DISCARD), FALSE); + EnableWindow(GetDlgItem(hwnd, IDC_UPDATEPREVIEW), FALSE); + EnableWindow(GetDlgItem(hwnd, IDC_VARHELP), FALSE); +/* HTREEITEM hItem = TreeView_GetChild(GetDlgItem(hwnd, IDC_TEMPLATES), tvi.hItem); + if (hItem) + { + TreeView_Expand(GetDlgItem(hwnd, IDC_TEMPLATES), tvi.hItem, TVE_EXPAND); + TreeView_SelectItem(GetDlgItem(hwnd, IDC_TEMPLATES), hItem); + }*/ + break; + } else + { + EnableWindow(GetDlgItem(hwnd, IDC_EDITTEMPLATE), TRUE); + EnableWindow(GetDlgItem(hwnd, IDC_GPREVIEW), TRUE); + EnableWindow(GetDlgItem(hwnd, IDC_PREVIEW), TRUE); + EnableWindow(GetDlgItem(hwnd, IDC_DISCARD), TRUE); + EnableWindow(GetDlgItem(hwnd, IDC_UPDATEPREVIEW), TRUE); + EnableWindow(GetDlgItem(hwnd, IDC_VARHELP), TRUE); + } + + if ((lpnmtv->itemOld.mask&TVIF_HANDLE) && lpnmtv->itemOld.hItem && (lpnmtv->itemOld.hItem != lpnmtv->itemNew.hItem) && (lpnmtv->itemOld.lParam >= 0) && (lpnmtv->itemOld.lParam < TPL_COUNT)) + { + if (templates[lpnmtv->itemOld.lParam].tmpValue) + free(templates[lpnmtv->itemOld.lParam].tmpValue); + int length = GetWindowTextLength(GetDlgItem(hwnd, IDC_EDITTEMPLATE))+1; + templates[lpnmtv->itemOld.lParam].tmpValue = (TCHAR *)malloc(length*sizeof(TCHAR)); + GetWindowText(GetDlgItem(hwnd, IDC_EDITTEMPLATE), templates[lpnmtv->itemOld.lParam].tmpValue, length); + } + + CurrentTemplate = tvi.lParam; + + if (templates[CurrentTemplate].tmpValue) + { + SetWindowText(GetDlgItem(hwnd, IDC_EDITTEMPLATE), templates[CurrentTemplate].tmpValue); + } else + if (templates[CurrentTemplate].value) + { + SetWindowText(GetDlgItem(hwnd, IDC_EDITTEMPLATE), templates[CurrentTemplate].value); + } else + { + SetWindowText(GetDlgItem(hwnd, IDC_EDITTEMPLATE), templates[CurrentTemplate].defvalue); + } + + PostMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDC_UPDATEPREVIEW,0), 0); + + break; + } + case TVN_KEYDOWN: + case NM_CLICK: + { + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + break; + } + +/* + { + TVHITTESTINFO hti; + hti.pt.x = (short)LOWORD(GetMessagePos()); + hti.pt.y = (short)HIWORD(GetMessagePos()); + ScreenToClient(((LPNMHDR)lParam)->hwndFrom,&hti.pt); + if(TreeView_HitTest(((LPNMHDR)lParam)->hwndFrom,&hti)) + if(hti.flags&TVHT_ONITEMSTATEICON) + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + } +*/ + + } + break; + } + } + break; + } + return FALSE; +} diff --git a/plugins/NewStory/src/templates.h b/plugins/NewStory/src/templates.h new file mode 100644 index 0000000000..9d9fba1679 --- /dev/null +++ b/plugins/NewStory/src/templates.h @@ -0,0 +1,76 @@ +#ifndef __templates_h__ +#define __templates_h__ + +enum +{ + VFM_VARS, + VFM_DESCS +}; + +struct TemplateVars +{ + bool del[256]; + TCHAR *val[256]; +}; +/* +struct VFArgs +{ + HANDLE hContact; + DBEVENTINFO *event; +}; +*/ +typedef void (* VarFunc)(int mode, TemplateVars *vars, HANDLE hContact, HistoryArray::ItemData *item); + +struct TemplateInfo +{ + enum { VF_COUNT = 5 }; + + char *setting; + TCHAR *group; + int icon; + TCHAR *title; + TCHAR *defvalue; + TCHAR *value; + TCHAR *tmpValue; + VarFunc vf[VF_COUNT]; +}; + +enum +{ + TPL_TITLE, + TPL_PASSWORDQUERY, + + TPL_MESSAGE, + TPL_FILE, + TPL_URL, + TPL_SIGN, + TPL_OTHER, + + TPL_AUTH, + TPL_ADDED, + TPL_DELETED, + + TPL_COPY_MESSAGE, + TPL_COPY_FILE, + TPL_COPY_URL, + TPL_COPY_SIGN, + TPL_COPY_OTHER, + + TPL_COPY_AUTH, + TPL_COPY_ADDED, + TPL_COPY_DELETED, + + TPL_COUNT +}; + +extern TemplateInfo templates[TPL_COUNT]; + +void LoadTemplates(); +void SaveTemplates(); + +TCHAR *TplFormatString(int tpl, HANDLE hContact, HistoryArray::ItemData *args); +TCHAR *TplFormatStringEx(int tpl, TCHAR *sztpl, HANDLE hContact, HistoryArray::ItemData *args); + +BOOL CALLBACK OptTemplatesDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); + +#endif // __templates_h__
\ No newline at end of file diff --git a/plugins/NewStory/src/utils.cpp b/plugins/NewStory/src/utils.cpp new file mode 100644 index 0000000000..717fe67042 --- /dev/null +++ b/plugins/NewStory/src/utils.cpp @@ -0,0 +1,246 @@ +#include "stdafx.h" + +DWORD toggleBit(DWORD dw, DWORD bit) +{ + if (dw & bit) + return dw & ~bit; + return dw | bit; +} + +bool CheckFilter(TCHAR *buf, TCHAR *filter) +{ +// MessageBox(0, buf, filter, MB_OK); + int l1 = lstrlen(buf); + int l2 = lstrlen(filter); + for (int i = 0; i < l1-l2+1; i++) + if (CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, buf+i, l2, filter, l2) == CSTR_EQUAL) + return true; + return false; +} + +void CopyText(HWND hwnd, TCHAR *text) +{ + OpenClipboard(hwnd); + EmptyClipboard(); + HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, sizeof(TCHAR)*(lstrlen(text)+1)); + TCHAR *s = (TCHAR *)GlobalLock(hMem); + lstrcpy(s, text); + GlobalUnlock(hMem); + #ifdef UNICODE + SetClipboardData(CF_UNICODETEXT, hMem); + #else + SetClipboardData(CF_TEXT, hMem); + #endif + CloseClipboard(); +// GlobalFree(hMem); +} + +void ExportHistory(HANDLE hContact, char *fnTemplate, char *fn, HWND hwndHistory) +{ +/* + char *szHeader = "---header---"; + char *szMsgIn = "---msgin---"; + char *szMsgOut = "---msgout---"; + char *szFile = "---file---"; + char *szURL = "---url---"; + char *szStatus = "---status---"; + char *szOther = "---other---"; + char *szFooter = "---footer---"; + char *szEnd = "---end---"; + + char *tHeader = 0; + char *tMsgIn = 0; + char *tMsgOut = 0; + char *tFile = 0; + char *tURL = 0; + char *tStatus = 0; + char *tOther = 0; + char *tFooter = 0; + char *tEnd = 0; + + char **tActive = 0; + int size; + + char line[1024]; + + FILE *f; + + f = fopen(fnTemplate, "rt"); + while (!feof(f)) + { + fgets(line, 1024, f); + int linesize = lstrlen(line)-1; + if (*line) line[linesize] = 0; + + if (!lstrcmp(line, szHeader)) + { + tActive = &tHeader; + size = 0; + } else + if (!lstrcmp(line, szMsgIn)) + { + tActive = &tMsgIn; + size = 0; + } else + if (!lstrcmp(line, szMsgOut)) + { + tActive = &tMsgOut; + size = 0; + } else + if (!lstrcmp(line, szFile)) + { + tActive = &tFile; + size = 0; + } else + if (!lstrcmp(line, szURL)) + { + tActive = &tURL; + size = 0; + } else + if (!lstrcmp(line, szStatus)) + { + tActive = &tStatus; + size = 0; + } else + if (!lstrcmp(line, szOther)) + { + tActive = &tOther; + size = 0; + } else + if (!lstrcmp(line, szFooter)) + { + tActive = &tFooter; + size = 0; + } else + if (!lstrcmp(line, szEnd)) + { + break; + } else + if (tActive) + { + line[linesize+0] = '\n'; + line[linesize+1] = '\0'; + *tActive = appendString(*tActive, line); + } + } + fclose(f); + + f = fopen(fn, "wt"); + if (!f) + { + MessageBox(hwndHistory, Translate("Can't open optput file."), Translate("Newstory Export"), MB_ICONSTOP|MB_OK); + free(tHeader); + free(tMsgIn); + free(tMsgOut); + free(tFile); + free(tURL); + free(tStatus); + free(tOther); + free(tFooter); + free(tEnd); + return; + } + + char *s; + + VFArgs args; + args.hContact = hContact; + args.event = 0; + + s = TplFormatStringEx(TPL_TITLE, tHeader, &args); + fputs(s,f); + free(s); + + int eventCount = SendMessage(hwndHistory, UM_GETEVENTCOUNT, 0, 0); + for (int i = 0; i < eventCount; i++) + { + if (!SendMessage(hwndHistory, UM_SELECTED, i, 0)) + continue; + + args.event = (DBEVENTINFO *)SendMessage(hwndHistory, UM_GETEVENT, i, TRUE); + switch (args.event->eventType) + { + case EVENTTYPE_MESSAGE: + if (args.event->flags & DBEF_SENT) + { + s = TplFormatStringEx(TPL_MESSAGE, tMsgOut?tMsgOut:tOther, &args); + } else + { + s = TplFormatStringEx(TPL_MESSAGE, tMsgIn?tMsgOut:tOther, &args); + } + break; + + case EVENTTYPE_FILE: + s = TplFormatStringEx(TPL_FILE, tFile?tFile:tOther, &args); + break; + + case EVENTTYPE_URL: + s = TplFormatStringEx(TPL_URL, tURL?tURL:tOther, &args); + break; + + case EVENTTYPE_STATUSCHANGE: + s = TplFormatStringEx(TPL_SIGN, tStatus?tStatus:tOther, &args); + break; + + default: + s = TplFormatStringEx(TPL_OTHER, tOther, &args); + break; + } + + fputs(s,f); + free(s); + } + + s = TplFormatStringEx(TPL_TITLE, tHeader, &args); + fputs(s,f); + free(s); + + fclose(f); + + free(tHeader); + free(tMsgIn); + free(tMsgOut); + free(tFile); + free(tURL); + free(tStatus); + free(tOther); + free(tFooter); + free(tEnd); +*/ +} + +char *appendString(char *s1, char *s2) +{ + if (s1) + { + int l1 = lstrlenA(s1); + int l2 = lstrlenA(s2); + char *buf = (char *)malloc(l1+l2+1); + _snprintf(buf, l1+l2+1, "%s%s", s1, s2); + free(s1); + return buf; + } else + { + char *buf = (char *)malloc(lstrlenA(s2)+1); + lstrcpyA(buf, s2); + return buf; + } +} + +WCHAR *appendString(WCHAR *s1, WCHAR *s2) +{ + if (s1) + { + int l1 = lstrlenW(s1); + int l2 = lstrlenW(s2); + WCHAR *buf = (WCHAR *)malloc(sizeof(WCHAR)*(l1+l2+1)); + _snwprintf(buf, l1+l2+1, L"%s%s", s1, s2); + free(s1); + return buf; + } else + { + WCHAR *buf = (WCHAR *)malloc(sizeof(WCHAR)*(lstrlenW(s2)+1)); + lstrcpyW(buf, s2); + return buf; + } +}
\ No newline at end of file diff --git a/plugins/NewStory/src/utils.h b/plugins/NewStory/src/utils.h new file mode 100644 index 0000000000..f97af5a829 --- /dev/null +++ b/plugins/NewStory/src/utils.h @@ -0,0 +1,19 @@ +DWORD toggleBit(DWORD dw, DWORD bit); +bool CheckFilter(TCHAR *buf, TCHAR *filter); + +void CopyText(HWND hwnd, TCHAR *text); +void ExportHistory(HANDLE hContact, char *fnTemplate, char *fn, HWND hwndList); + +char *appendString(char *s1, char *s2); +WCHAR *appendString(WCHAR *s1, WCHAR *s2); +/* +#ifdef DEBUG + #define DebugInfo(x) +#else + #define DebugInfo(x) DebugInfo_func x + __forceinline void DebugInfo_func(const TCHAR *title, const TCHAR *fmt, ...) + { + PopUp + } +#endif +*/
\ No newline at end of file diff --git a/plugins/NewStory/src/version.h b/plugins/NewStory/src/version.h new file mode 100644 index 0000000000..897499b656 --- /dev/null +++ b/plugins/NewStory/src/version.h @@ -0,0 +1,13 @@ +#define __MAJOR_VERSION 0 +#define __MINOR_VERSION 0 +#define __RELEASE_NUM 0 +#define __BUILD_NUM 4 + +#include <stdver.h> + +#define __PLUGIN_NAME "NewStory" +#define __FILENAME "NewStory.dll" +#define __DESCRIPTION "New history plugin for Miranda NG Messenger." +#define __AUTHOR "nullbie" +#define __AUTHORWEB "https://miranda-ng.org/p/NewStory/" +#define __COPYRIGHT "© 2005 Victor Pavlychko" |