summaryrefslogtreecommitdiff
path: root/Plugins/smh
diff options
context:
space:
mode:
Diffstat (limited to 'Plugins/smh')
-rw-r--r--Plugins/smh/Docs/helppack_smh.txt33
-rw-r--r--Plugins/smh/Docs/langpack_smh.txt64
-rw-r--r--Plugins/smh/Docs/smh_changelog.txt38
-rw-r--r--Plugins/smh/Docs/smh_readme.txt11
-rw-r--r--Plugins/smh/Docs/smh_version.txt1
-rw-r--r--Plugins/smh/ZIP/doit.bat80
-rw-r--r--Plugins/smh/commons.h95
-rw-r--r--Plugins/smh/m_smh.h60
-rw-r--r--Plugins/smh/options.cpp292
-rw-r--r--Plugins/smh/options.h89
-rw-r--r--Plugins/smh/popup.cpp319
-rw-r--r--Plugins/smh/popup.h60
-rw-r--r--Plugins/smh/resource.h55
-rw-r--r--Plugins/smh/resource.rc180
-rw-r--r--Plugins/smh/sdk/m_metacontacts.h162
-rw-r--r--Plugins/smh/sdk/m_updater.h146
-rw-r--r--Plugins/smh/smh.cpp671
-rw-r--r--Plugins/smh/smh.dsp247
-rw-r--r--Plugins/smh/smh.dsw29
19 files changed, 2632 insertions, 0 deletions
diff --git a/Plugins/smh/Docs/helppack_smh.txt b/Plugins/smh/Docs/helppack_smh.txt
new file mode 100644
index 0000000..600509d
--- /dev/null
+++ b/Plugins/smh/Docs/helppack_smh.txt
@@ -0,0 +1,33 @@
+Miranda Help Pack Version 1
+Language: English
+Locale: 0809
+Last-Modified-Using: Miranda IM 0.5
+Authors: Pescuma
+Plugins-included: smh
+
+[smh:1061@AyUEAyYEAywEByIEAy0EByMEAy4EDhEE]
+Log changes made by the users to the contact history=
+
+[smh:1062@AyUEAyYEAywEByIEAy0EByMEAy4EDhEE]
+Enable this option to test if the text to log has only ANSI chars and in this case avoid spending some database space=Due to the way miranda store the contact history in unicode the size of an entry can be up to 3 times bigger than the text itself. If the message contains only ANSI chars, then this can be avoided.
+
+[smh:1068@AyUEAyYEAywEByIEAy0EByMEAy4EDhEE]
+Enable this to monitor status message changes=This means that the status message was empty and has beeing filled or that the text has changed (but not to an empty text).<br>This is used to log to history and to show popups.
+
+[smh:1064@AyUEAyYEAywEByIEAy0EByMEAy4EDhEE]
+[smh:1058@AyUEAyYEAywEByIEAy0EByMEAy4EDhEE]
+Template of the text to be used for status message changes=The first %s found is replaced by the contact's new status message.<br>This is used to log to history and to show popups.
+
+[smh:1069@AyUEAyYEAywEByIEAy0EByMEAy4EDhEE]
+Enable this to monitor status message removal=This means that the user had a status message and changed it to an empty text.<br>This is used to log to history and to show popups.
+
+[smh:1065@AyUEAyYEAywEByIEAy0EByMEAy4EDhEE]
+[smh:1059@AyUEAyYEAywEByIEAy0EByMEAy4EDhEE]
+Template of the text to be used for status message removal=This is used to log to history and to show popups.
+
+[smh:1070@AyUEAyYEAywEByIEAy0EByMEAy4EDhEE]
+Enable this to ignore changes/removes when the user is offline=This is used to log to history and to show popups.
+
+[smh:1067@AyUEAyYEAywEByIEAy0EByMEAy4EDhEE]
+[smh:1041@AyUEAyYEAywEByIEAy0EByMEAy4EDhEE]
+List of protocols to be monitored=Status message changes/removes that happens in contacts from protocols that are not in this list will be ignored. Metacontact is a special case: the status message changes/removes is not tracked for metacontacts, but it is copied to the meta if it happens in one of its subcontacts.<br>This is used to log to history and to show popups.
diff --git a/Plugins/smh/Docs/langpack_smh.txt b/Plugins/smh/Docs/langpack_smh.txt
new file mode 100644
index 0000000..a82a878
--- /dev/null
+++ b/Plugins/smh/Docs/langpack_smh.txt
@@ -0,0 +1,64 @@
+; Status Message History
+; Author: Pescuma
+
+; Options
+
+[History]
+[Status Message]
+
+[ History ]
+[Log changes to history]
+[Don't save Unicode parts for 7bit ANSI history (saves db space)]
+
+[ Tracking ]
+[Track when contacts change their status messages]
+[Track when contacts remove their status messages]
+[Template:]
+[Only when the contact is not offline]
+
+[ Protocols ]
+[Enable tracking for these protocols:]
+
+[Popups]
+[Status Msg Change]
+
+[Enable popups]
+
+[ Colours ]
+[Background colour]
+[Text colour]
+[Use Windows colours]
+[Use default colours]
+
+[ Delay ]
+[From popup plugin]
+[Custom]
+[Permanent]
+
+[ Actions ]
+[On right click:]
+[On left click:]
+[Do nothing]
+[Close popup]
+[Show history]
+
+[Preview]
+
+
+; Test popup
+
+[Test Contact]
+[Test description]
+
+
+; Contact Menu
+
+[Log Status Message changes]
+[Don't log Status Message changes]
+
+
+; Template defaults
+
+[changed his/her status message to %s]
+[removed his/her status message]
+[<no status message>]
diff --git a/Plugins/smh/Docs/smh_changelog.txt b/Plugins/smh/Docs/smh_changelog.txt
new file mode 100644
index 0000000..f7242ca
--- /dev/null
+++ b/Plugins/smh/Docs/smh_changelog.txt
@@ -0,0 +1,38 @@
+Status Message History 0.1.0.3
+
+Changelog:
+
+. 0.1.0.3
+ + Added support for Miranda 0.8
+
+. 0.1.0.2
+ * -pv- patch
+
+. 0.1.0.1
+ + Added support for \n in template (represents a line break)
+
+. 0.1.0.0
+ + Added to FL
+ + Added help pack
+
+. 0.0.0.6
+ * Fixes for changes tracking
+ * Fixes for updater url
+
+. 0.0.0.5
+ + Changed to History entry in options
+ * Fixes in langpack
+
+. 0.0.0.4
+ * Fix for crash
+
+. 0.0.0.3
+ + Options to what to track
+ * Fix for popups
+
+. 0.0.0.2
+ + Options page
+ + Popups
+
+. 0.0.0.1
+ + Initial version \ No newline at end of file
diff --git a/Plugins/smh/Docs/smh_readme.txt b/Plugins/smh/Docs/smh_readme.txt
new file mode 100644
index 0000000..040c797
--- /dev/null
+++ b/Plugins/smh/Docs/smh_readme.txt
@@ -0,0 +1,11 @@
+Status Message History plugin
+-----------------------------
+
+THIS PLUGIN WAS DEPRECATED IN FAVOR OF:
+http://pescuma.mirandaim.ru/miranda/historykeeper
+
+This is a simple plugin that logs status message changes to the history and show popups.
+
+If you are using tabSRMM you can see this events in the message log too.
+
+To report bugs/make suggestions, go to the forum thread: http://forums.miranda-im.org/showthread.php?t=9912
diff --git a/Plugins/smh/Docs/smh_version.txt b/Plugins/smh/Docs/smh_version.txt
new file mode 100644
index 0000000..80e752c
--- /dev/null
+++ b/Plugins/smh/Docs/smh_version.txt
@@ -0,0 +1 @@
+Status Message History 0.1.0.3 \ No newline at end of file
diff --git a/Plugins/smh/ZIP/doit.bat b/Plugins/smh/ZIP/doit.bat
new file mode 100644
index 0000000..6bbcd99
--- /dev/null
+++ b/Plugins/smh/ZIP/doit.bat
@@ -0,0 +1,80 @@
+@echo off
+
+rem Batch file to build and upload files
+rem
+rem TODO: Integration with FL
+
+set name=smh
+
+rem To upload, this var must be set here or in other batch
+rem set ftp=ftp://<user>:<password>@<ftp>/<path>
+
+echo Building %name% ...
+
+msdev ..\%name%.dsp /MAKE "%name% - Win32 Release" /REBUILD
+msdev ..\%name%.dsp /MAKE "%name% - Win32 Unicode Release" /REBUILD
+
+echo Generating files for %name% ...
+
+del *.zip
+del *.dll
+copy ..\..\..\bin\release\Plugins\%name%.dll
+copy ..\..\..\bin\release\Plugins\%name%W.dll
+copy ..\Docs\%name%_changelog.txt
+copy ..\Docs\%name%_version.txt
+copy ..\Docs\%name%_readme.txt
+mkdir Docs
+cd Docs
+del /Q *.*
+copy ..\..\Docs\langpack_%name%.txt
+copy ..\..\Docs\helppack_%name%.txt
+copy ..\..\m_%name%.h
+cd ..
+mkdir src
+cd src
+del /Q *.*
+copy ..\..\*.h
+copy ..\..\*.cpp
+copy ..\..\*.
+copy ..\..\*.rc
+copy ..\..\*.dsp
+copy ..\..\*.dsw
+mkdir Docs
+cd Docs
+del /Q *.*
+copy ..\..\..\Docs\*.*
+cd ..
+cd ..
+
+"C:\Program Files\Filzip\Filzip.exe" -a -rp %name%.zip %name%.dll Docs
+"C:\Program Files\Filzip\Filzip.exe" -a -rp %name%W.zip %name%W.dll Docs
+"C:\Program Files\Filzip\Filzip.exe" -a -rp %name%_src.zip src\*.*
+
+del *.dll
+cd Docs
+del /Q *.*
+cd ..
+rmdir Docs
+cd src
+del /Q *.*
+cd Docs
+del /Q *.*
+cd ..
+rmdir Docs
+cd ..
+rmdir src
+
+if "%ftp%"=="" GOTO END
+
+echo Going to upload files...
+pause
+
+"C:\Program Files\FileZilla\FileZilla.exe" -u .\%name%.zip %ftp% -overwrite -close
+"C:\Program Files\FileZilla\FileZilla.exe" -u .\%name%W.zip %ftp% -overwrite -close
+"C:\Program Files\FileZilla\FileZilla.exe" -u .\%name%_changelog.txt %ftp% -overwrite -close
+"C:\Program Files\FileZilla\FileZilla.exe" -u .\%name%_readme.txt %ftp% -overwrite -close
+"C:\Program Files\FileZilla\FileZilla.exe" -u .\%name%_version.txt %ftp% -overwrite -close
+
+:END
+
+echo Done.
diff --git a/Plugins/smh/commons.h b/Plugins/smh/commons.h
new file mode 100644
index 0000000..5b1453b
--- /dev/null
+++ b/Plugins/smh/commons.h
@@ -0,0 +1,95 @@
+/*
+Copyright (C) 2006 Ricardo Pescuma Domenecci
+
+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.
+*/
+
+
+#ifndef __COMMONS_H__
+# define __COMMONS_H__
+
+
+#include <windows.h>
+#include <tchar.h>
+#include <stdio.h>
+#include <time.h>
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+// Miranda headers
+#include <newpluginapi.h>
+#include <m_system.h>
+#include <m_protocols.h>
+#include <m_protosvc.h>
+#include <m_clist.h>
+#include <m_contacts.h>
+#include <m_langpack.h>
+#include <m_database.h>
+#include <m_options.h>
+#include <m_utils.h>
+#include <m_updater.h>
+#include <m_metacontacts.h>
+#include <m_popup.h>
+#include <m_history.h>
+
+#include "../utils/mir_memory.h"
+#include "../utils/mir_options.h"
+
+#include "resource.h"
+#include "m_smh.h"
+#include "options.h"
+#include "popup.h"
+
+
+#define MODULE_NAME "SMH"
+
+
+// Global Variables
+extern HINSTANCE hInst;
+extern PLUGINLINK *pluginLink;
+
+
+#define MAX_REGS(_A_) ( sizeof(_A_) / sizeof(_A_[0]) )
+
+#define DEFAULT_TEMPLATE_CHANGED "changed his/her status message to %s"
+#define DEFAULT_TEMPLATE_REMOVED "removed his/her status message"
+
+
+#ifdef UNICODE
+
+#define TCHAR_TO_CHAR(dest, orig) mir_snprintf(dest, MAX_REGS(dest), "%S", orig)
+#define CHAR_TO_TCHAR(dest, orig) mir_sntprintf(dest, MAX_REGS(dest), "%S", orig)
+
+#else
+
+#define TCHAR_TO_CHAR(dest, orig) lstrcpynA(dest, orig, MAX_REGS(dest))
+#define CHAR_TO_TCHAR(dest, orig) lstrcpynA(dest, orig, MAX_REGS(dest))
+
+#endif
+
+
+BOOL AllowProtocol(const char *proto);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __COMMONS_H__
diff --git a/Plugins/smh/m_smh.h b/Plugins/smh/m_smh.h
new file mode 100644
index 0000000..c1dddf3
--- /dev/null
+++ b/Plugins/smh/m_smh.h
@@ -0,0 +1,60 @@
+/*
+Copyright (C) 2006 Ricardo Pescuma Domenecci
+
+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.
+*/
+
+
+#ifndef __M_SMH_H__
+# define __M_SMH_H__
+
+
+#define MIID_STATUS_MESSAGE_CHANGE_LOGGER { 0x821be252, 0xe20b, 0x41e7, { 0xa5, 0x1d, 0x3c, 0x34, 0x2e, 0x38, 0xae, 0x22 } }
+#define MIID_STATUS_MESSAGE_CHANGE_NOTIFIER { 0xb628b23b, 0x47ae, 0x430e, { 0x94, 0x81, 0x15, 0x9f, 0xa7, 0x26, 0xc4, 0x3a } }
+
+#define EVENTTYPE_STATUSMESSAGE_CHANGE 9002
+
+/*
+Return TRUE is Status Message History is enabled for this contact
+
+wParam: hContact
+lParam: ignored
+*/
+#define MS_SMH_ENABLED "SMH/Enabled"
+
+
+/*
+Enable Status Message History for a contact
+
+wParam: hContact
+lParam: ignored
+*/
+#define MS_SMH_ENABLE "SMH/Enable"
+
+
+/*
+Disable Status Message History for a contact
+
+wParam: hContact
+lParam: ignored
+*/
+#define MS_SMH_DISABLE "SMH/Disable"
+
+
+
+
+
+#endif // __M_SMH_H__
diff --git a/Plugins/smh/options.cpp b/Plugins/smh/options.cpp
new file mode 100644
index 0000000..f56b45c
--- /dev/null
+++ b/Plugins/smh/options.cpp
@@ -0,0 +1,292 @@
+/*
+Copyright (C) 2006 Ricardo Pescuma Domenecci
+
+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.
+*/
+
+
+#include "commons.h"
+
+
+
+// Prototypes /////////////////////////////////////////////////////////////////////////////////////
+
+HANDLE hOptHook = NULL;
+
+Options opts;
+
+
+static BOOL CALLBACK OptionsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static BOOL CALLBACK PopupsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+
+static OptPageControl optionsControls[] = {
+ { &opts.history_enable, CONTROL_CHECKBOX, IDC_HISTORY, "HistoryEnable", TRUE },
+ { &opts.history_only_ansi_if_possible, CONTROL_CHECKBOX, IDC_ANSI, "HistoryOnlyANSIIfPossible", TRUE },
+ { &opts.track_changes, CONTROL_CHECKBOX, IDC_TRACK_CHANGE, "TrackChanges", TRUE },
+ { &opts.template_changed, CONTROL_TEXT, IDC_CHANGED, "TemplateChanged", (DWORD) _T(DEFAULT_TEMPLATE_CHANGED) },
+ { &opts.track_removes, CONTROL_CHECKBOX, IDC_TRACK_REMOVE, "TrackRemoves", TRUE },
+ { &opts.template_removed, CONTROL_TEXT, IDC_REMOVED, "TemplateRemoved", (DWORD) _T(DEFAULT_TEMPLATE_REMOVED) },
+ { &opts.track_only_not_offline, CONTROL_CHECKBOX, IDC_ONLY_NOT_OFFLINE,"TrackOnlyWhenNotOffline", TRUE },
+ { NULL, CONTROL_PROTOCOL_LIST, IDC_PROTOCOLS, "%sEnabled", TRUE, (int) AllowProtocol }
+};
+
+static UINT optionsExpertControls[] = {
+#ifdef UNICODE
+ IDC_ANSI,
+#endif
+ IDC_TRACK_G, IDC_TRACK_CHANGE, IDC_CHANGED_L, IDC_CHANGED, IDC_TRACK_REMOVE, IDC_REMOVED_L, IDC_REMOVED, IDC_ONLY_NOT_OFFLINE,
+ IDC_PROTOCOLS_G, IDC_PROTOCOLS_L, IDC_PROTOCOLS
+};
+
+
+static OptPageControl popupsControls[] = {
+ { &opts.popup_enable, CONTROL_CHECKBOX, IDC_POPUPS, "PopupsEnable", FALSE },
+ { &opts.popup_bkg_color, CONTROL_COLOR, IDC_BGCOLOR, "PopupsBgColor", RGB(255,255,255) },
+ { &opts.popup_text_color, CONTROL_COLOR, IDC_TEXTCOLOR, "PopupsTextColor", RGB(0,0,0) },
+ { &opts.popup_use_win_colors, CONTROL_CHECKBOX, IDC_WINCOLORS, "PopupsWinColors", FALSE },
+ { &opts.popup_use_default_colors, CONTROL_CHECKBOX, IDC_DEFAULTCOLORS, "PopupsDefaultColors", FALSE },
+ { &opts.popup_delay_type, CONTROL_RADIO, IDC_DELAYFROMPU, "PopupsDelayType", POPUP_DELAY_DEFAULT, POPUP_DELAY_DEFAULT },
+ { NULL, CONTROL_RADIO, IDC_DELAYCUSTOM, "PopupsDelayType", POPUP_DELAY_DEFAULT, POPUP_DELAY_CUSTOM },
+ { NULL, CONTROL_RADIO, IDC_DELAYPERMANENT, "PopupsDelayType", POPUP_DELAY_DEFAULT, POPUP_DELAY_PERMANENT },
+ { &opts.popup_timeout, CONTROL_SPIN, IDC_DELAY, "PopupsTimeout", 10, IDC_DELAY_SPIN, (WORD) 1, (WORD) 255 },
+ { &opts.popup_right_click_action, CONTROL_COMBO, IDC_RIGHT_ACTION, "PopupsRightClick", POPUP_ACTION_CLOSEPOPUP },
+ { &opts.popup_left_click_action, CONTROL_COMBO, IDC_LEFT_ACTION, "PopupsLeftClick", POPUP_ACTION_OPENHISTORY }
+};
+
+static UINT popupsExpertControls[] = {
+ IDC_COLOURS_G, IDC_BGCOLOR, IDC_BGCOLOR_L, IDC_TEXTCOLOR, IDC_TEXTCOLOR_L, IDC_WINCOLORS, IDC_DEFAULTCOLORS,
+ IDC_DELAY_G, IDC_DELAYFROMPU, IDC_DELAYCUSTOM, IDC_DELAYPERMANENT, IDC_DELAY, IDC_DELAY_SPIN,
+ IDC_ACTIONS_G, IDC_RIGHT_ACTION_L, IDC_RIGHT_ACTION, IDC_LEFT_ACTION_L, IDC_LEFT_ACTION,
+ IDC_PREV
+};
+
+
+// Functions //////////////////////////////////////////////////////////////////////////////////////
+
+
+int InitOptionsCallback(WPARAM wParam,LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp;
+
+ ZeroMemory(&odp,sizeof(odp));
+ odp.cbSize=sizeof(odp);
+ odp.position=0;
+ odp.hInstance=hInst;
+ odp.ptszGroup = TranslateT("History");
+ odp.ptszTitle = TranslateT("Status Message");
+ odp.pfnDlgProc = OptionsDlgProc;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS);
+ odp.flags = ODPF_BOLDGROUPS | ODPF_TCHAR;
+ odp.expertOnlyControls = optionsExpertControls;
+ odp.nExpertOnlyControls = MAX_REGS(optionsExpertControls);
+ CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp);
+
+ if(ServiceExists(MS_POPUP_ADDPOPUPEX)
+#ifdef UNICODE
+ || ServiceExists(MS_POPUP_ADDPOPUPW)
+#endif
+ )
+ {
+ ZeroMemory(&odp,sizeof(odp));
+ odp.cbSize=sizeof(odp);
+ odp.position=0;
+ odp.hInstance=hInst;
+ odp.ptszGroup = TranslateT("Popups");
+ odp.ptszTitle = TranslateT("Status Msg Change");
+ odp.pfnDlgProc = PopupsDlgProc;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_POPUPS);
+ odp.flags = ODPF_BOLDGROUPS | ODPF_TCHAR;
+ odp.expertOnlyControls = popupsExpertControls;
+ odp.nExpertOnlyControls = MAX_REGS(popupsExpertControls);
+ CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp);
+ }
+
+ return 0;
+}
+
+
+void InitOptions()
+{
+ LoadOptions();
+
+ hOptHook = HookEvent(ME_OPT_INITIALISE, InitOptionsCallback);
+
+ //InitMirOptions();
+}
+
+
+void DeInitOptions()
+{
+ UnhookEvent(hOptHook);
+
+ //FreeMirOptions();
+}
+
+
+void LoadOptions()
+{
+ LoadOpts(optionsControls, MAX_REGS(optionsControls), MODULE_NAME);
+ LoadOpts(popupsControls, MAX_REGS(popupsControls), MODULE_NAME);
+}
+
+
+static void OptionsEnableDisableCtrls(HWND hwndDlg)
+{
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHANGED_L), IsDlgButtonChecked(hwndDlg, IDC_TRACK_CHANGE));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHANGED), IsDlgButtonChecked(hwndDlg, IDC_TRACK_CHANGE));
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_REMOVED_L), IsDlgButtonChecked(hwndDlg, IDC_TRACK_REMOVE));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_REMOVED), IsDlgButtonChecked(hwndDlg, IDC_TRACK_REMOVE));
+}
+
+
+static BOOL CALLBACK OptionsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ BOOL ret = SaveOptsDlgProc(optionsControls, MAX_REGS(optionsControls), MODULE_NAME, hwndDlg, msg, wParam, lParam);
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ OptionsEnableDisableCtrls(hwndDlg);
+
+#ifndef UNICODE
+ ShowWindow(GetDlgItem(hwndDlg, IDC_ANSI), SW_HIDE);
+#endif
+ break;
+ }
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_TRACK_REMOVE:
+ case IDC_TRACK_CHANGE:
+ case IDC_ONLY_NOT_OFFLINE:
+ {
+ if (HIWORD(wParam) == BN_CLICKED)
+ OptionsEnableDisableCtrls(hwndDlg);
+
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ return ret;
+}
+
+
+static void PopupsEnableDisableCtrls(HWND hwndDlg)
+{
+ BOOL enabled = IsDlgButtonChecked(hwndDlg, IDC_POPUPS);
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_COLOURS_G), enabled);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_BGCOLOR_L), enabled);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_TEXTCOLOR_L), enabled);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_DELAY_G), enabled);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_DELAYFROMPU), enabled);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_DELAYCUSTOM), enabled);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_DELAYPERMANENT), enabled);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ACTIONS_G), enabled);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_RIGHT_ACTION_L), enabled);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_RIGHT_ACTION), enabled);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LEFT_ACTION_L), enabled);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LEFT_ACTION), enabled);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_PREV), enabled);
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_BGCOLOR), enabled &&
+ !IsDlgButtonChecked(hwndDlg, IDC_WINCOLORS) &&
+ !IsDlgButtonChecked(hwndDlg, IDC_DEFAULTCOLORS));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_TEXTCOLOR), enabled &&
+ !IsDlgButtonChecked(hwndDlg, IDC_WINCOLORS) &&
+ !IsDlgButtonChecked(hwndDlg, IDC_DEFAULTCOLORS));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_DEFAULTCOLORS), enabled &&
+ !IsDlgButtonChecked(hwndDlg, IDC_WINCOLORS));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_WINCOLORS), enabled &&
+ !IsDlgButtonChecked(hwndDlg, IDC_DEFAULTCOLORS));
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_DELAY), enabled &&
+ IsDlgButtonChecked(hwndDlg, IDC_DELAYCUSTOM));
+}
+
+
+static BOOL CALLBACK PopupsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ SendDlgItemMessage(hwndDlg, IDC_RIGHT_ACTION, CB_ADDSTRING, 0, (LONG) TranslateT("Do nothing"));
+ SendDlgItemMessage(hwndDlg, IDC_RIGHT_ACTION, CB_ADDSTRING, 0, (LONG) TranslateT("Close popup"));
+ SendDlgItemMessage(hwndDlg, IDC_RIGHT_ACTION, CB_ADDSTRING, 0, (LONG) TranslateT("Show history"));
+
+ SendDlgItemMessage(hwndDlg, IDC_LEFT_ACTION, CB_ADDSTRING, 0, (LONG) TranslateT("Do nothing"));
+ SendDlgItemMessage(hwndDlg, IDC_LEFT_ACTION, CB_ADDSTRING, 0, (LONG) TranslateT("Close popup"));
+ SendDlgItemMessage(hwndDlg, IDC_LEFT_ACTION, CB_ADDSTRING, 0, (LONG) TranslateT("Show history"));
+
+ // Needs to be called here in this case
+ BOOL ret = SaveOptsDlgProc(popupsControls, MAX_REGS(popupsControls), MODULE_NAME, hwndDlg, msg, wParam, lParam);
+
+ PopupsEnableDisableCtrls(hwndDlg);
+
+ return ret;
+ }
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_POPUPS:
+ case IDC_WINCOLORS:
+ case IDC_DEFAULTCOLORS:
+ case IDC_DELAYFROMPU:
+ case IDC_DELAYPERMANENT:
+ case IDC_DELAYCUSTOM:
+ {
+ if (HIWORD(wParam) == BN_CLICKED)
+ PopupsEnableDisableCtrls(hwndDlg);
+
+ break;
+ }
+ case IDC_PREV:
+ {
+ Options op = opts;
+
+ if (IsDlgButtonChecked(hwndDlg, IDC_DELAYFROMPU))
+ op.popup_delay_type = POPUP_DELAY_DEFAULT;
+ else if (IsDlgButtonChecked(hwndDlg, IDC_DELAYCUSTOM))
+ op.popup_delay_type = POPUP_DELAY_CUSTOM;
+ else if (IsDlgButtonChecked(hwndDlg, IDC_DELAYPERMANENT))
+ op.popup_delay_type = POPUP_DELAY_PERMANENT;
+
+ op.popup_timeout = GetDlgItemInt(hwndDlg,IDC_DELAY, NULL, FALSE);
+ op.popup_bkg_color = SendDlgItemMessage(hwndDlg,IDC_BGCOLOR,CPM_GETCOLOUR,0,0);
+ op.popup_text_color = SendDlgItemMessage(hwndDlg,IDC_TEXTCOLOR,CPM_GETCOLOUR,0,0);
+ op.popup_use_win_colors = IsDlgButtonChecked(hwndDlg, IDC_WINCOLORS) != 0;
+ op.popup_use_default_colors = IsDlgButtonChecked(hwndDlg, IDC_DEFAULTCOLORS) != 0;
+
+ ShowTestPopup(TranslateT("Test Contact"), TranslateT("Test description"), &op);
+
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ return SaveOptsDlgProc(popupsControls, MAX_REGS(popupsControls), MODULE_NAME, hwndDlg, msg, wParam, lParam);
+}
diff --git a/Plugins/smh/options.h b/Plugins/smh/options.h
new file mode 100644
index 0000000..da0e1a6
--- /dev/null
+++ b/Plugins/smh/options.h
@@ -0,0 +1,89 @@
+/*
+Copyright (C) 2006 Ricardo Pescuma Domenecci
+
+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.
+*/
+
+
+#ifndef __OPTIONS_H__
+# define __OPTIONS_H__
+
+
+#include "commons.h"
+
+#include <windows.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define POPUP_ACTION_DONOTHING 0
+#define POPUP_ACTION_CLOSEPOPUP 1
+#define POPUP_ACTION_OPENHISTORY 2
+
+#define POPUP_DELAY_DEFAULT 0
+#define POPUP_DELAY_CUSTOM 1
+#define POPUP_DELAY_PERMANENT 2
+
+
+struct Options {
+ // Templates
+ TCHAR template_changed[1024];
+ TCHAR template_removed[1024];
+
+ // Track
+ BYTE track_changes;
+ BYTE track_removes;
+ BYTE track_only_not_offline;
+
+ // History
+ BYTE history_enable;
+ BYTE history_only_ansi_if_possible;
+
+ // Popup
+ BYTE popup_enable;
+ WORD popup_delay_type;
+ WORD popup_timeout;
+ BYTE popup_use_win_colors;
+ BYTE popup_use_default_colors;
+ COLORREF popup_bkg_color;
+ COLORREF popup_text_color;
+ WORD popup_left_click_action;
+ WORD popup_right_click_action;
+};
+
+extern Options opts;
+
+
+// Initializations needed by options
+void InitOptions();
+
+// Deinitializations needed by options
+void DeInitOptions();
+
+
+// Loads the options from DB
+// It don't need to be called, except in some rare cases
+void LoadOptions();
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __OPTIONS_H__
diff --git a/Plugins/smh/popup.cpp b/Plugins/smh/popup.cpp
new file mode 100644
index 0000000..4e40814
--- /dev/null
+++ b/Plugins/smh/popup.cpp
@@ -0,0 +1,319 @@
+/*
+Copyright (C) 2005 Ricardo Pescuma Domenecci
+
+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.
+*/
+
+
+#include "commons.h"
+
+
+
+// Prototypes /////////////////////////////////////////////////////////////////////////////////////
+
+#define WMU_ACTION (WM_USER + 1)
+
+
+LRESULT CALLBACK PopupWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+HWND hPopupWindow = NULL;
+
+
+static LRESULT CALLBACK PopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
+static LRESULT CALLBACK DumbPopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
+
+
+
+// Functions //////////////////////////////////////////////////////////////////////////////////////
+
+
+// Initializations needed by popups
+void InitPopups()
+{
+ // window needed for popup commands
+ hPopupWindow = CreateWindowEx(WS_EX_TOOLWINDOW, _T("static"), _T(MODULE_NAME) _T("_PopupWindow"),
+ 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWND_DESKTOP,
+ NULL, hInst, NULL);
+ SetWindowLong(hPopupWindow, GWL_WNDPROC, (LONG)(WNDPROC)PopupWndProc);
+}
+
+
+// Deinitializations needed by popups
+void DeInitPopups()
+{
+}
+
+
+// Show an error popup
+void ShowErrPopup(const TCHAR *description, const TCHAR *title)
+{
+ ShowPopupEx(NULL, title == NULL ? _T(MODULE_NAME) _T(" Error") : title, description,
+ NULL, POPUP_TYPE_ERROR, NULL);
+}
+
+
+void ShowTestPopup(const TCHAR *title, const TCHAR *description, const Options *op)
+{
+ ShowPopupEx(NULL, title, description, NULL, POPUP_TYPE_TEST, op);
+}
+
+
+void ShowPopup(HANDLE hContact, const TCHAR *title, const TCHAR *description)
+{
+ ShowPopupEx(hContact, title, description, hContact, POPUP_TYPE_NORMAL, &opts);
+}
+
+
+// Show an popup
+void ShowPopupEx(HANDLE hContact, const TCHAR *title, const TCHAR *description,
+ void *plugin_data, int type, const Options *op)
+{
+#ifdef UNICODE
+ if(ServiceExists(MS_POPUP_ADDPOPUPW))
+ {
+ // Make popup
+ POPUPDATAW ppd;
+
+ ZeroMemory(&ppd, sizeof(ppd));
+ ppd.lchContact = hContact;
+ ppd.lchIcon = (HICON) LoadImage(GetModuleHandle(NULL),MAKEINTRESOURCE(174),IMAGE_ICON,16,16,LR_DEFAULTCOLOR);
+
+ if (title != NULL)
+ lstrcpyn(ppd.lpwzContactName, title, MAX_REGS(ppd.lpwzContactName));
+ else if (hContact != NULL)
+ lstrcpyn(ppd.lpwzContactName, (TCHAR *) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR),
+ MAX_REGS(ppd.lpwzContactName));
+
+ if (description != NULL)
+ lstrcpyn(ppd.lpwzText, description, MAX_REGS(ppd.lpwzText));
+
+ if (type == POPUP_TYPE_NORMAL || type == POPUP_TYPE_TEST)
+ {
+ if (op->popup_use_default_colors)
+ {
+ ppd.colorBack = 0;
+ ppd.colorText = 0;
+ }
+ else if (op->popup_use_win_colors)
+ {
+ ppd.colorBack = GetSysColor(COLOR_BTNFACE);
+ ppd.colorText = GetSysColor(COLOR_WINDOWTEXT);
+ }
+ else
+ {
+ ppd.colorBack = op->popup_bkg_color;
+ ppd.colorText = op->popup_text_color;
+ }
+ }
+ else // if (type == POPUP_TYPE_ERROR)
+ {
+ ppd.colorBack = RGB(200,0,0);
+ ppd.colorText = RGB(255,255,255);
+ }
+
+ if (type == POPUP_TYPE_NORMAL)
+ {
+ ppd.PluginWindowProc = PopupDlgProc;
+ ppd.PluginData = plugin_data;
+ }
+ else // if (type == POPUP_TYPE_TEST || type == POPUP_TYPE_ERROR)
+ {
+ ppd.PluginWindowProc = DumbPopupDlgProc;
+ }
+
+ if (type == POPUP_TYPE_NORMAL || type == POPUP_TYPE_TEST)
+ {
+ switch (op->popup_delay_type)
+ {
+ case POPUP_DELAY_CUSTOM:
+ ppd.iSeconds = opts.popup_timeout;
+ break;
+
+ case POPUP_DELAY_PERMANENT:
+ ppd.iSeconds = -1;
+ break;
+
+ //case POPUP_DELAY_DEFAULT:
+ default:
+ ppd.iSeconds = 0;
+ break;
+ }
+ }
+ else // if (type == POPUP_TYPE_ERROR)
+ {
+ ppd.iSeconds = 0;
+ }
+
+ // Now that every field has been filled, we want to see the popup.
+ CallService(MS_POPUP_ADDPOPUPW, (WPARAM)&ppd,0);
+ }
+ else
+#endif
+ if(ServiceExists(MS_POPUP_ADDPOPUPEX))
+ {
+ // Make popup
+ POPUPDATAEX ppd;
+
+ ZeroMemory(&ppd, sizeof(ppd));
+ ppd.lchContact = hContact;
+ ppd.lchIcon = (HICON) LoadImage(GetModuleHandle(NULL),MAKEINTRESOURCE(174),IMAGE_ICON,16,16,LR_DEFAULTCOLOR);
+
+ if (title != NULL)
+ TCHAR_TO_CHAR(ppd.lpzContactName, title);
+ else
+ lstrcpynA(ppd.lpzContactName, (char *) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, 0),
+ MAX_REGS(ppd.lpzContactName));
+
+ if (description != NULL)
+ TCHAR_TO_CHAR(ppd.lpzText, description);
+
+ if (type == POPUP_TYPE_NORMAL || type == POPUP_TYPE_TEST)
+ {
+ if (op->popup_use_default_colors)
+ {
+ ppd.colorBack = 0;
+ ppd.colorText = 0;
+ }
+ else if (op->popup_use_win_colors)
+ {
+ ppd.colorBack = GetSysColor(COLOR_BTNFACE);
+ ppd.colorText = GetSysColor(COLOR_WINDOWTEXT);
+ }
+ else
+ {
+ ppd.colorBack = op->popup_bkg_color;
+ ppd.colorText = op->popup_text_color;
+ }
+ }
+ else // if (type == POPUP_TYPE_ERROR)
+ {
+ ppd.colorBack = RGB(200,0,0);
+ ppd.colorText = RGB(255,255,255);
+ }
+
+ if (type == POPUP_TYPE_NORMAL)
+ {
+ ppd.PluginWindowProc = PopupDlgProc;
+ ppd.PluginData = plugin_data;
+ }
+ else // if (type == POPUP_TYPE_TEST || type == POPUP_TYPE_ERROR)
+ {
+ ppd.PluginWindowProc = DumbPopupDlgProc;
+ }
+
+ if (type == POPUP_TYPE_NORMAL || type == POPUP_TYPE_TEST)
+ {
+ switch (op->popup_delay_type)
+ {
+ case POPUP_DELAY_CUSTOM:
+ ppd.iSeconds = opts.popup_timeout;
+ break;
+
+ case POPUP_DELAY_PERMANENT:
+ ppd.iSeconds = -1;
+ break;
+
+ //case POPUP_DELAY_DEFAULT:
+ default:
+ ppd.iSeconds = 0;
+ break;
+ }
+ }
+ else // if (type == POPUP_TYPE_ERROR)
+ {
+ ppd.iSeconds = 0;
+ }
+
+ // Now that every field has been filled, we want to see the popup.
+ CallService(MS_POPUP_ADDPOPUPEX, (WPARAM)&ppd,0);
+ }
+}
+
+
+// Handle to the hidden windows to handle actions for popup clicks
+// wParam has the number of MOTD in case of WMU_SHOW_MOTD_DETAILS
+LRESULT CALLBACK PopupWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ if (uMsg == WMU_ACTION)
+ {
+ if (lParam == POPUP_ACTION_OPENHISTORY)
+ {
+ CallService(MS_HISTORY_SHOWCONTACTHISTORY, wParam, 0);
+ }
+ }
+ return DefWindowProc(hWnd, uMsg, wParam, lParam);
+}
+
+
+// Handle to popup events
+static LRESULT CALLBACK PopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch(message) {
+ case WM_COMMAND:
+ {
+ SendMessage(hPopupWindow, WMU_ACTION, (WPARAM)PUGetPluginData(hWnd), opts.popup_left_click_action);
+
+ if (opts.popup_left_click_action != POPUP_ACTION_DONOTHING)
+ PUDeletePopUp(hWnd);
+
+ return TRUE;
+ }
+
+ case WM_CONTEXTMENU:
+ {
+ SendMessage(hPopupWindow, WMU_ACTION, (WPARAM)PUGetPluginData(hWnd), opts.popup_right_click_action);
+
+ if (opts.popup_right_click_action != POPUP_ACTION_DONOTHING)
+ PUDeletePopUp(hWnd);
+
+ return TRUE;
+ }
+
+ case UM_FREEPLUGINDATA:
+ {
+ return TRUE;
+ }
+ }
+
+ return DefWindowProc(hWnd, message, wParam, lParam);
+}
+
+
+// Handle to popup events
+static LRESULT CALLBACK DumbPopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch(message) {
+ case WM_COMMAND:
+ {
+ PUDeletePopUp(hWnd);
+ return TRUE;
+ }
+
+ case WM_CONTEXTMENU:
+ {
+ PUDeletePopUp(hWnd);
+ return TRUE;
+ }
+
+ case UM_FREEPLUGINDATA:
+ {
+ return TRUE;
+ }
+ }
+
+ return DefWindowProc(hWnd, message, wParam, lParam);
+}
+
diff --git a/Plugins/smh/popup.h b/Plugins/smh/popup.h
new file mode 100644
index 0000000..090657e
--- /dev/null
+++ b/Plugins/smh/popup.h
@@ -0,0 +1,60 @@
+/*
+Copyright (C) 2005 Ricardo Pescuma Domenecci
+
+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.
+*/
+
+
+#ifndef __POPUP_H__
+# define __POPUP_H__
+
+#include "commons.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+// Initializations needed by popups
+void InitPopups();
+
+// Deinitializations needed by popups
+void DeInitPopups();
+
+
+#define POPUP_TYPE_NORMAL 0
+#define POPUP_TYPE_TEST 1
+#define POPUP_TYPE_ERROR 2
+
+// Show an popup
+void ShowPopup(HANDLE hContact, const TCHAR *title, const TCHAR *description);
+
+// Show an test
+void ShowTestPopup(const TCHAR *title, const TCHAR *description, const Options *op);
+
+// Show an error popup
+void ShowErrPopup(const char *description, const char *title = NULL);
+
+void ShowPopupEx(HANDLE hContact, const TCHAR *title, const TCHAR *description,
+ void *plugin_data, int type, const Options *op);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif // __POPUP_H__
diff --git a/Plugins/smh/resource.h b/Plugins/smh/resource.h
new file mode 100644
index 0000000..dda44d5
--- /dev/null
+++ b/Plugins/smh/resource.h
@@ -0,0 +1,55 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by resource.rc
+//
+#define IDD_OPTIONS 119
+#define IDD_POPUPS 120
+#define IDC_DELAY 1001
+#define IDC_WINCOLORS 1002
+#define IDC_DEFAULTCOLORS 1003
+#define IDC_BGCOLOR 1004
+#define IDC_TEXTCOLOR 1005
+#define IDC_PREV 1006
+#define IDC_DELAYFROMPU 1007
+#define IDC_DELAYCUSTOM 1008
+#define IDC_DELAYPERMANENT 1009
+#define IDC_RIGHT_ACTION 1022
+#define IDC_LEFT_ACTION 1023
+#define IDC_PROTOCOLS 1041
+#define IDC_CHANGED 1058
+#define IDC_REMOVED 1059
+#define IDC_CHECK1 1060
+#define IDC_POPUPS 1060
+#define IDC_CHECK2 1061
+#define IDC_DELAY_SPIN 1061
+#define IDC_HISTORY 1061
+#define IDC_ANSI 1062
+#define IDC_TRACK_G 1063
+#define IDC_CHANGED_L 1064
+#define IDC_REMOVED_L 1065
+#define IDC_PROTOCOLS_G 1066
+#define IDC_PROTOCOLS_L 1067
+#define IDC_COLOURS_G 1068
+#define IDC_TRACK_CHANGE 1068
+#define IDC_BGCOLOR_L 1069
+#define IDC_TRACK_REMOVE 1069
+#define IDC_TEXTCOLOR_L 1070
+#define IDC_ONLY_NOT_OFFLINE 1070
+#define IDC_DELAY_G 1071
+#define IDC_ACTIONS_G 1072
+#define IDC_RIGHT_ACTION_L 1073
+#define IDC_LEFT_ACTION_L 1074
+#define IDC_STATIC -1
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NO_MFC 1
+#define _APS_3D_CONTROLS 1
+#define _APS_NEXT_RESOURCE_VALUE 120
+#define _APS_NEXT_COMMAND_VALUE 40004
+#define _APS_NEXT_CONTROL_VALUE 1075
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/Plugins/smh/resource.rc b/Plugins/smh/resource.rc
new file mode 100644
index 0000000..2b55fbb
--- /dev/null
+++ b/Plugins/smh/resource.rc
@@ -0,0 +1,180 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "resource.h"
+#include "winresrc.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_OPTIONS DIALOG DISCARDABLE 0, 0, 314, 240
+STYLE DS_SHELLFONT | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg"
+BEGIN
+ GROUPBOX " History ",IDC_STATIC,3,3,308,44
+ CONTROL "Log changes to history",IDC_HISTORY,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,12,16,291,11
+ CONTROL "Don't save Unicode parts for 7bit ANSI history (saves db space)",
+ IDC_ANSI,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,30,291,
+ 11
+ GROUPBOX " Tracking ",IDC_TRACK_G,3,51,308,90
+ CONTROL "Track when contacts change their status messages",
+ IDC_TRACK_CHANGE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 12,63,291,11
+ RTEXT "Template:",IDC_CHANGED_L,11,76,55,10
+ EDITTEXT IDC_CHANGED,72,75,233,13,ES_AUTOHSCROLL
+ CONTROL "Track when contacts remove their status messages",
+ IDC_TRACK_REMOVE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 12,92,291,11
+ RTEXT "Template:",IDC_REMOVED_L,11,106,55,10
+ EDITTEXT IDC_REMOVED,72,105,233,13,ES_AUTOHSCROLL
+ CONTROL "Only when the contact is not offline",
+ IDC_ONLY_NOT_OFFLINE,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,12,123,291,11
+ GROUPBOX " Protocols ",IDC_PROTOCOLS_G,3,144,308,93
+ LTEXT "Enable tracking for these protocols:",
+ IDC_PROTOCOLS_L,13,156,291,11
+ CONTROL "List1",IDC_PROTOCOLS,"SysListView32",LVS_REPORT |
+ LVS_SINGLESEL | LVS_SORTASCENDING | LVS_NOCOLUMNHEADER |
+ LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,12,168,158,62
+END
+
+IDD_POPUPS DIALOG DISCARDABLE 0, 0, 314, 240
+STYLE DS_SHELLFONT | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg"
+BEGIN
+ CONTROL "Enable popups",IDC_POPUPS,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,3,3,308,12
+ GROUPBOX " Colours ",IDC_COLOURS_G,3,25,158,75
+ CONTROL "",IDC_BGCOLOR,"ColourPicker",WS_TABSTOP,11,37,35,14
+ LTEXT "Background colour",IDC_BGCOLOR_L,55,41,66,8
+ CONTROL "",IDC_TEXTCOLOR,"ColourPicker",WS_TABSTOP,11,55,35,14
+ LTEXT "Text colour",IDC_TEXTCOLOR_L,55,59,66,8
+ CONTROL "Use Windows colours",IDC_WINCOLORS,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,11,74,108,10
+ CONTROL "Use default colours",IDC_DEFAULTCOLORS,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,11,84,107,10
+ GROUPBOX " Delay ",IDC_DELAY_G,166,25,145,75
+ CONTROL "From popup plugin",IDC_DELAYFROMPU,"Button",
+ BS_AUTORADIOBUTTON | WS_GROUP,175,38,122,10
+ CONTROL "Custom",IDC_DELAYCUSTOM,"Button",BS_AUTORADIOBUTTON,175,
+ 52,54,10
+ CONTROL "Permanent",IDC_DELAYPERMANENT,"Button",
+ BS_AUTORADIOBUTTON,175,66,122,10
+ EDITTEXT IDC_DELAY,233,50,31,14,ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "Spin1",IDC_DELAY_SPIN,"msctls_updown32",UDS_SETBUDDYINT |
+ UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_NOTHOUSANDS |
+ UDS_HOTTRACK,268,51,11,11
+ GROUPBOX " Actions ",IDC_ACTIONS_G,3,103,308,47
+ RTEXT "On right click:",IDC_RIGHT_ACTION_L,13,118,62,9
+ COMBOBOX IDC_RIGHT_ACTION,83,116,156,60,CBS_DROPDOWNLIST |
+ WS_VSCROLL | WS_TABSTOP
+ RTEXT "On left click:",IDC_LEFT_ACTION_L,13,132,62,9
+ COMBOBOX IDC_LEFT_ACTION,83,132,156,60,CBS_DROPDOWNLIST |
+ WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "Preview",IDC_PREV,131,161,50,14
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ IDD_OPTIONS, DIALOG
+ BEGIN
+ LEFTMARGIN, 3
+ RIGHTMARGIN, 311
+ TOPMARGIN, 3
+ BOTTOMMARGIN, 237
+ END
+
+ IDD_POPUPS, DIALOG
+ BEGIN
+ LEFTMARGIN, 3
+ RIGHTMARGIN, 311
+ TOPMARGIN, 3
+ BOTTOMMARGIN, 237
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// English (Canada) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENC)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_CAN
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""resource.h""\r\n"
+ "#include ""winresrc.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // English (Canada) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/Plugins/smh/sdk/m_metacontacts.h b/Plugins/smh/sdk/m_metacontacts.h
new file mode 100644
index 0000000..1da12b9
--- /dev/null
+++ b/Plugins/smh/sdk/m_metacontacts.h
@@ -0,0 +1,162 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright © 2004 Universite Louis PASTEUR, STRASBOURG.
+Copyright © 2004 Scott Ellis (www.scottellis.com.au mail@scottellis.com.au)
+
+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.
+*/
+
+#ifndef M_METACONTACTS_H__
+#define M_METACONTACTS_H__ 1
+
+//get the handle for a contact's parent metacontact
+//wParam=(HANDLE)hSubContact
+//lParam=0
+//returns a handle to the parent metacontact, or null if this contact is not a subcontact
+#define MS_MC_GETMETACONTACT "MetaContacts/GetMeta"
+
+//gets the handle for the default contact
+//wParam=(HANDLE)hMetaContact
+//lParam=0
+//returns a handle to the default contact, or null on failure
+#define MS_MC_GETDEFAULTCONTACT "MetaContacts/GetDefault"
+
+//gets the contact number for the default contact
+//wParam=(HANDLE)hMetaContact
+//lParam=0
+//returns a DWORD contact number, or -1 on failure
+#define MS_MC_GETDEFAULTCONTACTNUM "MetaContacts/GetDefaultNum"
+
+//gets the handle for the 'most online' contact
+//wParam=(HANDLE)hMetaContact
+//lParam=0
+//returns a handle to the 'most online' contact
+#define MS_MC_GETMOSTONLINECONTACT "MetaContacts/GetMostOnline"
+
+//gets the number of subcontacts for a metacontact
+//wParam=(HANDLE)hMetaContact
+//lParam=0
+//returns a DWORD representing the number of subcontacts for the given metacontact
+#define MS_MC_GETNUMCONTACTS "MetaContacts/GetNumContacts"
+
+//gets the handle of a subcontact, using the subcontact's number
+//wParam=(HANDLE)hMetaContact
+//lParam=(DWORD)contact number
+//returns a handle to the specified subcontact
+#define MS_MC_GETSUBCONTACT "MetaContacts/GetSubContact"
+
+//sets the default contact, using the subcontact's contact number
+//wParam=(HANDLE)hMetaContact
+//lParam=(DWORD)contact number
+//returns 0 on success
+#define MS_MC_SETDEFAULTCONTACTNUM "MetaContacts/SetDefault"
+
+//sets the default contact, using the subcontact's handle
+//wParam=(HANDLE)hMetaContact
+//lParam=(HANDLE)hSubcontact
+//returns 0 on success
+#define MS_MC_SETDEFAULTCONTACT "MetaContacts/SetDefaultByHandle"
+
+//forces the metacontact to send using a specific subcontact, using the subcontact's contact number
+//wParam=(HANDLE)hMetaContact
+//lParam=(DWORD)contact number
+//returns 0 on success
+#define MS_MC_FORCESENDCONTACTNUM "MetaContacts/ForceSendContact"
+
+//forces the metacontact to send using a specific subcontact, using the subcontact's handle
+//wParam=(HANDLE)hMetaContact
+//lParam=(HANDLE)hSubcontact
+//returns 0 on success (will fail if 'force default' is in effect)
+#define MS_MC_FORCESENDCONTACT "MetaContacts/ForceSendContactByHandle"
+
+//'unforces' the metacontact to send using a specific subcontact
+//wParam=(HANDLE)hMetaContact
+//lParam=0
+//returns 0 on success (will fail if 'force default' is in effect)
+#define MS_MC_UNFORCESENDCONTACT "MetaContacts/UnforceSendContact"
+
+//'forces' or 'unforces' (i.e. toggles) the metacontact to send using it's default contact
+// overrides (and clears) 'force send' above, and will even force use of offline contacts
+// will send ME_MC_FORCESEND or ME_MC_UNFORCESEND event
+//wParam=(HANDLE)hMetaContact
+//lParam=0
+//returns 1(true) or 0(false) representing new state of 'force default'
+#define MS_MC_FORCEDEFAULT "MetaContacts/ForceSendDefault"
+
+// method to get state of 'force' for a metacontact
+// wParam=(HANDLE)hMetaContact
+// lParam= (DWORD)&contact_number or NULL
+//
+// if lparam supplied, the contact_number of the contatct 'in force' will be copied to the address it points to,
+// or if none is in force, the value (DWORD)-1 will be copied
+// (v0.8.0.8+ returns 1 if 'force default' is true with *lParam == default contact number, else returns 0 with *lParam as above)
+#define MS_MC_GETFORCESTATE "MetaContacts/GetForceState"
+
+// fired when a metacontact's default contact changes (fired upon creation of metacontact also, when default is initially set)
+// wParam=(HANDLE)hMetaContact
+// lParam=(HANDLE)hDefaultContact
+#define ME_MC_DEFAULTTCHANGED "MetaContacts/DefaultChanged"
+
+// fired when a metacontact's subcontacts change (fired upon creation of metacontact, when contacts are added or removed, and when
+// contacts are reordered) - a signal to re-read metacontact data
+// wParam=(HANDLE)hMetaContact
+// lParam=0
+#define ME_MC_SUBCONTACTSCHANGED "MetaContacts/SubcontactsChanged"
+
+// fired when a metacontact is forced to send using a specific subcontact
+// wParam=(HANDLE)hMetaContact
+// lParam=(HANDLE)hForceContact
+#define ME_MC_FORCESEND "MetaContacts/ForceSend"
+
+// fired when a metacontact is 'unforced' to send using a specific subcontact
+// wParam=(HANDLE)hMetaContact
+// lParam=0
+#define ME_MC_UNFORCESEND "MetaContacts/UnforceSend"
+
+// method to get protocol name - used to be sure you're dealing with a "real" metacontacts plugin :)
+// wParam=lParam=0
+#define MS_MC_GETPROTOCOLNAME "MetaContacts/GetProtoName"
+
+
+// added 0.9.5.0 (22/3/05)
+// wParam=(HANDLE)hContact
+// lParam=0
+// convert a given contact into a metacontact
+#define MS_MC_CONVERTTOMETA "MetaContacts/ConvertToMetacontact"
+
+// added 0.9.5.0 (22/3/05)
+// wParam=(HANDLE)hContact
+// lParam=(HANDLE)hMeta
+// add an existing contact to a metacontact
+#define MS_MC_ADDTOMETA "MetaContacts/AddToMetacontact"
+
+// added 0.9.5.0 (22/3/05)
+// wParam=0
+// lParam=(HANDLE)hContact
+// remove a contact from a metacontact
+#define MS_MC_REMOVEFROMMETA "MetaContacts/RemoveFromMetacontact"
+
+
+// added 0.9.13.2 (6/10/05)
+// wParam=(BOOL)disable
+// lParam=0
+// enable/disable the 'hidden group hack' - for clists that support subcontact hiding using 'IsSubcontact' setting
+// should be called once in the clist 'onmodulesloaded' event handler (which, since it's loaded after the db, will be called
+// before the metacontact onmodulesloaded handler where the subcontact hiding is usually done)
+#define MS_MC_DISABLEHIDDENGROUP "MetaContacts/DisableHiddenGroup"
+
+#endif
diff --git a/Plugins/smh/sdk/m_updater.h b/Plugins/smh/sdk/m_updater.h
new file mode 100644
index 0000000..371b743
--- /dev/null
+++ b/Plugins/smh/sdk/m_updater.h
@@ -0,0 +1,146 @@
+#ifndef _M_UPDATER_H
+#define _M_UPDATER_H
+
+// NOTES:
+// - For langpack updates, include a string of the following format in the langpack text file:
+// ";FLID: <file listing name> <version>"
+// version must be four numbers seperated by '.', in the range 0-255 inclusive
+// - Updater will disable plugins that are downloaded but were not active prior to the update (this is so that, if an archive contains e.g. ansi and
+// unicode versions, the correct plugin will be the only one active after the new version is installed)...so if you add a support plugin, you may need
+// to install an ini file to make the plugin activate when miranda restarts after the update
+// - Updater will replace all dlls that have the same internal shortName as a downloaded update dll (this is so that msn1.dll and msn2.dll, for example,
+// will both be updated) - so if you have a unicode and a non-unicode version of a plugin in your archive, you should make the internal names different (which will break automatic
+// updates from the file listing if there is only one file listing entry for both versions, unless you use the 'MS_UPDATE_REGISTER' service below)
+// - Updater will install all files in the root of the archive into the plugins folder, except for langpack files that contain the FLID string which go into the root folder (same
+// folder as miranda32.exe)...all folders in the archive will also be copied to miranda's root folder, and their contents transferred into the new folders. The only exception is a
+// special folder called 'root_files' - if there is a folder by that name in the archive, it's contents will also be copied into miranda's root folder - this is intended to be used
+// to install additional dlls etc that a plugin may require)
+
+// if you set Update.szUpdateURL to the following value when registering, as well as setting your beta site and version data,
+// Updater will ignore szVersionURL and pbVersionPrefix, and attempt to find the file listing URL's from the backend XML data.
+// for this to work, the plugin name in pluginInfo.shortName must match the file listing exactly (except for case)
+#define UPDATER_AUTOREGISTER "UpdaterAUTOREGISTER"
+// Updater will also use the backend xml data if you provide URL's that reference the miranda file listing for updates (so you can use that method
+// if e.g. your plugin shortName does not match the file listing) - it will grab the file listing id from the end of these URLs
+
+typedef struct Update_tag {
+ int cbSize;
+ char *szComponentName; // component name as it will appear in the UI (will be translated before displaying)
+
+ char *szVersionURL; // URL where the current version can be found (NULL to disable)
+ BYTE *pbVersionPrefix; // bytes occuring in VersionURL before the version, used to locate the version information within the URL data
+ // (note that this URL could point at a binary file - dunno why, but it could :)
+ int cpbVersionPrefix; // number of bytes pointed to by pbVersionPrefix
+ char *szUpdateURL; // URL where dll/zip is located
+ // set to UPDATER_AUTOREGISTER if you want Updater to find the file listing URLs (ensure plugin shortName matches file listing!)
+
+ char *szBetaVersionURL; // URL where the beta version can be found (NULL to disable betas)
+ BYTE *pbBetaVersionPrefix; // bytes occuring in VersionURL before the version, used to locate the version information within the URL data
+ int cpbBetaVersionPrefix; // number of bytes pointed to by pbVersionPrefix
+ char *szBetaUpdateURL; // URL where dll/zip is located
+
+ BYTE *pbVersion; // bytes of current version, used for comparison with those in VersionURL
+ int cpbVersion; // number of bytes pointed to by pbVersion
+
+ char *szBetaChangelogURL; // url for displaying changelog for beta versions
+} Update;
+
+// register a comonent with Updater
+//
+// wparam = 0
+// lparam = (LPARAM)&Update
+#define MS_UPDATE_REGISTER "Update/Register"
+
+// utility functions to create a version string from a DWORD or from pluginInfo
+// point buf at a buffer at least 16 chars wide - but note the version string returned may be shorter
+//
+__inline static char *CreateVersionString(DWORD version, char *buf) {
+ mir_snprintf(buf, 16, "%d.%d.%d.%d", (version >> 24) & 0xFF, (version >> 16) & 0xFF, (version >> 8) & 0xFF, version & 0xFF);
+ return buf;
+}
+
+__inline static char *CreateVersionStringPlugin(PLUGININFO *pluginInfo, char *buf) {
+ return CreateVersionString(pluginInfo->version, buf);
+}
+
+
+// register the 'easy' way - use this method if you have no beta URL and the plugin is on the miranda file listing
+// NOTE: the plugin version string on the file listing must be the string version of the version in pluginInfo (i.e. 0.0.0.1,
+// four numbers between 0 and 255 inclusivem, so no letters, brackets, etc.)
+//
+// wParam = (int)fileID - this is the file ID from the file listing (i.e. the number at the end of the download link)
+// lParam = (PLUGININFO*)&pluginInfo
+#define MS_UPDATE_REGISTERFL "Update/RegisterFL"
+
+// this function can be used to 'unregister' components - useful for plugins that register non-plugin/langpack components and
+// may need to change those components on the fly
+// lParam = (char *)szComponentName
+#define MS_UPDATE_UNREGISTER "Update/Unregister"
+
+// this event is fired when the startup process is complete, but NOT if a restart is imminent
+// it is designed for status managment plugins to use as a trigger for beggining their own startup process
+// wParam = lParam = 0 (unused)
+// (added in version 0.1.6.0)
+#define ME_UPDATE_STARTUPDONE "Update/StartupDone"
+
+// this service can be used to enable/disable Updater's global status control
+// it can be called from the StartupDone event handler
+// wParam = (BOOL)enable
+// lParam = 0
+// (added in version 0.1.6.0)
+#define MS_UPDATE_ENABLESTATUSCONTROL "Update/EnableStatusControl"
+
+// An description of usage of the above service and event:
+// Say you are a status control plugin that normally sets protocol or global statuses in your ModulesLoaded event handler.
+// In order to make yourself 'Updater compatible', you would move the status control code from ModulesLoaded to another function,
+// say DoStartup. Then, in ModulesLoaded you would check for the existence of the MS_UPDATE_ENABLESTATUSCONTROL service.
+// If it does not exist, call DoStartup. If it does exist, hook the ME_UPDATE_STARTUPDONE event and call DoStartup from there. You may
+// also wish to call MS_UPDATE_ENABLESTATUSCONTROL with wParam == FALSE at this time, to disable Updater's own status control feature.
+
+// this service can be used to determine whether updates are possible for a component with the given name
+// wParam = 0
+// lParam = (char *)szComponentName
+// returns TRUE if updates are supported, FALSE otherwise
+#define MS_UPDATE_ISUPDATESUPPORTED "Update/IsUpdateSupported"
+
+#endif
+
+
+/////////////// Usage Example ///////////////
+
+#ifdef EXAMPLE_CODE
+
+// you need to #include "m_updater.h" and HookEvent(ME_SYSTEM_MODULESLOADED, OnModulesLoaded) in your Load function...
+
+int OnModulesLoaded(WPARAM wParam, LPARAM lParam) {
+
+ Update update = {0}; // for c you'd use memset or ZeroMemory...
+ char szVersion[16];
+
+ update.cbSize = sizeof(Update);
+
+ update.szComponentName = pluginInfo.shortName;
+ update.pbVersion = (BYTE *)CreateVersionString(&pluginInfo, szVersion);
+ update.cpbVersion = strlen((char *)update.pbVersion);
+
+ // these are the three lines that matter - the archive, the page containing the version string, and the text (or data)
+ // before the version that we use to locate it on the page
+ // (note that if the update URL and the version URL point to standard file listing entries, the backend xml
+ // data will be used to check for updates rather than the actual web page - this is not true for beta urls)
+ update.szUpdateURL = "http://scottellis.com.au:81/test/updater.zip";
+ update.szVersionURL = "http://scottellis.com.au:81/test/updater_test.html";
+ update.pbVersionPrefix = (BYTE *)"Updater version ";
+
+ update.cpbVersionPrefix = strlen((char *)update.pbVersionPrefix);
+
+ // do the same for the beta versions of the above struct members if you wish to allow beta updates from another URL
+
+ CallService(MS_UPDATE_REGISTER, 0, (WPARAM)&update);
+
+ // Alternatively, to register a plugin with e.g. file ID 2254 on the file listing...
+ // CallService(MS_UPDATE_REGISTERFL, (WPARAM)2254, (LPARAM)&pluginInfo);
+
+ return 0;
+}
+
+#endif
diff --git a/Plugins/smh/smh.cpp b/Plugins/smh/smh.cpp
new file mode 100644
index 0000000..6d54e97
--- /dev/null
+++ b/Plugins/smh/smh.cpp
@@ -0,0 +1,671 @@
+/*
+Copyright (C) 2006 Ricardo Pescuma Domenecci
+
+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.
+*/
+
+
+#include "commons.h"
+
+
+// Prototypes ///////////////////////////////////////////////////////////////////////////
+
+
+PLUGININFOEX pluginInfo={
+ sizeof(PLUGININFOEX),
+#ifdef UNICODE
+ "Status Message History (Unicode)",
+#else
+ "Status Message History",
+#endif
+ PLUGIN_MAKE_VERSION(0,1,0,3),
+ "Log status message changes to history",
+ "Ricardo Pescuma Domenecci",
+ "",
+ "© 2006 Ricardo Pescuma Domenecci",
+ "http://pescuma.mirandaim.ru/miranda/smh",
+ UNICODE_AWARE,
+ 0, //doesn't replace anything built-in
+#ifdef UNICODE
+ { 0x4f2b331e, 0xd894, 0x4fdc, { 0x8c, 0xb2, 0xd, 0x11, 0x54, 0xe5, 0xf3, 0x4c } } // {4F2B331E-D894-4fdc-8CB2-0D1154E5F34C}
+#else
+ { 0x9a911bc1, 0xf3f1, 0x4c47, { 0xb2, 0xfd, 0x31, 0x7d, 0xaa, 0x8e, 0x3b, 0xb } } // {9A911BC1-F3F1-4c47-B2FD-317DAA8E3B0B}
+#endif
+};
+
+
+HINSTANCE hInst;
+PLUGINLINK *pluginLink;
+
+HANDLE hEnableMenu = NULL;
+HANDLE hDisableMenu = NULL;
+HANDLE hModulesLoaded = NULL;
+HANDLE hPreBuildCMenu = NULL;
+HANDLE hSettingChanged = NULL;
+
+char *metacontacts_proto = NULL;
+BOOL loaded = FALSE;
+
+int ModulesLoaded(WPARAM wParam, LPARAM lParam);
+int PreBuildContactMenu(WPARAM wParam,LPARAM lParam);
+int SettingChanged(WPARAM wParam,LPARAM lParam);
+
+int EnableHistory(WPARAM wParam,LPARAM lParam);
+int DisableHistory(WPARAM wParam,LPARAM lParam);
+int HistoryEnabled(WPARAM wParam, LPARAM lParam);
+
+BOOL ContactEnabled(HANDLE hContact);
+BOOL ProtocolEnabled(const char *protocol);
+
+
+// Functions ////////////////////////////////////////////////////////////////////////////
+
+
+extern "C" BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+ hInst = hinstDLL;
+ return TRUE;
+}
+
+
+extern "C" __declspec(dllexport) PLUGININFO* MirandaPluginInfo(DWORD mirandaVersion)
+{
+ pluginInfo.cbSize = sizeof(PLUGININFO);
+ return (PLUGININFO*) &pluginInfo;
+}
+
+
+extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ pluginInfo.cbSize = sizeof(PLUGININFOEX);
+ return &pluginInfo;
+}
+
+
+static const MUUID interfaces[] = { MIID_STATUS_MESSAGE_CHANGE_LOGGER, MIID_STATUS_MESSAGE_CHANGE_NOTIFIER, MIID_LAST };
+extern "C" __declspec(dllexport) const MUUID* MirandaPluginInterfaces(void)
+{
+ return interfaces;
+}
+
+
+extern "C" int __declspec(dllexport) Load(PLUGINLINK *link)
+{
+ pluginLink = link;
+
+ init_mir_malloc();
+
+ CreateServiceFunction(MS_SMH_DISABLE, DisableHistory);
+ CreateServiceFunction(MS_SMH_ENABLE, EnableHistory);
+ CreateServiceFunction(MS_SMH_ENABLED, HistoryEnabled);
+
+ // Add menu item to enable/disable status message check
+ CLISTMENUITEM mi = {0};
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIF_NOTOFFLIST;
+ mi.position = 1000100010;
+
+ mi.pszName = Translate("Don't log Status Message changes");
+ mi.pszService = MS_SMH_DISABLE;
+ hDisableMenu = (HANDLE) CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi);
+
+ mi.pszName = Translate("Log Status Message changes");
+ mi.pszService = MS_SMH_ENABLE;
+ hEnableMenu = (HANDLE) CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi);
+
+ // hooks
+ hModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED, ModulesLoaded);
+ hPreBuildCMenu = HookEvent(ME_CLIST_PREBUILDCONTACTMENU, PreBuildContactMenu);
+ hSettingChanged = HookEvent(ME_DB_CONTACT_SETTINGCHANGED, SettingChanged);
+
+ InitOptions();
+ InitPopups();
+
+ return 0;
+}
+
+extern "C" int __declspec(dllexport) Unload(void)
+{
+ DeInitPopups();
+ DeInitOptions();
+
+ UnhookEvent(hModulesLoaded);
+ UnhookEvent(hPreBuildCMenu);
+ UnhookEvent(hSettingChanged);
+ return 0;
+}
+
+
+// Called when all the modules are loaded
+int ModulesLoaded(WPARAM wParam, LPARAM lParam)
+{
+ if (ServiceExists(MS_MC_GETPROTOCOLNAME))
+ metacontacts_proto = (char *) CallService(MS_MC_GETPROTOCOLNAME, 0, 0);
+
+ // add our modules to the KnownModules list
+ CallService("DBEditorpp/RegisterSingleModule", (WPARAM) MODULE_NAME, 0);
+
+ // updater plugin support
+ if(ServiceExists(MS_UPDATE_REGISTER))
+ {
+ Update upd = {0};
+ char szCurrentVersion[30];
+
+ upd.cbSize = sizeof(upd);
+ upd.szComponentName = pluginInfo.shortName;
+
+ upd.szUpdateURL = UPDATER_AUTOREGISTER;
+
+ upd.szBetaVersionURL = "http://pescuma.mirandaim.ru/miranda/smh_version.txt";
+ upd.szBetaChangelogURL = "http://pescuma.mirandaim.ru/miranda/smh#Changelog";
+ upd.pbBetaVersionPrefix = (BYTE *)"Status Message History ";
+ upd.cpbBetaVersionPrefix = strlen((char *)upd.pbBetaVersionPrefix);
+#ifdef UNICODE
+ upd.szBetaUpdateURL = "http://pescuma.mirandaim.ru/miranda/smhW.zip";
+#else
+ upd.szBetaUpdateURL = "http://pescuma.mirandaim.ru/miranda/smh.zip";
+#endif
+
+ upd.pbVersion = (BYTE *)CreateVersionStringPlugin((PLUGININFO*) &pluginInfo, szCurrentVersion);
+ upd.cpbVersion = strlen((char *)upd.pbVersion);
+
+ CallService(MS_UPDATE_REGISTER, 0, (LPARAM)&upd);
+ }
+
+ loaded = TRUE;
+
+ return 0;
+}
+
+
+int PreBuildContactMenu(WPARAM wParam,LPARAM lParam)
+{
+ CLISTMENUITEM clmi = {0};
+ clmi.cbSize = sizeof(clmi);
+
+ char *proto = (char*) CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0);
+ if (!ProtocolEnabled(proto))
+ {
+ clmi.flags = CMIM_FLAGS | CMIF_HIDDEN;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) hDisableMenu, (LPARAM) &clmi);
+
+ clmi.flags = CMIM_FLAGS | CMIF_HIDDEN;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) hEnableMenu, (LPARAM) &clmi);
+ }
+ else if (HistoryEnabled(wParam, 0))
+ {
+ clmi.flags = CMIM_FLAGS | CMIF_HIDDEN;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) hEnableMenu, (LPARAM) &clmi);
+
+ clmi.flags = CMIM_FLAGS | CMIM_ICON;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) hDisableMenu, (LPARAM) &clmi);
+ }
+ else
+ {
+ clmi.flags = CMIM_FLAGS | CMIF_HIDDEN;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) hDisableMenu, (LPARAM) &clmi);
+
+ clmi.flags = CMIM_FLAGS | CMIM_ICON;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) hEnableMenu, (LPARAM) &clmi);
+ }
+
+ return 0;
+}
+
+
+int EnableHistory(WPARAM wParam,LPARAM lParam)
+{
+ HANDLE hContact = (HANDLE) wParam;
+
+ if (hContact != NULL)
+ DBWriteContactSettingByte(hContact, MODULE_NAME, "Enabled", TRUE);
+
+ return 0;
+}
+
+
+int DisableHistory(WPARAM wParam,LPARAM lParam)
+{
+ HANDLE hContact = (HANDLE) wParam;
+
+ if (hContact != NULL)
+ DBWriteContactSettingByte(hContact, MODULE_NAME, "Enabled", FALSE);
+
+ return 0;
+}
+
+
+int HistoryEnabled(WPARAM wParam, LPARAM lParam)
+{
+ return ContactEnabled((HANDLE) wParam);
+}
+
+
+BOOL AllowProtocol(const char *proto)
+{
+ if ((CallProtoService(proto, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGRECV) == 0)
+ return FALSE;
+
+ return TRUE;
+}
+
+
+BOOL ProtocolEnabled(const char *proto)
+{
+ if (proto == NULL)
+ return FALSE;
+
+ if (!AllowProtocol(proto))
+ return FALSE;
+
+ char setting[256];
+ mir_snprintf(setting, sizeof(setting), "%sEnabled", proto);
+ return (BOOL) DBGetContactSettingByte(NULL, MODULE_NAME, setting, TRUE);
+}
+
+
+BOOL ContactEnabled(HANDLE hContact)
+{
+ if (hContact == NULL)
+ return FALSE;
+
+ char *proto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+ if (!ProtocolEnabled(proto))
+ return FALSE;
+
+ BYTE def = TRUE;
+
+ // Is a subcontact?
+ if (ServiceExists(MS_MC_GETMETACONTACT))
+ {
+ HANDLE hMetaContact = (HANDLE) CallService(MS_MC_GETMETACONTACT, (WPARAM)hContact, 0);
+
+ if (hMetaContact != NULL)
+ def = ContactEnabled(hMetaContact);
+ }
+
+ return DBGetContactSettingByte(hContact, MODULE_NAME, "Enabled", def);
+}
+
+
+// Returns true if the unicode buffer only contains 7-bit characters.
+BOOL IsUnicodeAscii(const WCHAR * pBuffer, int nSize)
+{
+ BOOL bResult = TRUE;
+ int nIndex;
+
+ for (nIndex = 0; nIndex < nSize; nIndex++) {
+ if (pBuffer[nIndex] > 0x7F) {
+ bResult = FALSE;
+ break;
+ }
+ }
+ return bResult;
+}
+
+
+HANDLE HistoryLog(HANDLE hContact, TCHAR *log_text)
+{
+ if (log_text != NULL)
+ {
+ DBEVENTINFO event = { 0 };
+ BYTE *tmp = NULL;
+
+ event.cbSize = sizeof(event);
+
+#ifdef UNICODE
+
+ size_t needed = WideCharToMultiByte(CP_ACP, 0, log_text, -1, NULL, 0, NULL, NULL);
+ size_t len = lstrlen(log_text);
+ size_t size;
+
+ if (opts.history_only_ansi_if_possible && IsUnicodeAscii(log_text, len))
+ size = needed;
+ else
+ size = needed + (len + 1) * sizeof(WCHAR);
+
+ tmp = (BYTE *) mir_alloc0(size);
+
+ WideCharToMultiByte(CP_ACP, 0, log_text, -1, (char *) tmp, needed, NULL, NULL);
+
+ if (size > needed)
+ lstrcpyn((WCHAR *) &tmp[needed], log_text, len + 1);
+
+ event.pBlob = tmp;
+ event.cbBlob = size;
+
+#else
+
+ event.pBlob = (PBYTE) log_text;
+ event.cbBlob = strlen(log_text) + 1;
+
+#endif
+
+ event.eventType = EVENTTYPE_STATUSMESSAGE_CHANGE;
+ event.flags = DBEF_READ;
+ event.timestamp = (DWORD) time(NULL);
+
+ event.szModule = MODULE_NAME;
+
+ // Is a subcontact?
+ if (ServiceExists(MS_MC_GETMETACONTACT))
+ {
+ HANDLE hMetaContact = (HANDLE) CallService(MS_MC_GETMETACONTACT, (WPARAM)hContact, 0);
+
+ if (hMetaContact != NULL && ContactEnabled(hMetaContact))
+ CallService(MS_DB_EVENT_ADD,(WPARAM)hMetaContact,(LPARAM)&event);
+ }
+
+ HANDLE ret = (HANDLE) CallService(MS_DB_EVENT_ADD,(WPARAM)hContact,(LPARAM)&event);
+
+ mir_free(tmp);
+
+ return ret;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+void ReplaceChars(TCHAR *text)
+{
+ TCHAR *p;
+ while(p = _tcsstr(text, _T("\\n")))
+ {
+ p[0] = _T('\r');
+ p[1] = _T('\n');
+ }
+}
+
+void Notify(HANDLE hContact, TCHAR *text)
+{
+ if (text != NULL && text[0] == _T('\0'))
+ text = NULL;
+
+ if (!opts.track_changes && text != NULL)
+ return;
+
+ if (!opts.track_removes && text == NULL)
+ return;
+
+ // Replace template with status_message
+ TCHAR templ[1024];
+ lstrcpyn(templ, text == NULL ? opts.template_removed : opts.template_changed, MAX_REGS(templ));
+ ReplaceChars(templ);
+
+ TCHAR log[1024];
+ mir_sntprintf(log, sizeof(log), templ,
+ text == NULL ? TranslateT("<no status message>") : text);
+
+ if (opts.history_enable)
+ HistoryLog(hContact, log);
+
+ if (opts.popup_enable)
+ ShowPopup(hContact, NULL, log);
+}
+
+int inline CheckStr(char *str, int not_empty, int empty)
+{
+ if (str == NULL || str[0] == '\0')
+ return empty;
+ else
+ return not_empty;
+}
+
+#ifdef UNICODE
+
+int inline CheckStr(TCHAR *str, int not_empty, int empty)
+{
+ if (str == NULL || str[0] == L'\0')
+ return empty;
+ else
+ return not_empty;
+}
+
+#endif
+
+// Return 0 if not changed, 1 if changed, 2 if removed
+int TrackChange(HANDLE hContact, DBCONTACTWRITESETTING *cws_new, BOOL ignore_remove)
+{
+ char current_setting[256];
+ mir_snprintf(current_setting, MAX_REGS(current_setting), "%sCurrent", cws_new->szSetting);
+
+ int ret = 0;
+
+ DBVARIANT dbv = {0};
+#ifdef UNICODE
+ BOOL found_current = (DBGetContactSettingW(hContact, cws_new->szModule, current_setting, &dbv) == 0);
+#else
+ BOOL found_current = (DBGetContactSetting(hContact, cws_new->szModule, current_setting, &dbv) == 0);
+#endif
+ if (!found_current)
+ {
+ // Current value does not exist
+
+ if (cws_new->value.type == DBVT_DELETED)
+ {
+ ret = 0;
+ }
+ else if (cws_new->value.type == DBVT_ASCIIZ)
+ {
+ ret = CheckStr(cws_new->value.pszVal, 1, 0);
+ }
+#ifdef UNICODE
+ else if (cws_new->value.type == DBVT_UTF8)
+ {
+ ret = CheckStr(cws_new->value.pszVal, 1, 0);
+ }
+ else if (cws_new->value.type == DBVT_WCHAR)
+ {
+ ret = CheckStr(cws_new->value.pwszVal, 1, 0);
+ }
+#endif
+ else
+ {
+ ret = 1;
+ }
+ }
+ else
+ {
+ // Current value exist
+
+ if (cws_new->value.type == DBVT_DELETED)
+ {
+ if (dbv.type == DBVT_ASCIIZ)
+ {
+ ret = CheckStr(dbv.pszVal, 2, 0);
+ }
+#ifdef UNICODE
+ else if (dbv.type == DBVT_UTF8)
+ {
+ ret = CheckStr(dbv.pszVal, 2, 0);
+ }
+ else if (dbv.type == DBVT_WCHAR)
+ {
+ ret = CheckStr(dbv.pwszVal, 2, 0);
+ }
+#endif
+ else
+ {
+ ret = 2;
+ }
+ }
+ else if (dbv.type != cws_new->value.type)
+ {
+#ifdef UNICODE
+ if ( (cws_new->value.type == DBVT_UTF8 || cws_new->value.type == DBVT_ASCIIZ || cws_new->value.type == DBVT_WCHAR)
+ && (dbv.type == DBVT_UTF8 || dbv.type == DBVT_ASCIIZ || dbv.type == DBVT_WCHAR))
+ {
+ WCHAR tmp_cws_new[1024] = L"";
+ if (cws_new->value.type == DBVT_ASCIIZ)
+ MultiByteToWideChar(CP_ACP, 0, cws_new->value.pszVal, -1, tmp_cws_new, MAX_REGS(tmp_cws_new));
+ else if (cws_new->value.type == DBVT_UTF8)
+ MultiByteToWideChar(CP_UTF8, 0, cws_new->value.pszVal, -1, tmp_cws_new, MAX_REGS(tmp_cws_new));
+ else if (cws_new->value.type == DBVT_WCHAR)
+ lstrcpyn(tmp_cws_new, cws_new->value.pwszVal, MAX_REGS(tmp_cws_new));
+
+ WCHAR tmp_dbv[1024] = L"";
+ if (dbv.type == DBVT_ASCIIZ)
+ MultiByteToWideChar(CP_ACP, 0, dbv.pszVal, -1, tmp_dbv, MAX_REGS(tmp_dbv));
+ else if (dbv.type == DBVT_UTF8)
+ MultiByteToWideChar(CP_UTF8, 0, dbv.pszVal, -1, tmp_dbv, MAX_REGS(tmp_dbv));
+ else if (dbv.type == DBVT_WCHAR)
+ lstrcpyn(tmp_dbv, dbv.pwszVal, MAX_REGS(tmp_dbv));
+
+ ret = (lstrcmpW(tmp_cws_new, tmp_dbv) ? CheckStr(tmp_cws_new, 1, 2) : 0);
+ }
+ else
+#endif
+ {
+ ret = 1;
+ }
+ }
+ else if (dbv.type == DBVT_BYTE)
+ {
+ ret = (cws_new->value.bVal != dbv.bVal ? 1 : 0);
+ }
+ else if (dbv.type == DBVT_WORD)
+ {
+ ret = (cws_new->value.wVal != dbv.wVal ? 1 : 0);
+ }
+ else if (dbv.type == DBVT_DWORD)
+ {
+ ret = (cws_new->value.dVal != dbv.dVal ? 1 : 0);
+ }
+ else if (dbv.type == DBVT_ASCIIZ)
+ {
+ ret = (strcmp(cws_new->value.pszVal, dbv.pszVal) ? CheckStr(cws_new->value.pszVal, 1, 2) : 0);
+ }
+#ifdef UNICODE
+ else if (dbv.type == DBVT_UTF8)
+ {
+ ret = (strcmp(cws_new->value.pszVal, dbv.pszVal) ? CheckStr(cws_new->value.pszVal, 1, 2) : 0);
+ }
+ else if (dbv.type == DBVT_WCHAR)
+ {
+ ret = (lstrcmp(cws_new->value.pwszVal, dbv.pwszVal) ? CheckStr(cws_new->value.pwszVal, 1, 2) : 0);
+ }
+#endif
+ }
+
+ if (ret == 1 || (ret == 2 && !ignore_remove))
+ {
+ // Copy current to old
+ char old_setting[256];
+ mir_snprintf(old_setting, MAX_REGS(old_setting), "%sOld", cws_new->szSetting);
+
+ if (dbv.type == DBVT_DELETED)
+ {
+ DBDeleteContactSetting(hContact, cws_new->szModule, old_setting);
+ }
+ else
+ {
+ DBCONTACTWRITESETTING cws_old;
+ cws_old.szModule = cws_new->szModule;
+ cws_old.szSetting = old_setting;
+ cws_old.value = dbv;
+ CallService(MS_DB_CONTACT_WRITESETTING, (WPARAM)hContact, (LPARAM)&cws_old);
+ }
+
+
+ // Copy new to current
+ if (cws_new->value.type == DBVT_DELETED)
+ {
+ DBDeleteContactSetting(hContact, cws_new->szModule, current_setting);
+ }
+ else
+ {
+ DBCONTACTWRITESETTING cws_old;
+ cws_old.szModule = cws_new->szModule;
+ cws_old.szSetting = current_setting;
+ cws_old.value = cws_new->value;
+ CallService(MS_DB_CONTACT_WRITESETTING, (WPARAM)hContact, (LPARAM)&cws_old);
+ }
+ }
+
+ if (found_current)
+ DBFreeVariant(&dbv);
+
+ return ret;
+}
+
+
+int SettingChanged(WPARAM wParam,LPARAM lParam)
+{
+ if (!loaded)
+ return 0;
+
+ if (!opts.history_enable && !opts.popup_enable)
+ return 0;
+
+ HANDLE hContact = (HANDLE) wParam;
+ if (hContact == NULL)
+ return 0;
+
+ DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING*)lParam;
+ if (!strcmp(cws->szModule, "CList") && !strcmp(cws->szSetting, "StatusMsg"))
+ {
+ char *proto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+ if (proto == NULL || (metacontacts_proto != NULL && !strcmp(proto, metacontacts_proto)))
+ return 0;
+
+ if (opts.track_only_not_offline)
+ {
+ if (DBGetContactSettingWord(hContact, proto, "Status", 0) <= ID_STATUS_OFFLINE)
+ return 0;
+ }
+
+ if (!ContactEnabled(hContact))
+ return 0;
+
+ int changed = TrackChange(hContact, cws, !opts.track_removes);
+ if (changed == 0)
+ return 0;
+
+ if (changed == 2)
+ {
+ Notify(hContact, NULL);
+ }
+ else // changed == 1
+#ifdef UNICODE
+ if (cws->value.type == DBVT_ASCIIZ)
+ {
+ WCHAR tmp[1024] = L"";
+ MultiByteToWideChar(CP_ACP, 0, cws->value.pszVal, -1, tmp, MAX_REGS(tmp));
+ Notify(hContact, tmp);
+ }
+ else if (cws->value.type == DBVT_UTF8)
+ {
+ WCHAR tmp[1024] = L"";
+ MultiByteToWideChar(CP_UTF8, 0, cws->value.pszVal, -1, tmp, MAX_REGS(tmp));
+ Notify(hContact, tmp);
+ }
+ else if (cws->value.type == DBVT_WCHAR)
+ {
+ Notify(hContact, cws->value.pwszVal);
+ }
+#else
+ if (cws->value.type == DBVT_ASCIIZ)
+ {
+ Notify(hContact, cws->value.pszVal);
+ }
+#endif
+ }
+
+ return 0;
+}
+
diff --git a/Plugins/smh/smh.dsp b/Plugins/smh/smh.dsp
new file mode 100644
index 0000000..e490159
--- /dev/null
+++ b/Plugins/smh/smh.dsp
@@ -0,0 +1,247 @@
+# Microsoft Developer Studio Project File - Name="smh" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=smh - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "smh.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "smh.mak" CFG="smh - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "smh - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "smh - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "smh - Win32 Unicode Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "smh - Win32 Unicode Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "smh - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /GX /O1 /YX /FD /c
+# SUBTRACT BASE CPP /Fr
+# ADD CPP /nologo /G4 /MT /W3 /GX /O2 /Ob0 /I "../../include" /I "sdk" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /Fr /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x417 /d "NDEBUG"
+# ADD RSC /l 0x417 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 user32.lib shell32.lib wininet.lib gdi32.lib /nologo /base:"0x67100000" /dll /machine:I386 /filealign:0x200
+# SUBTRACT BASE LINK32 /pdb:none /map
+# ADD LINK32 kernel32.lib user32.lib /nologo /base:"0x3EC20000" /dll /map /machine:I386 /out:"..\..\bin\release\Plugins\smh.dll" /filealign:0x200 /ALIGN:4096 /ignore:4108
+# SUBTRACT LINK32 /profile /pdb:none
+
+!ELSEIF "$(CFG)" == "smh - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /G4 /MT /W3 /GX /O2 /Ob0 /I "../../include" /FR /YX /FD /c
+# ADD CPP /nologo /G4 /MTd /W3 /GX /ZI /Od /I "../../include" /I "sdk" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /FR /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x417 /d "NDEBUG"
+# ADD RSC /l 0x417 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"..\..bin\release\Plugins\smh.dll" /filealign:0x200 /ALIGN:4096 /ignore:4108
+# SUBTRACT BASE LINK32 /profile /pdb:none
+# ADD LINK32 kernel32.lib user32.lib /nologo /base:"0x3EC20000" /dll /incremental:yes /debug /machine:I386 /out:"..\..\bin\debug\Plugins\smh.dll" /filealign:0x200 /ALIGN:4096 /ignore:4108
+# SUBTRACT LINK32 /profile /pdb:none
+
+!ELSEIF "$(CFG)" == "smh - Win32 Unicode Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "smh___Win32_Unicode_Debug"
+# PROP BASE Intermediate_Dir "smh___Win32_Unicode_Debug"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Unicode_Debug"
+# PROP Intermediate_Dir "Unicode_Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /G4 /MTd /W3 /GX /ZI /Od /I "../../include" /FR /YX /FD /c
+# ADD CPP /nologo /G4 /MTd /W3 /GX /ZI /Od /I "../../include" /I "sdk" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /D "_USRDLL" /FR /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x417 /d "NDEBUG"
+# ADD RSC /l 0x417 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /base:"0x32100000" /dll /incremental:yes /debug /machine:I386 /out:"..\..\bin\debug\Plugins\smh.dll" /filealign:0x200 /ALIGN:4096 /ignore:4108
+# SUBTRACT BASE LINK32 /profile /pdb:none
+# ADD LINK32 kernel32.lib user32.lib /nologo /base:"0x3EC20000" /dll /incremental:yes /debug /machine:I386 /out:"..\..\bin\debug unicode\Plugins\smhW.dll" /filealign:0x200 /ALIGN:4096 /ignore:4108
+# SUBTRACT LINK32 /profile /pdb:none
+
+!ELSEIF "$(CFG)" == "smh - Win32 Unicode Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "smh___Win32_Unicode_Release"
+# PROP BASE Intermediate_Dir "smh___Win32_Unicode_Release"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Unicode_Release"
+# PROP Intermediate_Dir "Unicode_Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /G4 /MT /W3 /GX /O2 /Ob0 /I "../../include" /Fr /YX /FD /c
+# ADD CPP /nologo /G4 /MT /W3 /GX /O2 /Ob0 /I "../../include" /I "sdk" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /D "_USRDLL" /Fr /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x417 /d "NDEBUG"
+# ADD RSC /l 0x417 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /base:"0x32100000" /dll /map /machine:I386 /out:"..\..\bin\release\Plugins\smh.dll" /filealign:0x200 /ALIGN:4096 /ignore:4108
+# SUBTRACT BASE LINK32 /profile /pdb:none
+# ADD LINK32 kernel32.lib user32.lib /nologo /base:"0x3EC20000" /dll /map /machine:I386 /out:"..\..\bin\release\Plugins\smhW.dll" /filealign:0x200 /ALIGN:4096 /ignore:4108
+# SUBTRACT LINK32 /profile /pdb:none
+
+!ENDIF
+
+# Begin Target
+
+# Name "smh - Win32 Release"
+# Name "smh - Win32 Debug"
+# Name "smh - Win32 Unicode Debug"
+# Name "smh - Win32 Unicode Release"
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\commons.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\m_smh.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\utils\mir_memory.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\utils\mir_options.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\options.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\popup.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\resource.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE=.\resource.rc
+# End Source File
+# End Group
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\utils\mir_memory.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\utils\mir_options.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\options.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\popup.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\smh.cpp
+# End Source File
+# End Group
+# Begin Group "Docs"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\Docs\helppack_smh.txt
+# End Source File
+# Begin Source File
+
+SOURCE=.\Docs\langpack_smh.txt
+# End Source File
+# Begin Source File
+
+SOURCE=.\Docs\smh_changelog.txt
+# End Source File
+# Begin Source File
+
+SOURCE=.\Docs\smh_readme.txt
+# End Source File
+# Begin Source File
+
+SOURCE=.\Docs\smh_version.txt
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/Plugins/smh/smh.dsw b/Plugins/smh/smh.dsw
new file mode 100644
index 0000000..ed7906d
--- /dev/null
+++ b/Plugins/smh/smh.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "smh"=".\smh.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+