summaryrefslogtreecommitdiff
path: root/plugins/NewStory/src
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/NewStory/src')
-rw-r--r--plugins/NewStory/src/calendartool.cpp91
-rw-r--r--plugins/NewStory/src/calendartool.h6
-rw-r--r--plugins/NewStory/src/fonts.cpp120
-rw-r--r--plugins/NewStory/src/fonts.h57
-rw-r--r--plugins/NewStory/src/history.cpp1074
-rw-r--r--plugins/NewStory/src/history.h40
-rw-r--r--plugins/NewStory/src/history_array.cpp256
-rw-r--r--plugins/NewStory/src/history_array.h226
-rw-r--r--plugins/NewStory/src/history_control.cpp1009
-rw-r--r--plugins/NewStory/src/history_control.h66
-rw-r--r--plugins/NewStory/src/icons.cpp74
-rw-r--r--plugins/NewStory/src/icons.h47
-rw-r--r--plugins/NewStory/src/main.cpp103
-rw-r--r--plugins/NewStory/src/opt_passwords.cpp174
-rw-r--r--plugins/NewStory/src/opt_passwords.h6
-rw-r--r--plugins/NewStory/src/options.cpp161
-rw-r--r--plugins/NewStory/src/options.h15
-rw-r--r--plugins/NewStory/src/password.cpp258
-rw-r--r--plugins/NewStory/src/password.h8
-rw-r--r--plugins/NewStory/src/quicklist.h34
-rw-r--r--plugins/NewStory/src/resource.h182
-rw-r--r--plugins/NewStory/src/stdafx.cxx18
-rw-r--r--plugins/NewStory/src/stdafx.h86
-rw-r--r--plugins/NewStory/src/templates.cpp713
-rw-r--r--plugins/NewStory/src/templates.h76
-rw-r--r--plugins/NewStory/src/utils.cpp246
-rw-r--r--plugins/NewStory/src/utils.h19
-rw-r--r--plugins/NewStory/src/version.h13
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"