summaryrefslogtreecommitdiff
path: root/plugins/ClientChangeNotify/src
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/ClientChangeNotify/src')
-rw-r--r--plugins/ClientChangeNotify/src/ClientChangeNotify.cpp481
-rw-r--r--plugins/ClientChangeNotify/src/Common.h142
-rw-r--r--plugins/ClientChangeNotify/src/Misc.h83
-rw-r--r--plugins/ClientChangeNotify/src/OptDlg.cpp215
-rw-r--r--plugins/ClientChangeNotify/src/VersionNo.h11
-rw-r--r--plugins/ClientChangeNotify/src/resource.h42
6 files changed, 974 insertions, 0 deletions
diff --git a/plugins/ClientChangeNotify/src/ClientChangeNotify.cpp b/plugins/ClientChangeNotify/src/ClientChangeNotify.cpp
new file mode 100644
index 0000000000..3318c3ec92
--- /dev/null
+++ b/plugins/ClientChangeNotify/src/ClientChangeNotify.cpp
@@ -0,0 +1,481 @@
+/*
+ ClientChangeNotify - Plugin for Miranda IM
+ Copyright (c) 2006-2008 Chervov Dmitry
+
+ 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "Common.h"
+#include "Misc.h"
+#include "VersionNo.h"
+#include "m_message.h"
+#include "m_userinfo.h"
+#include "m_history.h"
+#include "m_protocols.h"
+#include "m_updater.h"
+#include "m_protosvc.h"
+#include "m_metacontacts.h"
+#include "m_icolib.h"
+#include "m_genmenu.h"
+#include "m_ContactSettings.h"
+
+HINSTANCE g_hInstance;
+HANDLE g_hMainThread;
+HANDLE g_hTogglePopupsMenuItem;
+int hLangpack;
+TMyArray<HANDLE> hHooks, hServices;
+COptPage *g_PreviewOptPage; // we need to show popup even for the NULL contact if g_PreviewOptPage is not NULL (used for popup preview)
+
+PLUGININFOEX pluginInfo = {
+ sizeof(PLUGININFOEX),
+ "ClientChangeNotify",
+ PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
+ "ClientChangeNotify plugin for Miranda IM.",
+ "Deathdemon",
+ "dchervov@yahoo.com",
+ "© 2006-2008 Chervov Dmitry",
+ "http://deathdemon.int.ru/",
+ UNICODE_AWARE,
+ // {B68A8906-748B-435d-930E-21CC6E8F3B3F}
+ {0xb68a8906, 0x748b, 0x435d, {0x93, 0xe, 0x21, 0xcc, 0x6e, 0x8f, 0x3b, 0x3f}}
+};
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+ g_hInstance = hinstDLL;
+ return TRUE;
+}
+
+#define MIID_CLIENTCHANGENOTIFY {0xe9d1f0d4, 0xd65d, 0x4840, {0x87, 0xbd, 0x59, 0xd7, 0xb4, 0x70, 0x2c, 0x47}}
+// {E9D1F0D4-D65D-4840-87BD-59D7B4702C47}
+
+static const MUUID interfaces[] = {MIID_CLIENTCHANGENOTIFY, MIID_LAST};
+extern "C" __declspec(dllexport) const MUUID *MirandaPluginInterfaces(void)
+{
+ return interfaces;
+}
+
+extern "C" __declspec(dllexport) PLUGININFOEX *MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ return &pluginInfo;
+}
+
+static int CALLBACK MenuWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_MEASUREITEM:
+ {
+ return CallService(MS_CLIST_MENUMEASUREITEM, wParam, lParam);
+ }
+ case WM_DRAWITEM:
+ {
+ return CallService(MS_CLIST_MENUDRAWITEM, wParam, lParam);
+ }
+ }
+ return DefWindowProc(hWnd, uMsg, wParam, lParam);
+}
+
+
+static VOID NTAPI ShowContactMenu(ULONG_PTR wParam)
+// wParam = hContact
+{
+ POINT pt;
+ HWND hMenuWnd = CreateWindowEx(WS_EX_TOOLWINDOW, _T("static"), _T(MOD_NAME)_T("_MenuWindow"), 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWND_DESKTOP, NULL, g_hInstance, NULL);
+ SetWindowLongPtr(hMenuWnd, GWLP_WNDPROC, (LONG)(WNDPROC)MenuWndProc);
+ HMENU hMenu = (HMENU)CallService(MS_CLIST_MENUBUILDCONTACT, (WPARAM)wParam, 0);
+ GetCursorPos(&pt);
+ SetForegroundWindow(hMenuWnd);
+ CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(TrackPopupMenu(hMenu, TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, pt.x, pt.y, 0, hMenuWnd, NULL), MPCF_CONTACTMENU), (LPARAM)wParam);
+ PostMessage(hMenuWnd, WM_NULL, 0, 0);
+ DestroyMenu(hMenu);
+ DestroyWindow(hMenuWnd);
+}
+
+
+void Popup_DoAction(HWND hWnd, BYTE Action, PLUGIN_DATA *pdata)
+{
+ HANDLE hContact = (HANDLE)CallService(MS_POPUP_GETCONTACT, (WPARAM)hWnd, 0);
+ switch (Action) {
+ case PCA_OPENMESSAGEWND: // open message window
+ if (hContact && hContact != INVALID_HANDLE_VALUE)
+ CallServiceSync(ServiceExists("SRMsg/LaunchMessageWindow") ? "SRMsg/LaunchMessageWindow" : MS_MSG_SENDMESSAGE, (WPARAM)hContact, 0);
+ break;
+
+ case PCA_OPENMENU: // open contact menu
+ if (hContact && hContact != INVALID_HANDLE_VALUE)
+ QueueUserAPC(ShowContactMenu, g_hMainThread, (ULONG_PTR)hContact);
+ break;
+
+ case PCA_OPENDETAILS: // open contact details window
+ if (hContact != INVALID_HANDLE_VALUE)
+ CallServiceSync(MS_USERINFO_SHOWDIALOG, (WPARAM)hContact, 0);
+ break;
+
+ case PCA_OPENHISTORY: // open contact history
+ if (hContact != INVALID_HANDLE_VALUE)
+ CallServiceSync(MS_HISTORY_SHOWCONTACTHISTORY, (WPARAM)hContact, 0);
+ break;
+
+ case PCA_OPENLOG: // open log file
+ {
+ TCString LogFilePath;
+ LS_LOGINFO li = {0};
+ li.cbSize = sizeof(li);
+ li.szID = LOG_ID;
+ li.hContact = hContact;
+ li.Flags = LSLI_TCHAR;
+ li.tszLogPath = LogFilePath.GetBuffer(MAX_PATH);
+ if (!CallService(MS_LOGSERVICE_GETLOGINFO, (WPARAM)&li, 0)) {
+ LogFilePath.ReleaseBuffer();
+ ShowLog(LogFilePath);
+ }
+ else LogFilePath.ReleaseBuffer();
+ break;
+ }
+ case PCA_CLOSEPOPUP: // close popup
+ PUDeletePopUp(hWnd);
+ break;
+
+ case PCA_DONOTHING: // do nothing
+ break;
+ }
+}
+
+
+static LRESULT CALLBACK PopupWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ PLUGIN_DATA *pdata = (PLUGIN_DATA*)CallService(MS_POPUP_GETPLUGINDATA, (WPARAM)hWnd, 0);
+ if (pdata) {
+ switch (message) {
+ case WM_COMMAND:
+ if (HIWORD(wParam) == STN_CLICKED) { // left mouse button
+ Popup_DoAction(hWnd, pdata->PopupLClickAction, pdata);
+ return true;
+ }
+ break;
+
+ case WM_CONTEXTMENU: // right mouse button
+ Popup_DoAction(hWnd, pdata->PopupRClickAction, pdata);
+ return true;
+
+ case UM_FREEPLUGINDATA:
+ if (pdata->hIcon)
+ DestroyIcon(pdata->hIcon);
+
+ free(pdata);
+ return false;
+ break;
+ }
+ }
+ return DefWindowProc(hWnd, message, wParam, lParam);
+}
+
+
+void ShowPopup(SHOWPOPUP_DATA *sd)
+{
+ TCString PopupText;
+ if (sd->PopupOptPage->GetValue(IDC_POPUPOPTDLG_SHOWPREVCLIENT)) {
+ mir_sntprintf(PopupText.GetBuffer(MAX_MSG_LEN), MAX_MSG_LEN, TranslateT("changed client to %s (was %s)"), (const TCHAR*)sd->MirVer, (const TCHAR*)sd->OldMirVer);
+ PopupText.ReleaseBuffer();
+ }
+ else {
+ mir_sntprintf(PopupText.GetBuffer(MAX_MSG_LEN), MAX_MSG_LEN, TranslateT("changed client to %s"), (const TCHAR*)sd->MirVer);
+ PopupText.ReleaseBuffer();
+ }
+
+ PLUGIN_DATA *pdata = (PLUGIN_DATA*)calloc(1, sizeof(PLUGIN_DATA));
+ POPUPDATAT ppd = {0};
+ ppd.lchContact = sd->hContact;
+ char *szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)sd->hContact, 0);
+ pdata->hIcon = ppd.lchIcon = (HICON)CallService(MS_FP_GETCLIENTICON, (WPARAM)(const char*)TCHAR2ANSI(sd->MirVer), false);
+ _ASSERT(ppd.lchIcon);
+ if (!ppd.lchIcon || (DWORD)ppd.lchIcon == CALLSERVICE_NOTFOUND) {
+ // if we didn't succeed retrieving client icon, show the usual status icon instead
+ ppd.lchIcon = LoadSkinnedProtoIcon(szProto, DBGetContactSettingWord(sd->hContact, szProto, "Status", ID_STATUS_OFFLINE));
+ pdata->hIcon = NULL;
+ }
+ _tcsncpy(ppd.lptzContactName, (TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)sd->hContact, GCDNF_TCHAR), lengthof(ppd.lptzContactName) - 1);
+ _tcsncpy(ppd.lptzText, PopupText, lengthof(ppd.lptzText) - 1);
+ ppd.colorBack = (sd->PopupOptPage->GetValue(IDC_POPUPOPTDLG_DEFBGCOLOUR) ? 0 : sd->PopupOptPage->GetValue(IDC_POPUPOPTDLG_BGCOLOUR));
+ ppd.colorText = (sd->PopupOptPage->GetValue(IDC_POPUPOPTDLG_DEFTEXTCOLOUR) ? 0 : sd->PopupOptPage->GetValue(IDC_POPUPOPTDLG_TEXTCOLOUR));
+ ppd.PluginWindowProc = PopupWndProc;
+ pdata->PopupLClickAction = sd->PopupOptPage->GetValue(IDC_POPUPOPTDLG_LCLICK_ACTION);
+ pdata->PopupRClickAction = sd->PopupOptPage->GetValue(IDC_POPUPOPTDLG_RCLICK_ACTION);
+ ppd.iSeconds = sd->PopupOptPage->GetValue(IDC_POPUPOPTDLG_POPUPDELAY);
+ ppd.PluginData = pdata;
+ PUAddPopUpT(&ppd);
+}
+
+int ContactSettingChanged(WPARAM wParam, LPARAM lParam)
+{
+ DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING*)lParam;
+ if (!lstrcmpA(cws->szSetting, DB_MIRVER)) {
+ HANDLE hContact = (HANDLE)wParam;
+ SHOWPOPUP_DATA sd = {0};
+ char *szProto = NULL;
+ if (g_PreviewOptPage)
+ sd.MirVer = _T("Miranda IM 0.6.0.1 (ICQ v0.3.7 alpha)");
+ else {
+ if (!hContact) // exit if hContact == NULL and it's not a popup preview
+ return 0;
+
+ szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ _ASSERT(szProto);
+ if (ServiceExists(MS_MC_GETPROTOCOLNAME) && !strcmp(szProto, (char*)CallService(MS_MC_GETPROTOCOLNAME, 0, 0))) // workaround for metacontacts
+ return 0;
+
+ sd.MirVer = DBGetContactSettingString(hContact, szProto, DB_MIRVER, _T(""));
+ if (sd.MirVer.IsEmpty())
+ return 0;
+ }
+ sd.OldMirVer = DBGetContactSettingString(hContact, MOD_NAME, DB_OLDMIRVER, _T(""));
+ DBWriteContactSettingTString(hContact, MOD_NAME, DB_OLDMIRVER, sd.MirVer); // we have to write it here, because we modify sd.OldMirVer and sd.MirVer to conform our settings later
+ if (sd.OldMirVer.IsEmpty()) // looks like it's the right way to do
+ return 0;
+
+ COptPage PopupOptPage;
+ if (g_PreviewOptPage)
+ PopupOptPage = *g_PreviewOptPage;
+ else {
+ PopupOptPage = g_PopupOptPage;
+ PopupOptPage.DBToMem();
+ }
+
+ HANDLE hContactOrMeta = (hContact && ServiceExists(MS_MC_GETMETACONTACT)) ? (HANDLE)CallService(MS_MC_GETMETACONTACT, (WPARAM)hContact, 0) : hContact;
+ if (!hContactOrMeta)
+ hContactOrMeta = hContact;
+
+ if (hContact && DBGetContactSettingByte(hContactOrMeta, "CList", "Hidden", 0))
+ return 0;
+
+ int PerContactSetting = hContact ? DBGetContactSettingByte(hContact, MOD_NAME, DB_CCN_NOTIFY, NOTIFY_USEGLOBAL) : NOTIFY_ALWAYS; // NOTIFY_ALWAYS for preview
+ if (PerContactSetting == NOTIFY_USEGLOBAL && hContactOrMeta != hContact) // subcontact setting has a priority over a metacontact setting
+ PerContactSetting = DBGetContactSettingByte(hContactOrMeta, MOD_NAME, DB_CCN_NOTIFY, NOTIFY_USEGLOBAL);
+
+ if (PerContactSetting && (PerContactSetting == NOTIFY_ALMOST_ALWAYS || PerContactSetting == NOTIFY_ALWAYS || !PopupOptPage.GetValue(IDC_POPUPOPTDLG_USESTATUSNOTIFYFLAG) || !(DBGetContactSettingDword(hContactOrMeta, "Ignore", "Mask1", 0) & 0x8))) { // check if we need to notify at all
+ sd.hContact = hContact;
+ sd.PopupOptPage = &PopupOptPage;
+ if (!PopupOptPage.GetValue(IDC_POPUPOPTDLG_VERCHGNOTIFY) || !PopupOptPage.GetValue(IDC_POPUPOPTDLG_SHOWVER)) {
+ CString OldMirVerA = TCHAR2ANSI(sd.OldMirVer);
+ CString MirVerA = TCHAR2ANSI(sd.MirVer);
+ if (ServiceExists(MS_FP_SAMECLIENTS)) {
+ char *szOldClient = (char*)CallService(MS_FP_SAMECLIENTS, (WPARAM)(const char*)OldMirVerA, (LPARAM)(const char*)OldMirVerA); // remove version from MirVer strings. I know, the way in which MS_FP_SAMECLIENTS is used here is pretty ugly, but at least it gives necessary results
+ char *szClient = (char*)CallService(MS_FP_SAMECLIENTS, (WPARAM)(const char*)MirVerA, (LPARAM)(const char*)MirVerA);
+ if (szOldClient && szClient) {
+ if (PerContactSetting != NOTIFY_ALMOST_ALWAYS && PerContactSetting != NOTIFY_ALWAYS && !PopupOptPage.GetValue(IDC_POPUPOPTDLG_VERCHGNOTIFY) && !strcmp(szClient, szOldClient))
+ return 0;
+
+ if (!PopupOptPage.GetValue(IDC_POPUPOPTDLG_SHOWVER)) {
+ sd.MirVer = ANSI2TCHAR(szClient);
+ sd.OldMirVer = ANSI2TCHAR(szOldClient);
+ }
+ }
+ }
+ }
+ if (sd.MirVer == (const TCHAR*)sd.OldMirVer) {
+ _ASSERT(hContact);
+ return 0;
+ }
+ if (PerContactSetting == NOTIFY_ALWAYS || (PopupOptPage.GetValue(IDC_POPUPOPTDLG_POPUPNOTIFY) && (g_PreviewOptPage || PerContactSetting == NOTIFY_ALMOST_ALWAYS || !PcreCheck(sd.MirVer)))) {
+ ShowPopup(&sd);
+ SkinPlaySound(CLIENTCHANGED_SOUND);
+ }
+ }
+ if (hContact) {
+ TCString ClientName;
+ if (PopupOptPage.GetValue(IDC_POPUPOPTDLG_SHOWPREVCLIENT) && sd.OldMirVer.GetLen()) {
+ mir_sntprintf(ClientName.GetBuffer(MAX_MSG_LEN), MAX_MSG_LEN, TranslateT("%s (was %s)"), (const TCHAR*)sd.MirVer, (const TCHAR*)sd.OldMirVer);
+ ClientName.ReleaseBuffer();
+ }
+ else ClientName = sd.MirVer;
+
+ if (ServiceExists(MS_VARS_FORMATSTRING))
+ logservice_log(LOG_ID, hContact, ClientName);
+ else {
+ _ASSERT(szProto);
+ TCString szUID(_T(""));
+ char *uid = (char*)CallProtoService(szProto, PS_GETCAPS, PFLAG_UNIQUEIDSETTING, 0);
+ if (uid && (int)uid != CALLSERVICE_NOTFOUND)
+ szUID = DBGetContactSettingAsString(hContact, szProto, uid, _T(""));
+
+ logservice_log(LOG_ID, hContact, TCString((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR)) + _T(" (") + szUID + TranslateT(") changed client to ") + ClientName);
+ }
+ }
+ _ASSERT(sd.MirVer.GetLen()); // save the last known MirVer value even if the new one is empty
+ }
+ return 0;
+}
+
+static int ContactSettingsInit(WPARAM wParam, LPARAM lParam)
+{
+ CONTACTSETTINGSINIT *csi = (CONTACTSETTINGSINIT*)wParam;
+ char *szProto = (csi->Type == CSIT_CONTACT) ? (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)csi->hContact, 0) : NULL;
+ if ((csi->Type == CSIT_GROUP) || (szProto && csi->Type == CSIT_CONTACT)) {
+ int Flag1 = (csi->Type == CSIT_CONTACT) ? CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_1, 0) : PF1_IM; // if it's a group settings dialog, we assume that there are possibly some contacts in the group with PF1_IM capability
+ if (Flag1 & (PF1_IMRECV | PF1_URLRECV | PF1_FILERECV)) { // I hope, these flags are sufficient to describe which protocols can theoretically have a client
+ CONTACTSETTINGSCONTROL csc = {0};
+ csc.cbSize = sizeof(csc);
+ csc.cbStateSize = sizeof(CSCONTROLSTATE);
+ csc.Position = CSPOS_SORTBYALPHABET;
+ csc.Flags = CSCF_TCHAR;
+ csc.ControlType = CSCT_COMBOBOX;
+ csc.ptszTitle = LPGENT("Client change notifications:");
+ csc.ptszGroup = CSGROUP_NOTIFICATIONS;
+ csc.szModule = MOD_NAME;
+ csc.szSetting = DB_CCN_NOTIFY;
+ csc.StateNum = 4;
+ csc.DefState = 3;
+ CSCONTROLSTATE States[] = {CSCONTROLSTATE(LPGENT("Never, ignore client changes for this contact"), (BYTE)NOTIFY_IGNORE), CSCONTROLSTATE(LPGENT("Always except when client change notifications are disabled globally"), (BYTE)NOTIFY_ALMOST_ALWAYS), CSCONTROLSTATE(LPGENT("Always, even when client change notifications are disabled globally"), (BYTE)NOTIFY_ALWAYS), CSCONTROLSTATE(LPGENT("Use global settings (default)"), (BYTE)NOTIFY_USEGLOBAL)};
+ csc.pStates = States;
+ CallService(MS_CONTACTSETTINGS_ADDCONTROL, wParam, (LPARAM)&csc);
+ }
+ }
+ return 0;
+}
+
+
+static INT_PTR srvTogglePopups(WPARAM wParam, LPARAM lParam)
+{
+ g_PopupOptPage.SetDBValueCopy(IDC_POPUPOPTDLG_POPUPNOTIFY, !g_PopupOptPage.GetDBValueCopy(IDC_POPUPOPTDLG_POPUPNOTIFY));
+ return 0;
+}
+
+
+static int PrebuildMainMenu(WPARAM wParam, LPARAM lParam)
+{
+ // we have to use ME_CLIST_PREBUILDMAINMENU instead of updating menu items only on settings change, because "popup_enabled" and "popup_disabled" icons are not always available yet in ModulesLoaded
+ if (ServiceExists(MS_POPUP_ADDPOPUPT)) {
+ CLISTMENUITEM mi = {0};
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIF_TCHAR | CMIM_NAME | CMIM_ICON;
+ if (g_PopupOptPage.GetDBValueCopy(IDC_POPUPOPTDLG_POPUPNOTIFY)) {
+ mi.ptszName = LPGENT("Disable c&lient change notification");
+ mi.hIcon = ServiceExists(MS_SKIN2_GETICON) ? (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)"popup_enabled") : NULL;
+ }
+ else {
+ mi.ptszName = LPGENT("Enable c&lient change notification");
+ mi.hIcon = ServiceExists(MS_SKIN2_GETICON) ? (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)"popup_disabled") : NULL;
+ }
+ mi.ptszPopupName = LPGENT("PopUps");
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)g_hTogglePopupsMenuItem, (LPARAM)&mi);
+ }
+ return 0;
+}
+
+INT_PTR CALLBACK CCNErrorDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ return true;
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
+ DestroyWindow(hwndDlg);
+ break;
+
+ case WM_DESTROY:
+ if (IsDlgButtonChecked(hwndDlg, IDC_DONTREMIND))
+ DBWriteContactSettingByte(NULL, MOD_NAME, DB_NO_FINGERPRINT_ERROR, 1);
+ break;
+ }
+ return 0;
+}
+
+int MirandaLoaded(WPARAM wParam, LPARAM lParam)
+{
+ InitPcre();
+ COptPage PopupOptPage(g_PopupOptPage);
+ PopupOptPage.DBToMem();
+ RecompileRegexps(*(TCString*)PopupOptPage.GetValue(IDC_POPUPOPTDLG_IGNORESTRINGS));
+ hHooks.AddElem(HookEvent(ME_OPT_INITIALISE, OptionsDlgInit));
+ hHooks.AddElem(HookEvent(ME_DB_CONTACT_SETTINGCHANGED, ContactSettingChanged));
+ hHooks.AddElem(HookEvent(ME_CONTACTSETTINGS_INITIALISE, ContactSettingsInit));
+ SkinAddNewSoundEx(CLIENTCHANGED_SOUND, NULL, LPGEN("ClientChangeNotify: Client changed"));
+// updater plugin support
+ Update update = {0};
+ char szVersion[16];
+ update.cbSize = sizeof(Update);
+ update.szComponentName = pluginInfo.shortName;
+ update.pbVersion = (BYTE*)CreateVersionString(PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM), szVersion);
+ update.cpbVersion = (int)strlen((char*)update.pbVersion);
+ update.szUpdateURL = "http://deathdemon.int.ru/projects/ClientChangeNotifyW.zip";
+ update.szVersionURL = "http://deathdemon.int.ru/updaterinfo.php";
+ update.pbVersionPrefix = (BYTE*)"ClientChangeNotify Unicode version ";
+ update.cpbVersionPrefix = (int)strlen((char*)update.pbVersionPrefix);
+ CallService(MS_UPDATE_REGISTER, 0, (WPARAM)&update);
+
+ if (ServiceExists(MS_POPUP_ADDPOPUPT)) {
+ hServices.AddElem(CreateServiceFunction(MS_CCN_TOGGLEPOPUPS, srvTogglePopups));
+ hHooks.AddElem(HookEvent(ME_CLIST_PREBUILDMAINMENU, PrebuildMainMenu));
+ CLISTMENUITEM mi = {0};
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIF_TCHAR;
+ if (g_PopupOptPage.GetDBValueCopy(IDC_POPUPOPTDLG_POPUPNOTIFY))
+ mi.ptszName = LPGENT("Disable c&lient change notification");
+ else
+ mi.ptszName = LPGENT("Enable c&lient change notification");
+
+ mi.pszService = MS_CCN_TOGGLEPOPUPS;
+ mi.ptszPopupName = LPGENT("PopUps");
+ g_hTogglePopupsMenuItem = Menu_AddMainMenuItem(&mi);
+ }
+
+ // seems that Fingerprint is not installed
+ if ((!ServiceExists(MS_FP_SAMECLIENTS) || !ServiceExists(MS_FP_GETCLIENTICON)) && !DBGetContactSettingByte(NULL, MOD_NAME, DB_NO_FINGERPRINT_ERROR, 0))
+ CreateDialog(g_hInstance, MAKEINTRESOURCE(IDD_CCN_ERROR), NULL, CCNErrorDlgProc);
+
+ logservice_register(LOG_ID, LPGENT("ClientChangeNotify"), _T("ClientChangeNotify?puts(p,?dbsetting(%subject%,Protocol,p))?if2(_?dbsetting(,?get(p),?pinfo(?get(p),uidsetting)),).log"), TranslateT("`[`!cdate()-!ctime()`]` ?cinfo(%subject%,display) (?cinfo(%subject%,id)) changed client to %extratext%"));
+ return 0;
+}
+
+
+extern "C" int __declspec(dllexport) Load(void)
+{
+ mir_getLP( &pluginInfo );
+
+ hHooks.AddElem(HookEvent(ME_SYSTEM_MODULESLOADED, MirandaLoaded));
+ DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &g_hMainThread, THREAD_SET_CONTEXT, false, 0);
+ InitOptions();
+ if (DBGetContactSettingString(NULL, "KnownModules", MOD_NAME, (char*)NULL) == NULL)
+ DBWriteContactSettingString(NULL, "KnownModules", MOD_NAME, MOD_NAME);
+
+ if (DBGetContactSettingByte(NULL, MOD_NAME, DB_SETTINGSVER, 0) < 1) {
+ TCString Str;
+ Str = DBGetContactSettingString(NULL, MOD_NAME, DB_IGNORESUBSTRINGS, _T(""));
+ if (Str.GetLen()) // fix incorrect regexp from v0.1.1.0
+ DBWriteContactSettingTString(NULL, MOD_NAME, DB_IGNORESUBSTRINGS, Str.Replace(_T("/Miranda[0-9A-F]{8}/"), _T("/[0-9A-F]{8}(\\W|$)/")));
+
+ DBWriteContactSettingByte(NULL, MOD_NAME, DB_SETTINGSVER, 1);
+ }
+ return 0;
+}
+
+extern "C" int __declspec(dllexport) Unload()
+{
+ CloseHandle(g_hMainThread);
+ int I;
+ for (I = 0; I < hHooks.GetSize(); I++)
+ if (hHooks[I])
+ UnhookEvent(hHooks[I]);
+
+ for (I = 0; I < hServices.GetSize(); I++)
+ if (hServices[I])
+ DestroyServiceFunction(hServices[I]);
+
+ UninitPcre();
+ return 0;
+}
diff --git a/plugins/ClientChangeNotify/src/Common.h b/plugins/ClientChangeNotify/src/Common.h
new file mode 100644
index 0000000000..62d41732a7
--- /dev/null
+++ b/plugins/ClientChangeNotify/src/Common.h
@@ -0,0 +1,142 @@
+/*
+ ClientChangeNotify - Plugin for Miranda IM
+ Copyright (c) 2006-2008 Chervov Dmitry
+
+ 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#pragma once
+
+#define _CRT_SECURE_NO_WARNINGS
+#define WIN32_LEAN_AND_MEAN
+
+#define CHARARRAY_CONVERT
+
+#include <windows.h>
+#include <commctrl.h>
+#include <stdlib.h>
+#include <crtdbg.h>
+#include <shellapi.h>
+#include <commdlg.h>
+
+#include "resource.h"
+#include "newpluginapi.h"
+#include "statusmodes.h"
+#include "m_popup.h"
+#include "m_skin.h"
+#include "m_langpack.h"
+#include "m_options.h"
+#include "m_clist.h"
+#include "m_LogService.h"
+#include "m_system.h"
+#include "m_fingerprint.h"
+#include "..\CommonLibs\TMyArray.h"
+#include "..\CommonLibs\Options.h"
+#include "..\CommonLibs\CString.h"
+#include "..\CommonLibs\pcre.h"
+
+#pragma comment(lib,"comctl32.lib")
+
+#ifndef lengthof
+#define lengthof(s) (sizeof(s) / sizeof((s)[0]))
+#endif
+
+// Actions on popup click
+#define PCA_OPENMESSAGEWND 0 // open message window
+#define PCA_CLOSEPOPUP 1 // close popup
+#define PCA_OPENDETAILS 2 // open contact details window
+#define PCA_OPENMENU 3 // open contact menu
+#define PCA_OPENHISTORY 4 // open contact history
+#define PCA_OPENLOG 5 // open log file
+#define PCA_DONOTHING 6 // do nothing
+
+#define POPUP_DEF_LCLICKACTION PCA_OPENMESSAGEWND
+#define POPUP_DEF_RCLICKACTION PCA_CLOSEPOPUP
+#define POPUP_DEF_POPUP_BGCOLOUR 0xEAFFFB
+#define POPUP_DEF_POPUP_TEXTCOLOUR 0
+#define POPUP_DEF_USEDEFBGCOLOUR 0
+#define POPUP_DEF_USEDEFTEXTCOLOUR 0
+#define POPUP_DEF_POPUPDELAY 0
+
+#define IGNORESTRINGS_MAX_LEN 2048
+#define MAX_MSG_LEN 8192
+
+#define NOTIFYTIMER_INTERVAL 3500
+
+#define MOD_NAME "ClientChangeNotify"
+#define LOG_ID MOD_NAME
+#define LOG_PREFIX MOD_NAME ": " // for netlib.log
+
+#define MS_NETLIB_LOG "Netlib/Log"
+
+#define DB_MIRVER "MirVer"
+#define DB_OLDMIRVER "OldMirVer"
+#define DB_NO_FINGERPRINT_ERROR "NoFingerprintError"
+#define DB_IGNORESUBSTRINGS "IgnoreSubstrings"
+#define DB_SETTINGSVER "SettingsVer"
+
+#define DB_CCN_NOTIFY "Notify" // database key name used for per-contact settings; 0 = ignore, 1 = notify always, 2 = use global settings
+#define NOTIFY_IGNORE 0
+#define NOTIFY_ALMOST_ALWAYS 1 // don't notify only when CCN popups are disabled globally in the plugin
+#define NOTIFY_ALWAYS 2
+#define NOTIFY_USEGLOBAL 3
+
+#define CLIENTCHANGED_SOUND "ClientChanged"
+
+extern HINSTANCE g_hInstance;
+
+extern COptPage g_PopupOptPage;
+extern COptPage *g_PreviewOptPage;
+
+#define MS_VARS_FORMATSTRING "Vars/FormatString"
+#define MS_CCN_TOGGLEPOPUPS "ClientChangeNotify/TogglePopups"
+
+
+static __inline CString LogMessage(const char *Format, ...)
+{
+ va_list va;
+ char szText[8096];
+ strcpy(szText, LOG_PREFIX);
+ va_start(va, Format);
+ mir_vsnprintf(szText + (lengthof(LOG_PREFIX) - 1), sizeof(szText) - (lengthof(LOG_PREFIX) - 1), Format, va);
+ va_end(va);
+ CallService(MS_NETLIB_LOG, NULL, (LPARAM)szText);
+ return CString(szText);
+}
+
+
+// ClientChangeNotify.cpp
+
+struct PLUGIN_DATA
+{
+ HICON hIcon; // needed here to destroy its handle on UM_FREEPLUGINDATA
+ int PopupLClickAction;
+ int PopupRClickAction;
+};
+
+struct SHOWPOPUP_DATA
+{
+ HANDLE hContact;
+ TCString OldMirVer;
+ TCString MirVer;
+ COptPage *PopupOptPage;
+};
+
+
+int ContactSettingChanged(WPARAM wParam, LPARAM lParam);
+
+// OptDlg.cpp
+int OptionsDlgInit(WPARAM wParam, LPARAM lParam);
+void InitOptions();
diff --git a/plugins/ClientChangeNotify/src/Misc.h b/plugins/ClientChangeNotify/src/Misc.h
new file mode 100644
index 0000000000..262193dc26
--- /dev/null
+++ b/plugins/ClientChangeNotify/src/Misc.h
@@ -0,0 +1,83 @@
+/*
+ ClientChangeNotify - Plugin for Miranda IM
+ Copyright (c) 2006-2008 Chervov Dmitry
+
+ 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "Common.h"
+
+
+__inline void ShowMsg(TCHAR *FirstLine, TCHAR *SecondLine = _T(""), bool IsErrorMsg = false, int Timeout = 0)
+{
+ if (ServiceExists(MS_POPUP_ADDPOPUPEX))
+ {
+ POPUPDATAT ppd = {0};
+ ppd.lchIcon = LoadIcon(NULL, IsErrorMsg ? IDI_EXCLAMATION : IDI_INFORMATION);
+ lstrcpy(ppd.lptzContactName, FirstLine);
+ lstrcpy(ppd.lptzText, SecondLine);
+ ppd.colorBack = IsErrorMsg ? 0x0202E3 : 0xE8F1FD;
+ ppd.colorText = IsErrorMsg ? 0xE8F1FD : 0x000000;
+ ppd.iSeconds = Timeout;
+ CallService(MS_POPUP_ADDPOPUPT, (WPARAM)&ppd, 0);
+ } else
+ {
+ MessageBox(NULL, SecondLine, FirstLine, MB_OK | (IsErrorMsg ? MB_ICONEXCLAMATION : MB_ICONINFORMATION));
+ }
+}
+
+
+__inline TCString Path_ToRelative(TCString &Path)
+{
+ CString Str;
+ Str.GetBuffer(MAX_PATH);
+ CallService(MS_UTILS_PATHTORELATIVE, (WPARAM)(const char*)TCHAR2ANSI(Path), (LPARAM)(char*)Str);
+ Str.ReleaseBuffer();
+ return ANSI2TCHAR(Str);
+}
+
+
+__inline TCString Path_ToAbsolute(TCString &Path)
+{
+ CString Str;
+ Str.GetBuffer(MAX_PATH);
+ CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)(const char*)TCHAR2ANSI(Path), (LPARAM)(char*)Str);
+ Str.ReleaseBuffer();
+ return ANSI2TCHAR(Str);
+}
+
+
+__inline void ShowLog(TCString &LogFilePath)
+{
+ int Result = (int)ShellExecute(NULL, _T("open"), LogFilePath, NULL, NULL, SW_SHOW);
+ if (Result <= 32) // Error
+ {
+ TCHAR szError[64];
+ mir_sntprintf(szError, lengthof(szError), TranslateT("Error #%d"), Result);
+ ShowMsg(szError, TranslateT("Can't open log file ") + LogFilePath, true);
+ }
+}
+
+
+__inline void RecompileRegexps(TCString IgnoreSubstrings)
+{
+ FreePcreCompileData();
+ TCHAR *p = _tcstok(IgnoreSubstrings, _T(";"));
+ while (p)
+ {
+ CompileRegexp(p, p[0] != '/');
+ p = _tcstok(NULL, _T(";"));
+ }
+}
diff --git a/plugins/ClientChangeNotify/src/OptDlg.cpp b/plugins/ClientChangeNotify/src/OptDlg.cpp
new file mode 100644
index 0000000000..164e51e795
--- /dev/null
+++ b/plugins/ClientChangeNotify/src/OptDlg.cpp
@@ -0,0 +1,215 @@
+/*
+ ClientChangeNotify - Plugin for Miranda IM
+ Copyright (c) 2006-2008 Chervov Dmitry
+
+ 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "Common.h"
+#include "Misc.h"
+
+
+// ================================================ Popup options ================================================
+
+COptPage g_PopupOptPage(MOD_NAME, NULL);
+
+
+void EnablePopupOptDlgControls()
+{
+ int I;
+ g_PopupOptPage.PageToMem();
+ int UsePopups = g_PopupOptPage.GetValue(IDC_POPUPOPTDLG_POPUPNOTIFY);
+ for (I = 0; I < g_PopupOptPage.Items.GetSize(); I++)
+ {
+ switch (g_PopupOptPage.Items[I]->GetParam())
+ {
+ case IDC_POPUPOPTDLG_POPUPNOTIFY:
+ {
+ g_PopupOptPage.Items[I]->Enable(UsePopups);
+ } break;
+ case IDC_POPUPOPTDLG_DEFBGCOLOUR:
+ {
+ g_PopupOptPage.Items[I]->Enable(UsePopups && !g_PopupOptPage.GetValue(IDC_POPUPOPTDLG_DEFBGCOLOUR));
+ } break;
+ case IDC_POPUPOPTDLG_DEFTEXTCOLOUR:
+ {
+ g_PopupOptPage.Items[I]->Enable(UsePopups && !g_PopupOptPage.GetValue(IDC_POPUPOPTDLG_DEFTEXTCOLOUR));
+ } break;
+ }
+ }
+ if (g_PopupOptPage.GetValue(IDC_POPUPOPTDLG_VERCHGNOTIFY))
+ {
+ COptItem *ShowVer = g_PopupOptPage.Find(IDC_POPUPOPTDLG_SHOWVER);
+ ShowVer->SetValue(1);
+ ShowVer->Enable(false);
+ ShowVer->MemToWnd(g_PopupOptPage.hWnd);
+ }
+ if (!ServiceExists(MS_FP_SAMECLIENTS))
+ { // disable these checkboxes if Fingerprint wasn't found
+ g_PopupOptPage.Find(IDC_POPUPOPTDLG_VERCHGNOTIFY)->Enable(false);
+ g_PopupOptPage.Find(IDC_POPUPOPTDLG_SHOWVER)->Enable(false);
+ }
+ if (PcreEnabled())
+ {
+ SetDlgItemText(g_PopupOptPage.GetWnd(), IDC_POPUPOPTDLG_STATIC_REGEXP, TranslateT("(you can use regular expressions here)"));
+ }
+ g_PopupOptPage.MemToPage(true);
+ InvalidateRect(GetDlgItem(g_PopupOptPage.GetWnd(), IDC_POPUPOPTDLG_POPUPDELAY_SPIN), NULL, false); // update spin control
+}
+
+static struct {
+ TCHAR *Text;
+ int Action;
+}
+PopupActions[] =
+{
+ LPGENT("Open message window"), PCA_OPENMESSAGEWND,
+ LPGENT("Close popup"), PCA_CLOSEPOPUP,
+ LPGENT("Open contact details window"), PCA_OPENDETAILS,
+ LPGENT("Open contact menu"), PCA_OPENMENU,
+ LPGENT("Open contact history"), PCA_OPENHISTORY,
+ LPGENT("Open log file"), PCA_OPENLOG,
+ LPGENT("Do nothing"), PCA_DONOTHING
+};
+
+INT_PTR CALLBACK PopupOptDlg(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ static int ChangeLock = 0;
+ switch (msg) {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ ChangeLock++;
+ g_PopupOptPage.SetWnd(hwndDlg);
+ SendDlgItemMessage(hwndDlg, IDC_POPUPOPTDLG_POPUPDELAY, EM_LIMITTEXT, 4, 0);
+ SendDlgItemMessage(hwndDlg, IDC_POPUPOPTDLG_IGNORESTRINGS, EM_LIMITTEXT, IGNORESTRINGS_MAX_LEN, 0);
+ SendDlgItemMessage(hwndDlg, IDC_POPUPOPTDLG_POPUPDELAY_SPIN, UDM_SETRANGE32, -1, 9999);
+
+ HWND hLCombo = GetDlgItem(hwndDlg, IDC_POPUPOPTDLG_LCLICK_ACTION);
+ HWND hRCombo = GetDlgItem(hwndDlg, IDC_POPUPOPTDLG_RCLICK_ACTION);
+ int I;
+ for (I = 0; I < lengthof(PopupActions); I++) {
+ SendMessage(hLCombo, CB_SETITEMDATA, SendMessage(hLCombo, CB_ADDSTRING, 0, (LPARAM)TranslateTS(PopupActions[I].Text)), PopupActions[I].Action);
+ SendMessage(hRCombo, CB_SETITEMDATA, SendMessage(hRCombo, CB_ADDSTRING, 0, (LPARAM)TranslateTS(PopupActions[I].Text)), PopupActions[I].Action);
+ }
+ g_PopupOptPage.DBToMemToPage();
+ EnablePopupOptDlgControls();
+ ChangeLock--;
+ }
+ return true;
+
+ case WM_NOTIFY:
+ switch (((NMHDR*)lParam)->code) {
+ case PSN_APPLY:
+ g_PopupOptPage.PageToMemToDB();
+ RecompileRegexps(*(TCString*)g_PopupOptPage.GetValue(IDC_POPUPOPTDLG_IGNORESTRINGS));
+ return true;
+ }
+ break;
+
+ case WM_COMMAND:
+ switch (HIWORD(wParam)) {
+ case BN_CLICKED:
+ switch (LOWORD(wParam)) {
+ case IDC_POPUPOPTDLG_POPUPNOTIFY:
+ case IDC_POPUPOPTDLG_DEFBGCOLOUR:
+ case IDC_POPUPOPTDLG_DEFTEXTCOLOUR:
+ case IDC_POPUPOPTDLG_VERCHGNOTIFY:
+ EnablePopupOptDlgControls();
+ // go through
+
+ case IDC_POPUPOPTDLG_SHOWPREVCLIENT:
+ case IDC_POPUPOPTDLG_SHOWVER:
+ case IDC_POPUPOPTDLG_USESTATUSNOTIFYFLAG:
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+ return 0;
+
+ case IDC_POPUPOPTDLG_POPUPPREVIEW:
+ g_PreviewOptPage = new COptPage(g_PopupOptPage);
+ g_PreviewOptPage->PageToMem();
+ DBCONTACTWRITESETTING cws = {0};
+ cws.szModule = "ICQ";
+ cws.szSetting = DB_MIRVER;
+ DBWriteContactSettingString(NULL, MOD_NAME, DB_OLDMIRVER, "ICQ Lite v5");
+ ContactSettingChanged(NULL, (LPARAM)&cws); // simulate a version change
+ delete g_PreviewOptPage;
+ g_PreviewOptPage = NULL;
+ break;
+ }
+ break;
+
+ case EN_CHANGE:
+ if (LOWORD(wParam) == IDC_POPUPOPTDLG_POPUPDELAY || LOWORD(wParam) == IDC_POPUPOPTDLG_IGNORESTRINGS)
+ if (!ChangeLock && g_PopupOptPage.GetWnd())
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+
+ break;
+
+ case CBN_SELCHANGE:
+ if ((LOWORD(wParam) == IDC_POPUPOPTDLG_LCLICK_ACTION) || (LOWORD(wParam) == IDC_POPUPOPTDLG_RCLICK_ACTION) || (LOWORD(wParam) == IDC_POPUPOPTDLG_BGCOLOUR) || (LOWORD(wParam) == IDC_POPUPOPTDLG_TEXTCOLOUR))
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+
+ break;
+ }
+ break;
+
+ case WM_DESTROY:
+ g_PopupOptPage.SetWnd(NULL);
+ return 0;
+ }
+ return 0;
+}
+
+int OptionsDlgInit(WPARAM wParam, LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE optDi = {0};
+ optDi.cbSize = sizeof(optDi);
+ optDi.position = 920000000;
+ optDi.ptszTitle = LPGENT("ClientChangeNotify");
+ optDi.pfnDlgProc = PopupOptDlg;
+ optDi.pszTemplate = MAKEINTRESOURCEA(IDD_POPUPOPTDLG);
+ optDi.hInstance = g_hInstance;
+ optDi.ptszGroup = LPGENT("PopUps");
+ optDi.flags = ODPF_BOLDGROUPS | ODPF_TCHAR;
+ Options_AddPage(wParam, &optDi);
+ return 0;
+}
+
+void InitOptions()
+{
+ g_PopupOptPage.Items.AddElem(new COptItem_Checkbox(IDC_POPUPOPTDLG_POPUPNOTIFY, "PopupNotify", DBVT_BYTE, 1));
+ g_PopupOptPage.Items.AddElem(new COptItem_Checkbox(IDC_POPUPOPTDLG_SHOWPREVCLIENT, "ShowPrevClient", DBVT_BYTE, 0, 0, IDC_POPUPOPTDLG_POPUPNOTIFY));
+ g_PopupOptPage.Items.AddElem(new COptItem_Checkbox(IDC_POPUPOPTDLG_VERCHGNOTIFY, "VerChgNotify", DBVT_BYTE, 0, 0, IDC_POPUPOPTDLG_POPUPNOTIFY));
+ g_PopupOptPage.Items.AddElem(new COptItem_Checkbox(IDC_POPUPOPTDLG_SHOWVER, "ShowVer", DBVT_BYTE, 1, 0, IDC_POPUPOPTDLG_POPUPNOTIFY));
+ g_PopupOptPage.Items.AddElem(new COptItem_Checkbox(IDC_POPUPOPTDLG_USESTATUSNOTIFYFLAG, "UseStatusNotifyFlag", DBVT_BYTE, 1, 0, IDC_POPUPOPTDLG_POPUPNOTIFY));
+ g_PopupOptPage.Items.AddElem(new COptItem_Generic(IDC_POPUPOPTDLG_POPUPPREVIEW, IDC_POPUPOPTDLG_POPUPNOTIFY));
+ g_PopupOptPage.Items.AddElem(new COptItem_Combobox(IDC_POPUPOPTDLG_LCLICK_ACTION, "PopupLClickAction", DBVT_BYTE, POPUP_DEF_LCLICKACTION, IDC_POPUPOPTDLG_POPUPNOTIFY));
+ g_PopupOptPage.Items.AddElem(new COptItem_Combobox(IDC_POPUPOPTDLG_RCLICK_ACTION, "PopupRClickAction", DBVT_BYTE, POPUP_DEF_RCLICKACTION, IDC_POPUPOPTDLG_POPUPNOTIFY));
+ g_PopupOptPage.Items.AddElem(new COptItem_Generic(IDC_POPUPOPTDLG_STATIC_LCLICK, IDC_POPUPOPTDLG_POPUPNOTIFY));
+ g_PopupOptPage.Items.AddElem(new COptItem_Generic(IDC_POPUPOPTDLG_STATIC_RCLICK, IDC_POPUPOPTDLG_POPUPNOTIFY));
+ g_PopupOptPage.Items.AddElem(new COptItem_Colourpicker(IDC_POPUPOPTDLG_BGCOLOUR, "PopupBGColour", POPUP_DEF_POPUP_BGCOLOUR, IDC_POPUPOPTDLG_DEFBGCOLOUR));
+ g_PopupOptPage.Items.AddElem(new COptItem_Colourpicker(IDC_POPUPOPTDLG_TEXTCOLOUR, "PopupTextColour", POPUP_DEF_POPUP_TEXTCOLOUR, IDC_POPUPOPTDLG_DEFTEXTCOLOUR));
+ g_PopupOptPage.Items.AddElem(new COptItem_Checkbox(IDC_POPUPOPTDLG_DEFBGCOLOUR, "UseDefBGColour", DBVT_BYTE, POPUP_DEF_USEDEFBGCOLOUR, 0, IDC_POPUPOPTDLG_POPUPNOTIFY));
+ g_PopupOptPage.Items.AddElem(new COptItem_Checkbox(IDC_POPUPOPTDLG_DEFTEXTCOLOUR, "UseDefTextColour", DBVT_BYTE, POPUP_DEF_USEDEFTEXTCOLOUR, 0, IDC_POPUPOPTDLG_POPUPNOTIFY));
+ g_PopupOptPage.Items.AddElem(new COptItem_Generic(IDC_POPUPOPTDLG_STATIC_BGCOLOUR, IDC_POPUPOPTDLG_POPUPNOTIFY));
+ g_PopupOptPage.Items.AddElem(new COptItem_Generic(IDC_POPUPOPTDLG_STATIC_TEXTCOLOUR, IDC_POPUPOPTDLG_POPUPNOTIFY));
+ g_PopupOptPage.Items.AddElem(new COptItem_IntEdit(IDC_POPUPOPTDLG_POPUPDELAY, "PopupDelay", DBVT_WORD, true, POPUP_DEF_POPUPDELAY, IDC_POPUPOPTDLG_POPUPNOTIFY));
+ g_PopupOptPage.Items.AddElem(new COptItem_Generic(IDC_POPUPOPTDLG_STATIC_SEC, IDC_POPUPOPTDLG_POPUPNOTIFY));
+ g_PopupOptPage.Items.AddElem(new COptItem_Generic(IDC_POPUPOPTDLG_STATIC_DEFAULT, IDC_POPUPOPTDLG_POPUPNOTIFY));
+ g_PopupOptPage.Items.AddElem(new COptItem_Generic(IDC_POPUPOPTDLG_STATIC_INFINITE, IDC_POPUPOPTDLG_POPUPNOTIFY));
+ g_PopupOptPage.Items.AddElem(new COptItem_Generic(IDC_POPUPOPTDLG_STATIC_IGNORESTRINGS, IDC_POPUPOPTDLG_POPUPNOTIFY));
+ g_PopupOptPage.Items.AddElem(new COptItem_Edit(IDC_POPUPOPTDLG_IGNORESTRINGS, DB_IGNORESUBSTRINGS, IGNORESTRINGS_MAX_LEN, _T("gmail;skype;/Miranda[0-9A-F]{8}/"), IDC_POPUPOPTDLG_POPUPNOTIFY));
+ g_PopupOptPage.Items.AddElem(new COptItem_Generic(IDC_POPUPOPTDLG_STATIC_REGEXP, IDC_POPUPOPTDLG_POPUPNOTIFY));
+}
diff --git a/plugins/ClientChangeNotify/src/VersionNo.h b/plugins/ClientChangeNotify/src/VersionNo.h
new file mode 100644
index 0000000000..13ba7afb9f
--- /dev/null
+++ b/plugins/ClientChangeNotify/src/VersionNo.h
@@ -0,0 +1,11 @@
+#define __MAJOR_VERSION 0
+#define __MINOR_VERSION 1
+#define __RELEASE_NUM 1
+#define __BUILD_NUM 3
+
+#define __FILEVERSION_STRING __MAJOR_VERSION,__MINOR_VERSION,__RELEASE_NUM,__BUILD_NUM
+#define __FILEVERSION_DOTS __MAJOR_VERSION.__MINOR_VERSION.__RELEASE_NUM.__BUILD_NUM
+
+#define __STRINGIFY_IMPL(x) #x
+#define __STRINGIFY(x) __STRINGIFY_IMPL(x)
+#define __VERSION_STRING __STRINGIFY(__FILEVERSION_DOTS)
diff --git a/plugins/ClientChangeNotify/src/resource.h b/plugins/ClientChangeNotify/src/resource.h
new file mode 100644
index 0000000000..e9a86ee449
--- /dev/null
+++ b/plugins/ClientChangeNotify/src/resource.h
@@ -0,0 +1,42 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by Resources.rc
+//
+#define IDD_POPUPOPTDLG 101
+#define IDD_CCN_ERROR 103
+#define IDC_POPUPOPTDLG_POPUPNOTIFY 1002
+#define IDC_POPUPOPTDLG_BGCOLOUR 1003
+#define IDC_POPUPOPTDLG_TEXTCOLOUR 1004
+#define IDC_POPUPOPTDLG_LCLICK_ACTION 1005
+#define IDC_POPUPOPTDLG_RCLICK_ACTION 1006
+#define IDC_POPUPOPTDLG_POPUPPREVIEW 1007
+#define IDC_POPUPOPTDLG_DEFBGCOLOUR 1013
+#define IDC_POPUPOPTDLG_DEFTEXTCOLOUR 1014
+#define IDC_POPUPOPTDLG_STATIC_LCLICK 1016
+#define IDC_POPUPOPTDLG_STATIC_RCLICK 1017
+#define IDC_POPUPOPTDLG_STATIC_BGCOLOUR 1018
+#define IDC_POPUPOPTDLG_STATIC_TEXTCOLOUR 1019
+#define IDC_POPUPOPTDLG_POPUPDELAY 1020
+#define IDC_POPUPOPTDLG_STATIC_SEC 1021
+#define IDC_POPUPOPTDLG_STATIC_DEFAULT 1022
+#define IDC_POPUPOPTDLG_STATIC_INFINITE 1023
+#define IDC_POPUPOPTDLG_POPUPDELAY_SPIN 1024
+#define IDC_POPUPOPTDLG_VERCHGNOTIFY 1025
+#define IDC_POPUPOPTDLG_SHOWPREVCLIENT 1026
+#define IDC_POPUPOPTDLG_USESTATUSNOTIFYFLAG 1032
+#define IDC_POPUPOPTDLG_SHOWVER 1033
+#define IDC_DONTREMIND 1034
+#define IDC_POPUPOPTDLG_IGNORESTRINGS 1035
+#define IDC_POPUPOPTDLG_STATIC_IGNORESTRINGS 1036
+#define IDC_POPUPOPTDLG_STATIC_REGEXP 1037
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 104
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1038
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif