From 48540940b6c28bb4378abfeb500ec45a625b37b6 Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Tue, 15 May 2012 10:38:20 +0000 Subject: initial commit git-svn-id: http://svn.miranda-ng.org/main/trunk@2 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/NewXstatusNotify/NewXstatusNotify.vcproj | 306 ++++ plugins/NewXstatusNotify/NewXstatusNotify_10.sln | 26 + .../NewXstatusNotify/NewXstatusNotify_10.vcxproj | 355 +++++ .../NewXstatusNotify_10.vcxproj.filters | 121 ++ plugins/NewXstatusNotify/NewXstatusNotify_9.vcproj | 365 +++++ plugins/NewXstatusNotify/common.h | 152 ++ plugins/NewXstatusNotify/docs/nxsn_readme.txt | 127 ++ plugins/NewXstatusNotify/docs/nxsn_translate.txt | 195 +++ plugins/NewXstatusNotify/indsnd.cpp | 681 +++++++++ plugins/NewXstatusNotify/indsnd.h | 41 + plugins/NewXstatusNotify/main.cpp | 1458 ++++++++++++++++++++ plugins/NewXstatusNotify/options.cpp | 1092 +++++++++++++++ plugins/NewXstatusNotify/options.h | 90 ++ plugins/NewXstatusNotify/popup.cpp | 194 +++ plugins/NewXstatusNotify/popup.h | 54 + plugins/NewXstatusNotify/res/disable_all.ico | Bin 0 -> 2550 bytes plugins/NewXstatusNotify/res/enable_all.ico | Bin 0 -> 2550 bytes plugins/NewXstatusNotify/res/logging.ico | Bin 0 -> 2550 bytes plugins/NewXstatusNotify/res/main_off.ico | Bin 0 -> 2550 bytes plugins/NewXstatusNotify/res/main_on.ico | Bin 0 -> 2550 bytes plugins/NewXstatusNotify/res/popup.ico | Bin 0 -> 2550 bytes plugins/NewXstatusNotify/res/reset.ico | Bin 0 -> 2550 bytes plugins/NewXstatusNotify/res/sound.ico | Bin 0 -> 2550 bytes plugins/NewXstatusNotify/res/status_message.ico | Bin 0 -> 2550 bytes plugins/NewXstatusNotify/res/variables.ico | Bin 0 -> 2550 bytes plugins/NewXstatusNotify/res/xstatus.ico | Bin 0 -> 2550 bytes plugins/NewXstatusNotify/resource.h | 147 ++ plugins/NewXstatusNotify/resource.rc | 411 ++++++ plugins/NewXstatusNotify/utils.cpp | 124 ++ plugins/NewXstatusNotify/utils.h | 33 + plugins/NewXstatusNotify/version.h | 4 + plugins/NewXstatusNotify/version.rc | 37 + plugins/NewXstatusNotify/xstatus.cpp | 524 +++++++ plugins/NewXstatusNotify/xstatus.h | 106 ++ 34 files changed, 6643 insertions(+) create mode 100644 plugins/NewXstatusNotify/NewXstatusNotify.vcproj create mode 100644 plugins/NewXstatusNotify/NewXstatusNotify_10.sln create mode 100644 plugins/NewXstatusNotify/NewXstatusNotify_10.vcxproj create mode 100644 plugins/NewXstatusNotify/NewXstatusNotify_10.vcxproj.filters create mode 100644 plugins/NewXstatusNotify/NewXstatusNotify_9.vcproj create mode 100644 plugins/NewXstatusNotify/common.h create mode 100644 plugins/NewXstatusNotify/docs/nxsn_readme.txt create mode 100644 plugins/NewXstatusNotify/docs/nxsn_translate.txt create mode 100644 plugins/NewXstatusNotify/indsnd.cpp create mode 100644 plugins/NewXstatusNotify/indsnd.h create mode 100644 plugins/NewXstatusNotify/main.cpp create mode 100644 plugins/NewXstatusNotify/options.cpp create mode 100644 plugins/NewXstatusNotify/options.h create mode 100644 plugins/NewXstatusNotify/popup.cpp create mode 100644 plugins/NewXstatusNotify/popup.h create mode 100644 plugins/NewXstatusNotify/res/disable_all.ico create mode 100644 plugins/NewXstatusNotify/res/enable_all.ico create mode 100644 plugins/NewXstatusNotify/res/logging.ico create mode 100644 plugins/NewXstatusNotify/res/main_off.ico create mode 100644 plugins/NewXstatusNotify/res/main_on.ico create mode 100644 plugins/NewXstatusNotify/res/popup.ico create mode 100644 plugins/NewXstatusNotify/res/reset.ico create mode 100644 plugins/NewXstatusNotify/res/sound.ico create mode 100644 plugins/NewXstatusNotify/res/status_message.ico create mode 100644 plugins/NewXstatusNotify/res/variables.ico create mode 100644 plugins/NewXstatusNotify/res/xstatus.ico create mode 100644 plugins/NewXstatusNotify/resource.h create mode 100644 plugins/NewXstatusNotify/resource.rc create mode 100644 plugins/NewXstatusNotify/utils.cpp create mode 100644 plugins/NewXstatusNotify/utils.h create mode 100644 plugins/NewXstatusNotify/version.h create mode 100644 plugins/NewXstatusNotify/version.rc create mode 100644 plugins/NewXstatusNotify/xstatus.cpp create mode 100644 plugins/NewXstatusNotify/xstatus.h (limited to 'plugins/NewXstatusNotify') diff --git a/plugins/NewXstatusNotify/NewXstatusNotify.vcproj b/plugins/NewXstatusNotify/NewXstatusNotify.vcproj new file mode 100644 index 0000000000..4349e3c71e --- /dev/null +++ b/plugins/NewXstatusNotify/NewXstatusNotify.vcproj @@ -0,0 +1,306 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/NewXstatusNotify/NewXstatusNotify_10.sln b/plugins/NewXstatusNotify/NewXstatusNotify_10.sln new file mode 100644 index 0000000000..7a420272c0 --- /dev/null +++ b/plugins/NewXstatusNotify/NewXstatusNotify_10.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NewXstatusNotify", "NewXstatusNotify_10.vcxproj", "{78E0E6B0-2D7E-4B4D-899A-DA244FBBEC73}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug Unicode|Win32 = Debug Unicode|Win32 + Debug Unicode|x64 = Debug Unicode|x64 + Release Unicode|Win32 = Release Unicode|Win32 + Release Unicode|x64 = Release Unicode|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {78E0E6B0-2D7E-4B4D-899A-DA244FBBEC73}.Debug Unicode|Win32.ActiveCfg = Debug Unicode|Win32 + {78E0E6B0-2D7E-4B4D-899A-DA244FBBEC73}.Debug Unicode|Win32.Build.0 = Debug Unicode|Win32 + {78E0E6B0-2D7E-4B4D-899A-DA244FBBEC73}.Debug Unicode|x64.ActiveCfg = Debug Unicode|x64 + {78E0E6B0-2D7E-4B4D-899A-DA244FBBEC73}.Debug Unicode|x64.Build.0 = Debug Unicode|x64 + {78E0E6B0-2D7E-4B4D-899A-DA244FBBEC73}.Release Unicode|Win32.ActiveCfg = Release Unicode|Win32 + {78E0E6B0-2D7E-4B4D-899A-DA244FBBEC73}.Release Unicode|Win32.Build.0 = Release Unicode|Win32 + {78E0E6B0-2D7E-4B4D-899A-DA244FBBEC73}.Release Unicode|x64.ActiveCfg = Release Unicode|x64 + {78E0E6B0-2D7E-4B4D-899A-DA244FBBEC73}.Release Unicode|x64.Build.0 = Release Unicode|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/plugins/NewXstatusNotify/NewXstatusNotify_10.vcxproj b/plugins/NewXstatusNotify/NewXstatusNotify_10.vcxproj new file mode 100644 index 0000000000..37ef8fe327 --- /dev/null +++ b/plugins/NewXstatusNotify/NewXstatusNotify_10.vcxproj @@ -0,0 +1,355 @@ + + + + + Debug Unicode + Win32 + + + Debug Unicode + x64 + + + Release Unicode + Win32 + + + Release Unicode + x64 + + + + NewXstatusNotify + {78E0E6B0-2D7E-4B4D-899A-DA244FBBEC73} + NewStatusNotify + + + + DynamicLibrary + Unicode + + + DynamicLibrary + false + Unicode + true + + + DynamicLibrary + false + Unicode + true + + + DynamicLibrary + false + Unicode + true + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Configuration)/Plugins\ + $(SolutionDir)$(Configuration)64/Plugins\ + $(SolutionDir)$(Configuration)/Obj/$(ProjectName)\ + $(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\ + true + true + $(SolutionDir)$(Configuration)/Plugins\ + $(SolutionDir)$(Configuration)64/Plugins\ + $(SolutionDir)$(Configuration)/Obj/$(ProjectName)\ + $(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\ + AllRules.ruleset + AllRules.ruleset + + + + + AllRules.ruleset + AllRules.ruleset + + + + + newxstatusnotify + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + .\Release/NewStatusNotify.tlb + + + + + /D "_CRT_SECURE_NO_DEPRECATE" +/D "_CRT_NON_CONFORMING_SWPRINTFS" %(AdditionalOptions) + Full + OnlyExplicitInline + Size + true + false + true + ../../include;../../ExternalAPI + true + Sync + MultiThreadedDLL + true + + + + + Level3 + ProgramDatabase + + + + + NDEBUG;%(PreprocessorDefinitions) + + + /release %(AdditionalOptions) + winmm.lib;comctl32.lib;%(AdditionalDependencies) + + + + + true + true + UseLinkTimeCodeGeneration + + + false + + + $(IntDir)$(TargetName).lib + MachineX86 + true + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + .\Release/NewStatusNotify.tlb + + + + + /D "_CRT_SECURE_NO_DEPRECATE" +/D "_CRT_NON_CONFORMING_SWPRINTFS" %(AdditionalOptions) + Full + OnlyExplicitInline + Size + true + false + true + ..\..\include\;%(AdditionalIncludeDirectories) + true + Sync + MultiThreadedDLL + true + + + + + $(IntDir) + $(OutDir)$(ProjectName).pdb + Level3 + + + CompileAsCpp + + + + + NDEBUG;%(PreprocessorDefinitions) + 0x0000 + + + /release %(AdditionalOptions) + winmm.lib;comctl32.lib;%(AdditionalDependencies) + NotSet + true + %(AdditionalLibraryDirectories) + + + true + true + true + UseLinkTimeCodeGeneration + + + false + + + $(OutDir)$(ProjectName).lib + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + .\Release/NewStatusNotify.tlb + + + + + /D "_CRT_SECURE_NO_DEPRECATE" +/D "_CRT_NON_CONFORMING_SWPRINTFS" %(AdditionalOptions) + Disabled + ../../include;../../ExternalAPI + WIN32;_WINDOWS;_USRDLL;NewStatusNotify_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + + + Level3 + EditAndContinue + + + NDEBUG;%(PreprocessorDefinitions) + + + comctl32.lib;winmm.lib;%(AdditionalDependencies) + + + + + true + + + + + false + + + $(IntDir)$(TargetName).lib + Windows + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + .\Release/NewStatusNotify.tlb + + + + + /D "_CRT_SECURE_NO_DEPRECATE" +/D "_CRT_NON_CONFORMING_SWPRINTFS" %(AdditionalOptions) + Disabled + Default + false + ..\..\include\;%(AdditionalIncludeDirectories) + WIN32;_WINDOWS;_USRDLL;NewStatusNotify_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + + + $(OutDir) + $(OutDir)$(ProjectName).pdb + true + $(OutDir) + Level3 + ProgramDatabase + CompileAsCpp + + + NDEBUG;%(PreprocessorDefinitions) + 0x0000 + + + comctl32.lib;winmm.lib;%(AdditionalDependencies) + + + true + %(AdditionalLibraryDirectories) + true + $(OutDir)$(ProjectName).map + + + + + false + + + $(OutDir)$(ProjectName).lib + + + + + + $(IntDir)%(Filename)1.obj + $(IntDir)%(Filename)1.obj + $(IntDir)%(Filename)1.obj + $(IntDir)%(Filename)1.obj + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/NewXstatusNotify/NewXstatusNotify_10.vcxproj.filters b/plugins/NewXstatusNotify/NewXstatusNotify_10.vcxproj.filters new file mode 100644 index 0000000000..ac27c23a02 --- /dev/null +++ b/plugins/NewXstatusNotify/NewXstatusNotify_10.vcxproj.filters @@ -0,0 +1,121 @@ + + + + + {a8bf4619-eb52-427c-a9f5-50ea7c6cc9e9} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {db6dcda6-51e6-4dca-99e3-a84ef7eb6a08} + h;hpp;hxx;hm;inl + + + {4ce36c6f-321c-49f3-aeb5-00c9b133ff56} + ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + {f1d6472d-58b0-4381-84de-ee90f6f50830} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Docs + + + Docs + + + Docs + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + + + Resource Files + + + Resource Files + + + \ No newline at end of file diff --git a/plugins/NewXstatusNotify/NewXstatusNotify_9.vcproj b/plugins/NewXstatusNotify/NewXstatusNotify_9.vcproj new file mode 100644 index 0000000000..ae4a1ddb88 --- /dev/null +++ b/plugins/NewXstatusNotify/NewXstatusNotify_9.vcproj @@ -0,0 +1,365 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/NewXstatusNotify/common.h b/plugins/NewXstatusNotify/common.h new file mode 100644 index 0000000000..070bd2a15c --- /dev/null +++ b/plugins/NewXstatusNotify/common.h @@ -0,0 +1,152 @@ +/* + NewXstatusNotify YM - Plugin for Miranda IM + Copyright (c) 2001-2004 Luca Santarelli + Copyright (c) 2005-2007 Vasilich + Copyright (c) 2007-2011 yaho + + 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 COMMON_H +#define COMMON_H + +#pragma once + +#define STRICT +#define WIN32_LEAN_AND_MEAN + +#define _WIN32_WINNT 0x0500 +#define WINVER 0x0600 +#define MIRANDA_VER 0x0A00 + +//Standard Windows "libraries" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "newpluginapi.h" +#include "statusmodes.h" +#include "win2k.h" + +#include "m_awaymsg.h" +#include "m_button.h" +#include "m_clc.h" +#include "m_database.h" +#include "m_genmenu.h" +#include "m_history.h" +#include "m_icolib.h" +#include "m_ignore.h" +#include "m_langpack.h" +#include "m_message.h" +#include "m_options.h" +#include "m_plugins.h" +#include "m_popup.h" +#include "m_protosvc.h" +#include "m_skin.h" +#include "m_system.h" +#include "m_userinfo.h" +#include "m_utils.h" +#include "m_icq.h" + +#include "m_metacontacts.h" +#include "m_updater.h" +#include "m_toolbar.h" +#include "resource.h" + +#if defined _WIN64 +#define MIID_NXSN { 0x16f0674f, 0xc4e7, 0x494e, { 0xb7, 0x5e, 0x41, 0xbb, 0xf4, 0xaf, 0xe6, 0x11 } } +#elif defined _UNICODE +#define MIID_NXSN { 0xebf19652, 0xe434, 0x4d79, { 0x98, 0x97, 0x91, 0xa0, 0xff, 0x22, 0x6f, 0x51 } } +#else +#define MIID_NXSN { 0x90887a8f, 0x9087, 0x44d6, { 0xb4, 0xcc, 0xa6, 0x9d, 0xe0, 0x2e, 0x15, 0x17 } } +#endif + +#define MODULE "NewStatusNotify" + +#define WM_AWAYMSG WM_USER + 0x0192 + +#define MAX_STATUSTEXT 36 +#define MAX_STANDARDTEXT 36 +#define MAX_SKINSOUNDNAME 36 +#define MAX_SKINSOUNDDESC 36 + +#define GENDER_UNSPECIFIED 0 +#define GENDER_MALE 1 +#define GENDER_FEMALE 2 + +#define NOTIFY_INTERVAL_JABBER 2000 +#define NOTIFY_INTERVAL_ICQ 5000 + +#define ID_STATUS_FROMOFFLINE 1 +#define ID_STATUS_EXTRASTATUS 40081 +#define ID_STATUS_MIN ID_STATUS_OFFLINE +#define ID_STATUS_MAX ID_STATUS_OUTTOLUNCH +#define ID_STATUS_MAX2 ID_STATUS_EXTRASTATUS +#define STATUS_COUNT ID_STATUS_MAX2 - ID_STATUS_MIN + 1 +#define Index(ID_STATUS) ID_STATUS - ID_STATUS_OFFLINE + +#define COLOR_BG_AVAILDEFAULT RGB(173,206,247) +#define COLOR_BG_NAVAILDEFAULT RGB(255,189,189) +#define COLOR_TX_DEFAULT RGB(0,0,0) + +#define ICO_NOTIFICATION_OFF "notification_off" +#define ICO_NOTIFICATION_ON "notification_on" + +#define JS_PARSE_XMPP_URI "/ParseXmppURI" + +extern LIST_INTERFACE li; + +typedef struct tagSTATUS +{ + int ID; + int icon; + TCHAR lpzMStatusText[MAX_STATUSTEXT]; + TCHAR lpzFStatusText[MAX_STATUSTEXT]; + TCHAR lpzUStatusText[MAX_STATUSTEXT]; + TCHAR lpzStandardText[MAX_STANDARDTEXT]; + char lpzSkinSoundName[MAX_SKINSOUNDNAME]; + char lpzSkinSoundDesc[MAX_SKINSOUNDDESC]; + char lpzSkinSoundFile[MAX_PATH]; + COLORREF colorBack; + COLORREF colorText; +} STATUS; + +typedef struct tagPLUGINDATA +{ + WORD newStatus; + WORD oldStatus; + HANDLE hAwayMsgProcess; + HANDLE hAwayMsgHook; +} PLUGINDATA; + +/* +HANDLE hContact = (HANDLE)wParam; +WORD oldStatus = LOWORD(lParam); +WORD newStatus = HIWORD(lParam); +oldStatus is the status the contact was before the change. +newStatus is the status the contact is now. +Cast them to (int) if you need them that way. +*/ +#define ME_STATUSCHANGE_CONTACTSTATUSCHANGED "Miranda/StatusChange/ContactStatusChanged" + +#define MS_STATUSCHANGE_MENUCOMMAND "NewStatusNotify/EnableDisableMenuCommand" + +#endif //COMMON_H diff --git a/plugins/NewXstatusNotify/docs/nxsn_readme.txt b/plugins/NewXstatusNotify/docs/nxsn_readme.txt new file mode 100644 index 0000000000..95e868b92d --- /dev/null +++ b/plugins/NewXstatusNotify/docs/nxsn_readme.txt @@ -0,0 +1,127 @@ +******************* +NewXstatusNotify YM +******************* + +Description +=========== +This plugin is modified NewStatusNotify plugin by Vasilich with added extra status +notification and many other features. Plugin shows a popup and logs to a message window +when someone in your contact list changes status, ICQ XStatus or Jabber mood/activity. + + +changelog +********** + +--- 1.4.0.9 --- +! fixed crash on opening message log + +--- 1.4.0.8 --- +! fixed individual sounds +! fixed xstatus notification when contact goes offline +! fixed logging to ML when contact has no extra status +! removed empty line before status message in popup +! fixed bunch of minor bugs + +--- 1.4.0.7 --- ++ added clist modern toolbar support +! fixed stupid bug introduced in the last release + +--- 1.4.0.6 --- ++ option for Read status message can be enabled independently +! fixed crash with dbx_tree +! fixed memory leaks + +--- 1.4.0.5 --- +! fixed buffer overrun + +--- 1.4.0.4 --- +! fixed bug when notification stop working after some time + +--- 1.4.0.3 --- +! fixed duplicated protocols and disappeared contacts after meta contact changes status + +--- 1.4.0.2 --- +! fixed status icon in popup for meta contacts +! workaround for double logged Jabber activity in tabsrmm +! fixed behavior of the Apply button in options +! fixed saving of "enable/disable popup notification" option to db + +--- 1.4.0.1 --- ++ option for disable status description in popup ++ log jabber activity when opening ML +! fixed possible hang of Miranda + +--- 1.4.0.0 --- ++ support for Jabber mood and activity ++ better integration of extra status notification +* major part of code was rewritten +! many fixes and improvements + +--- 1.3.2.1 --- ++ option for disable notifications only for global status changes +! translation fixes + +--- 1.3.2.0 --- ++ added support for Jabber +* automatic close popup after execute click action +* redesigned options pages +* resized individual sounds dialog to fit userinfo window +! fixed notification if 'Disable for XStatus Music' was checked +! fixed disappearing of xstatus log from message log + +--- 1.3.1.3 --- ++ added options for global popups and sounds disabling on defined statuses (Status - Notify -> Configure) +* automatic popups and sounds disabling affect xstatus notifications too +! fixed crash after new mradio 'contact' was added +! fixed wrong size of pluginInfoEx structure (thx eblis) + +--- 1.3.1.2 --- ++ updater support +! some fixes in options + +--- 1.3.1.1 --- +! fixed crash in options + +--- 1.3.1.0 --- ++ support for templates (xstatus module) ++ options for disable notification for xstatus 'Music' ++ options for cut message length to specific number of characters ++ sounds for xstatus message change and xstatus remove +* separate xstatus options for popups and logging to message window +! individual xstatus notification setting available only for protocols that support it +! other fixes and optimalizations + +--- 1.3.0.2 --- +* extended individual contact notification setting (separate status and xstatus notification) + +--- 1.3.0.1 --- ++ option for disable saving to history ++ option for prevent log indentical events + +--- 1.3.0.0 --- +* completely rewrited xstatus module (better integration into the NSN) +* new detection of the xstatus changes (prompt notificaton after change) +* options page redesigned +* many other changes +! fixed Unicode logging to message log +! attempt to fix automatic reading of the status message + +--- 1.2.0.2 --- +! fixed individual sounds + +--- 1.2.0.1 --- +* SVN-sync 677 + - fixed bug which can lead to MIM crash in Clist module (double free) + - finally fixed rightclick on popup + - made unload with destroying created services ("clean exit") + +Symbols used in changelog: + = new / * = changed / ! = fixed + + +Author +====== +mod by yaho -> YM + +ICQ: 356344824 +email: yaho@miranda-easy.net +www: www.miranda-easy.net diff --git a/plugins/NewXstatusNotify/docs/nxsn_translate.txt b/plugins/NewXstatusNotify/docs/nxsn_translate.txt new file mode 100644 index 0000000000..870c41dd56 --- /dev/null +++ b/plugins/NewXstatusNotify/docs/nxsn_translate.txt @@ -0,0 +1,195 @@ +;**************** +;NewStatusNotify +;**************** + +;general strings +;---------------------------- +[You cannot specify a value lower than %d and higher than %d.] +[] +[Can't open the log file!] +[%s is now %s] +[%s, %s. %s changed to: %s (was: %s).\r\n] +[%s, %s. %s changed %s to: %s.\r\n] +[%s, %s. %s removed %s.\r\n] +[Wave Files (*.wav)\0*.WAV\0All Files (*)\0*\0] + +[Status Notify] +[General] +[Notify] +[Popups] +[Status] +[Sounds] +[Events] +[Filtering] +[Extra status] +[Extra status logging] + +[From offline] +[Online] +[Offline] +[Invisible] +[Free for chat] +[Away] +[NA] +[Occupied] +[DND] +[Out to lunch] +[On the phone] +[Always when changing from offline] + +[User: Online] +[User: Offline] +[User: Invisible] +[User: Free For Chat] +[User: Away] +[User: Not Available] +[User: Occupied] +[User: Do Not Disturb] +[User: Out To Lunch] +[User: On The Phone] +[User: from offline (has priority!)] + +[(M) is back online!] +[(F) is back online!] +[(U) is back online!] +[(M) went offline! :(] +[(F) went offline! :(] +[(U) went offline! :(] +[(M) hides in shadows...] +[(F) hides in shadows...] +[(U) hides in shadows...] +[(M) feels talkative!] +[(F) feels talkative!] +[(U) feels talkative!] +[(M) went Away] +[(F) went Away] +[(U) went Away] +[(M) isn't there anymore!] +[(F) isn't there anymore!] +[(U) isn't there anymore!] +[(M) has something else to do.] +[(F) has something else to do.] +[(U) has something else to do.] +[(M) doesn't want to be disturbed!] +[(F) doesn't want to be disturbed!] +[(U) doesn't want to be disturbed!] +[(M) is eating something] +[(F) is eating something] +[(U) is eating something] +[(M) had to answer the phone] +[(F) had to answer the phone] +[(U) had to answer the phone] + +;menu item +;---------------------------- +[Enable status ¬ification] +[Disable status ¬ification] + +;autodisable options +;---------------------------- +[Disable notifications] +[Disable globally] +[Disable when my status is:] +[Disable globally] +[Disable only if I change global status] + +;IDD_OPT_GENERAL +;---------------------------- +[Notify when a contact changes to one of these statuses] +[Plugin activation] +[Automatically turn off PopUps and Sounds on status change] +[Don't warn me for people not in my Contact List] +[Configure] +[Use individual sounds] +[Blink icon in the system tray] +[Use status icon] +[Log to file] +[Enable] +[Open] +[Go to Customize -> Sound to select the sounds] + +;IDD_OPT_FILTERS +;---------------------------- +[** All contacts **] +[Sounds] +[Popups] +[Extra status notify] +[Extra status logging] +[Disable All] +[Enable all] + +;IDD_OPT_XLOG +;---------------------------- +[Log to message window] +[Enable logging to message window] +[Prevent identical logs] +[Keep events in history] +[Disable for extra status 'Music'] +[Truncate message length to:] +[characters] +[Templates] +[New status:] +[New message:] +[Remove:] +[On opening ML:] +[Title - text delimiter:] +[Variables] +[Show available variables] +[Reset all templates to default] +[Reset templates] +[Do you want to reset all templates to default?] + +;IDD_OPT_POPUP +;---------------------------- +[Popups on contact status change to:] +[Background] +[Text] +[Colours] +[Use custom colours] +[Use Popup colours] +[Use Windows colours] +[Popup title] +[Show contact group name] +[Use alternative descriptions] +[Show previous status too] +[Read status message] +[Timeout] +[0 = Default] +[-1 = Infinite] +[Click action] +[On left click] +[On right click] +[Open message window] +[Close popup] +[Open contact details window] +[Open contact menu] +[Open contact history] +[Do nothing] +[Preview] +[This is \"from offline\" status message] + +;user options page +;---------------------------- +[Sound for the status] +[(default sound)] +[Change] +[Preview] +[Delete] +[Enable popups] +[Enable sounds] +[Individual sounds are disabled.\n\nTo enable them, go to Options - Status - Notify, enable \n""Use individual sounds"" checkbox, and then reopen this dialog.] + +;default templates +;---------------------------- +[changed %N to: %T%D%I] +[changed %N message to:%D%I] +[removed %N] +[changed %N @ %T%D%I] +[changed %N message @ %I] +[has %N @ %T%D%I] +[These variables are available:\r\n\r\n\ +%N\textra status name (Xstatus, Mood, Activity)\r\n\ +%T\textra status title\r\n\ +%I\textra status text\r\n\ +%D\tdelimiter\r\n\ +%B\tline break (can be used as delimiter)] \ No newline at end of file diff --git a/plugins/NewXstatusNotify/indsnd.cpp b/plugins/NewXstatusNotify/indsnd.cpp new file mode 100644 index 0000000000..2934c25256 --- /dev/null +++ b/plugins/NewXstatusNotify/indsnd.cpp @@ -0,0 +1,681 @@ +/* + NewXstatusNotify YM - Plugin for Miranda IM + Copyright (c) 2001-2004 Luca Santarelli + Copyright (c) 2005-2007 Vasilich + Copyright (c) 2007-2011 yaho + + 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 "options.h" +#include "indsnd.h" +#include "utils.h" + +extern STATUS StatusList[]; +extern OPTIONS opt; +extern HINSTANCE hInst; + +void PreviewSound(HWND hList) +{ + TCHAR buff[MAX_PATH], stzSoundPath[MAX_PATH]; + + LVITEM lvi = {0}; + lvi.mask = LVIF_PARAM; + lvi.iItem = ListView_GetNextItem(hList, -1, LVNI_SELECTED); + ListView_GetItem(hList, &lvi); + + int hlpStatus = lvi.lParam; + + ListView_GetItemText(hList, lvi.iItem, 1, buff, SIZEOF(buff)); + if (_tcscmp(buff, TranslateT(DEFAULT_SOUND)) == 0) + { + if (hlpStatus == ID_STATUS_FROMOFFLINE) + SkinPlaySound("UserFromOffline"); + else + SkinPlaySound(StatusList[Index(hlpStatus)].lpzSkinSoundName); + } + else + { + CallService(MS_UTILS_PATHTOABSOLUTET, (WPARAM)buff, (LPARAM)stzSoundPath); + PlaySound(stzSoundPath, NULL, SND_ASYNC | SND_FILENAME); + } +} + +BOOL RemoveSoundFromList(HWND hList) +{ + int iSel = ListView_GetSelectionMark(hList); + if (iSel != -1) + { + iSel = -1; + while ((iSel = ListView_GetNextItem(hList, iSel, LVNI_SELECTED)) != -1) + ListView_SetItemText(hList, iSel, 1, TranslateT(DEFAULT_SOUND)); + return TRUE; + } + + return FALSE; +} + +TCHAR *SelectSound(HWND hwndDlg, TCHAR *buff) +{ + OPENFILENAME ofn = {0}; + + HWND hList = GetDlgItem(hwndDlg, IDC_INDSNDLIST); + ListView_GetItemText(hList, ListView_GetNextItem(hList,- 1, LVNI_SELECTED), 1, buff, SIZEOF(buff)); + + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = GetParent(hwndDlg); + ofn.hInstance = hInst; + TCHAR filter[MAX_PATH]; + mir_sntprintf(filter, SIZEOF(filter), _T("%s (*.wav)%c*.WAV%c%s (*.*)%c*%c"), TranslateT("Wave Files"), 0, 0, TranslateT("All Files"), 0, 0); + ofn.lpstrFilter = filter; + ofn.lpstrFile = buff; + ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_EXPLORER | OFN_NOCHANGEDIR; + ofn.nMaxFile = MAX_PATH; + ofn.nMaxFileTitle = MAX_PATH; + ofn.lpstrDefExt = _T("wav"); + if (GetOpenFileName(&ofn)) + return buff; + + return NULL; +} + +HIMAGELIST GetStatusIconsImgList(char *szProto) +{ + HIMAGELIST hList = NULL; + if (szProto) + { + hList = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), IsWinVerXPPlus() ? ILC_COLOR32 : ILC_COLOR16 | ILC_MASK, STATUS_COUNT, 0); + if (hList != NULL) + { + for (int i = ID_STATUS_MIN; i <= ID_STATUS_MAX; i++) + ImageList_AddIcon(hList, LoadSkinnedProtoIcon(szProto, StatusList[Index(i)].ID)); + ImageList_AddIcon(hList, LoadSkinnedIcon(SKINICON_OTHER_USERONLINE)); + } + } + + return hList; +} + +INT_PTR CALLBACK DlgProcSoundUIPage(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static HANDLE hContact = NULL; + switch (msg) + { + case WM_INITDIALOG: + { + TranslateDialogDefault(hwndDlg); + + hContact = (HANDLE)lParam; + char *szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + HWND hList = GetDlgItem(hwndDlg, IDC_INDSNDLIST); + + ListView_SetImageList(hList, GetStatusIconsImgList(szProto), LVSIL_SMALL); + ListView_SetExtendedListViewStyleEx(hList, LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP, LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP); + + RECT rc = {0}; + GetClientRect(hList, &rc); + + LV_COLUMN lvc = {0}; + lvc.mask = LVCF_WIDTH | LVCF_TEXT; + lvc.cx = STATUS_COLUMN; + lvc.pszText = TranslateT("Status"); + ListView_InsertColumn(hList, 0, &lvc); + + lvc.cx = rc.right - STATUS_COLUMN - GetSystemMetrics(SM_CXVSCROLL); + lvc.pszText = TranslateT("Sound for the status"); + ListView_InsertColumn(hList, 1, &lvc); + + if (szProto) + { + DBVARIANT dbv; + TCHAR buff[MAX_PATH]; + + for (int i = ID_STATUS_MAX; i >= ID_STATUS_MIN; i--) + { + int flags = CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_2, 0); + if (flags == 0) + flags = PF2_ONLINE|PF2_INVISIBLE|PF2_SHORTAWAY|PF2_LONGAWAY|PF2_LIGHTDND|PF2_HEAVYDND|PF2_FREECHAT|PF2_OUTTOLUNCH|PF2_ONTHEPHONE; + + if ((flags & Proto_Status2Flag(i)) || i == ID_STATUS_OFFLINE) + { + LV_ITEM lvi = {0}; + lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE; + lvi.iItem = 0; + lvi.iSubItem = 0; + lvi.iImage = Index(i); + lvi.lParam = (LPARAM)i; + lvi.pszText = TranslateTS(StatusList[Index(i)].lpzStandardText); + lvi.iItem = ListView_InsertItem(hList, &lvi); + + if (!DBGetContactSettingTString(hContact, MODULE, StatusList[Index(i)].lpzSkinSoundName, &dbv)) + { + _tcscpy(buff, dbv.ptszVal); + DBFreeVariant(&dbv); + } + else + _tcscpy(buff, TranslateT(DEFAULT_SOUND)); + + ListView_SetItemText(hList, lvi.iItem, 1, buff); + } + } + + LV_ITEM lvi = {0}; + lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE; + lvi.iItem = 0; + lvi.iSubItem = 0; + lvi.iImage = Index(ID_STATUS_MAX) + 1; // additional icon + lvi.lParam = (LPARAM)ID_STATUS_FROMOFFLINE; + lvi.pszText = TranslateT("From offline"); + lvi.iItem = ListView_InsertItem(hList, &lvi); + + if (!DBGetContactSettingTString(hContact, MODULE, "UserFromOffline", &dbv)) + { + _tcscpy(buff, dbv.ptszVal); + DBFreeVariant(&dbv); + } + else + _tcscpy(buff, TranslateT(DEFAULT_SOUND)); + + ListView_SetItemText(hList, lvi.iItem, 1, buff); + } + + CheckDlgButton(hwndDlg, IDC_CHECK_NOTIFYSOUNDS, DBGetContactSettingByte(hContact, MODULE, "EnableSounds", 1)); + CheckDlgButton(hwndDlg, IDC_CHECK_NOTIFYPOPUPS, DBGetContactSettingByte(hContact, MODULE, "EnablePopups", 1)); + + ShowWindow(GetDlgItem(hwndDlg, IDC_INDSNDLIST), opt.UseIndSnd ? SW_SHOW : SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_TEXT_ENABLE_IS), opt.UseIndSnd ? SW_HIDE : SW_SHOW); + ShowWindow(GetDlgItem(hwndDlg, IDC_CHANGE), opt.UseIndSnd ? SW_SHOW : SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_PREVIEW), opt.UseIndSnd ? SW_SHOW : SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_DELETE), opt.UseIndSnd ? SW_SHOW : SW_HIDE); + + return TRUE; + } + case WM_COMMAND: + { + switch (LOWORD(wParam)) + { + case IDC_PREVIEW: + { + HWND hList = GetDlgItem(hwndDlg, IDC_INDSNDLIST); + if (ListView_GetSelectionMark(hList) != -1) + PreviewSound(hList); + break; + } + case IDC_CHANGE: + { + HWND hList = GetDlgItem(hwndDlg, IDC_INDSNDLIST); + int iSel = ListView_GetNextItem(GetDlgItem(hwndDlg, IDC_INDSNDLIST), -1, LVNI_SELECTED); + if (iSel != -1) + { + TCHAR stzFilePath[MAX_PATH]; + if (SelectSound(hwndDlg, stzFilePath) != NULL) + { + iSel = -1; + while ((iSel = ListView_GetNextItem(hList, iSel, LVNI_SELECTED)) != -1) + ListView_SetItemText(hList, iSel, 1, stzFilePath); + + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + } + break; + } + case IDC_DELETE: + { + HWND hList = GetDlgItem(hwndDlg, IDC_INDSNDLIST); + if (ListView_GetSelectionMark(hList) != -1) + { + if (RemoveSoundFromList(GetDlgItem(hwndDlg, IDC_INDSNDLIST))) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + break; + } + case IDC_CHECK_NOTIFYSOUNDS: + { + DBWriteContactSettingByte(hContact, MODULE, "EnableSounds", IsDlgButtonChecked(hwndDlg, IDC_CHECK_NOTIFYSOUNDS) ? 1 : 0); + break; + } + case IDC_CHECK_NOTIFYPOPUPS: + { + DBWriteContactSettingByte(hContact, MODULE, "EnablePopups", IsDlgButtonChecked(hwndDlg, IDC_CHECK_NOTIFYPOPUPS) ? 1 : 0); + break; + } + } + break; + } + case WM_NOTIFY: + { + LPNMHDR pParam = (LPNMHDR)lParam; + if (pParam->code == PSN_APPLY) + { + TCHAR buff[MAX_PATH]; + HWND hList = GetDlgItem(hwndDlg, IDC_INDSNDLIST); + + LVITEM lvi = {0}; + lvi.mask = LVIF_PARAM; + //Cycle through the list reading the text associated to each status. + for (lvi.iItem = ListView_GetItemCount(hList) - 1; lvi.iItem >= 0; lvi.iItem--) + { + ListView_GetItem(hList, &lvi); + ListView_GetItemText(hList, lvi.iItem, 1, buff, SIZEOF(buff)); + + if (!_tcscmp(buff, TranslateT(DEFAULT_SOUND))) + { + if (lvi.lParam == ID_STATUS_FROMOFFLINE) + DBDeleteContactSetting(hContact, MODULE, "UserFromOffline"); + else + DBDeleteContactSetting(hContact, MODULE, StatusList[Index(lvi.lParam)].lpzSkinSoundName); + } + else + { + TCHAR stzSoundPath[MAX_PATH] = { 0 }; + CallService(MS_UTILS_PATHTORELATIVET, (WPARAM)buff, (LPARAM)stzSoundPath); + if (lvi.lParam == ID_STATUS_FROMOFFLINE) + DBWriteContactSettingTString(hContact, MODULE, "UserFromOffline", stzSoundPath); + else + DBWriteContactSettingTString(hContact, MODULE, StatusList[Index(lvi.lParam)].lpzSkinSoundName, stzSoundPath); + } + } + + return TRUE; + } + + int hlpControlID = (int)wParam; + switch (hlpControlID) + { + case IDC_INDSNDLIST: + { + if (pParam->code == NM_DBLCLK) + { + TCHAR stzFilePath[MAX_PATH]; + if (SelectSound(hwndDlg, stzFilePath) != NULL) + { + int iSel = -1; + HWND hList = GetDlgItem(hwndDlg, IDC_INDSNDLIST); + while ((iSel = ListView_GetNextItem(hList, iSel, LVNI_SELECTED)) != -1) + ListView_SetItemText(hList, iSel, 1, stzFilePath); + + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + return TRUE; + } + else if (pParam->code == LVN_KEYDOWN) + { + LPNMLVKEYDOWN pnkd = (LPNMLVKEYDOWN)lParam; + if (pnkd->wVKey == VK_DELETE) + RemoveSoundFromList(GetDlgItem(hwndDlg, IDC_INDSNDLIST)); + } + + break; + } + } + break; + } + } + return FALSE; +} + +int UserInfoInitialise(WPARAM wParam, LPARAM lParam) +{ + if (lParam == NULL) + return 0; + + OPTIONSDIALOGPAGE odp = {0}; + odp.cbSize = sizeof(odp); + odp.position = 100000000; + odp.hInstance = hInst; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_INFO_SOUNDS); + odp.pszTitle = LPGEN("Status Notify"); + odp.pfnDlgProc = DlgProcSoundUIPage; + CallService(MS_USERINFO_ADDPAGE, wParam, (LPARAM)&odp); + + return 0; +} + +void ResetListOptions(HWND hwndList) +{ + SendMessage(hwndList, CLM_SETBKBITMAP, 0, (LPARAM)NULL); + SendMessage(hwndList, CLM_SETBKCOLOR, GetSysColor(COLOR_WINDOW), 0); + SendMessage(hwndList, CLM_SETGREYOUTFLAGS, 0, 0); + SendMessage(hwndList, CLM_SETLEFTMARGIN, 4, 0); + SendMessage(hwndList, CLM_SETINDENT, 10, 0); + + for (int i = 0; i <= FONTID_MAX; i++) + SendMessage(hwndList, CLM_SETTEXTCOLOR, i, GetSysColor(COLOR_WINDOWTEXT)); + + SetWindowLong(hwndList, GWL_STYLE, GetWindowLong(hwndList,GWL_STYLE) | CLS_SHOWHIDDEN); +} + +__inline int GetExtraImage(HWND hwndList, HANDLE hItem, int column) +{ + return SendMessage(hwndList, CLM_GETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(column, 0)); +} + +__inline void SetExtraImage(HWND hwndList, HANDLE hItem, int column, int imageID) +{ + SendMessage(hwndList, CLM_SETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(column, imageID)); +} + +void SetAllContactsIcons(HWND hwndList) +{ + BYTE EnableSounds, EnablePopups, EnableXStatus, EnableLogging; + HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + while (hContact) + { + HANDLE hItem = (HANDLE)SendMessage(hwndList, CLM_FINDCONTACT, (WPARAM)hContact, 0); + if (hItem) + { + char *szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO,(WPARAM)hContact,0); + if (szProto) + { + EnableSounds = DBGetContactSettingByte(hContact, MODULE, "EnableSounds", 1); + EnablePopups = DBGetContactSettingByte(hContact, MODULE, "EnablePopups", 1); + EnableXStatus = DBGetContactSettingByte(hContact, MODULE, "EnableXStatusNotify", 1); + EnableLogging = DBGetContactSettingByte(hContact, MODULE, "EnableLogging", 1); + } + else + EnableSounds = EnablePopups = EnableXStatus = EnableLogging = 0; + + SetExtraImage(hwndList, hItem, EXTRA_IMAGE_SOUND, EnableSounds ? EXTRA_IMAGE_SOUND : EXTRA_IMAGE_DOT); + SetExtraImage(hwndList, hItem, EXTRA_IMAGE_POPUP, EnablePopups? EXTRA_IMAGE_POPUP : EXTRA_IMAGE_DOT); + SetExtraImage(hwndList, hItem, EXTRA_IMAGE_XSTATUS, EnableXStatus ? EXTRA_IMAGE_XSTATUS : EXTRA_IMAGE_DOT); + SetExtraImage(hwndList, hItem, EXTRA_IMAGE_LOGGING, EnableLogging ? EXTRA_IMAGE_LOGGING : EXTRA_IMAGE_DOT); + SetExtraImage(hwndList, hItem, EXTRA_IMAGE_DISABLEALL, EXTRA_IMAGE_DISABLEALL); + SetExtraImage(hwndList, hItem, EXTRA_IMAGE_ENABLEALL, EXTRA_IMAGE_ENABLEALL); + } + + hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0); + } +} + +void SetGroupsIcons(HWND hwndList, HANDLE hFirstItem, HANDLE hParentItem, int *groupChildCount) +{ + int iconOn[6] = {1,1,1,1,1,1}; + int childCount[6] = {0}; + HANDLE hItem; + + int typeOfFirst = SendMessage(hwndList, CLM_GETITEMTYPE, (WPARAM)hFirstItem, 0); + if (typeOfFirst == CLCIT_GROUP) + hItem = hFirstItem; + else + hItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXTGROUP, (LPARAM)hFirstItem); + + while (hItem) + { + HANDLE hChildItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_CHILD, (LPARAM)hItem); + if (hChildItem) + SetGroupsIcons(hwndList, hChildItem, hItem, childCount); + + for (int i = 0; i < SIZEOF(iconOn); i++) + { + if (iconOn[i] && GetExtraImage(hwndList, hItem, i) == EXTRA_IMAGE_DOT) + iconOn[i] = 0; + } + + hItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXTGROUP, (LPARAM)hItem); + } + + //check contacts + if (typeOfFirst == CLCIT_CONTACT) + hItem = hFirstItem; + else + hItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXTCONTACT, (LPARAM)hFirstItem); + + while(hItem) + { + for (int i = 0; i < SIZEOF(iconOn); i++) + { + int image = GetExtraImage(hwndList, hItem, i); + if (iconOn[i] && image == EXTRA_IMAGE_DOT) + iconOn[i] = 0; + + if (image != EXTRA_IMAGE_BLANK) + childCount[i]++; + } + + hItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXTCONTACT, (LPARAM)hItem); + } + + //set icons + for(int i = 0; i < SIZEOF(iconOn); i++) + { + SetExtraImage(hwndList, hParentItem, i, childCount[i] ? (iconOn[i] ? i : EXTRA_IMAGE_DOT) : EXTRA_IMAGE_BLANK); + if (groupChildCount) + groupChildCount[i] += childCount[i]; + } +} + +void SetAllChildrenIcons(HWND hwndList, HANDLE hFirstItem, int column, int image) +{ + HANDLE hItem, hChildItem; + + int typeOfFirst = SendMessage(hwndList, CLM_GETITEMTYPE, (WPARAM)hFirstItem, 0); + if (typeOfFirst == CLCIT_GROUP) + hItem = hFirstItem; + else + hItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXTGROUP, (LPARAM)hFirstItem); + + while(hItem) + { + hChildItem = (HANDLE)SendMessage(hwndList ,CLM_GETNEXTITEM, CLGN_CHILD, (LPARAM)hItem); + if (hChildItem) + SetAllChildrenIcons(hwndList, hChildItem, column, image); + + hItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXTGROUP, (LPARAM)hItem); + } + + if (typeOfFirst == CLCIT_CONTACT) + hItem = hFirstItem; + else + hItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXTCONTACT, (LPARAM)hFirstItem); + + while(hItem) + { + int oldIcon = GetExtraImage(hwndList, hItem, column); + if (oldIcon != EXTRA_IMAGE_BLANK && oldIcon != image) + SetExtraImage(hwndList, hItem, column, image); + + hItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXTCONTACT, (LPARAM)hItem); + } +} + +INT_PTR CALLBACK DlgProcFiltering(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static HANDLE hItemAll; + switch (msg) + { + case WM_INITDIALOG: + { + TranslateDialogDefault(hwndDlg); + + HIMAGELIST hImageList = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), IsWinVerXPPlus() ? ILC_COLOR32 : ILC_COLOR16 | ILC_MASK, 3, 3); + + ImageList_AddIcon(hImageList, LoadIcon(hInst,MAKEINTRESOURCE(IDI_SOUND))); + SendDlgItemMessage(hwndDlg,IDC_SOUNDICON,STM_SETICON, (WPARAM)ImageList_GetIcon(hImageList, EXTRA_IMAGE_SOUND, ILD_NORMAL), 0); + ImageList_AddIcon(hImageList, LoadIcon(hInst, MAKEINTRESOURCE(IDI_POPUP))); + SendDlgItemMessage(hwndDlg, IDC_POPUPICON, STM_SETICON, (WPARAM)ImageList_GetIcon(hImageList, EXTRA_IMAGE_POPUP, ILD_NORMAL), 0); + ImageList_AddIcon(hImageList, LoadIcon(hInst,MAKEINTRESOURCE(IDI_XSTATUS))); + SendDlgItemMessage(hwndDlg, IDC_XSTATUSICON, STM_SETICON, (WPARAM)ImageList_GetIcon(hImageList, EXTRA_IMAGE_XSTATUS, ILD_NORMAL), 0); + ImageList_AddIcon(hImageList, LoadIcon(hInst,MAKEINTRESOURCE(IDI_LOGGING))); + SendDlgItemMessage(hwndDlg, IDC_LOGGINGICON, STM_SETICON, (WPARAM)ImageList_GetIcon(hImageList, EXTRA_IMAGE_LOGGING, ILD_NORMAL), 0); + ImageList_AddIcon(hImageList, LoadIcon(hInst,MAKEINTRESOURCE(IDI_DISABLEALL))); + SendDlgItemMessage(hwndDlg, IDC_DISABLEALLICON, STM_SETICON, (WPARAM)ImageList_GetIcon(hImageList, EXTRA_IMAGE_DISABLEALL, ILD_NORMAL), 0); + ImageList_AddIcon(hImageList, LoadIcon(hInst,MAKEINTRESOURCE(IDI_ENABLEALL))); + SendDlgItemMessage(hwndDlg, IDC_ENABLEALLICON, STM_SETICON, (WPARAM)ImageList_GetIcon(hImageList, EXTRA_IMAGE_ENABLEALL, ILD_NORMAL), 0); + + ImageList_AddIcon(hImageList, LoadSkinnedIcon(SKINICON_OTHER_SMALLDOT)); + + SendDlgItemMessage(hwndDlg, IDC_INDSNDLIST, CLM_SETEXTRAIMAGELIST, 0, (LPARAM)hImageList); + SendDlgItemMessage(hwndDlg, IDC_INDSNDLIST, CLM_SETEXTRACOLUMNS, 6, 0); + + HWND hList = GetDlgItem(hwndDlg, IDC_INDSNDLIST); + ResetListOptions(hList); + + CLCINFOITEM cii = {0}; + cii.cbSize = sizeof(cii); + cii.flags = CLCIIF_GROUPFONT; + cii.pszText = TranslateT("** All contacts **"); + hItemAll = (HANDLE)SendDlgItemMessage(hwndDlg, IDC_INDSNDLIST, CLM_ADDINFOITEM, 0, (LPARAM)&cii); + + return TRUE; + } + case WM_SETFOCUS: + { + SetFocus(GetDlgItem(hwndDlg, IDC_INDSNDLIST)); + break; + } + case WM_NOTIFY: + { + HWND hList = GetDlgItem(hwndDlg, IDC_INDSNDLIST); + switch(((LPNMHDR)lParam)->idFrom) + { + case IDC_INDSNDLIST: + switch (((LPNMHDR)lParam)->code) + { + case CLN_NEWCONTACT: + case CLN_LISTREBUILT: + SetAllContactsIcons(hList); + //fall through + case CLN_CONTACTMOVED: + SetGroupsIcons(hList, (HANDLE)SendMessage(hList, CLM_GETNEXTITEM, CLGN_ROOT, 0), hItemAll, NULL); + break; + case CLN_OPTIONSCHANGED: + ResetListOptions(hList); + break; + case NM_CLICK: + { + NMCLISTCONTROL *nm = (NMCLISTCONTROL*)lParam; + DWORD hitFlags; + + // Make sure we have an extra column + if (nm->iColumn == -1) break; + + // Find clicked item + HANDLE hItem = (HANDLE)SendMessage(hList, CLM_HITTEST, (WPARAM)&hitFlags, MAKELPARAM(nm->pt.x, nm->pt.y)); + if (hItem == NULL) break; + if(!(hitFlags & CLCHT_ONITEMEXTRA)) break; + + int itemType = SendMessage(hList, CLM_GETITEMTYPE, (WPARAM)hItem, 0); + + // Get image in clicked column + int image = GetExtraImage(hList, hItem, nm->iColumn); + if (image == EXTRA_IMAGE_DOT) + image = nm->iColumn; + else if (image >= EXTRA_IMAGE_SOUND && image <= EXTRA_IMAGE_LOGGING) + image = EXTRA_IMAGE_DOT; + + // Get item type (contact, group, etc...) + if (itemType == CLCIT_CONTACT) + { + if (image == EXTRA_IMAGE_DISABLEALL) + { + for (int i = 0; i < 4; i++) + SetExtraImage(hList, hItem, i, EXTRA_IMAGE_DOT); + } + else if (image == EXTRA_IMAGE_ENABLEALL) + { + for (int i = 0; i < 4; i++) + SetExtraImage(hList, hItem, i, i); + } + else + { + SetExtraImage(hList, hItem, nm->iColumn, image); + } + } + else if (itemType == CLCIT_INFO || itemType == CLCIT_GROUP) + { + if (itemType == CLCIT_GROUP) + hItem = (HANDLE)SendMessage(hList, CLM_GETNEXTITEM, CLGN_CHILD, (LPARAM)hItem); + + if (hItem) + { + if (image == EXTRA_IMAGE_DISABLEALL) + { + for (int i = 0; i < 4; i++) + SetAllChildrenIcons(hList, hItem, i, EXTRA_IMAGE_DOT); + } + else if (image == EXTRA_IMAGE_ENABLEALL) + { + for (int i = 0; i < 4; i++) + SetAllChildrenIcons(hList, hItem, i, i); + } + else + { + SetAllChildrenIcons(hList, hItem, nm->iColumn, image); + } + } + } + + // Update the all/none icons + SetGroupsIcons(hList, (HANDLE)SendMessage(hList, CLM_GETNEXTITEM, CLGN_ROOT, 0), hItemAll, NULL); + // Activate Apply button + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + } + } + break; + case 0: + switch (((LPNMHDR)lParam)->code) + { + case PSN_APPLY: + { + HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + do + { + HANDLE hItem = (HANDLE)SendMessage(hList, CLM_FINDCONTACT, (WPARAM)hContact, 0); + if (hItem) + { + if (GetExtraImage(hList, hItem, EXTRA_IMAGE_SOUND) == EXTRA_IMAGE_SOUND) + DBDeleteContactSetting(hContact, MODULE, "EnableSounds"); + else + DBWriteContactSettingByte(hContact, MODULE, "EnableSounds", 0); + + if (GetExtraImage(hList, hItem, EXTRA_IMAGE_POPUP) == EXTRA_IMAGE_POPUP) + DBDeleteContactSetting(hContact, MODULE, "EnablePopups"); + else + DBWriteContactSettingByte(hContact, MODULE, "EnablePopups", 0); + + if(GetExtraImage(hList, hItem, EXTRA_IMAGE_XSTATUS) == EXTRA_IMAGE_XSTATUS) + DBDeleteContactSetting(hContact, MODULE, "EnableXStatusNotify"); + else + DBWriteContactSettingByte(hContact, MODULE, "EnableXStatusNotify", 0); + + if (GetExtraImage(hList, hItem, EXTRA_IMAGE_LOGGING) == EXTRA_IMAGE_LOGGING) + DBDeleteContactSetting(hContact, MODULE, "EnableLogging"); + else + DBWriteContactSettingByte(hContact, MODULE, "EnableLogging", 0); + + } + } while(hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0)); + + return TRUE; + } + } + break; + } + break; + } + case WM_DESTROY: + { + HIMAGELIST hImageList = (HIMAGELIST)SendMessage(GetDlgItem(hwndDlg, IDC_INDSNDLIST), CLM_GETEXTRAIMAGELIST, 0, 0); + for (int i = 0; i < ImageList_GetImageCount(hImageList); i++) + DestroyIcon(ImageList_GetIcon(hImageList, i, ILD_NORMAL)); + ImageList_Destroy(hImageList); + break; + } + } + return FALSE; +} + diff --git a/plugins/NewXstatusNotify/indsnd.h b/plugins/NewXstatusNotify/indsnd.h new file mode 100644 index 0000000000..c4dde34ea1 --- /dev/null +++ b/plugins/NewXstatusNotify/indsnd.h @@ -0,0 +1,41 @@ +/* + NewXstatusNotify YM - Plugin for Miranda IM + Copyright (c) 2001-2004 Luca Santarelli + Copyright (c) 2005-2007 Vasilich + Copyright (c) 2007-2011 yaho + + 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 INDSND_H +#define INDSND_H + +#define EXTRA_IMAGE_SOUND 0 +#define EXTRA_IMAGE_POPUP 1 +#define EXTRA_IMAGE_XSTATUS 2 +#define EXTRA_IMAGE_LOGGING 3 +#define EXTRA_IMAGE_DISABLEALL 4 +#define EXTRA_IMAGE_ENABLEALL 5 +#define EXTRA_IMAGE_DOT 6 +#define EXTRA_IMAGE_BLANK 0xFF + +#define STATUS_COLUMN 110 + +#define DEFAULT_SOUND "(default sound)" + +int UserInfoInitialise(WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK DlgProcFiltering(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); + +#endif \ No newline at end of file diff --git a/plugins/NewXstatusNotify/main.cpp b/plugins/NewXstatusNotify/main.cpp new file mode 100644 index 0000000000..419018be95 --- /dev/null +++ b/plugins/NewXstatusNotify/main.cpp @@ -0,0 +1,1458 @@ +/* + NewXstatusNotify YM - Plugin for Miranda IM + Copyright (c) 2001-2004 Luca Santarelli + Copyright (c) 2005-2007 Vasilich + Copyright (c) 2007-2011 yaho + + 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 "indsnd.h" +#include "options.h" +#include "popup.h" +#include "utils.h" +#include "version.h" +#include "xstatus.h" + +HINSTANCE hInst; +PLUGINLINK *pluginLink; + +MM_INTERFACE mmi = {0}; +UTF8_INTERFACE utfi = {0}; +LIST_INTERFACE li = {0}; + +SortedList *eventList; +SortedList *xstatusList; + +HANDLE hEnableDisableMenu, hOptionsInitialize, hModulesLoaded, hUserInfoInitialise; +HANDLE hContactSettingChanged, hHookContactStatusChanged, hContactStatusChanged; +HANDLE hStatusModeChange, hServiceMenu, hProtoAck; +HANDLE hMessageWindowOpen; + +char szMetaModuleName[256] = {0}; +STATUS StatusList[STATUS_COUNT]; +DWORD LoadTime = 0; +int hLangpack; + +extern OPTIONS opt; + +PLUGININFOEX pluginInfoEx = { + sizeof(PLUGININFOEX), +#ifdef _UNICODE + #ifdef _WIN64 + "NewXstatusNotify YM (Unicode x64) Mataes Release", + #else + "NewXstatusNotify YM (Unicode) Mataes Release", + #endif +#else + "NewXstatusNotify YM Mataes Release", +#endif + __VERSION_DWORD, + "Notifies you when a contact changes his/her (X)status or status message.", + "Luca Santarelli, Vasilich, yaho", + "yaho@miranda-easy.net", + "© 2001-2004 Luca Santarelli, 2005-2007 Vasilich, 2007-2011 yaho", + "http://miranda-easy.net/mods.php", + UNICODE_AWARE, + DEFMOD_RNDUSERONLINE, + MIID_NXSN +}; + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + hInst = hinstDLL; + DisableThreadLibraryCalls(hInst); + return TRUE; +} + +extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion) +{ + if (mirandaVersion < PLUGIN_MAKE_VERSION(0, 9, 0, 0)) + return NULL; + + return &pluginInfoEx; +} + +static const MUUID interfaces[] = {MIID_USERONLINE, MIID_LAST}; +extern "C" __declspec(dllexport) const MUUID* MirandaPluginInterfaces(void) +{ + return interfaces; +} + +BYTE GetGender(HANDLE hContact) +{ + char *szProto =(char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + if (szProto) + { + switch (DBGetContactSettingByte(hContact, szProto, "Gender", 0)) + { + case 'M': case 'm': + return GENDER_MALE; + case 'F': case 'f': + return GENDER_FEMALE; + default: + return GENDER_UNSPECIFIED; + } + } + + return GENDER_UNSPECIFIED; +} + +HANDLE GetIconHandle(char *szIcon) +{ + char szSettingName[64]; + mir_snprintf(szSettingName, sizeof(szSettingName), "%s_%s", MODULE, szIcon); + return (HANDLE)CallService(MS_SKIN2_GETICONHANDLE, 0, (LPARAM)szSettingName); +} + +__inline void AddXSC(XSTATUSCHANGE *xsc) +{ + li.List_Insert(xstatusList, xsc, xstatusList->realCount); +} + +__inline void RemoveXSC(XSTATUSCHANGE *xsc) +{ + int id = li.List_IndexOf(xstatusList, xsc); + if (id != -1) + li.List_Remove(xstatusList, id); +} + +XSTATUSCHANGE *FindXSC(HANDLE hContact) +{ + XSTATUSCHANGE *xsc; + for (int i = 0; i < xstatusList->realCount; i++) + { + xsc = (XSTATUSCHANGE *)xstatusList->items[i]; + if (xsc->hContact == hContact) + return xsc; + } + + return NULL; +} + +XSTATUSCHANGE *FindAndRemoveXSC(HANDLE hContact) +{ + XSTATUSCHANGE *result = FindXSC(hContact); + if (result) RemoveXSC(result); + return result; +} + +bool IsNewExtraStatus(HANDLE hContact, char *szSetting, TCHAR *newStatusTitle) +{ + DBVARIANT dbv; + bool result = true; + + if (!DBGetContactSettingTString(hContact, MODULE, szSetting, &dbv)) + { + result = _tcscmp(newStatusTitle, dbv.ptszVal) ? true : false; + DBFreeVariant(&dbv); + } + + return result; +} + +int ProcessExtraStatus(DBCONTACTWRITESETTING *cws, HANDLE hContact) +{ + XSTATUSCHANGE *xsc; + char *szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + + if (ProtoServiceExists(szProto, JS_PARSE_XMPP_URI)) + { + if (cws->value.type == DBVT_DELETED) + return 0; + + if (strstr(cws->szSetting, "/mood/") || strstr(cws->szSetting, "/activity/")) // Jabber mood or activity changed + { + char *szSetting; + int type; + + if (strstr(cws->szSetting, "/mood/")) + { + type = TYPE_JABBER_MOOD; + szSetting = "LastJabberMood"; + } + else + { + type = TYPE_JABBER_ACTIVITY; + szSetting = "LastJabberActivity"; + } + + if (strstr(cws->szSetting, "title")) + { + TCHAR *stzValue = db2t(&cws->value); + if (stzValue) + { + if (!IsNewExtraStatus(hContact, szSetting, stzValue)) + { + mir_free(stzValue); + return 0; + } + + xsc = NewXSC(hContact, szProto, type, NOTIFY_NEW_XSTATUS, stzValue, NULL); + DBWriteContactSettingTString(hContact, MODULE, szSetting, stzValue); + } + else + { + xsc = NewXSC(hContact, szProto, type, NOTIFY_REMOVE, NULL, NULL); + DBWriteContactSettingTString(hContact, MODULE, szSetting, _T("")); + } + + AddXSC(xsc); + if (xsc != NULL) + { + ExtraStatusChanged(xsc); + FreeXSC(xsc); + } + } + else if (strstr(cws->szSetting, "text")) + { + xsc = FindAndRemoveXSC(hContact); + TCHAR *stzValue = db2t(&cws->value); + if (stzValue) + { + if (xsc != NULL) + xsc->stzText = stzValue; + else + xsc = NewXSC(hContact, szProto, type, NOTIFY_NEW_MESSAGE, NULL, stzValue); + } + + if (xsc != NULL) + { + ExtraStatusChanged(xsc); + FreeXSC(xsc); + } + } + + return 1; + } + } + else if (strstr(cws->szSetting, "XStatus") || strcmp(cws->szSetting, "StatusNote") == 0) + { + if (strcmp(cws->szSetting, "XStatusName") == 0) + { + xsc = FindAndRemoveXSC(hContact); + if (xsc) FreeXSC(xsc); + + if (cws->value.type == DBVT_DELETED) + { + xsc = NewXSC(hContact, szProto, TYPE_ICQ_XSTATUS, NOTIFY_REMOVE, NULL, NULL); + } + else + { + TCHAR *stzValue = db2t(&cws->value); + if (!stzValue) + { + TCHAR buff[64]; + int statusID = DBGetContactSettingByte(hContact, szProto, "XStatusId", -1); + GetDefaultXstatusName(statusID, szProto, buff, SIZEOF(buff)); + stzValue = mir_tstrdup(buff); + } + + xsc = NewXSC(hContact, szProto, TYPE_ICQ_XSTATUS, NOTIFY_NEW_XSTATUS, stzValue, NULL); + } + + AddXSC(xsc); + if (xsc != NULL) + { + ExtraStatusChanged(xsc); + FreeXSC(xsc); + } + } + else if (strstr(cws->szSetting, "XStatusMsg") || strcmp(cws->szSetting, "StatusNote") == 0) + { + if (cws->value.type == DBVT_DELETED) + return 1; + + TCHAR *stzValue = db2t(&cws->value); + xsc = FindXSC(hContact); + if (xsc) + { + if (xsc->action == NOTIFY_NEW_XSTATUS) + xsc->stzText = stzValue; + } + else + { + xsc = NewXSC(hContact, szProto, TYPE_ICQ_XSTATUS, NOTIFY_NEW_MESSAGE, NULL, stzValue); + AddXSC(xsc); + } + if (xsc != NULL) + { + ExtraStatusChanged(xsc); + FreeXSC(xsc); + } + } + + return 1; + } + + return 0; +} + +static int __inline CheckStr(char *str, int not_empty, int empty) { + if (str == NULL || str[0] == '\0') + return empty; + else + return not_empty; +} + +#ifdef UNICODE + +static int __inline CheckStrW(WCHAR *str, int not_empty, int empty) { + if (str == NULL || str[0] == L'\0') + return empty; + else + return not_empty; +} + +#endif + +WCHAR *mir_dupToUnicodeEx(char *ptr, UINT CodePage) +{ + size_t size; + WCHAR *tmp; + + if (ptr == NULL) + return NULL; + + size = strlen(ptr) + 1; + tmp = (WCHAR *) mir_alloc(size * sizeof(WCHAR)); + + MultiByteToWideChar(CodePage, 0, ptr, -1, tmp, size * sizeof(WCHAR)); + + return tmp; +} + +static int CompareStatusMsg(STATUSMSGINFO *smi, DBCONTACTWRITESETTING *cws_new) { + DBVARIANT dbv_old; + int ret; + + switch (cws_new->value.type) + { + case DBVT_DELETED: + smi->newstatusmsg = NULL; + break; + case DBVT_ASCIIZ: +#ifdef UNICODE + smi->newstatusmsg = (CheckStr(cws_new->value.pszVal, 0, 1) ? NULL : mir_dupToUnicodeEx(cws_new->value.pszVal, CP_ACP)); + break; + case DBVT_UTF8: + smi->newstatusmsg = (CheckStr(cws_new->value.pszVal, 0, 1) ? NULL : mir_dupToUnicodeEx(cws_new->value.pszVal, CP_UTF8)); + break; + case DBVT_WCHAR: + smi->newstatusmsg = (CheckStrW(cws_new->value.pwszVal, 0, 1) ? NULL : mir_wstrdup(cws_new->value.pwszVal)); +#else + smi->newstatusmsg = (CheckStr(cws_new->value.pszVal, 0, 1) ? NULL : mir_strdup(cws_new->value.pszVal)); +#endif + break; + default: + smi->newstatusmsg = NULL; + break; + } + + if (! +#ifdef UNICODE + DBGetContactSettingW(smi->hContact, "UserOnline", "OldStatusMsg", &dbv_old) +#else + DBGetContactSetting(smi->hContact, "UserOnline", "OldStatusMsg", &dbv_old) +#endif + ) + { + switch (dbv_old.type) + { + case DBVT_ASCIIZ: +#ifdef UNICODE + smi->oldstatusmsg = (CheckStr(dbv_old.pszVal, 0, 1) ? NULL : mir_dupToUnicodeEx(dbv_old.pszVal, CP_ACP)); + break; + case DBVT_UTF8: + smi->oldstatusmsg = (CheckStr(dbv_old.pszVal, 0, 1) ? NULL : mir_dupToUnicodeEx(dbv_old.pszVal, CP_UTF8)); + break; + case DBVT_WCHAR: + smi->oldstatusmsg = (CheckStrW(dbv_old.pwszVal, 0, 1) ? NULL : mir_wstrdup(dbv_old.pwszVal)); +#else + smi->oldstatusmsg = (CheckStr(dbv_old.pszVal, 0, 1) ? NULL : mir_strdup(dbv_old.pszVal)); +#endif + break; + default: + smi->oldstatusmsg = NULL; + break; + } + + if (cws_new->value.type == DBVT_DELETED) + if ( +#ifdef UNICODE + dbv_old.type == DBVT_WCHAR) + ret = CheckStrW(dbv_old.pwszVal, 2, 0); + else if (dbv_old.type == DBVT_UTF8 || +#endif + dbv_old.type == DBVT_ASCIIZ) + ret = CheckStr(dbv_old.pszVal, 2, 0); + else + ret = 2; + else if (dbv_old.type != cws_new->value.type) +#ifdef UNICODE + ret = (lstrcmpW(smi->newstatusmsg, smi->oldstatusmsg) ? CheckStrW(smi->newstatusmsg, 1, 2) : 0); +#else + ret = 1; +#endif; + else if (dbv_old.type == DBVT_ASCIIZ) + ret = (lstrcmpA(cws_new->value.pszVal, dbv_old.pszVal) ? CheckStr(cws_new->value.pszVal, 1, 2) : 0); +#ifdef UNICODE + else if (dbv_old.type == DBVT_UTF8) + ret = (lstrcmpA(cws_new->value.pszVal, dbv_old.pszVal) ? CheckStr(cws_new->value.pszVal, 1, 2) : 0); + else if (dbv_old.type == DBVT_WCHAR) + ret = (lstrcmpW(cws_new->value.pwszVal, dbv_old.pwszVal) ? CheckStrW(cws_new->value.pwszVal, 1, 2) : 0); +#endif + DBFreeVariant(&dbv_old); + } + else + { + if (cws_new->value.type == DBVT_DELETED) + ret = 0; + else if ( +#ifdef UNICODE + cws_new->value.type == DBVT_WCHAR) + ret = CheckStrW(cws_new->value.pwszVal, 1, 0); + else if (cws_new->value.type == DBVT_UTF8 || +#endif + cws_new->value.type == DBVT_ASCIIZ) + ret = CheckStr(cws_new->value.pszVal, 1, 0); + else + ret = 1; + + smi->oldstatusmsg = NULL; + } + + return ret; +} + +BOOL FreeSmiStr(STATUSMSGINFO *smi) +{ + mir_free(smi->newstatusmsg); + mir_free(smi->oldstatusmsg); + return 0; +} + +// return TRUE if timeout is over +BOOL TimeoutCheck() +{ + if (GetTickCount() - LoadTime > TMR_CONNECTIONTIMEOUT) + return TRUE; + return FALSE; +} + +TCHAR* AddCR(const TCHAR *statusmsg) { + TCHAR *tmp; + const TCHAR *found; + int i = 0, len = lstrlen(statusmsg), j; + tmp = (TCHAR*)mir_alloc(1024 * sizeof(TCHAR)); + *tmp = _T('\0'); + while((found = _tcsstr((statusmsg + i), _T("\n"))) != NULL && _tcslen(tmp) + 1 < 1024){ + j = (int)(found - statusmsg); + if(lstrlen(tmp) + j - i + 2 < 1024){ + tmp = _tcsncat(tmp, statusmsg + i, j - i); + } + else { + break; + } + if(j == 0 || *(statusmsg + j - 1) != _T('\r')){ + tmp = lstrcat(tmp, _T("\r")); + } + tmp = lstrcat(tmp, _T("\n")); + i = j + 1; + } + if(lstrlen(tmp) + len - i + 1 < 1024){ + tmp = lstrcat(tmp, statusmsg + i); + } + + return tmp; +} + +TCHAR* GetStr(STATUSMSGINFO *n, const TCHAR *tmplt) { + TCHAR tmp[1024]; + TCHAR *str; + int i; + int len; + + if (tmplt == NULL || tmplt[0] == _T('\0')) + return NULL; + + str = (TCHAR*)mir_alloc(2048 * sizeof(TCHAR)); + str[0] = _T('\0'); + len = lstrlen(tmplt); + + for (i = 0; i < len; i++) + { + tmp[0] = _T('\0'); + + if (tmplt[i] == _T('%')) + { + i++; + switch (tmplt[i]) + { + case 'n': + if (n->compare == 2 || _tcscmp(n->newstatusmsg, TranslateT("")) == 0) + lstrcpyn(tmp, TranslateT(""), SIZEOF(tmp)); + else { + TCHAR *_tmp = AddCR(n->newstatusmsg); + lstrcpyn(tmp, _tmp, SIZEOF(tmp)); + mir_free(_tmp); + } + break; + case 'o': + if (n->oldstatusmsg == NULL || n->oldstatusmsg[0] == _T('\0') || _tcscmp(n->oldstatusmsg, TranslateT("")) == 0) + lstrcpyn(tmp, TranslateT(""), SIZEOF(tmp)); + else { + TCHAR *_tmp = AddCR(n->oldstatusmsg); + lstrcpyn(tmp, _tmp, SIZEOF(tmp)); + mir_free(_tmp); + } + break; + case 'c': + if (n->cust == NULL || n->cust[0] == _T('\0')) lstrcpyn(tmp, TranslateT("Contact"), SIZEOF(tmp)); + else lstrcpyn(tmp, n->cust, SIZEOF(tmp)); + break; + default: + //lstrcpyn(tmp, _T("%"), TMPMAX); + i--; + tmp[0] = tmplt[i]; tmp[1] = _T('\0'); + break; + } + } + else if (tmplt[i] == _T('\\')) + { + i++; + switch (tmplt[i]) + { + case 'n': + //_tcscat_s(tmp, TMPMAX, _T("\r\n")); + tmp[0] = _T('\r'); tmp[1] = _T('\n'); tmp[2] = _T('\0'); + break; + case 't': + //_tcscat_s(tmp, TMPMAX, _T("\t")); + tmp[0] = _T('\t'); tmp[1] = _T('\0'); + break; + default: + //lstrcpyn(tmp, _T("\\"), TMPMAX); + i--; + tmp[0] = tmplt[i]; tmp[1] = _T('\0'); + break; + } + } + else + { + tmp[0] = tmplt[i]; tmp[1] = _T('\0'); + } + + if (tmp[0] != _T('\0')) + { + if (lstrlen(tmp) + lstrlen(str) < 2044) + { + lstrcat(str, tmp); + } + else + { + lstrcat(str, _T("...")); + break; + } + } + } + + return str; +} + +int ProcessStatus(DBCONTACTWRITESETTING *cws, HANDLE hContact) +{ + if (strcmp(cws->szSetting, "Status") == 0) + { + WORD newStatus = cws->value.wVal; + if (newStatus < ID_STATUS_MIN || newStatus > ID_STATUS_MAX) + return 0; + + DBVARIANT dbv; + if (!DBGetContactSettingString(hContact, "Protocol", "p", &dbv)) + { + BOOL temp = strcmp(cws->szModule, dbv.pszVal) != 0; + DBFreeVariant(&dbv); + if (temp) return 0; + } + + WORD oldStatus = DBGetContactSettingRangedWord(hContact, "UserOnline", "OldStatus", ID_STATUS_OFFLINE, ID_STATUS_MIN, ID_STATUS_MAX); + if (oldStatus == newStatus) + return 0; + + //If we get here, the two stauses differ, so we can proceed. + DBWriteContactSettingWord(hContact, "UserOnline", "OldStatus", newStatus); + + //If *Miranda* ignores the UserOnline event, exit! + if (CallService(MS_IGNORE_ISIGNORED, (WPARAM)hContact, IGNOREEVENT_USERONLINE)) + return 0; + + //If we get here, we have to notify the Hooks. + NotifyEventHooks(hHookContactStatusChanged, (WPARAM)hContact, (LPARAM)MAKELPARAM(oldStatus, newStatus)); + return 1; + } + + if (!lstrcmpA(cws->szModule, "CList") && !lstrcmpA(cws->szSetting, "StatusMsg")) + { + STATUSMSGINFO smi; + BOOL retem = TRUE, rettime = TRUE; + + DBVARIANT dbv; + if (!DBGetContactSettingString(hContact, "Protocol", "p", &dbv)) + { + char dbSetting[128]; + mir_snprintf(dbSetting, SIZEOF(dbSetting), "%s_enabled", dbv.pszVal); + if (!DBGetContactSettingByte(NULL, MODULE, dbSetting, 1)) + return 0; + } + smi.proto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + + //don't show popup when mradio connecting and disconnecting + if (_stricmp(smi.proto, "mRadio") == 0 && !cws->value.type == DBVT_DELETED) + { + TCHAR buf[MAX_PATH]; + mir_sntprintf(buf, SIZEOF(buf), _T(" (%s)"), TranslateT("connecting")); + char* pszUtf = mir_utf8encodeT(buf); + mir_sntprintf(buf, SIZEOF(buf), _T(" (%s)"), TranslateT("aborting")); + char* pszUtf2 = mir_utf8encodeT(buf); + mir_sntprintf(buf, SIZEOF(buf), _T(" (%s)"), TranslateT("playing")); + char* pszUtf3 = mir_utf8encodeT(buf); + if (_stricmp(cws->value.pszVal, pszUtf) == 0 || _stricmp(cws->value.pszVal, pszUtf2) == 0 || _stricmp(cws->value.pszVal, pszUtf3) == 0) + { + mir_free(pszUtf); + mir_free(pszUtf2); + mir_free(pszUtf3); + return 0; + } + else + { + mir_free(pszUtf); + mir_free(pszUtf2); + mir_free(pszUtf3); + } + } + + if (smi.proto != NULL && CallProtoService(smi.proto, PS_GETSTATUS, 0, 0) != ID_STATUS_OFFLINE) + { + smi.hContact = hContact; + smi.compare = CompareStatusMsg(&smi, cws); + if ((smi.compare == 0) || (opt.IgnoreEmpty && (smi.compare == 2))) + return FreeSmiStr(&smi); + + if (cws->value.type == DBVT_DELETED) + { + DBDeleteContactSetting(smi.hContact, "UserOnline", "OldStatusMsg"); + } + else + { + DBCONTACTWRITESETTING cws_old; + cws_old.szModule = "UserOnline"; + cws_old.szSetting = "OldStatusMsg"; + cws_old.value = cws->value; + CallService(MS_DB_CONTACT_WRITESETTING, (WPARAM)smi.hContact, (LPARAM)&cws_old); + } + smi.cust = (TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)smi.hContact, GCDNF_TCHAR); + + if (opt.IgnoreEmpty && (smi.compare == 2)) + retem = FALSE; + else if (!TimeoutCheck() && !opt.PopupOnConnect) + rettime = FALSE; + + char status[8]; + mir_snprintf(status, SIZEOF(status), "%d", IDC_CHK_STATUS_MESSAGE); + if (DBGetContactSettingByte(hContact, MODULE, "EnablePopups", 1) && DBGetContactSettingByte(0, MODULE, status, 1) && retem && rettime) + { + POPUPDATAT ppd = {0}; + char* protoname = (char*)CallService(MS_PROTO_GETCONTACTBASEACCOUNT, (WPARAM)smi.hContact, 0); + PROTOACCOUNT* pdescr = (PROTOACCOUNT*)CallService(MS_PROTO_GETACCOUNT, 0, (LPARAM)protoname); + protoname = mir_t2a(pdescr->tszAccountName); + protoname = (char*)mir_realloc(protoname, lstrlenA(protoname) + lstrlenA("_TSMChange") + 1); + lstrcatA(protoname, "_TSMChange"); + TCHAR *str; + DBVARIANT dbVar = {0}; + DBGetContactSettingTString(NULL, MODULE, protoname, &dbVar); + if (lstrcmp(dbVar.ptszVal, NULL) == 0) + { + DBFreeVariant(&dbVar); + str = GetStr(&smi, TranslateT(DEFAULT_POPUP_STATUSMESSAGE)); + } + else + { + str = GetStr(&smi, dbVar.ptszVal); + } + mir_free(protoname); + + ppd.lchContact = smi.hContact; + ppd.lchIcon = LoadSkinnedProtoIcon(smi.proto, DBGetContactSettingWord(smi.hContact, smi.proto, "Status", ID_STATUS_ONLINE)); + lstrcpyn(ppd.lptzContactName, smi.cust, MAX_CONTACTNAME); + lstrcpyn(ppd.lptzText, str, MAX_SECONDLINE); + switch (opt.Colors) + { + case POPUP_COLOR_OWN: + ppd.colorBack = StatusList[Index(DBGetContactSettingWord(smi.hContact, smi.proto, "Status", ID_STATUS_ONLINE))].colorBack; + ppd.colorText = StatusList[Index(DBGetContactSettingWord(smi.hContact, smi.proto, "Status", ID_STATUS_ONLINE))].colorText; + break; + case POPUP_COLOR_WINDOWS: + ppd.colorBack = GetSysColor(COLOR_BTNFACE); + ppd.colorText = GetSysColor(COLOR_WINDOWTEXT); + break; + case POPUP_COLOR_POPUP: + ppd.colorBack = ppd.colorText = 0; + break; + } + ppd.PluginWindowProc = (WNDPROC)PopupDlgProc; + ppd.PluginData = NULL; + ppd.iSeconds = opt.PopupTimeout; + PUAddPopUpT(&ppd); + mir_free(str); + } + mir_free(smi.newstatusmsg); + mir_free(smi.oldstatusmsg); + return 1; + } + } + return 0; +} + +int ContactSettingChanged(WPARAM wParam, LPARAM lParam) +{ + DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING *)lParam; + HANDLE hContact = (HANDLE)wParam; + + if (hContact == NULL) + return 0; + + char *szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + if (szProto == NULL) + return 0; + + if (DBGetContactSettingWord(hContact, szProto, "Status", ID_STATUS_OFFLINE) != ID_STATUS_OFFLINE) + { + if (ProcessExtraStatus(cws, hContact)) + return 0; + } + + ProcessStatus(cws, hContact); + return 0; +} + +int StatusModeChanged(WPARAM wParam, LPARAM lParam) +{ + char *szProto = (char *)lParam; + if (opt.AutoDisable && (!opt.OnlyGlobalChanges || szProto == NULL)) + { + if (opt.DisablePopupGlobally && ServiceExists(MS_POPUP_QUERY)) + { + char szSetting[12]; + wsprintfA(szSetting, "p%d", wParam); + BYTE hlpDisablePopup = DBGetContactSettingByte(0, MODULE, szSetting, 0); + + if (hlpDisablePopup != opt.PopupAutoDisabled) + { + BYTE hlpPopupStatus = (BYTE)CallService(MS_POPUP_QUERY, PUQS_GETSTATUS, 0); + opt.PopupAutoDisabled = hlpDisablePopup; + + if (hlpDisablePopup) + { + DBWriteContactSettingByte(0, MODULE, "OldPopupStatus", hlpPopupStatus); + CallService(MS_POPUP_QUERY, PUQS_DISABLEPOPUPS, 0); + } + else + { + if (hlpPopupStatus == FALSE) + { + if (DBGetContactSettingByte(0, MODULE, "OldPopupStatus", TRUE) == TRUE) + CallService(MS_POPUP_QUERY, PUQS_ENABLEPOPUPS, 0); + else + CallService(MS_POPUP_QUERY, PUQS_DISABLEPOPUPS, 0); + } + } + } + } + + if (opt.DisableSoundGlobally) + { + char szSetting[12]; + wsprintfA(szSetting, "s%d", wParam); + BYTE hlpDisableSound = DBGetContactSettingByte(0, MODULE, szSetting, 0); + + if (hlpDisableSound != opt.SoundAutoDisabled) + { + BYTE hlpUseSound = DBGetContactSettingByte(NULL, "Skin", "UseSound", 1); + opt.SoundAutoDisabled = hlpDisableSound; + + if (hlpDisableSound) + { + DBWriteContactSettingByte(0, MODULE, "OldUseSound", hlpUseSound); + DBWriteContactSettingByte(0, "Skin", "UseSound", FALSE); + } + else + { + if (hlpUseSound == FALSE) + DBWriteContactSettingByte(0, "Skin", "UseSound", DBGetContactSettingByte(0, MODULE, "OldUseSound", 1)); + } + } + } + } + + return 0; +} + +void ShowStatusChangePopup(HANDLE hContact, char *szProto, WORD oldStatus, WORD newStatus) +{ + TCHAR stzStatusText[MAX_SECONDLINE] = {0}; + WORD myStatus = (WORD)CallProtoService(szProto, PS_GETSTATUS, (WPARAM)0, (LPARAM)0); + + POPUPDATAT ppd = {0}; + ppd.lchContact = hContact; + ppd.lchIcon = LoadSkinnedProtoIcon(szProto, newStatus); + _tcscpy(ppd.lptzContactName, (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GSMDF_TCHAR)); + + if (opt.ShowGroup) //add group name to popup title + { + DBVARIANT dbv; + if (!DBGetContactSettingTString(hContact, "CList", "Group", &dbv)) + { + _tcscat(ppd.lptzContactName, _T(" (")); + _tcscat(ppd.lptzContactName, dbv.ptszVal); + _tcscat(ppd.lptzContactName, _T(")")); + DBFreeVariant(&dbv); + } + } + + if (opt.ShowStatus) + { + if (opt.UseAlternativeText) + { + switch (GetGender(hContact)) + { + case GENDER_MALE: + _tcsncpy(stzStatusText, StatusList[Index(newStatus)].lpzMStatusText, MAX_STATUSTEXT); + break; + case GENDER_FEMALE: + _tcsncpy(stzStatusText, StatusList[Index(newStatus)].lpzFStatusText, MAX_STATUSTEXT); + break; + case GENDER_UNSPECIFIED: + _tcsncpy(stzStatusText, StatusList[Index(newStatus)].lpzUStatusText, MAX_STATUSTEXT); + break; + } + } + else + { + _tcsncpy(stzStatusText, StatusList[Index(newStatus)].lpzStandardText, MAX_STATUSTEXT); + } + + if (opt.ShowPreviousStatus) + { + TCHAR buff[MAX_STATUSTEXT]; + wsprintf(buff, TranslateTS(STRING_SHOWPREVIOUSSTATUS), StatusList[Index(oldStatus)].lpzStandardText); + _tcscat(_tcscat(stzStatusText, _T(" ")), buff); + } + } + + if (opt.ReadAwayMsg && + myStatus != ID_STATUS_INVISIBLE && + StatusHasAwayMessage(szProto, newStatus)) + { + DBWriteContactSettingTString(hContact, MODULE, "LastPopupText", stzStatusText); + } + + _tcscpy(ppd.lptzText, stzStatusText); + + switch (opt.Colors) + { + case POPUP_COLOR_OWN: + ppd.colorBack = StatusList[Index(newStatus)].colorBack; + ppd.colorText = StatusList[Index(newStatus)].colorText; + break; + case POPUP_COLOR_WINDOWS: + ppd.colorBack = GetSysColor(COLOR_BTNFACE); + ppd.colorText = GetSysColor(COLOR_WINDOWTEXT); + break; + case POPUP_COLOR_POPUP: + ppd.colorBack = ppd.colorText = 0; + break; + } + + ppd.PluginWindowProc = (WNDPROC)PopupDlgProc; + + PLUGINDATA *pdp = (PLUGINDATA *)mir_alloc(sizeof(PLUGINDATA)); + pdp->oldStatus = oldStatus; + pdp->newStatus = newStatus; + pdp->hAwayMsgHook = NULL; + pdp->hAwayMsgProcess = NULL; + ppd.PluginData = pdp; + ppd.iSeconds = opt.PopupTimeout; + PUAddPopUpT(&ppd); +} + +void BlinkIcon(HANDLE hContact, char* szProto, WORD status) +{ + CLISTEVENT cle = {0}; + TCHAR stzTooltip[256]; + + cle.cbSize = sizeof(cle); + cle.flags = CLEF_ONLYAFEW | CLEF_TCHAR; + cle.hContact = hContact; + cle.hDbEvent = hContact; + if (opt.BlinkIcon_Status) + cle.hIcon = LoadSkinnedProtoIcon(szProto, status); + else + cle.hIcon = LoadSkinnedIcon(SKINICON_OTHER_USERONLINE); + cle.pszService = "UserOnline/Description"; + cle.ptszTooltip = stzTooltip; + + TCHAR *hlpName = (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR); + mir_sntprintf(stzTooltip, SIZEOF(stzTooltip), TranslateT("%s is now %s"), hlpName, StatusList[Index(status)].lpzStandardText); + CallService(MS_CLIST_ADDEVENT, 0, (LPARAM)&cle); +} + +void PlayChangeSound(HANDLE hContact, WORD oldStatus, WORD newStatus) +{ + DBVARIANT dbv; + if (opt.UseIndSnd) + { + TCHAR stzSoundFile[MAX_PATH] = {0}; + if (!DBGetContactSettingTString(hContact, MODULE, "UserFromOffline", &dbv) && + oldStatus == ID_STATUS_OFFLINE) + { + _tcscpy(stzSoundFile, dbv.ptszVal); + DBFreeVariant(&dbv); + } + else if (!DBGetContactSettingTString(hContact, MODULE, StatusList[Index(newStatus)].lpzSkinSoundName, &dbv)) + { + lstrcpy(stzSoundFile, dbv.ptszVal); + DBFreeVariant(&dbv); + } + + if (stzSoundFile[0]) + { + //Now make path to IndSound absolute, as it isn't registered + TCHAR stzSoundPath[MAX_PATH]; + CallService(MS_UTILS_PATHTOABSOLUTET, (WPARAM)stzSoundFile, (LPARAM)stzSoundPath); + PlaySound(stzSoundPath, NULL, SND_ASYNC | SND_FILENAME | SND_NOSTOP); + return; + } + } + + char szSoundFile[MAX_PATH] = {0}; + + if (!DBGetContactSettingByte(0, "SkinSoundsOff", "UserFromOffline", 0) && + !DBGetContactSettingString(0,"SkinSounds", "UserFromOffline", &dbv) && + oldStatus == ID_STATUS_OFFLINE) + { + strcpy(szSoundFile, "UserFromOffline"); + DBFreeVariant(&dbv); + } + else if (!DBGetContactSettingByte(0, "SkinSoundsOff", StatusList[Index(newStatus)].lpzSkinSoundName, 0) && + !DBGetContactSetting(0, "SkinSounds", StatusList[Index(newStatus)].lpzSkinSoundName, &dbv)) + { + strcpy(szSoundFile, StatusList[Index(newStatus)].lpzSkinSoundName); + DBFreeVariant(&dbv); + } + + if (szSoundFile[0]) + SkinPlaySound(szSoundFile); +} + +int ContactStatusChanged(WPARAM wParam, LPARAM lParam) +{ + WORD oldStatus = LOWORD(lParam); + WORD newStatus = HIWORD(lParam); + HANDLE hContact = (HANDLE)wParam; + char buff[8], szProto[64], szSubProto[64]; + bool bEnablePopup = true, bEnableSound = true; + + char *hlpProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0); + if (hlpProto == NULL || opt.TempDisabled) + return 0; + + strcpy(szProto, hlpProto); + WORD myStatus = (WORD)CallProtoService(szProto, PS_GETSTATUS, (WPARAM)0, (LPARAM)0); + + if (strcmp(szProto, szMetaModuleName) == 0) //this contact is Meta + { + HANDLE hSubContact = (HANDLE)CallService(MS_MC_GETMOSTONLINECONTACT, (WPARAM)hContact, 0); + strcpy(szSubProto, (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hSubContact,0)); + + if (newStatus == ID_STATUS_OFFLINE) + { + // read last online proto for metaconatct if exists, + // to avoid notifying when meta went offline but default contact's proto still online + DBVARIANT dbv; + if (!DBGetContactSettingString(hContact, szProto, "LastOnline", &dbv)) + { + strcpy(szSubProto, dbv.pszVal); + DBFreeVariant(&dbv); + } + } + else + DBWriteContactSettingString(hContact, szProto, "LastOnline", szSubProto); + + if (!DBGetContactSettingByte(0, MODULE, szSubProto, 1)) + return 0; + + strcpy(szProto, szSubProto); + } + else + { + if (myStatus == ID_STATUS_OFFLINE) + return 0; + } + + if (!opt.FromOffline || oldStatus != ID_STATUS_OFFLINE) // Either it wasn't a change from Offline or we didn't enable that. + { + wsprintfA(buff, "%d", newStatus); + if (DBGetContactSettingByte(0, MODULE, buff, 1) == 0) + return 0; // "Notify when a contact changes to one of..." is unchecked + } + + if (!opt.HiddenContactsToo && (DBGetContactSettingByte(hContact, "CList", "Hidden", 0) == 1)) + return 0; + + // we don't want to be notified if new chatroom comes online + if (DBGetContactSettingByte(hContact, szProto, "ChatRoom", 0) == 1) + return 0; + + // check if that proto from which we received statuschange notification, isn't in autodisable list + char statusIDs[12], statusIDp[12]; + if (opt.AutoDisable) + { + wsprintfA(statusIDs, "s%d", myStatus); + wsprintfA(statusIDp, "p%d", myStatus); + bEnableSound = DBGetContactSettingByte(0, MODULE, statusIDs, 1) ? FALSE : TRUE; + bEnablePopup = DBGetContactSettingByte(0, MODULE, statusIDp, 1) ? FALSE : TRUE; + } + + if (bEnablePopup && DBGetContactSettingByte(hContact, MODULE, "EnablePopups", 1) && TimeoutCheck()) + ShowStatusChangePopup(hContact, szProto, oldStatus, newStatus); + + if (opt.BlinkIcon) + BlinkIcon(hContact, szProto, newStatus); + + if (bEnableSound && + DBGetContactSettingByte(0, "Skin", "UseSound", TRUE) && + DBGetContactSettingByte(hContact, MODULE, "EnableSounds", 1)) + { + PlayChangeSound(hContact, oldStatus, newStatus); + } + + if (opt.Log) + { + TCHAR stzName[64], stzStatus[MAX_STATUSTEXT], stzOldStatus[MAX_STATUSTEXT]; + TCHAR stzDate[MAX_STATUSTEXT], stzTime[MAX_STATUSTEXT]; + TCHAR stzText[1024]; + + _tcscpy(stzName, (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR)); + _tcsncpy(stzStatus, StatusList[Index(newStatus)].lpzStandardText, MAX_STATUSTEXT); + _tcsncpy(stzOldStatus, StatusList[Index(oldStatus)].lpzStandardText, MAX_STATUSTEXT); + GetTimeFormat(LOCALE_USER_DEFAULT, 0, NULL,_T("HH':'mm"), stzTime, SIZEOF(stzTime)); + GetDateFormat(LOCALE_USER_DEFAULT, 0, NULL,_T("dd/MM/yyyy"), stzDate, SIZEOF(stzDate)); + wsprintf(stzText, TranslateT("%s, %s. %s changed to: %s (was: %s).\r\n"), stzDate, stzTime, stzName, stzStatus, stzOldStatus); + LogToFile(stzText); + } + + return 0; +} + +void InitStatusList() +{ + int index = 0; + //Online + index = Index(ID_STATUS_ONLINE); + StatusList[index].ID = ID_STATUS_ONLINE; + StatusList[index].icon = SKINICON_STATUS_ONLINE; + lstrcpyn(StatusList[index].lpzMStatusText, TranslateT("(M) is back online!"), MAX_STATUSTEXT); + lstrcpyn(StatusList[index].lpzFStatusText, TranslateT("(F) is back online!"), MAX_STATUSTEXT); + lstrcpyn(StatusList[index].lpzUStatusText, TranslateT("(U) is back online!"), MAX_STATUSTEXT); + lstrcpyn(StatusList[index].lpzStandardText, TranslateT("Online"), MAX_STANDARDTEXT); + lstrcpynA(StatusList[index].lpzSkinSoundName, "UserOnline", MAX_SKINSOUNDNAME); + lstrcpynA(StatusList[index].lpzSkinSoundDesc, Translate("User: Online"), MAX_SKINSOUNDDESC); + lstrcpynA(StatusList[index].lpzSkinSoundFile, "global.wav", MAX_PATH); + StatusList[index].colorBack = DBGetContactSettingDword(NULL, MODULE, "40072bg", COLOR_BG_AVAILDEFAULT); + StatusList[index].colorText = DBGetContactSettingDword(NULL, MODULE, "40072tx", COLOR_TX_DEFAULT); + + //Offline + index = Index(ID_STATUS_OFFLINE); + StatusList[index].ID = ID_STATUS_OFFLINE; + StatusList[index].icon = SKINICON_STATUS_OFFLINE; + lstrcpyn(StatusList[index].lpzMStatusText, TranslateT("(M) went offline! :("), MAX_STATUSTEXT); + lstrcpyn(StatusList[index].lpzFStatusText, TranslateT("(F) went offline! :("), MAX_STATUSTEXT); + lstrcpyn(StatusList[index].lpzUStatusText, TranslateT("(U) went offline! :("), MAX_STATUSTEXT); + lstrcpyn(StatusList[index].lpzStandardText, TranslateT("Offline"), MAX_STANDARDTEXT); + lstrcpynA(StatusList[index].lpzSkinSoundName, "UserOffline", MAX_SKINSOUNDNAME); + lstrcpynA(StatusList[index].lpzSkinSoundDesc, Translate("User: Offline"), MAX_SKINSOUNDDESC); + lstrcpynA(StatusList[index].lpzSkinSoundFile, "offline.wav", MAX_PATH); + StatusList[index].colorBack = DBGetContactSettingDword(NULL, MODULE, "40071bg", COLOR_BG_NAVAILDEFAULT); + StatusList[index].colorText = DBGetContactSettingDword(NULL, MODULE, "40071tx", COLOR_TX_DEFAULT); + + //Invisible + index = Index(ID_STATUS_INVISIBLE); + StatusList[index].ID = ID_STATUS_INVISIBLE; + StatusList[index].icon = SKINICON_STATUS_INVISIBLE; + lstrcpyn(StatusList[index].lpzMStatusText, TranslateT("(M) hides in shadows..."), MAX_STATUSTEXT); + lstrcpyn(StatusList[index].lpzFStatusText, TranslateT("(F) hides in shadows..."), MAX_STATUSTEXT); + lstrcpyn(StatusList[index].lpzUStatusText, TranslateT("(U) hides in shadows..."), MAX_STATUSTEXT); + lstrcpyn(StatusList[index].lpzStandardText, TranslateT("Invisible"), MAX_STANDARDTEXT); + lstrcpynA(StatusList[index].lpzSkinSoundName, "UserInvisible", MAX_SKINSOUNDNAME); + lstrcpynA(StatusList[index].lpzSkinSoundDesc, Translate("User: Invisible"), MAX_SKINSOUNDDESC); + lstrcpynA(StatusList[index].lpzSkinSoundFile, "invisible.wav", MAX_PATH); + StatusList[index].colorBack = DBGetContactSettingDword(NULL, MODULE, "40078bg", COLOR_BG_AVAILDEFAULT); + StatusList[index].colorText = DBGetContactSettingDword(NULL, MODULE, "40078tx", COLOR_TX_DEFAULT); + + //Free for chat + index = Index(ID_STATUS_FREECHAT); + StatusList[index].ID = ID_STATUS_FREECHAT; + StatusList[index].icon = SKINICON_STATUS_FREE4CHAT; + lstrcpyn(StatusList[index].lpzMStatusText, TranslateT("(M) feels talkative!"), MAX_STATUSTEXT); + lstrcpyn(StatusList[index].lpzFStatusText, TranslateT("(F) feels talkative!"), MAX_STATUSTEXT); + lstrcpyn(StatusList[index].lpzUStatusText, TranslateT("(U) feels talkative!"), MAX_STATUSTEXT); + lstrcpyn(StatusList[index].lpzStandardText, TranslateT("Free for chat"), MAX_STANDARDTEXT); + lstrcpynA(StatusList[index].lpzSkinSoundName, "UserFreeForChat", MAX_SKINSOUNDNAME); + lstrcpynA(StatusList[index].lpzSkinSoundDesc, Translate("User: Free For Chat"), MAX_SKINSOUNDDESC); + lstrcpynA(StatusList[index].lpzSkinSoundFile, "free4chat.wav", MAX_PATH); + StatusList[index].colorBack = DBGetContactSettingDword(NULL, MODULE, "40077bg", COLOR_BG_AVAILDEFAULT); + StatusList[index].colorText = DBGetContactSettingDword(NULL, MODULE, "40077tx", COLOR_TX_DEFAULT); + + //Away + index = Index(ID_STATUS_AWAY); + StatusList[index].ID = ID_STATUS_AWAY; + StatusList[index].icon = SKINICON_STATUS_AWAY; + lstrcpyn(StatusList[index].lpzMStatusText, TranslateT("(M) went Away"), MAX_STATUSTEXT); + lstrcpyn(StatusList[index].lpzFStatusText, TranslateT("(F) went Away"), MAX_STATUSTEXT); + lstrcpyn(StatusList[index].lpzUStatusText, TranslateT("(U) went Away"), MAX_STATUSTEXT); + lstrcpyn(StatusList[index].lpzStandardText, TranslateT("Away"), MAX_STANDARDTEXT); + lstrcpynA(StatusList[index].lpzSkinSoundName, "UserAway", MAX_SKINSOUNDNAME); + lstrcpynA(StatusList[index].lpzSkinSoundDesc, Translate("User: Away"), MAX_SKINSOUNDDESC); + lstrcpynA(StatusList[index].lpzSkinSoundFile, "away.wav", MAX_PATH); + StatusList[index].colorBack = DBGetContactSettingDword(NULL, MODULE, "40073bg", COLOR_BG_NAVAILDEFAULT); + StatusList[index].colorText = DBGetContactSettingDword(NULL, MODULE, "40073tx", COLOR_TX_DEFAULT); + + //NA + index = Index(ID_STATUS_NA); + StatusList[index].ID = ID_STATUS_NA; + StatusList[index].icon = SKINICON_STATUS_NA; + lstrcpyn(StatusList[index].lpzMStatusText, TranslateT("(M) isn't there anymore!"), MAX_STATUSTEXT); + lstrcpyn(StatusList[index].lpzFStatusText, TranslateT("(F) isn't there anymore!"), MAX_STATUSTEXT); + lstrcpyn(StatusList[index].lpzUStatusText, TranslateT("(U) isn't there anymore!"), MAX_STATUSTEXT); + lstrcpyn(StatusList[index].lpzStandardText, TranslateT("NA"), MAX_STANDARDTEXT); + lstrcpynA(StatusList[index].lpzSkinSoundName, "UserNA", MAX_SKINSOUNDNAME); + lstrcpynA(StatusList[index].lpzSkinSoundDesc, Translate("User: Not Available"), MAX_SKINSOUNDDESC); + lstrcpynA(StatusList[index].lpzSkinSoundFile, "na.wav", MAX_PATH); + StatusList[index].colorBack = DBGetContactSettingDword(NULL, MODULE, "40075bg", COLOR_BG_NAVAILDEFAULT); + StatusList[index].colorText = DBGetContactSettingDword(NULL, MODULE, "40075tx", COLOR_TX_DEFAULT); + + //Occupied + index = Index(ID_STATUS_OCCUPIED); + StatusList[index].ID = ID_STATUS_OCCUPIED; + StatusList[index].icon = SKINICON_STATUS_OCCUPIED; + lstrcpyn(StatusList[index].lpzMStatusText, TranslateT("(M) has something else to do."), MAX_STATUSTEXT); + lstrcpyn(StatusList[index].lpzFStatusText, TranslateT("(F) has something else to do."), MAX_STATUSTEXT); + lstrcpyn(StatusList[index].lpzUStatusText, TranslateT("(U) has something else to do."), MAX_STATUSTEXT); + lstrcpyn(StatusList[index].lpzStandardText, TranslateT("Occupied"), MAX_STANDARDTEXT); + lstrcpynA(StatusList[index].lpzSkinSoundName, "UserOccupied", MAX_SKINSOUNDNAME); + lstrcpynA(StatusList[index].lpzSkinSoundDesc, Translate("User: Occupied"), MAX_SKINSOUNDDESC); + lstrcpynA(StatusList[index].lpzSkinSoundFile, "occupied.wav", MAX_PATH); + StatusList[index].colorBack = DBGetContactSettingDword(NULL, MODULE, "40076bg", COLOR_BG_NAVAILDEFAULT); + StatusList[index].colorText = DBGetContactSettingDword(NULL, MODULE, "40076tx", COLOR_TX_DEFAULT); + + //DND + index = Index(ID_STATUS_DND); + StatusList[index].ID = ID_STATUS_DND; + StatusList[index].icon = SKINICON_STATUS_DND; + lstrcpyn(StatusList[index].lpzMStatusText, TranslateT("(M) doesn't want to be disturbed!"), MAX_STATUSTEXT); + lstrcpyn(StatusList[index].lpzFStatusText, TranslateT("(F) doesn't want to be disturbed!"), MAX_STATUSTEXT); + lstrcpyn(StatusList[index].lpzUStatusText, TranslateT("(U) doesn't want to be disturbed!"), MAX_STATUSTEXT); + lstrcpyn(StatusList[index].lpzStandardText, TranslateT("DND"), MAX_STANDARDTEXT); + lstrcpynA(StatusList[index].lpzSkinSoundName, "UserDND", MAX_SKINSOUNDNAME); + lstrcpynA(StatusList[index].lpzSkinSoundDesc, Translate("User: Do Not Disturb"), MAX_SKINSOUNDDESC); + lstrcpynA(StatusList[index].lpzSkinSoundFile, "dnd.wav", MAX_PATH); + StatusList[index].colorBack = DBGetContactSettingDword(NULL, MODULE, "40074bg", COLOR_BG_NAVAILDEFAULT); + StatusList[index].colorText = DBGetContactSettingDword(NULL, MODULE, "40074tx", COLOR_TX_DEFAULT); + + //OutToLunch + index = Index(ID_STATUS_OUTTOLUNCH); + StatusList[index].ID = ID_STATUS_OUTTOLUNCH; + StatusList[index].icon = SKINICON_STATUS_OUTTOLUNCH; + lstrcpyn(StatusList[index].lpzMStatusText, TranslateT("(M) is eating something"), MAX_STATUSTEXT); + lstrcpyn(StatusList[index].lpzFStatusText, TranslateT("(F) is eating something"), MAX_STATUSTEXT); + lstrcpyn(StatusList[index].lpzUStatusText, TranslateT("(U) is eating something"), MAX_STATUSTEXT); + lstrcpyn(StatusList[index].lpzStandardText, TranslateT("Out to lunch"), MAX_STANDARDTEXT); + lstrcpynA(StatusList[index].lpzSkinSoundName, "UserOutToLunch", MAX_SKINSOUNDNAME); + lstrcpynA(StatusList[index].lpzSkinSoundDesc, Translate("User: Out To Lunch"), MAX_SKINSOUNDDESC); + lstrcpynA(StatusList[index].lpzSkinSoundFile, "lunch.wav", MAX_PATH); + StatusList[index].colorBack = DBGetContactSettingDword(NULL, MODULE, "40080bg", COLOR_BG_NAVAILDEFAULT); + StatusList[index].colorText = DBGetContactSettingDword(NULL, MODULE, "40080tx", COLOR_TX_DEFAULT); + + //OnThePhone + index = Index(ID_STATUS_ONTHEPHONE); + StatusList[index].ID = ID_STATUS_ONTHEPHONE; + StatusList[index].icon = SKINICON_STATUS_ONTHEPHONE; + lstrcpyn(StatusList[index].lpzMStatusText, TranslateT("(M) had to answer the phone"), MAX_STATUSTEXT); + lstrcpyn(StatusList[index].lpzFStatusText, TranslateT("(F) had to answer the phone"), MAX_STATUSTEXT); + lstrcpyn(StatusList[index].lpzUStatusText, TranslateT("(U) had to answer the phone"), MAX_STATUSTEXT); + lstrcpyn(StatusList[index].lpzStandardText, TranslateT("On the phone"), MAX_STANDARDTEXT); + lstrcpynA(StatusList[index].lpzSkinSoundName, "UserOnThePhone", MAX_SKINSOUNDNAME); + lstrcpynA(StatusList[index].lpzSkinSoundDesc, Translate("User: On The Phone"), MAX_SKINSOUNDDESC); + lstrcpynA(StatusList[index].lpzSkinSoundFile, "phone.wav", MAX_PATH); + StatusList[index].colorBack = DBGetContactSettingDword(NULL, MODULE, "40079bg", COLOR_BG_NAVAILDEFAULT); + StatusList[index].colorText = DBGetContactSettingDword(NULL, MODULE, "40079tx", COLOR_TX_DEFAULT); + + //Extra status + index = Index(ID_STATUS_EXTRASTATUS); + StatusList[index].ID = ID_STATUS_EXTRASTATUS; + StatusList[index].colorBack = DBGetContactSettingDword(NULL, MODULE, "40081bg", COLOR_BG_AVAILDEFAULT); + StatusList[index].colorText = DBGetContactSettingDword(NULL, MODULE, "40081tx", COLOR_TX_DEFAULT); +} + +void InitUpdaterSupport() +{ +#ifndef _WIN64 + if (ServiceExists(MS_UPDATE_REGISTER)) + { + Update update = {0}; + char szVersion[16]; + + update.cbSize = sizeof(Update); + update.szComponentName = pluginInfoEx.shortName; + update.pbVersion = (BYTE *)CreateVersionString(pluginInfoEx.version, szVersion); + update.cpbVersion = strlen((char *)update.pbVersion); +#ifdef _UNICODE + update.szUpdateURL = "http://miranda-easy.net/addons/updater/nxsn-ym.zip"; +#else + update.szUpdateURL = "http://miranda-easy.net/addons/updater/nxsn-ym_ansi.zip"; +#endif + update.szVersionURL = "http://miranda-easy.net/addons/updater/nxsn_version.txt"; + update.pbVersionPrefix = (BYTE *)"NewXstatusNotify YM "; + update.cpbVersionPrefix = strlen((char *)update.pbVersionPrefix); + + CallService(MS_UPDATE_REGISTER, 0, (WPARAM)&update); + } +#endif +} + +int ProtoAck(WPARAM wParam,LPARAM lParam) +{ + ACKDATA *ack = (ACKDATA *)lParam; + + if (ack->type == ACKTYPE_STATUS) + { + WORD newStatus = (WORD)ack->lParam; + WORD oldStatus = (WORD)ack->hProcess; + char *szProto = (char *)ack->szModule; + + if (oldStatus == newStatus) + return 0; + + if (newStatus == ID_STATUS_OFFLINE) + { + //The protocol switched to offline. Disable the popups for this protocol + DBWriteContactSettingByte(NULL, MODULE, szProto, 0); + } + else if (oldStatus < ID_STATUS_ONLINE && newStatus >= ID_STATUS_ONLINE) + { + //The protocol changed from a disconnected status to a connected status. + //Enable the popups for this protocol. + LoadTime = GetTickCount(); + } + } + + return 0; +} + +INT_PTR EnableDisableMenuCommand(WPARAM wParam, LPARAM lParam) +{ + opt.TempDisabled = !opt.TempDisabled; + DBWriteContactSettingByte(0, MODULE, "TempDisable", opt.TempDisabled); + + CLISTMENUITEM mi = {0}; + mi.cbSize = sizeof(mi); + mi.flags = CMIM_ICON | CMIM_NAME | CMIF_TCHAR; + if (opt.TempDisabled) + { + mi.ptszName = _T("Enable status notification"); + mi.icolibItem = GetIconHandle(ICO_NOTIFICATION_OFF); + } + else + { + mi.ptszName = _T("Disable status notification"); + mi.icolibItem = GetIconHandle(ICO_NOTIFICATION_ON); + } + + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hEnableDisableMenu, (LPARAM)&mi); + CallService(MS_TB_SETBUTTONSTATEBYID, (WPARAM)"StatusNotificationToggle", opt.TempDisabled ? TBST_PUSHED : TBST_RELEASED); + return 0; +} + +void InitMainMenuItem() +{ + CLISTMENUITEM mi = { 0 }; + mi.cbSize = sizeof(mi); + mi.flags = CMIF_TCHAR | CMIF_ICONFROMICOLIB; + mi.ptszPopupName = ServiceExists(MS_POPUP_ADDPOPUP) ? _T("PopUps") : NULL; + mi.pszService = MS_STATUSCHANGE_MENUCOMMAND; + hEnableDisableMenu = (HANDLE)CallService(MS_CLIST_ADDMAINMENUITEM, 0, (LPARAM)&mi); + + opt.TempDisabled = !opt.TempDisabled; + EnableDisableMenuCommand(0, 0); + + hServiceMenu = (HANDLE)CreateServiceFunction(MS_STATUSCHANGE_MENUCOMMAND, EnableDisableMenuCommand); +} + +struct _tag_iconList +{ + char *szDescr; + char *szName; + int iIconID; +} +static const iconList[] = +{ + { "Notification enabled", ICO_NOTIFICATION_OFF, IDI_NOTIFICATION_OFF }, + { "Notification disabled", ICO_NOTIFICATION_ON, IDI_NOTIFICATION_ON } +}; + +void InitIcolib() +{ + char szFile[MAX_PATH]; + char szSettingName[100]; + SKINICONDESC sid = {0}; + + sid.cbSize = sizeof(sid); + sid.cx = sid.cy = 16; + sid.pszDefaultFile = szFile; + sid.pszName = szSettingName; + sid.pszSection = MODULE; + + GetModuleFileNameA(hInst, szFile, MAX_PATH); + + for (int i = 0; i < SIZEOF(iconList); i++) + { + mir_snprintf(szSettingName, sizeof(szSettingName), "%s_%s", MODULE, iconList[i].szName); + sid.pszDescription = Translate(iconList[i].szDescr); + sid.iDefaultIndex = -iconList[i].iIconID; + CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid); + } +} + +void InitSound() +{ + for (int i = ID_STATUS_MIN; i <= ID_STATUS_MAX; i++) + SkinAddNewSoundEx(StatusList[Index(i)].lpzSkinSoundName, "Status Notify", StatusList[Index(i)].lpzSkinSoundDesc); + + SkinAddNewSoundEx("UserFromOffline", "Status Notify", Translate("User: from offline (has priority!)")); + SkinAddNewSoundEx(XSTATUS_SOUND_CHANGED, "Status Notify", "Extra status changed"); + SkinAddNewSoundEx(XSTATUS_SOUND_MSGCHANGED, "Status Notify", "Extra status message changed"); + SkinAddNewSoundEx(XSTATUS_SOUND_REMOVED, "Status Notify", "Extra status removed"); +} + +void InitTopToolbar() +{ + if (ServiceExists(MS_TB_ADDBUTTON)) + { + TBButton tbb = {0}; + tbb.cbSize = sizeof(TBButton); + tbb.pszServiceName = MS_STATUSCHANGE_MENUCOMMAND; + tbb.pszButtonID = "StatusNotificationToggle"; + tbb.pszButtonName = "Toggle status notification"; + tbb.pszTooltipUp = "Status notification enabled"; + tbb.pszTooltipDn = "Status notification disabled"; + tbb.hPrimaryIconHandle = GetIconHandle(ICO_NOTIFICATION_ON); + tbb.hSecondaryIconHandle = GetIconHandle(ICO_NOTIFICATION_OFF); + tbb.tbbFlags = (opt.TempDisabled ? TBBF_PUSHED : 0); + tbb.defPos = 20; + CallService(MS_TB_ADDBUTTON, 0, (LPARAM)&tbb); + } +} + +int ModulesLoaded(WPARAM wParam, LPARAM lParam) +{ + InitUpdaterSupport(); + InitMainMenuItem(); + InitTopToolbar(); + + eventList = li.List_Create(0, 10); + xstatusList = li.List_Create(0, 10); + + hUserInfoInitialise = HookEvent(ME_USERINFO_INITIALISE, UserInfoInitialise); + hContactStatusChanged = HookEvent(ME_STATUSCHANGE_CONTACTSTATUSCHANGED, ContactStatusChanged); + hMessageWindowOpen = HookEvent(ME_MSG_WINDOWEVENT, OnWindowEvent); + + int count = 0; + PROTOACCOUNT **accounts = NULL; + CallService(MS_PROTO_ENUMACCOUNTS, (WPARAM)&count, (LPARAM)&accounts); + for (int i = 0; i < count; i++) + { + if (IsAccountEnabled(accounts[i])) + DBWriteContactSettingByte(NULL, MODULE, accounts[i]->szModuleName, 0); + } + + if (ServiceExists(MS_MC_GETPROTOCOLNAME)) + strcpy(szMetaModuleName, (char *)CallService(MS_MC_GETPROTOCOLNAME, 0, 0)); + + return 0; +} + +extern "C" int __declspec(dllexport) Load(PLUGINLINK *link) +{ + pluginLink = link; + + if (mir_getMMI(&mmi) || mir_getLI(&li) || mir_getUTFI(&utfi)) + { + MessageBox(NULL, TranslateT("Cannot obtain required interfaces!\nPlugin will not be loaded until you upgrade Miranda IM to the newest version."), TranslateT("NewXstatusNotify"), MB_OK | MB_ICONSTOP); + return 1; + } + mir_getLP(&pluginInfoEx); + + //"Service" Hook, used when the DB settings change: we'll monitor the "status" setting. + hContactSettingChanged = HookEvent(ME_DB_CONTACT_SETTINGCHANGED, ContactSettingChanged); + //We create this Hook which will notify everyone when a contact changes his status. + hHookContactStatusChanged = CreateHookableEvent(ME_STATUSCHANGE_CONTACTSTATUSCHANGED); + hModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED, ModulesLoaded); + //We add the option page and the user info page (it's needed because options are loaded after plugins) + hOptionsInitialize = HookEvent(ME_OPT_INITIALISE, OptionsInitialize); + //This is needed for "NoSound"-like routines. + hStatusModeChange = HookEvent(ME_CLIST_STATUSMODECHANGE, StatusModeChanged); + hProtoAck = HookEvent(ME_PROTO_ACK, ProtoAck); + + LoadOptions(); + InitStatusList(); + InitIcolib(); + InitSound(); + + CallService(MS_DB_SETSETTINGRESIDENT, (WPARAM)TRUE, (LPARAM)"MetaContacts/LastOnline"); + CallService(MS_DB_SETSETTINGRESIDENT, (WPARAM)TRUE, (LPARAM)"NewStatusNotify/LastPopupText"); + return 0; +} + +extern "C" int __declspec(dllexport) Unload(void) +{ + li.List_Destroy(eventList); + li.List_Destroy(xstatusList); + mir_free(eventList); + mir_free(xstatusList); + + UnhookEvent(hContactSettingChanged); + UnhookEvent(hOptionsInitialize); + UnhookEvent(hModulesLoaded); + UnhookEvent(hUserInfoInitialise); + UnhookEvent(hStatusModeChange); + UnhookEvent(hProtoAck); + DestroyHookableEvent(hHookContactStatusChanged); + DestroyServiceFunction(hServiceMenu); + UnhookEvent(hMessageWindowOpen); + + return 0; +} \ No newline at end of file diff --git a/plugins/NewXstatusNotify/options.cpp b/plugins/NewXstatusNotify/options.cpp new file mode 100644 index 0000000000..1c05e976a4 --- /dev/null +++ b/plugins/NewXstatusNotify/options.cpp @@ -0,0 +1,1092 @@ +/* + NewXstatusNotify YM - Plugin for Miranda IM + Copyright (c) 2001-2004 Luca Santarelli + Copyright (c) 2005-2007 Vasilich + Copyright (c) 2007-2011 yaho + + 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 "indsnd.h" +#include "options.h" +#include "popup.h" +#include "xstatus.h" +#include "utils.h" + +OPTIONS opt = {0}; +TEMPLATES templates = {0}; +BOOL UpdateListFlag = FALSE; +SortedList *ProtoTamplates; +int LastItem = 0; + +extern HINSTANCE hInst; +extern HANDLE hEnableDisableMenu; +extern STATUS StatusList[STATUS_COUNT]; + +INT_PTR CALLBACK DlgProcAutoDisableOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); + +void LoadTemplates() +{ + DBGetStringDefault(0, MODULE, "TPopupDelimiter", templates.PopupDelimiter, SIZEOF(templates.PopupDelimiter), DEFAULT_POPUP_DELIMITER); + DBGetStringDefault(0, MODULE, "TPopupChange", templates.PopupNewXstatus, SIZEOF(templates.PopupNewXstatus), DEFAULT_POPUP_NEW); + DBGetStringDefault(0, MODULE, "TPopupChangeMsg", templates.PopupNewMsg, SIZEOF(templates.PopupNewMsg), DEFAULT_POPUP_CHANGEMSG); + DBGetStringDefault(0, MODULE, "TPopupRemoval", templates.PopupRemove, SIZEOF(templates.PopupRemove), DEFAULT_POPUP_REMOVE); + + DBGetStringDefault(0, MODULE, "TLogDelimiter", templates.LogDelimiter, SIZEOF(templates.LogDelimiter), DEFAULT_LOG_DELIMITER); + DBGetStringDefault(0, MODULE, "TLogChange", templates.LogNewXstatus, SIZEOF(templates.LogNewXstatus), DEFAULT_LOG_NEW); + DBGetStringDefault(0, MODULE, "TLogChangeMsg", templates.LogNewMsg, SIZEOF(templates.LogNewMsg), DEFAULT_LOG_CHANGEMSG); + DBGetStringDefault(0, MODULE, "TLogRemoval", templates.LogRemove, SIZEOF(templates.LogRemove), DEFAULT_LOG_REMOVE); + DBGetStringDefault(0, MODULE, "TLogOpening", templates.LogOpening, SIZEOF(templates.LogOpening), DEFAULT_LOG_OPENING); + templates.PopupFlags = DBGetContactSettingByte(0, MODULE, "TPopupFlags", NOTIFY_NEW_XSTATUS | NOTIFY_NEW_MESSAGE); + templates.LogFlags = DBGetContactSettingByte(0, MODULE, "TLogFlags", NOTIFY_NEW_XSTATUS | NOTIFY_NEW_MESSAGE | NOTIFY_OPENING_ML); +} + +void LoadOptions() +{ + // IDD_OPT_POPUP + opt.Colors = DBGetContactSettingByte(0,MODULE, "Colors", DEFAULT_COLORS); + opt.ShowGroup = DBGetContactSettingByte(0, MODULE, "ShowGroup", 0); + opt.ShowStatus = DBGetContactSettingByte(0, MODULE, "ShowStatus", 1); + opt.UseAlternativeText = DBGetContactSettingByte(0, MODULE, "UseAlternativeText", 0); + opt.ShowPreviousStatus = DBGetContactSettingByte(0, MODULE, "ShowPreviousStatus", 0); + opt.ReadAwayMsg = DBGetContactSettingByte(0, MODULE, "ReadAwayMsg", 0); + opt.PopupTimeout = DBGetContactSettingDword(0, MODULE, "PopupTimeout", 0); + opt.LeftClickAction= DBGetContactSettingByte(0, MODULE, "LeftClickAction", 5); + opt.RightClickAction = DBGetContactSettingByte(0, MODULE, "RightClickAction", 1); + // IDD_OPT_XPOPUP + opt.PDisableForMusic = DBGetContactSettingByte(0, MODULE, "PDisableForMusic", 1); + opt.PTruncateMsg = DBGetContactSettingByte(0, MODULE, "PTruncateMsg", 0); + opt.PMsgLen = DBGetContactSettingDword(0, MODULE, "PMsgLen", 64); + // IDD_OPT_GENERAL + opt.FromOffline = DBGetContactSettingByte(0, MODULE, "FromOffline", 1); + opt.AutoDisable = DBGetContactSettingByte(0, MODULE, "AutoDisable", 1); + opt.HiddenContactsToo = DBGetContactSettingByte(0, MODULE, "HiddenContactsToo", 1); + opt.UseIndSnd = DBGetContactSettingByte(0, MODULE, "UseIndSounds", 1); + opt.BlinkIcon = DBGetContactSettingByte(0, MODULE, "BlinkIcon", 0); + opt.BlinkIcon_Status = DBGetContactSettingByte(0, MODULE, "BlinkIcon_Status", 0); + opt.Log = DBGetContactSettingByte(0, MODULE, "Log", 0); + DBGetStringDefault(0, MODULE, "LogFilePath", opt.LogFilePath, MAX_PATH, _T("")); + // IDD_AUTODISABLE + opt.OnlyGlobalChanges = DBGetContactSettingByte(0, MODULE, "OnlyGlobalChanges", 1); + opt.DisablePopupGlobally = DBGetContactSettingByte(0, MODULE, "DisablePopupGlobally", 1); + opt.DisableSoundGlobally = DBGetContactSettingByte(0, MODULE, "DisableSoundGlobally", 1); + // IDD_OPT_XLOG + opt.EnableLogging = DBGetContactSettingByte(0, MODULE, "EnableLogging", 0); + opt.PreventIdentical = DBGetContactSettingByte(0, MODULE, "PreventIdentical", 1); + opt.KeepInHistory = DBGetContactSettingByte(0, MODULE, "KeepInHistory", 0); + opt.LDisableForMusic = DBGetContactSettingByte(0, MODULE, "LDisableForMusic", 1); + opt.LTruncateMsg = DBGetContactSettingByte(0, MODULE, "LTruncateMsg", 0); + opt.LMsgLen = DBGetContactSettingDword(0, MODULE, "LMsgLen", 128); + //IDD_OPT_SMPOPUP + opt.IgnoreEmpty = DBGetContactSettingByte(0, MODULE, "IgnoreEmpty", 1); + opt.PopupOnConnect = DBGetContactSettingByte(0, MODULE, "PopupOnConnect", 0); + // OTHER + opt.TempDisabled = DBGetContactSettingByte(0, MODULE, "TempDisable", 0); + + LoadTemplates(); + + return; +} + +void SaveTemplates() +{ + DBWriteContactSettingTString(0, MODULE, "TPopupDelimiter", templates.PopupDelimiter); + DBWriteContactSettingTString(0, MODULE, "TPopupChange", templates.PopupNewXstatus); + DBWriteContactSettingTString(0, MODULE, "TPopupChangeMsg", templates.PopupNewMsg); + DBWriteContactSettingTString(0, MODULE, "TPopupRemoval", templates.PopupRemove); + DBWriteContactSettingTString(0, MODULE, "TLogDelimiter", templates.LogDelimiter); + DBWriteContactSettingTString(0, MODULE, "TLogChange", templates.LogNewXstatus); + DBWriteContactSettingTString(0, MODULE, "TLogChangeMsg", templates.LogNewMsg); + DBWriteContactSettingTString(0, MODULE, "TLogRemoval", templates.LogRemove); + DBWriteContactSettingTString(0, MODULE, "TLogOpening", templates.LogOpening); + DBWriteContactSettingByte(0, MODULE, "TPopupFlags", templates.PopupFlags); + DBWriteContactSettingByte(0, MODULE, "TLogFlags", templates.LogFlags); + for (int i = 0; i < ProtoTamplates->realCount; i++) + { + PROTOTAMPLATE *prototamplate = (PROTOTAMPLATE *)ProtoTamplates->items[i]; + TCHAR str[MAX_PATH]; + mir_sntprintf(str, SIZEOF(str), _T("%s_TSMChange"), prototamplate->ProtoName); + char *szstr = mir_t2a(str); + DBWriteContactSettingTString(0, MODULE, szstr, prototamplate->ProtoTamplate); + } +} + +void SaveOptions() +{ + // IDD_OPT_POPUP + DBWriteContactSettingByte(0, MODULE, "Colors", opt.Colors); + DBWriteContactSettingByte(0, MODULE, "ShowGroup", opt.ShowGroup); + DBWriteContactSettingByte(0, MODULE, "ShowStatus", opt.ShowStatus); + DBWriteContactSettingByte(0, MODULE, "UseAlternativeText", opt.UseAlternativeText); + DBWriteContactSettingByte(0, MODULE, "ShowPreviousStatus", opt.ShowPreviousStatus); + DBWriteContactSettingByte(0, MODULE, "ReadAwayMsg", opt.ReadAwayMsg); + DBWriteContactSettingDword(0, MODULE, "PopupTimeout", opt.PopupTimeout); + DBWriteContactSettingByte(0, MODULE, "LeftClickAction", opt.LeftClickAction); + DBWriteContactSettingByte(0, MODULE, "RightClickAction", opt.RightClickAction); + // IDD_OPT_XPOPUP + DBWriteContactSettingByte(0, MODULE, "PDisableForMusic", opt.PDisableForMusic); + DBWriteContactSettingByte(0, MODULE, "PTruncateMsg", opt.PTruncateMsg); + DBWriteContactSettingDword(0, MODULE, "PMsgLen", opt.PMsgLen); + // IDD_OPT_GENERAL + DBWriteContactSettingByte(0, MODULE, "FromOffline", opt.FromOffline); + DBWriteContactSettingByte(0, MODULE, "AutoDisable", opt.AutoDisable); + DBWriteContactSettingByte(0, MODULE, "HiddenContactsToo", opt.HiddenContactsToo); + DBWriteContactSettingByte(0, MODULE, "UseIndSounds", opt.UseIndSnd); + DBWriteContactSettingByte(0, MODULE, "BlinkIcon", opt.BlinkIcon); + DBWriteContactSettingByte(0, MODULE, "BlinkIcon_Status", opt.BlinkIcon_Status); + DBWriteContactSettingByte(0, MODULE, "Log", opt.Log); + DBWriteContactSettingTString(0, MODULE, "LogFilePath", opt.LogFilePath); + // IDD_AUTODISABLE + DBWriteContactSettingByte(0, MODULE, "OnlyGlobalChanges", opt.OnlyGlobalChanges); + DBWriteContactSettingByte(0, MODULE, "DisablePopupGlobally", opt.DisablePopupGlobally); + DBWriteContactSettingByte(0, MODULE, "DisableSoundGlobally", opt.DisableSoundGlobally); + // IDD_OPT_XLOG + DBWriteContactSettingByte(0, MODULE, "EnableLogging", opt.EnableLogging); + DBWriteContactSettingByte(0, MODULE, "PreventIdentical", opt.PreventIdentical); + DBWriteContactSettingByte(0, MODULE, "KeepInHistory", opt.KeepInHistory); + DBWriteContactSettingByte(0, MODULE, "LDisableForMusic", opt.LDisableForMusic); + DBWriteContactSettingByte(0, MODULE, "LTruncateMsg", opt.LTruncateMsg); + DBWriteContactSettingDword(0, MODULE, "LMsgLen", opt.LMsgLen); + //IDD_OPT_SMPOPUP + DBWriteContactSettingByte(0, MODULE, "IgnoreEmpty", opt.IgnoreEmpty); + DBWriteContactSettingByte(0, MODULE, "PopupOnConnect", opt.PopupOnConnect); +} + +INT_PTR CALLBACK DlgProcGeneralOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + case WM_INITDIALOG: + { + TranslateDialogDefault(hwndDlg); + + CheckDlgButton(hwndDlg, IDC_AUTODISABLE, opt.AutoDisable); + EnableWindow(GetDlgItem(hwndDlg, IDC_CONFIGUREAUTODISABLE), opt.AutoDisable); + + CheckDlgButton(hwndDlg, IDC_HIDDENCONTACTSTOO, opt.HiddenContactsToo); + CheckDlgButton(hwndDlg, IDC_USEINDIVSOUNDS, opt.UseIndSnd); + CheckDlgButton(hwndDlg, IDC_BLINKICON, opt.BlinkIcon); + CheckDlgButton(hwndDlg, IDC_BLINKICON_STATUS, opt.BlinkIcon_Status); + EnableWindow(GetDlgItem(hwndDlg, IDC_BLINKICON_STATUS), opt.BlinkIcon); + + CheckDlgButton(hwndDlg, IDC_LOG, opt.Log); + SetDlgItemText(hwndDlg, IDC_LOGFILE, opt.LogFilePath); + EnableWindow(GetDlgItem(hwndDlg, IDC_LOGFILE), opt.Log); + EnableWindow(GetDlgItem(hwndDlg, IDC_BT_CHOOSELOGFILE), opt.Log); + EnableWindow(GetDlgItem(hwndDlg, IDC_BT_VIEWLOG), opt.Log); + + //Statuses notified + char status[8]; + for (int i = ID_STATUS_MIN; i <= ID_STATUS_MAX2; i++) + { + wsprintfA(status, "%d", i); + CheckDlgButton(hwndDlg, i, DBGetContactSettingByte(0, MODULE, status, 1)); + } + CheckDlgButton(hwndDlg, IDC_CHK_FROMOFFLINE, opt.FromOffline); + + return TRUE; + } + case WM_COMMAND: + { + switch(LOWORD(wParam)) + { + case IDC_CONFIGUREAUTODISABLE: + CreateDialog(hInst, MAKEINTRESOURCE(IDD_AUTODISABLE), hwndDlg, DlgProcAutoDisableOpts); + return FALSE; + case IDC_AUTODISABLE: + EnableWindow(GetDlgItem(hwndDlg, IDC_CONFIGUREAUTODISABLE), IsDlgButtonChecked(hwndDlg, IDC_AUTODISABLE)); + break; + case IDC_BLINKICON: + EnableWindow(GetDlgItem(hwndDlg, IDC_BLINKICON_STATUS), IsDlgButtonChecked(hwndDlg, IDC_BLINKICON)); + break; + case IDC_BT_VIEWLOG: + ShowLog(opt.LogFilePath); + return FALSE; + case IDC_BT_CHOOSELOGFILE: + { + TCHAR buff[MAX_PATH]; + OPENFILENAME ofn = {0}; + + GetDlgItemText(hwndDlg, IDC_LOGFILE, buff, MAX_PATH); + + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.lpstrFile = buff; + ofn.nMaxFile = MAX_PATH; + ofn.hwndOwner = hwndDlg; + TCHAR filter[MAX_PATH]; + mir_sntprintf(filter, SIZEOF(filter), _T("%s (*.*)%c*.*%c%s (*.log)%c*.log%c%s (*.txt)%c*.txt%c"), TranslateT("All Files"), 0, 0, TranslateT("Log"), 0, 0, TranslateT("Text"), 0, 0); + ofn.lpstrFilter = filter; + ofn.nFilterIndex = 2; + ofn.lpstrInitialDir = buff; + ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY; + ofn.lpstrDefExt = _T("log"); + if (GetSaveFileName(&ofn)) + SetDlgItemText(hwndDlg, IDC_LOGFILE, buff); + + break; + } + case IDC_LOG: + EnableWindow(GetDlgItem(hwndDlg, IDC_LOGFILE), IsDlgButtonChecked(hwndDlg, IDC_LOG)); + EnableWindow(GetDlgItem(hwndDlg, IDC_BT_CHOOSELOGFILE), IsDlgButtonChecked(hwndDlg, IDC_LOG)); + EnableWindow(GetDlgItem(hwndDlg, IDC_BT_VIEWLOG), IsDlgButtonChecked(hwndDlg, IDC_LOG)); + break; + case IDC_HYPERLINK: + { + OPENOPTIONSDIALOG ood = {0}; + ood.cbSize = sizeof(ood); + ood.pszGroup = "Customize"; + ood.pszPage = "Sounds"; + CallService(MS_OPT_OPENOPTIONS, 0, (LPARAM)&ood); + return FALSE; + } + } + + if (HIWORD(wParam) == BN_CLICKED || (HIWORD(wParam) == EN_CHANGE && (HWND)lParam == GetFocus())) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + + break; + } + case WM_NOTIFY: + { + if (((LPNMHDR)lParam)->code == PSN_APPLY) + { + opt.AutoDisable = IsDlgButtonChecked(hwndDlg, IDC_AUTODISABLE); + opt.BlinkIcon = IsDlgButtonChecked(hwndDlg, IDC_BLINKICON); + opt.BlinkIcon_Status = IsDlgButtonChecked(hwndDlg, IDC_BLINKICON_STATUS); + opt.HiddenContactsToo = IsDlgButtonChecked(hwndDlg, IDC_HIDDENCONTACTSTOO); + opt.UseIndSnd = IsDlgButtonChecked(hwndDlg, IDC_USEINDIVSOUNDS); + + opt.Log = IsDlgButtonChecked(hwndDlg, IDC_LOG); + GetDlgItemText(hwndDlg, IDC_LOGFILE, opt.LogFilePath, SIZEOF(opt.LogFilePath)); + + //Notified statuses + char status[8]; + for (int i = ID_STATUS_MIN; i <= ID_STATUS_MAX2; i++) + { + wsprintfA(status, "%d", i); + DBWriteContactSettingByte(NULL, MODULE, status, (BYTE)IsDlgButtonChecked(hwndDlg, i)); + } + opt.FromOffline = IsDlgButtonChecked(hwndDlg, IDC_CHK_FROMOFFLINE); + + SaveOptions(); + return TRUE; + } + } + } + + return FALSE; +} + +void EnablePopupTextControls(HWND hwndDlg, BOOL bEnable) +{ + EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWALTDESCS), bEnable); + EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWPREVIOUSSTATUS), bEnable); + //EnableWindow(GetDlgItem(hwndDlg, IDC_READAWAYMSG), bEnable); +} + +INT_PTR CALLBACK DlgProcPopUpOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + case WM_INITDIALOG: + { + TranslateDialogDefault(hwndDlg); + + CheckDlgButton(hwndDlg, IDC_USEOWNCOLORS, (opt.Colors == POPUP_COLOR_OWN) ? 1 : 0); + CheckDlgButton(hwndDlg, IDC_USEPOPUPCOLORS, (opt.Colors == POPUP_COLOR_POPUP) ? 1 : 0); + CheckDlgButton(hwndDlg, IDC_USEWINCOLORS, (opt.Colors == POPUP_COLOR_WINDOWS) ? 1 : 0); + + for (int i = ID_STATUS_MIN; i <= ID_STATUS_MAX2 - 1; i++) + { + SendDlgItemMessage(hwndDlg, (i+2000), CPM_SETCOLOUR, 0, StatusList[Index(i)].colorBack); + SendDlgItemMessage(hwndDlg, (i+1000), CPM_SETCOLOUR, 0, StatusList[Index(i)].colorText); + EnableWindow(GetDlgItem(hwndDlg, (i+2000)), (opt.Colors == POPUP_COLOR_OWN)); + EnableWindow(GetDlgItem(hwndDlg, (i+1000)), (opt.Colors == POPUP_COLOR_OWN)); + } + + CheckDlgButton(hwndDlg, IDC_SHOWSTATUS, opt.ShowStatus); + CheckDlgButton(hwndDlg, IDC_SHOWALTDESCS, opt.UseAlternativeText); + CheckDlgButton(hwndDlg, IDC_READAWAYMSG, opt.ReadAwayMsg); + CheckDlgButton(hwndDlg, IDC_SHOWPREVIOUSSTATUS, opt.ShowPreviousStatus); + CheckDlgButton(hwndDlg, IDC_SHOWGROUP, opt.ShowGroup); + + SendDlgItemMessage(hwndDlg, IDC_TIMEOUT_VALUE, EM_LIMITTEXT, 3, 0); + SendDlgItemMessage(hwndDlg, IDC_TIMEOUT_VALUE_SPIN, UDM_SETRANGE32, -1, 999); + SetDlgItemInt(hwndDlg, IDC_TIMEOUT_VALUE, opt.PopupTimeout, TRUE); + + //Mouse actions + for (int i = 0; i < SIZEOF(PopupActions); i++) + { + SendMessage(GetDlgItem(hwndDlg, IDC_STATUS_LC), CB_SETITEMDATA, SendMessage(GetDlgItem(hwndDlg, IDC_STATUS_LC), CB_ADDSTRING, 0, (LPARAM)TranslateTS(PopupActions[i].Text)), PopupActions[i].Action); + SendMessage(GetDlgItem(hwndDlg, IDC_STATUS_RC), CB_SETITEMDATA, SendMessage(GetDlgItem(hwndDlg, IDC_STATUS_RC), CB_ADDSTRING, 0, (LPARAM)TranslateTS(PopupActions[i].Text)), PopupActions[i].Action); + } + + SendDlgItemMessage(hwndDlg, IDC_STATUS_LC, CB_SETCURSEL, opt.LeftClickAction, 0); + SendDlgItemMessage(hwndDlg, IDC_STATUS_RC, CB_SETCURSEL, opt.RightClickAction, 0); + + EnablePopupTextControls(hwndDlg, opt.ShowStatus); + + return TRUE; + } + case WM_COMMAND: + { + WORD idCtrl = LOWORD(wParam); + if (HIWORD(wParam) == CPN_COLOURCHANGED) + { + if(idCtrl > 40070) + { + COLORREF colour = SendDlgItemMessage(hwndDlg, idCtrl, CPM_GETCOLOUR, 0, 0); + if ((idCtrl > 41070) && (idCtrl < 42070)) //Text colour + StatusList[Index(idCtrl - 1000)].colorText = colour; + else //Background colour + StatusList[Index(idCtrl - 2000)].colorBack = colour; + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + return TRUE; + } + } + + if (HIWORD(wParam) == BN_CLICKED) + { + switch(idCtrl) + { + case IDC_USEOWNCOLORS: + case IDC_USEWINCOLORS: + case IDC_USEPOPUPCOLORS: + { + for (int i = ID_STATUS_MIN; i <= ID_STATUS_MAX2 - 1; i++) + { + EnableWindow(GetDlgItem(hwndDlg, (i+2000)), idCtrl == IDC_USEOWNCOLORS); //Background + EnableWindow(GetDlgItem(hwndDlg, (i+1000)), idCtrl == IDC_USEOWNCOLORS); //Text + } + + break; + } + case IDC_SHOWSTATUS: + { + EnablePopupTextControls(hwndDlg, IsDlgButtonChecked(hwndDlg, IDC_SHOWSTATUS)); + break; + } + case IDC_PREVIEW: + { + POPUPDATAT ppd = {0}; + ppd.iSeconds = opt.PopupTimeout; + + for (int i = ID_STATUS_MIN; i <= (ID_STATUS_MAX+1); i++) + { + WORD status = i <= ID_STATUS_MAX2 ? i : ID_STATUS_MIN; + ppd.lchIcon = LoadSkinnedIcon(StatusList[Index(status)].icon); + + _tcscpy(ppd.lptzContactName, (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)NULL, GSMDF_TCHAR)); + _tcscpy(ppd.lptzText, _T("")); + + if (opt.ShowStatus) + { + if (opt.UseAlternativeText == 1) + _tcscpy(ppd.lptzText, StatusList[Index(status)].lpzUStatusText); + else + _tcscpy(ppd.lptzText, StatusList[Index(status)].lpzStandardText); + + if (opt.ShowPreviousStatus) + { + TCHAR buff[MAX_STATUSTEXT]; + mir_sntprintf(buff, SIZEOF(buff), TranslateTS(STRING_SHOWPREVIOUSSTATUS), StatusList[Index(status)].lpzStandardText); + mir_sntprintf(ppd.lptzText, SIZEOF(ppd.lptzText), _T("%s %s"), ppd.lptzText, buff); + } + } + + if (opt.ReadAwayMsg) + { + if (ppd.lptzText[0]) _tcscat(ppd.lptzText, _T("\n")); + _tcscat(ppd.lptzText, TranslateT("This is status message")); + } + + switch (opt.Colors) + { + case POPUP_COLOR_WINDOWS: + ppd.colorBack = GetSysColor(COLOR_BTNFACE); + ppd.colorText = GetSysColor(COLOR_WINDOWTEXT); + break; + case POPUP_COLOR_OWN: + ppd.colorBack = StatusList[Index(status)].colorBack; + ppd.colorText = StatusList[Index(status)].colorText; + break; + case POPUP_COLOR_POPUP: + ppd.colorBack = ppd.colorText = 0; + break; + } + + PUAddPopUpT(&ppd); + } + + return FALSE; + } + } + } + + if ((HIWORD(wParam) == BN_CLICKED || HIWORD(wParam) == CBN_SELCHANGE || HIWORD(wParam) == EN_CHANGE) && (HWND)lParam == GetFocus()) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + + break; + } + case WM_NOTIFY: + { + if (((LPNMHDR)lParam)->code == PSN_APPLY) + { + char str[8]; + DWORD ctlColour = 0; + for (int i = ID_STATUS_MIN; i <= ID_STATUS_MAX2 - 1; i++) + { + ctlColour = SendDlgItemMessage(hwndDlg, (i+2000), CPM_GETCOLOUR, 0, 0); + StatusList[Index(i)].colorBack = SendDlgItemMessage(hwndDlg, (i+2000), CPM_GETCOLOUR, 0, 0); + wsprintfA(str, "%ibg", i); + DBWriteContactSettingDword(0, MODULE, str, ctlColour); + + ctlColour = SendDlgItemMessage(hwndDlg, (i+1000), CPM_GETCOLOUR, 0, 0); + StatusList[Index(i)].colorText = ctlColour; + wsprintfA(str, "%itx", i); + DBWriteContactSettingDword(0, MODULE, str, ctlColour); + } + + if (IsDlgButtonChecked(hwndDlg, IDC_USEOWNCOLORS)) + opt.Colors = POPUP_COLOR_OWN; + else if (IsDlgButtonChecked(hwndDlg, IDC_USEPOPUPCOLORS)) + opt.Colors = POPUP_COLOR_POPUP; + else + opt.Colors = POPUP_COLOR_WINDOWS; + + opt.ShowStatus = IsDlgButtonChecked(hwndDlg, IDC_SHOWSTATUS); + opt.UseAlternativeText = IsDlgButtonChecked(hwndDlg, IDC_SHOWALTDESCS); + opt.ReadAwayMsg = IsDlgButtonChecked(hwndDlg, IDC_READAWAYMSG); + opt.ShowPreviousStatus = IsDlgButtonChecked(hwndDlg, IDC_SHOWPREVIOUSSTATUS); + opt.ShowGroup = IsDlgButtonChecked(hwndDlg, IDC_SHOWGROUP); + opt.PopupTimeout = GetDlgItemInt(hwndDlg, IDC_TIMEOUT_VALUE, 0, TRUE); + opt.LeftClickAction = (BYTE)SendDlgItemMessage(hwndDlg, IDC_STATUS_LC, CB_GETCURSEL, 0, 0); + opt.RightClickAction = (BYTE)SendDlgItemMessage(hwndDlg, IDC_STATUS_RC, CB_GETCURSEL, 0, 0); + + SaveOptions(); + return TRUE; + } + + break; + } + } + + return FALSE; +} + +INT_PTR CALLBACK DlgProcAutoDisableOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + case WM_INITDIALOG: + { + TranslateDialogDefault(hwndDlg); + CheckDlgButton(hwndDlg, IDC_CHK_PGLOBAL, opt.DisablePopupGlobally); + CheckDlgButton(hwndDlg, IDC_CHK_SGLOBAL, opt.DisableSoundGlobally); + CheckDlgButton(hwndDlg, IDC_CHK_ONLYGLOBAL, opt.OnlyGlobalChanges); + + char str[8]; + for (int i = ID_STATUS_MIN; i <= ID_STATUS_MAX; i++) + { + wsprintfA(str, "p%d", i); + CheckDlgButton(hwndDlg, i, DBGetContactSettingByte(0, MODULE, str, 0)); + } + + for (int i = ID_STATUS_MIN; i <= ID_STATUS_MAX; i++) + { + wsprintfA(str, "s%d", i); + CheckDlgButton(hwndDlg, (i+2000),DBGetContactSettingByte(NULL, MODULE, str, 0)); + } + + return TRUE; + } + case WM_COMMAND: + { + switch (LOWORD(wParam)) + { + case IDC_OK: + char str[8]; + opt.DisablePopupGlobally = IsDlgButtonChecked(hwndDlg, IDC_CHK_PGLOBAL); + opt.DisableSoundGlobally = IsDlgButtonChecked(hwndDlg, IDC_CHK_SGLOBAL); + opt.OnlyGlobalChanges = IsDlgButtonChecked(hwndDlg, IDC_CHK_ONLYGLOBAL); + + for (int i = ID_STATUS_MIN; i <= ID_STATUS_MAX; i++) + { + wsprintfA(str, "p%d", i); + DBWriteContactSettingByte(NULL, MODULE, str, IsDlgButtonChecked(hwndDlg, i)); + } + for (int i = ID_STATUS_MIN; i <= ID_STATUS_MAX; i++) + { + wsprintfA(str, "s%d", i); + DBWriteContactSettingByte(NULL, MODULE, str, IsDlgButtonChecked(hwndDlg, i+2000)); + } + + SaveOptions(); + //Fall through + case IDC_CANCEL: + DestroyWindow(hwndDlg); + break; + } + break; + } + case WM_CLOSE: + { + DestroyWindow(hwndDlg); + break; + } + } + + return FALSE; +} + +int ResetTemplatesToDefault(HWND hwndDlg) +{ + int result = MessageBox(hwndDlg, + TranslateT("Do you want to reset all templates to default?"), + TranslateT("Reset templates"), + MB_ICONQUESTION | MB_YESNO); + if (result == IDYES) + { + SetDlgItemText(hwndDlg, IDC_ED_TDELIMITER, DEFAULT_POPUP_DELIMITER); + SetDlgItemText(hwndDlg, IDC_ED_TCHANGE, DEFAULT_POPUP_NEW); + SetDlgItemText(hwndDlg, IDC_ED_TCHANGEMSG, DEFAULT_POPUP_CHANGEMSG); + SetDlgItemText(hwndDlg, IDC_ED_TREMOVE, DEFAULT_POPUP_REMOVE); + SetDlgItemText(hwndDlg, IDC_POPUPTEXT, TranslateT(DEFAULT_POPUP_STATUSMESSAGE)); + CheckDlgButton(hwndDlg, IDC_CHK_XSTATUSCHANGE, 1); + CheckDlgButton(hwndDlg, IDC_CHK_MSGCHANGE, 1); + CheckDlgButton(hwndDlg, IDC_CHK_REMOVE, 1); + EnableWindow(GetDlgItem(hwndDlg, IDC_ED_TCHANGE), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_ED_TCHANGEMSG), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_ED_TREMOVE), TRUE); + } + + return result; +} + +INT_PTR CALLBACK DlgProcXPopupOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + case WM_INITDIALOG: + { + TranslateDialogDefault(hwndDlg); + + SendDlgItemMessage(hwndDlg, IDC_ED_MSGLEN, EM_LIMITTEXT, 3, 0); + SendDlgItemMessage(hwndDlg, IDC_UD_MSGLEN, UDM_SETRANGE, 0, MAKELONG(999, 1)); + + CheckDlgButton(hwndDlg, IDC_CHK_DISABLEMUSIC, opt.PDisableForMusic); + CheckDlgButton(hwndDlg, IDC_CHK_CUTMSG, opt.PTruncateMsg); + SetDlgItemInt(hwndDlg, IDC_ED_MSGLEN, opt.PMsgLen, FALSE); + + // Templates + CheckDlgButton(hwndDlg, IDC_CHK_XSTATUSCHANGE, templates.PopupFlags & NOTIFY_NEW_XSTATUS ? 1 : 0); + CheckDlgButton(hwndDlg, IDC_CHK_MSGCHANGE, templates.PopupFlags & NOTIFY_NEW_MESSAGE ? 1 : 0); + CheckDlgButton(hwndDlg, IDC_CHK_REMOVE, templates.PopupFlags & NOTIFY_REMOVE ? 1 : 0); + + SetDlgItemText(hwndDlg, IDC_ED_TDELIMITER, templates.PopupDelimiter); + SetDlgItemText(hwndDlg, IDC_ED_TCHANGE, templates.PopupNewXstatus); + SetDlgItemText(hwndDlg, IDC_ED_TCHANGEMSG, templates.PopupNewMsg); + SetDlgItemText(hwndDlg, IDC_ED_TREMOVE, templates.PopupRemove); + + EnableWindow(GetDlgItem(hwndDlg, IDC_ED_TCHANGE), templates.PopupFlags & NOTIFY_NEW_XSTATUS); + EnableWindow(GetDlgItem(hwndDlg, IDC_ED_TCHANGEMSG), templates.PopupFlags & NOTIFY_NEW_MESSAGE); + EnableWindow(GetDlgItem(hwndDlg, IDC_ED_TREMOVE), templates.PopupFlags & NOTIFY_REMOVE); + + // Buttons + SendDlgItemMessage(hwndDlg, IDC_BT_VARIABLES, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Show available variables"), BATF_TCHAR); + HICON hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_VARIABLES)); + SendDlgItemMessage(hwndDlg, IDC_BT_VARIABLES, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon); + DestroyIcon(hIcon); + + SendDlgItemMessage(hwndDlg, IDC_BT_RESET, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Reset all templates to default"), BATF_TCHAR); + hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_RESET)); + SendDlgItemMessage(hwndDlg, IDC_BT_RESET, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon); + DestroyIcon(hIcon); + + return TRUE; + } + case WM_COMMAND: + { + switch (HIWORD(wParam)) + { + case BN_CLICKED: + { + switch (LOWORD(wParam)) + { + case IDC_CHK_CUTMSG: + EnableWindow(GetDlgItem(hwndDlg, IDC_ED_MSGLEN), IsDlgButtonChecked(hwndDlg, IDC_CHK_CUTMSG)); + break; + case IDC_CHK_XSTATUSCHANGE: + EnableWindow(GetDlgItem(hwndDlg, IDC_ED_TCHANGE), IsDlgButtonChecked(hwndDlg, IDC_CHK_XSTATUSCHANGE)); + break; + case IDC_CHK_MSGCHANGE: + EnableWindow(GetDlgItem(hwndDlg, IDC_ED_TCHANGEMSG), IsDlgButtonChecked(hwndDlg, IDC_CHK_MSGCHANGE)); + break; + case IDC_CHK_REMOVE: + EnableWindow(GetDlgItem(hwndDlg, IDC_ED_TREMOVE), IsDlgButtonChecked(hwndDlg, IDC_CHK_REMOVE)); + break; + case IDC_BT_VARIABLES: + MessageBox(hwndDlg, VARIABLES_HELP_TEXT, TranslateT("Variables"), MB_OK | MB_ICONINFORMATION); + break; + case IDC_BT_RESET: + if (ResetTemplatesToDefault(hwndDlg) == IDYES) break; + else return FALSE; + } + + if (LOWORD(wParam) != IDC_BT_VARIABLES) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + + break; + } + case EN_CHANGE: + { + if ((HWND)lParam == GetFocus()) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + } + + } + + return TRUE; + } + case WM_NOTIFY: + { + if (((LPNMHDR)lParam)->code == PSN_APPLY ) + { + opt.PDisableForMusic = IsDlgButtonChecked(hwndDlg, IDC_CHK_DISABLEMUSIC); + opt.PTruncateMsg = IsDlgButtonChecked(hwndDlg, IDC_CHK_CUTMSG); + opt.PMsgLen = GetDlgItemInt(hwndDlg, IDC_ED_MSGLEN, 0, FALSE); + + templates.PopupFlags = 0; + templates.PopupFlags |= (IsDlgButtonChecked(hwndDlg, IDC_CHK_XSTATUSCHANGE) ? NOTIFY_NEW_XSTATUS : 0) | + (IsDlgButtonChecked(hwndDlg, IDC_CHK_MSGCHANGE) ? NOTIFY_NEW_MESSAGE : 0) | + (IsDlgButtonChecked(hwndDlg, IDC_CHK_REMOVE) ? NOTIFY_REMOVE : 0); + + // Templates + GetDlgItemText(hwndDlg, IDC_ED_TDELIMITER, templates.PopupDelimiter, SIZEOF(templates.PopupDelimiter)); + GetDlgItemText(hwndDlg, IDC_ED_TCHANGE, templates.PopupNewXstatus, SIZEOF(templates.PopupNewXstatus)); + GetDlgItemText(hwndDlg, IDC_ED_TCHANGEMSG, templates.PopupNewMsg, SIZEOF(templates.PopupNewMsg)); + GetDlgItemText(hwndDlg, IDC_ED_TREMOVE, templates.PopupRemove, SIZEOF(templates.PopupRemove)); + + // Save options to db + SaveOptions(); + SaveTemplates(); + } + + return TRUE; + } + } + + return FALSE; +} + +bool IsSuitableProto( PROTOACCOUNT* pa ) +{ + if ( pa == NULL ) + return false; + + if ( pa->bDynDisabled || !pa->bIsEnabled ) + return false; + + if ( CallProtoService( pa->szProtoName, PS_GETCAPS, PFLAGNUM_2, 0 ) == 0 ) + return false; + + return true; +} + +INT_PTR CALLBACK DlgProcSMPopupOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + case WM_INITDIALOG: + { + TranslateDialogDefault(hwndDlg); + CheckDlgButton(hwndDlg, IDC_ONCONNECT, opt.PopupOnConnect); + CheckDlgButton(hwndDlg, IDC_PUIGNOREREMOVE, opt.IgnoreEmpty); + + // Buttons + SendDlgItemMessage(hwndDlg, IDC_BT_VARIABLES, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Show available variables"), BATF_TCHAR); + HICON hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_VARIABLES)); + SendDlgItemMessage(hwndDlg, IDC_BT_VARIABLES, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon); + DestroyIcon(hIcon); + + SendDlgItemMessage(hwndDlg, IDC_BT_RESET, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Reset all templates to default"), BATF_TCHAR); + hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_RESET)); + SendDlgItemMessage(hwndDlg, IDC_BT_RESET, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon); + DestroyIcon(hIcon); + + // proto list + HWND hList = GetDlgItem(hwndDlg, IDC_PROTOCOLLIST); + SendMessage(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES); + LVCOLUMN lvCol = {0}; + lvCol.mask = LVCF_WIDTH|LVCF_TEXT; + lvCol.pszText=TranslateT("Protocol"); + lvCol.cx = 118; + ListView_InsertColumn(hList, 0, &lvCol); + // fill the list + LVITEM lvItem = {0}; + lvItem.mask=LVIF_TEXT|LVIF_PARAM; + lvItem.iItem=0; + lvItem.iSubItem=0; + + int count; + PROTOACCOUNT** protos; + ProtoEnumAccounts( &count, &protos ); + ProtoTamplates = li.List_Create(0, 10); + + for(int i=0;itszAccountName; + lvItem.lParam = (LPARAM)protos[i]->szModuleName; + PROTOTAMPLATE *prototamplate = (PROTOTAMPLATE *)mir_alloc(sizeof(PROTOTAMPLATE)); + prototamplate->ProtoName = protos[i]->tszAccountName; + TCHAR protoname[MAX_PATH] = {0}; + mir_sntprintf(protoname, SIZEOF(protoname), _T("%s_TSMChange"), protos[i]->tszAccountName); + char *szprotoname = mir_t2a(protoname); + DBVARIANT dbVar = {0}; + DBGetContactSettingTString(NULL, MODULE, szprotoname, &dbVar); + if (lstrcmp(dbVar.ptszVal, NULL) == 0) + { + DBFreeVariant(&dbVar); + _tcsncpy(prototamplate->ProtoTamplate, TranslateT(DEFAULT_POPUP_STATUSMESSAGE), SIZEOF(prototamplate->ProtoTamplate)); + } + else + { + _tcsncpy(prototamplate->ProtoTamplate, dbVar.ptszVal, SIZEOF(prototamplate->ProtoTamplate)); + } + mir_free(szprotoname); + ListView_InsertItem(hList,&lvItem); + li.List_Insert(ProtoTamplates, prototamplate, ProtoTamplates->realCount); + + char dbSetting[128]; + mir_snprintf(dbSetting, SIZEOF(dbSetting), "%s_enabled", protos[i]->szModuleName); + ListView_SetCheckState(hList, lvItem.iItem, DBGetContactSettingByte(NULL, MODULE, dbSetting, TRUE)); + lvItem.iItem++; + } + UpdateListFlag = FALSE; + return TRUE; + } + case WM_COMMAND: + { + switch (HIWORD(wParam)) + { + case BN_CLICKED: + { + switch (LOWORD(wParam)) + { + case IDC_BT_VARIABLES: + MessageBox(0, VARIABLES_SM_HELP_TEXT, TranslateT("Variables"), MB_OK | MB_ICONINFORMATION); + break; + + case IDC_BT_RESET: + if (ResetTemplatesToDefault(hwndDlg) == IDYES) break; + else return FALSE; + } + + if (LOWORD(wParam) != IDC_BT_VARIABLES) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + + break; + } + case EN_CHANGE: + { + if ((HWND)lParam == GetFocus()) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + } + + } + return TRUE; + } + case WM_NOTIFY: + { + if (((NMHDR*)lParam)->idFrom == IDC_PROTOCOLLIST) { + switch(((NMHDR*)lParam)->code) { + case LVN_ITEMCHANGED: + { + NMLISTVIEW *nmlv = (NMLISTVIEW *)lParam; + if (nmlv->uNewState == 3 && !UpdateListFlag) + { + HWND hList = GetDlgItem(hwndDlg,IDC_PROTOCOLLIST); + PROTOTAMPLATE *prototamplate; + if (ListView_GetHotItem(hList) != ListView_GetSelectionMark(hList)) + { + prototamplate = (PROTOTAMPLATE *)ProtoTamplates->items[ListView_GetSelectionMark(hList)]; + GetDlgItemText(hwndDlg, IDC_POPUPTEXT, prototamplate->ProtoTamplate, MAX_PATH); + li.List_Remove(ProtoTamplates, ListView_GetSelectionMark(hList)); + li.List_Insert(ProtoTamplates, prototamplate, ListView_GetSelectionMark(hList)); + + } + LastItem = ListView_GetHotItem(hList); + prototamplate = (PROTOTAMPLATE *)ProtoTamplates->items[LastItem]; + SetDlgItemText(hwndDlg, IDC_POPUPTEXT, prototamplate->ProtoTamplate); + } + if ((nmlv->uNewState^nmlv->uOldState)&LVIS_STATEIMAGEMASK && !UpdateListFlag) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + break; + } } + if (((LPNMHDR)lParam)->code == PSN_APPLY ) + { + + opt.IgnoreEmpty = IsDlgButtonChecked(hwndDlg, IDC_PUIGNOREREMOVE); + opt.PopupOnConnect = IsDlgButtonChecked(hwndDlg, IDC_ONCONNECT); + + // Templates + PROTOTAMPLATE *prototamplate = (PROTOTAMPLATE *)ProtoTamplates->items[LastItem]; + GetDlgItemText(hwndDlg, IDC_POPUPTEXT, prototamplate->ProtoTamplate, MAX_PATH); + li.List_Remove(ProtoTamplates, LastItem); + li.List_Insert(ProtoTamplates, prototamplate, LastItem); + + // Save options to db + SaveOptions(); + SaveTemplates(); + HWND hList = GetDlgItem(hwndDlg,IDC_PROTOCOLLIST); + LVITEM lvItem = {0}; + lvItem.mask=LVIF_PARAM; + for (int i=0;icode == PSN_APPLY ) + { + opt.EnableLogging = IsDlgButtonChecked(hwndDlg, IDC_CHK_LOGGING); + opt.KeepInHistory = IsDlgButtonChecked(hwndDlg, IDC_CHK_SAVETOHISTORY); + opt.PreventIdentical = IsDlgButtonChecked(hwndDlg, IDC_CHK_PREVENTIDENTICAL); + opt.LDisableForMusic = IsDlgButtonChecked(hwndDlg, IDC_CHK_DISABLEMUSIC); + opt.LTruncateMsg = IsDlgButtonChecked(hwndDlg, IDC_CHK_CUTMSG); + opt.LMsgLen = GetDlgItemInt(hwndDlg, IDC_ED_MSGLEN, 0, FALSE); + + templates.LogFlags = 0; + templates.LogFlags |= (IsDlgButtonChecked(hwndDlg, IDC_CHK_XSTATUSCHANGE) ? NOTIFY_NEW_XSTATUS : 0) | + (IsDlgButtonChecked(hwndDlg, IDC_CHK_MSGCHANGE) ? NOTIFY_NEW_MESSAGE : 0) | + (IsDlgButtonChecked(hwndDlg, IDC_CHK_REMOVE) ? NOTIFY_REMOVE : 0) | + (IsDlgButtonChecked(hwndDlg, IDC_CHK_OPENING) ? NOTIFY_OPENING_ML : 0); + + // Templates + GetDlgItemText(hwndDlg, IDC_ED_TDELIMITER, templates.LogDelimiter, SIZEOF(templates.LogDelimiter)); + GetDlgItemText(hwndDlg, IDC_ED_TCHANGE, templates.LogNewXstatus, SIZEOF(templates.LogNewXstatus)); + GetDlgItemText(hwndDlg, IDC_ED_TCHANGEMSG, templates.LogNewMsg, SIZEOF(templates.LogNewMsg)); + GetDlgItemText(hwndDlg, IDC_ED_TREMOVE, templates.LogRemove, SIZEOF(templates.LogRemove)); + GetDlgItemText(hwndDlg, IDC_ED_TOPENING, templates.LogOpening, SIZEOF(templates.LogOpening)); + + SaveOptions(); + SaveTemplates(); + } + return TRUE; + } + } + + return FALSE; +} + +int OptionsInitialize(WPARAM wParam, LPARAM lParam) +{ + OPTIONSDIALOGPAGE odp = {0}; + + odp.cbSize = sizeof(odp); + odp.position = -100000000; + odp.hInstance = hInst; + odp.flags = ODPF_BOLDGROUPS | ODPF_TCHAR; + odp.ptszTitle = LPGENT("Status Notify"); + odp.ptszGroup = LPGENT("Status"); + odp.ptszTab = LPGENT("General"); + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_GENERAL); + odp.pfnDlgProc = DlgProcGeneralOpts; + CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp); + + odp.ptszTab = LPGENT("Filtering"); + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_FILTERS); + odp.pfnDlgProc = DlgProcFiltering; + CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp); + + odp.ptszTab = LPGENT("Message log"); + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_XLOG); + odp.pfnDlgProc = DlgProcXLogOpts; + CallService(MS_OPT_ADDPAGE, wParam, (LPARAM)&odp); + + if (ServiceExists(MS_POPUP_ADDPOPUP)) + { + odp.ptszTitle = LPGENT("Status Notify"); + odp.ptszGroup = LPGENT("Popups"); + odp.ptszTab = LPGENT("General"); + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_POPUP); + odp.pfnDlgProc = DlgProcPopUpOpts; + CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp); + + odp.ptszTab = LPGENT("Extra status"); + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_XPOPUP); + odp.pfnDlgProc = DlgProcXPopupOpts; + CallService(MS_OPT_ADDPAGE, wParam, (LPARAM)&odp); + + odp.ptszTab = LPGENT("Status message"); + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_SMPOPUP); + odp.pfnDlgProc = DlgProcSMPopupOpts; + CallService(MS_OPT_ADDPAGE, wParam, (LPARAM)&odp); + } + + return 0; +} \ No newline at end of file diff --git a/plugins/NewXstatusNotify/options.h b/plugins/NewXstatusNotify/options.h new file mode 100644 index 0000000000..59c1bfff4f --- /dev/null +++ b/plugins/NewXstatusNotify/options.h @@ -0,0 +1,90 @@ +/* + NewXstatusNotify YM - Plugin for Miranda IM + Copyright (c) 2001-2004 Luca Santarelli + Copyright (c) 2005-2007 Vasilich + Copyright (c) 2007-2011 yaho + + 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 OPTIONS_H +#define OPTIONS_H + +#include "common.h" + +#define DEFAULT_LOGFILE "NewStatusNotify.log" + +typedef struct tagOPTIONS { + // IDD_OPT_POPUP + BYTE Colors; + BYTE ShowGroup; + BYTE ShowStatus; + BYTE UseAlternativeText; + BYTE ShowPreviousStatus; + BYTE ReadAwayMsg; + int PopupTimeout; + BYTE LeftClickAction; + BYTE RightClickAction; + // IDD_OPT_XPOPUP + BYTE PDisableForMusic; + BYTE PTruncateMsg; + DWORD PMsgLen; + // IDD_OPT_GENERAL + BYTE FromOffline; + BYTE AutoDisable; + BYTE HiddenContactsToo; + BYTE UseIndSnd; + BYTE BlinkIcon; + BYTE BlinkIcon_Status; + BYTE Log; + TCHAR LogFilePath[MAX_PATH]; + // IDD_AUTODISABLE + BYTE OnlyGlobalChanges; + BYTE DisableSoundGlobally; + BYTE DisablePopupGlobally; + // IDD_OPT_XLOG + BYTE EnableLogging; + BYTE PreventIdentical; + BYTE KeepInHistory; + BYTE LDisableForMusic; + BYTE LTruncateMsg; + DWORD LMsgLen; + //IDD_OPT_SMPOPUP + BYTE PopupOnConnect; + BYTE IgnoreEmpty; + // OTHER + BYTE TempDisabled; + BYTE PopupAutoDisabled; + BYTE SoundAutoDisabled; +} OPTIONS; + +typedef struct tagTEMPLATES { + BYTE PopupFlags; + BYTE LogFlags; + TCHAR PopupDelimiter[32]; + TCHAR PopupNewXstatus[256]; + TCHAR PopupNewMsg[256]; + TCHAR PopupRemove[256]; + TCHAR LogDelimiter[32]; + TCHAR LogNewXstatus[256]; + TCHAR LogNewMsg[256]; + TCHAR LogRemove[256]; + TCHAR LogOpening[256]; +} TEMPLATES; + +int OptionsInitialize(WPARAM wParam, LPARAM lParam); +void LoadOptions(); + +#endif \ No newline at end of file diff --git a/plugins/NewXstatusNotify/popup.cpp b/plugins/NewXstatusNotify/popup.cpp new file mode 100644 index 0000000000..761ec3578f --- /dev/null +++ b/plugins/NewXstatusNotify/popup.cpp @@ -0,0 +1,194 @@ +/* + NewXstatusNotify YM - Plugin for Miranda IM + Copyright (c) 2001-2004 Luca Santarelli + Copyright (c) 2005-2007 Vasilich + Copyright (c) 2007-2011 yaho + + 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 "popup.h" +#include "options.h" +#include "utils.h" + +extern OPTIONS opt; + +void QueryAwayMessage(HWND hWnd, PLUGINDATA *pdp) +{ + HANDLE hContact = PUGetContact(hWnd); + char *szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + if (szProto) + { + if ((CallProtoService(szProto, PS_GETCAPS,PFLAGNUM_1, 0) & PF1_MODEMSGRECV) && + (CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_3, 0) & Proto_Status2Flag(pdp->newStatus))) + { + //The following HookEventMessage will hook the ME_PROTO_ACK event and send a WM_AWAYMSG to hWnd when the hooks get notified. + pdp->hAwayMsgHook = HookEventMessage(ME_PROTO_ACK, hWnd, WM_AWAYMSG); + //The following instruction asks Miranda to retrieve the away message and associates a hProcess (handle) to this request. This handle will appear in the ME_PROTO_ACK event. + pdp->hAwayMsgProcess = (HANDLE)CallContactService(hContact, PSS_GETAWAYMSG, 0, 0); + } + } +} + +void ReceivedAwayMessage(HWND hWnd, LPARAM lParam, PLUGINDATA * pdp) +{ + HANDLE hContact = PUGetContact(hWnd); + ACKDATA *ack = (ACKDATA *)lParam; + + if (ack->type != ACKTYPE_AWAYMSG) + return; + + if (ack->hProcess == pdp->hAwayMsgProcess) //It's my hProcess, so it's ok to continue. + { + //The first thing we go is removing the hook from the chain to avoid useless calls. + UnhookEvent(pdp->hAwayMsgHook); + pdp->hAwayMsgHook = NULL; + + if (ack->result != ACKRESULT_SUCCESS) + return; + + DBVARIANT dbv; + TCHAR stzText[MAX_SECONDLINE]; + + if (!DBGetContactSettingTString(hContact, MODULE, "LastPopupText", &dbv)) + { + _tcscpy(stzText, dbv.ptszVal); + DBFreeVariant(&dbv); + + if (!DBGetContactSettingTString(ack->hContact, "CList", "StatusMsg", &dbv)) + { + if (dbv.ptszVal && dbv.ptszVal[0]) + { + if (stzText[0]) _tcscat(stzText, _T("\n")); + _tcscat(stzText, dbv.ptszVal); + SendMessage(hWnd, WM_SETREDRAW, FALSE, 0); + PUChangeTextT(hWnd, stzText); + SendMessage(hWnd, WM_SETREDRAW, TRUE, 0); + } + DBFreeVariant(&dbv); + } + + } + } +} + +void PopupAction(HWND hWnd, BYTE action) +{ + HANDLE hContact = PUGetContact(hWnd); + if (hContact && hContact != INVALID_HANDLE_VALUE) + { + switch (action) + { + case PCA_OPENMESSAGEWND: + { + CallServiceSync(ServiceExists("SRMsg/LaunchMessageWindow") ? "SRMsg/LaunchMessageWindow" : MS_MSG_SENDMESSAGE, (WPARAM)hContact, 0); + break; + } + case PCA_OPENMENU: + { + POINT pt = {0}; + HMENU hMenu = (HMENU)CallService(MS_CLIST_MENUBUILDCONTACT, (WPARAM)hContact, 0); + GetCursorPos(&pt); + TrackPopupMenu(hMenu, 0, pt.x, pt.y, 0, hWnd, NULL); + DestroyMenu(hMenu); + return; + } + case PCA_OPENDETAILS: + { + CallServiceSync(MS_USERINFO_SHOWDIALOG, (WPARAM)hContact, 0); + break; + } + case PCA_OPENHISTORY: + { + CallServiceSync(MS_HISTORY_SHOWCONTACTHISTORY, (WPARAM)hContact, 0); + break; + } + case PCA_CLOSEPOPUP: + break; + case PCA_DONOTHING: + return; + } + + PUDeletePopUp(hWnd); + } +} + +INT_PTR CALLBACK PopupDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + PLUGINDATA *pdp = NULL; + + switch(message) + { + case WM_MEASUREITEM: //Needed by the contact's context menu + return CallService(MS_CLIST_MENUMEASUREITEM, wParam, lParam); + case WM_DRAWITEM: //Needed by the contact's context menu + return CallService(MS_CLIST_MENUDRAWITEM, wParam, lParam); + case WM_COMMAND: + { + //This one returns TRUE if it processed the menu command, and FALSE if it did not process it. + if (CallServiceSync(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(wParam), MPCF_CONTACTMENU), (LPARAM)PUGetContact(hwnd))) + break; + + PopupAction(hwnd, opt.LeftClickAction); + break; + } + case WM_CONTEXTMENU: + { + PopupAction(hwnd, opt.RightClickAction); + break; + } + case UM_FREEPLUGINDATA: + { + PLUGINDATA *pdp = (PLUGINDATA *)PUGetPluginData(hwnd); + if (pdp != NULL) + { + if (pdp->hAwayMsgHook != NULL) + { + UnhookEvent(pdp->hAwayMsgHook); + pdp->hAwayMsgHook = NULL; + } + + mir_free(pdp); + } + return FALSE; + } + case UM_INITPOPUP: + { + pdp = (PLUGINDATA *)PUGetPluginData(hwnd); + if (pdp != NULL) + { + char *szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)PUGetContact(hwnd), 0); + if (szProto && opt.ReadAwayMsg && StatusHasAwayMessage(szProto, pdp->newStatus)) + { + WORD myStatus = (WORD)CallProtoService(szProto, PS_GETSTATUS, 0, 0); + if (myStatus != ID_STATUS_INVISIBLE) + QueryAwayMessage(hwnd, pdp); + } + } + + return FALSE; + } + case WM_AWAYMSG: //We're here because ME_PROTO_ACK has been hooked to this window (too!). + { + pdp = (PLUGINDATA *)PUGetPluginData(hwnd); + if (pdp != NULL) ReceivedAwayMessage(hwnd, lParam, pdp); + return FALSE; + } + } + + return DefWindowProc(hwnd, message, wParam, lParam); +} + diff --git a/plugins/NewXstatusNotify/popup.h b/plugins/NewXstatusNotify/popup.h new file mode 100644 index 0000000000..e6e56f6c5b --- /dev/null +++ b/plugins/NewXstatusNotify/popup.h @@ -0,0 +1,54 @@ +/* + NewXstatusNotify YM - Plugin for Miranda IM + Copyright (c) 2001-2004 Luca Santarelli + Copyright (c) 2005-2007 Vasilich + Copyright (c) 2007-2011 yaho + + 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 POPUP_H +#define POPUP_H + +#define POPUP_COLOR_OWN 1 +#define POPUP_COLOR_WINDOWS 2 +#define POPUP_COLOR_POPUP 3 +#define DEFAULT_COLORS POPUP_COLOR_POPUP + +// 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_DONOTHING 5 // do nothing + +#define STRING_SHOWPREVIOUSSTATUS _T("(was %s)") + +static struct { + TCHAR *Text; + int Action; +} PopupActions[] = { + _T("Open message window"), PCA_OPENMESSAGEWND, + _T("Close popup"), PCA_CLOSEPOPUP, + _T("Open contact details window"), PCA_OPENDETAILS, + _T("Open contact menu"), PCA_OPENMENU, + _T("Open contact history"), PCA_OPENHISTORY, + _T("Do nothing"), PCA_DONOTHING +}; + +INT_PTR CALLBACK PopupDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); + +#endif \ No newline at end of file diff --git a/plugins/NewXstatusNotify/res/disable_all.ico b/plugins/NewXstatusNotify/res/disable_all.ico new file mode 100644 index 0000000000..1ba34d7244 Binary files /dev/null and b/plugins/NewXstatusNotify/res/disable_all.ico differ diff --git a/plugins/NewXstatusNotify/res/enable_all.ico b/plugins/NewXstatusNotify/res/enable_all.ico new file mode 100644 index 0000000000..416e4eabc5 Binary files /dev/null and b/plugins/NewXstatusNotify/res/enable_all.ico differ diff --git a/plugins/NewXstatusNotify/res/logging.ico b/plugins/NewXstatusNotify/res/logging.ico new file mode 100644 index 0000000000..10c7d18641 Binary files /dev/null and b/plugins/NewXstatusNotify/res/logging.ico differ diff --git a/plugins/NewXstatusNotify/res/main_off.ico b/plugins/NewXstatusNotify/res/main_off.ico new file mode 100644 index 0000000000..c5543f923c Binary files /dev/null and b/plugins/NewXstatusNotify/res/main_off.ico differ diff --git a/plugins/NewXstatusNotify/res/main_on.ico b/plugins/NewXstatusNotify/res/main_on.ico new file mode 100644 index 0000000000..6fb625b1bf Binary files /dev/null and b/plugins/NewXstatusNotify/res/main_on.ico differ diff --git a/plugins/NewXstatusNotify/res/popup.ico b/plugins/NewXstatusNotify/res/popup.ico new file mode 100644 index 0000000000..57a1a25ae4 Binary files /dev/null and b/plugins/NewXstatusNotify/res/popup.ico differ diff --git a/plugins/NewXstatusNotify/res/reset.ico b/plugins/NewXstatusNotify/res/reset.ico new file mode 100644 index 0000000000..34970649ab Binary files /dev/null and b/plugins/NewXstatusNotify/res/reset.ico differ diff --git a/plugins/NewXstatusNotify/res/sound.ico b/plugins/NewXstatusNotify/res/sound.ico new file mode 100644 index 0000000000..5e7d8db327 Binary files /dev/null and b/plugins/NewXstatusNotify/res/sound.ico differ diff --git a/plugins/NewXstatusNotify/res/status_message.ico b/plugins/NewXstatusNotify/res/status_message.ico new file mode 100644 index 0000000000..57a1a25ae4 Binary files /dev/null and b/plugins/NewXstatusNotify/res/status_message.ico differ diff --git a/plugins/NewXstatusNotify/res/variables.ico b/plugins/NewXstatusNotify/res/variables.ico new file mode 100644 index 0000000000..ab0371586b Binary files /dev/null and b/plugins/NewXstatusNotify/res/variables.ico differ diff --git a/plugins/NewXstatusNotify/res/xstatus.ico b/plugins/NewXstatusNotify/res/xstatus.ico new file mode 100644 index 0000000000..279c85f9b1 Binary files /dev/null and b/plugins/NewXstatusNotify/res/xstatus.ico differ diff --git a/plugins/NewXstatusNotify/resource.h b/plugins/NewXstatusNotify/resource.h new file mode 100644 index 0000000000..b68a263716 --- /dev/null +++ b/plugins/NewXstatusNotify/resource.h @@ -0,0 +1,147 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by resource.rc +// +#define IDD_OPT_XPOPUP 101 +#define IDD_INFO_SOUNDS 102 +#define IDD_OPT_GENERAL 103 +#define IDI_RESET 109 +#define IDI_VARIABLES 110 +#define IDD_AUTODISABLE 113 +#define IDD_OPT_FILTERS 114 +#define IDD_OPT_POPUP 115 +#define IDD_OPT_XLOG 116 +#define IDI_POPUP 117 +#define IDD_OPT_SMPOPUP 117 +#define IDI_SOUND 118 +#define IDI_LOGGING 119 +#define IDI_XSTATUS 120 +#define IDI_DISABLEALL 121 +#define IDI_ENABLEALL 122 +#define IDI_NOTIFICATION_OFF 123 +#define IDI_NOTIFICATION_ON 124 +#define IDI_STATUS_MESSAGE 125 +#define IDC_STATUS_STATIC_INFINITE 1002 +#define IDC_STATUS_STATIC_DEFAULT 1003 +#define IDC_TIMEOUT_VALUE_SPIN 1004 +#define IDC_STATUS_STATIC_SEC 1005 +#define IDC_STATUS_LC 1006 +#define IDC_USEWINCOLORS 1007 +#define IDC_STATUS_RC 1008 +#define IDC_READAWAYMSG 1011 +#define IDC_CHK_DISABLEMUSIC 1011 +#define IDC_SHOWPREVIOUSSTATUS 1012 +#define IDC_CHK_CUTMSG 1012 +#define IDC_USEPOPUPCOLORS 1013 +#define IDC_ED_MSGLEN 1013 +#define IDC_ED_TOPENING 1018 +#define IDC_ED_TCHANGE 1024 +#define IDC_ED_TCHANGEMSG 1025 +#define IDC_BT_VARIABLES 1028 +#define IDC_BT_RESET 1029 +#define IDC_PREVIEW 1030 +#define IDC_CHANGE 1031 +#define IDC_CHK_MSGCHANGE 1031 +#define IDC_DELETE 1032 +#define IDC_CHK_XSTATUSCHANGE 1032 +#define IDC_CHK_OPENING 1033 +#define IDC_UD_MSGLEN 1034 +#define IDC_CHK_PGLOBAL 1035 +#define IDC_CHK_SGLOBAL 1036 +#define IDC_CHK_ONLYGLOBAL 1037 +#define IDC_HYPERLINK 1038 +#define IDC_CHK_REMOVE 1039 +#define IDC_ED_TREMOVE 1040 +#define IDC_ED_TDELIMITER 1042 +#define IDC_INDSNDLIST 1044 +#define IDC_HIDDENCONTACTSTOO 1052 +#define IDC_USEINDIVSOUNDS 1053 +#define IDC_OK 1055 +#define IDC_CANCEL 1056 +#define IDC_CONFIGUREAUTODISABLE 1057 +#define IDC_AUTODISABLE 1060 +#define IDC_LOG 1061 +#define IDC_TIMEOUT_VALUE 1066 +#define IDC_BLINKICON 1067 +#define IDC_BLINKICON_STATUS 1068 +#define IDC_SOUNDICON 1069 +#define IDC_POPUPICON 1070 +#define IDC_CHECK_NOTIFYSOUNDS 1071 +#define IDC_CHECK_NOTIFYPOPUPS 1073 +#define IDC_TEXT_ENABLE_IS 1074 +#define IDC_USEOWNCOLORS 1076 +#define IDC_SHOWALTDESCS 1077 +#define IDC_LOGGINGICON 1078 +#define IDC_SHOWSTATUS 1078 +#define IDC_XSTATUSICON 1079 +#define IDC_DISABLEALLICON 1080 +#define IDC_ENABLEALLICON 1081 +#define IDC_SHOWGROUP 1082 +#define IDC_STATUSMESSAGEICON 1082 +#define IDC_ONCONNECT 1101 +#define IDC_PUIGNOREREMOVE 1102 +#define IDC_POPUPTEXT 1115 +#define IDC_PROTOCOLLIST 1207 +#define IDC_LOGFILE 2029 +#define IDC_BT_CHOOSELOGFILE 2030 +#define IDC_BT_VIEWLOG 2031 +#define IDC_CHK_LOGGING 2034 +#define IDC_CHK_SAVETOHISTORY 2039 +#define IDC_CHK_PREVENTIDENTICAL 2040 +#define IDC_CHK_OFFLINE 40071 +#define IDC_CHK_ONLINE 40072 +#define IDC_CHK_AWAY 40073 +#define IDC_CHK_DND 40074 +#define IDC_CHK_NA 40075 +#define IDC_CHK_OCCUPIED 40076 +#define IDC_CHK_FREECHAT 40077 +#define IDC_CHK_INVISIBLE 40078 +#define IDC_CHK_ONTHEPHONE 40079 +#define IDC_CHK_OUTTOLUNCH 40080 +#define IDC_CHK_XSTATUS 40081 +#define IDC_CHK_STATUS_MESSAGE 40082 +#define IDC_CHK_FROMOFFLINE 40083 +#define IDC_OFFLINE_TX 41071 +#define IDC_ONLINE_TX 41072 +#define IDC_AWAY_TX 41073 +#define IDC_DND_TX 41074 +#define IDC_NA_TX 41075 +#define IDC_OCCUPIED_TX 41076 +#define IDC_FREEFORCHAT_TX 41077 +#define IDC_INVISIBLE_TX 41078 +#define IDC_ONTHEPHONE_TX 41079 +#define IDC_OUTTOLUNCH_TX 41080 +#define IDC_XSTATUS_TX 41081 +#define IDC_STATUSMESSAGE_TX 41082 +#define IDC_OFFLINE_BG 42071 +#define IDC_ONLINE_BG 42072 +#define IDC_CHK_ONLINE2 42072 +#define IDC_AWAY_BG 42073 +#define IDC_CHK_AWAY2 42073 +#define IDC_DND_BG 42074 +#define IDC_CHK_DND2 42074 +#define IDC_NA_BG 42075 +#define IDC_CHK_NA2 42075 +#define IDC_OCCUPIED_BG 42076 +#define IDC_CHK_OCCUPIED2 42076 +#define IDC_FREEFORCHAT_BG 42077 +#define IDC_CHK_FREECHAT2 42077 +#define IDC_INVISIBLE_BG 42078 +#define IDC_CHK_INVISIBLE2 42078 +#define IDC_ONTHEPHONE_BG 42079 +#define IDC_CHK_ONTHEPHONE2 42079 +#define IDC_OUTTOLUNCH_BG 42080 +#define IDC_CHK_OUTTOLUNCH2 42080 +#define IDC_XSTATUS_BG 42081 +#define IDC_STATUSMESSAGE_BG 42082 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 111 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1044 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/plugins/NewXstatusNotify/resource.rc b/plugins/NewXstatusNotify/resource.rc new file mode 100644 index 0000000000..fcdf8fc2d3 --- /dev/null +++ b/plugins/NewXstatusNotify/resource.rc @@ -0,0 +1,411 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Íåéòðàëüíûé resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU) +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL +#pragma code_page(1251) + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_OPT_GENERAL, DIALOG + BEGIN + LEFTMARGIN, 5 + RIGHTMARGIN, 295 + TOPMARGIN, 5 + BOTTOMMARGIN, 220 + END + + IDD_INFO_SOUNDS, DIALOG + BEGIN + LEFTMARGIN, 5 + RIGHTMARGIN, 217 + BOTTOMMARGIN, 151 + END + + IDD_OPT_FILTERS, DIALOG + BEGIN + VERTGUIDE, 6 + END + + IDD_OPT_POPUP, DIALOG + BEGIN + RIGHTMARGIN, 308 + VERTGUIDE, 6 + VERTGUIDE, 163 + VERTGUIDE, 288 + BOTTOMMARGIN, 142 + END + + IDD_OPT_XPOPUP, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 296 + TOPMARGIN, 7 + BOTTOMMARGIN, 179 + END + + IDD_AUTODISABLE, DIALOG + BEGIN + LEFTMARGIN, 5 + RIGHTMARGIN, 281 + TOPMARGIN, 5 + BOTTOMMARGIN, 187 + END + + IDD_OPT_XLOG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 296 + TOPMARGIN, 7 + BOTTOMMARGIN, 179 + END + + IDD_OPT_SMPOPUP, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 296 + TOPMARGIN, 7 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_OPT_GENERAL DIALOGEX 0, 0, 300, 225 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + GROUPBOX "Notify when a contact changes to one of these statuses",IDC_STATIC,4,7,292,72,WS_GROUP + CONTROL "Online",IDC_CHK_ONLINE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,17,89,10 + CONTROL "Offline",IDC_CHK_OFFLINE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,103,17,89,10 + CONTROL "Invisible",IDC_CHK_INVISIBLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,208,17,83,10 + CONTROL "Free for chat",IDC_CHK_FREECHAT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,28,89,10 + CONTROL "Away",IDC_CHK_AWAY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,103,28,89,10 + CONTROL "NA",IDC_CHK_NA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,208,28,83,10 + CONTROL "Occupied",IDC_CHK_OCCUPIED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,39,89,10 + CONTROL "DND",IDC_CHK_DND,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,103,39,89,10 + CONTROL "Out to lunch",IDC_CHK_OUTTOLUNCH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,208,39,83,10 + CONTROL "On the phone",IDC_CHK_ONTHEPHONE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,50,89,10 + CONTROL "Always when changing from offline",IDC_CHK_FROMOFFLINE, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,61,163,10 + GROUPBOX "Plugin activation",IDC_STATIC,4,82,292,82,WS_GROUP + CONTROL "Automatically turn off Popups and Sounds on status change",IDC_AUTODISABLE, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,96,219,10 + PUSHBUTTON "Configure",IDC_CONFIGUREAUTODISABLE,239,94,50,14 + CONTROL "Don't notify me for people not in my Contact List",IDC_HIDDENCONTACTSTOO, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,109,279,10 + CONTROL "Blink icon in the system tray",IDC_BLINKICON,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,135,279,10 + CONTROL "Use status icon",IDC_BLINKICON_STATUS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,148,279,10 + CONTROL "Use individual sounds",IDC_USEINDIVSOUNDS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,122,279,10 + GROUPBOX "Log to file",IDC_STATIC,3,166,292,28 + CONTROL "Enable",IDC_LOG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,178,57,10 + CONTROL "Go to Customize -> Sound to select the sounds",IDC_HYPERLINK, + "Hyperlink",WS_TABSTOP,6,203,288,14 + CONTROL "Extra status",IDC_CHK_XSTATUS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,103,50,89,10 + EDITTEXT IDC_LOGFILE,72,175,154,14,ES_AUTOHSCROLL | ES_READONLY + PUSHBUTTON "...",IDC_BT_CHOOSELOGFILE,229,175,18,14 + PUSHBUTTON "Open",IDC_BT_VIEWLOG,249,175,42,14 + CONTROL "Status message",IDC_CHK_STATUS_MESSAGE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,208,50,87,10 +END + +IDD_INFO_SOUNDS DIALOGEX 0, 0, 222, 152 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + CONTROL "IndSndList",IDC_INDSNDLIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | WS_TABSTOP,4,1,213,95,WS_EX_CLIENTEDGE + PUSHBUTTON "Change",IDC_CHANGE,23,100,50,13 + PUSHBUTTON "Preview",IDC_PREVIEW,86,100,50,13 + PUSHBUTTON "Delete",IDC_DELETE,149,100,50,13 + CONTROL "Enable sounds",IDC_CHECK_NOTIFYSOUNDS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,117,131,96,10 + CONTROL "Enable popups",IDC_CHECK_NOTIFYPOPUPS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,9,131,101,10 + GROUPBOX "Status Notify",IDC_STATIC,4,119,213,29 + CTEXT "Individual sounds are disabled.\n\nTo enable them, go to Options - Status - Notify, enable \n""Use individual sounds"" checkbox, and then reopen this dialog.",IDC_TEXT_ENABLE_IS,5,22,210,56 +END + +IDD_OPT_FILTERS DIALOGEX 0, 0, 300, 230 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + CONTROL "",IDC_INDSNDLIST,"CListControl",WS_TABSTOP | 0x1d0,5,6,290,185,WS_EX_CLIENTEDGE + LTEXT "Sounds",IDC_STATIC,26,200,70,9 + LTEXT "Popups",IDC_STATIC,26,214,70,9 + ICON IDI_SOUND,IDC_SOUNDICON,8,196,16,16,SS_CENTERIMAGE + ICON IDI_POPUP,IDC_POPUPICON,8,210,16,16,SS_CENTERIMAGE + LTEXT "Extra status notify",IDC_STATIC,119,200,86,9 + LTEXT "Extra status logging",IDC_STATIC,119,214,86,9 + ICON IDI_XSTATUS,IDC_XSTATUSICON,101,196,16,16,SS_CENTERIMAGE + ICON IDI_LOGGING,IDC_LOGGINGICON,101,210,16,16,SS_CENTERIMAGE + LTEXT "Disable all",IDC_STATIC,229,200,60,9 + LTEXT "Enable all",IDC_STATIC,229,214,60,9 + ICON IDI_DISABLEALL,IDC_DISABLEALLICON,211,196,16,16,SS_CENTERIMAGE + ICON IDI_ENABLEALL,IDC_ENABLEALLICON,211,210,16,16,SS_CENTERIMAGE +END + +IDD_OPT_POPUP DIALOGEX 0, 0, 309, 230 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + CTEXT "Background",IDC_STATIC,63,11,44,8 + CTEXT "Text",IDC_STATIC,106,11,24,8 + CONTROL "",IDC_OFFLINE_BG,"ColourPicker",WS_TABSTOP,72,22,24,12 + CONTROL "",IDC_OFFLINE_TX,"ColourPicker",WS_TABSTOP,105,22,24,12 + CONTROL "",IDC_ONLINE_BG,"ColourPicker",WS_TABSTOP,72,38,24,12 + CONTROL "",IDC_ONLINE_TX,"ColourPicker",WS_TABSTOP,105,38,24,12 + CONTROL "",IDC_AWAY_BG,"ColourPicker",WS_TABSTOP,72,54,24,12 + CONTROL "",IDC_AWAY_TX,"ColourPicker",WS_TABSTOP,105,54,24,12 + CONTROL "",IDC_NA_BG,"ColourPicker",WS_TABSTOP,72,70,24,12 + CONTROL "",IDC_NA_TX,"ColourPicker",WS_TABSTOP,105,70,24,12 + CONTROL "",IDC_OCCUPIED_BG,"ColourPicker",WS_TABSTOP,72,86,24,12 + CONTROL "",IDC_OCCUPIED_TX,"ColourPicker",WS_TABSTOP,105,86,24,12 + CONTROL "",IDC_DND_BG,"ColourPicker",WS_TABSTOP,72,102,24,12 + CONTROL "",IDC_DND_TX,"ColourPicker",WS_TABSTOP,105,102,24,12 + CONTROL "",IDC_FREEFORCHAT_BG,"ColourPicker",WS_TABSTOP,72,118,24,12 + CONTROL "",IDC_FREEFORCHAT_TX,"ColourPicker",WS_TABSTOP,105,118,24,12 + CONTROL "",IDC_INVISIBLE_BG,"ColourPicker",WS_TABSTOP,72,134,24,12 + CONTROL "",IDC_INVISIBLE_TX,"ColourPicker",WS_TABSTOP,105,134,24,12 + CONTROL "",IDC_OUTTOLUNCH_BG,"ColourPicker",WS_TABSTOP,72,150,24,12 + CONTROL "",IDC_OUTTOLUNCH_TX,"ColourPicker",WS_TABSTOP,105,150,24,12 + CONTROL "",IDC_ONTHEPHONE_BG,"ColourPicker",WS_TABSTOP,72,166,24,12 + CONTROL "",IDC_ONTHEPHONE_TX,"ColourPicker",WS_TABSTOP,105,166,24,12 + GROUPBOX "Colours",IDC_STATIC,143,0,164,44,WS_GROUP + CONTROL "Use custom colours",IDC_USEOWNCOLORS,"Button",BS_AUTORADIOBUTTON | BS_MULTILINE | BS_NOTIFY,151,8,151,13 + CONTROL "Use Windows colours",IDC_USEWINCOLORS,"Button",BS_AUTORADIOBUTTON | BS_MULTILINE | BS_NOTIFY,151,30,151,13 + CONTROL "Use Popup colours",IDC_USEPOPUPCOLORS,"Button",BS_AUTORADIOBUTTON | BS_MULTILINE | BS_NOTIFY,151,19,151,13 + GROUPBOX "Popup text",IDC_STATIC,144,46,164,76,WS_GROUP + CONTROL "Read status message",IDC_READAWAYMSG,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,151,104,151,13 + CONTROL "Show previous status too",IDC_SHOWPREVIOUSSTATUS,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,151,92,151,13 + GROUPBOX "Timeout",IDC_STATIC,144,124,164,35 + EDITTEXT IDC_TIMEOUT_VALUE,160,138,32,12,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER + CONTROL "",IDC_TIMEOUT_VALUE_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,181,138,11,12 + PUSHBUTTON "Preview",IDC_PREVIEW,43,206,57,15 + GROUPBOX "Popups on contact status change to:",IDC_STATIC,0,0,138,200,WS_GROUP + GROUPBOX "Click action",IDC_STATIC,144,160,164,67,WS_GROUP + CONTROL "Show contact group name",IDC_SHOWGROUP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,151,58,151,9 + CONTROL "Use alternative descriptions",IDC_SHOWALTDESCS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,151,80,151,13 + CTEXT "0 = Default",IDC_STATUS_STATIC_DEFAULT,225,135,76,8 + CTEXT "-1 = Infinite",IDC_STATUS_STATIC_INFINITE,223,145,76,8 + LTEXT "Sec",IDC_STATUS_STATIC_SEC,197,140,21,8 + COMBOBOX IDC_STATUS_LC,151,182,150,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_STATUS_RC,151,209,150,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "On left click",IDC_STATIC,153,171,151,8 + LTEXT "On right click",IDC_STATIC,153,198,151,8 + CONTROL "",IDC_XSTATUS_TX,"ColourPicker",WS_TABSTOP,105,182,24,12 + CONTROL "",IDC_XSTATUS_BG,"ColourPicker",WS_TABSTOP,72,182,24,12 + LTEXT "Offline",IDC_STATIC,5,24,56,8 + LTEXT "Online",IDC_STATIC,5,40,56,8 + LTEXT "Away",IDC_STATIC,5,56,56,8 + LTEXT "NA",IDC_STATIC,5,72,56,8 + LTEXT "Occupied",IDC_STATIC,5,88,56,8 + LTEXT "DND",IDC_STATIC,5,104,56,8 + LTEXT "Free for chat",IDC_STATIC,5,120,56,8 + LTEXT "Invisible",IDC_STATIC,5,136,56,8 + LTEXT "Out to lunch",IDC_STATIC,5,152,56,8 + LTEXT "On the phone",IDC_STATIC,5,168,56,8 + LTEXT "Extra status",IDC_STATIC,5,184,56,8 + CONTROL "Show status description",IDC_SHOWSTATUS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,151,68,151,13 +END + +IDD_OPT_XPOPUP DIALOGEX 0, 0, 305, 230 +STYLE DS_SETFONT | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CONTROL | DS_CENTER | WS_CHILD +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + GROUPBOX "Notification",IDC_STATIC,5,6,292,45 + CONTROL "Disable for extra status 'Music'",IDC_CHK_DISABLEMUSIC, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,19,276,10 + CONTROL "Truncate message length to:",IDC_CHK_CUTMSG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,34,137,10 + EDITTEXT IDC_ED_MSGLEN,153,33,34,12,ES_AUTOHSCROLL + CONTROL "",IDC_UD_MSGLEN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,179,30,11,14 + LTEXT "characters",IDC_STATIC,191,35,85,8 + GROUPBOX "Templates",IDC_STATIC,5,55,292,89 + EDITTEXT IDC_ED_TCHANGE,89,70,202,12,ES_AUTOHSCROLL + EDITTEXT IDC_ED_TCHANGEMSG,89,87,202,12,ES_AUTOHSCROLL + EDITTEXT IDC_ED_TREMOVE,89,104,202,12,ES_AUTOHSCROLL + EDITTEXT IDC_ED_TDELIMITER,259,121,32,12,ES_AUTOHSCROLL + RTEXT "Title - text delimiter:",IDC_STATIC,145,123,111,8 + CONTROL "Remove:",IDC_CHK_REMOVE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,106,73,10 + CONTROL "New message:",IDC_CHK_MSGCHANGE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,88,73,10 + CONTROL "New status:",IDC_CHK_XSTATUSCHANGE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,70,73,10 + CONTROL "Variables",IDC_BT_VARIABLES,"MButtonClass",WS_TABSTOP,11,123,16,14 + CONTROL "Reset",IDC_BT_RESET,"MButtonClass",WS_TABSTOP,29,123,16,14 +END + +IDD_AUTODISABLE DIALOGEX 0, 0, 286, 192 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_NOFAILCREATE | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +CAPTION "Disable notifications" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + CONTROL "Online",IDC_CHK_ONLINE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,49,116,10 + CONTROL "Invisible",IDC_CHK_INVISIBLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,59,116,10 + CONTROL "Free for chat",IDC_CHK_FREECHAT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,69,116,10 + CONTROL "Away",IDC_CHK_AWAY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,79,116,10 + CONTROL "NA",IDC_CHK_NA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,89,116,10 + CONTROL "Occupied",IDC_CHK_OCCUPIED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,99,116,10 + CONTROL "DND",IDC_CHK_DND,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,109,116,10 + CONTROL "Out to lunch",IDC_CHK_OUTTOLUNCH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,129,116,10 + CONTROL "On the phone",IDC_CHK_ONTHEPHONE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,119,116,10 + PUSHBUTTON "OK",IDC_OK,90,169,50,14 + GROUPBOX "Popups",IDC_STATIC,6,8,132,136 + CONTROL "Online",IDC_CHK_ONLINE2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,157,50,116,10 + CONTROL "Invisible",IDC_CHK_INVISIBLE2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,157,60,116,10 + CONTROL "Free for chat",IDC_CHK_FREECHAT2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,157,70,116,10 + CONTROL "Away",IDC_CHK_AWAY2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,157,80,116,10 + CONTROL "NA",IDC_CHK_NA2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,157,90,116,10 + CONTROL "Occupied",IDC_CHK_OCCUPIED2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,157,100,116,10 + CONTROL "DND",IDC_CHK_DND2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,157,110,116,10 + CONTROL "Out to lunch",IDC_CHK_OUTTOLUNCH2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,157,130,116,10 + CONTROL "On the phone",IDC_CHK_ONTHEPHONE2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,157,120,116,10 + GROUPBOX "Sounds",IDC_STATIC,147,8,132,136 + PUSHBUTTON "Cancel",IDC_CANCEL,144,169,50,14 + CONTROL "Disable globally",IDC_CHK_PGLOBAL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,20,116,10 + CONTROL "Disable globally",IDC_CHK_SGLOBAL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,157,20,116,10 + CONTROL "Disable only if I change global status",IDC_CHK_ONLYGLOBAL, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,151,258,10 + LTEXT "Disable when my status is:",IDC_STATIC,15,37,116,8 + LTEXT "Disable when my status is:",IDC_STATIC,157,36,116,8 +END + +IDD_OPT_XLOG DIALOGEX 0, 0, 305, 230 +STYLE DS_SETFONT | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CONTROL | DS_CENTER | WS_CHILD +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + GROUPBOX "Extra status log",65534,5,6,294,83 + CONTROL "Enable logging extra status to message window",IDC_CHK_LOGGING, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,19,276,10 + CONTROL "Keep events in history",IDC_CHK_SAVETOHISTORY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,45,276,10 + CONTROL "Prevent identical logs",IDC_CHK_PREVENTIDENTICAL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,32,276,10 + CONTROL "Disable for extra status 'Music'",IDC_CHK_DISABLEMUSIC, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,58,276,10 + CONTROL "Truncate message length to:",IDC_CHK_CUTMSG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,71,133,10 + EDITTEXT IDC_ED_MSGLEN,150,70,34,12,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "",IDC_UD_MSGLEN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,175,70,11,14 + LTEXT "characters",IDC_STATIC,188,73,84,8 + GROUPBOX "Templates",IDC_STATIC,5,94,294,107 + EDITTEXT IDC_ED_TCHANGE,89,107,202,12,ES_AUTOHSCROLL + EDITTEXT IDC_ED_TOPENING,89,161,202,12,ES_AUTOHSCROLL + EDITTEXT IDC_ED_TCHANGEMSG,89,125,202,12,ES_AUTOHSCROLL + EDITTEXT IDC_ED_TREMOVE,89,143,202,12,ES_AUTOHSCROLL + EDITTEXT IDC_ED_TDELIMITER,259,180,32,12,ES_AUTOHSCROLL + RTEXT "Title - text delimiter:",IDC_STATIC,89,182,167,8 + CONTROL "Remove:",IDC_CHK_REMOVE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,144,73,10 + CONTROL "New message:",IDC_CHK_MSGCHANGE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,126,73,10 + CONTROL "New status:",IDC_CHK_XSTATUSCHANGE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,108,73,10 + CONTROL "On opening ML:",IDC_CHK_OPENING,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,162,73,10 + CONTROL "Variables",IDC_BT_VARIABLES,"MButtonClass",WS_TABSTOP,11,180,16,14 + CONTROL "Reset",IDC_BT_RESET,"MButtonClass",WS_TABSTOP,29,180,16,14 +END + +IDD_OPT_SMPOPUP DIALOGEX 0, 0, 305, 194 +STYLE DS_SETFONT | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CONTROL | DS_CENTER | WS_CHILD +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + GROUPBOX "General",IDC_STATIC,0,0,296,39 + CONTROL "Show PopUps when I connect",IDC_ONCONNECT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,11,202,8 + CONTROL "Ignore empty status messages",IDC_PUIGNOREREMOVE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,25,202,8 + GROUPBOX "Protocols",IDC_STATIC,0,41,296,94 + CTEXT "Enable/Disable protocols which you don't wish to be notified for:",IDC_STATIC,10,52,280,10 + CONTROL "",IDC_PROTOCOLLIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_NOCOLUMNHEADER | WS_BORDER | WS_TABSTOP,100,66,110,64 + GROUPBOX "Text",IDC_STATIC,0,135,152,34 + EDITTEXT IDC_POPUPTEXT,6,145,140,20,ES_MULTILINE | ES_AUTOHSCROLL | NOT WS_BORDER,WS_EX_STATICEDGE + CONTROL "Variables",IDC_BT_VARIABLES,"MButtonClass",WS_TABSTOP,11,174,16,14 + CONTROL "Reset",IDC_BT_RESET,"MButtonClass",WS_TABSTOP,29,174,16,14 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_RESET ICON "res\\reset.ico" +IDI_POPUP ICON "res\\popup.ico" +IDI_LOGGING ICON "res\\logging.ico" +IDI_SOUND ICON "res\\sound.ico" +IDI_NOTIFICATION_OFF ICON "res\\main_off.ico" +IDI_NOTIFICATION_ON ICON "res\\main_on.ico" +IDI_XSTATUS ICON "res\\xstatus.ico" +IDI_DISABLEALL ICON "res\\disable_all.ico" +IDI_ENABLEALL ICON "res\\enable_all.ico" +IDI_VARIABLES ICON "res\\variables.ico" +IDI_STATUS_MESSAGE ICON "res\\status_message.ico" +#endif // Íåéòðàëüíûé resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Íåìåöêèé (Ãåðìàíèÿ) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) +LANGUAGE LANG_GERMAN, SUBLANG_GERMAN +#pragma code_page(1252) + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Íåìåöêèé (Ãåðìàíèÿ) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/plugins/NewXstatusNotify/utils.cpp b/plugins/NewXstatusNotify/utils.cpp new file mode 100644 index 0000000000..0037639827 --- /dev/null +++ b/plugins/NewXstatusNotify/utils.cpp @@ -0,0 +1,124 @@ +/* + NewXstatusNotify YM - Plugin for Miranda IM + Copyright (c) 2001-2004 Luca Santarelli + Copyright (c) 2005-2007 Vasilich + Copyright (c) 2007-2011 yaho + + 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 "options.h" + +extern OPTIONS opt; +extern STATUS StatusList[STATUS_COUNT]; + +TCHAR *db2t(DBVARIANT *dbv) +{ + TCHAR *buff; + switch (dbv->type) + { + case DBVT_ASCIIZ: buff = mir_a2t(dbv->pszVal); break; + case DBVT_WCHAR: buff = mir_tstrdup(dbv->ptszVal); break; + case DBVT_UTF8: buff = mir_utf8decodeT(dbv->pszVal); break; + default: buff = mir_tstrdup(_T("")); + } + + if (buff[0] == 0) + { + mir_free(buff); + buff = NULL; + } + + return buff; +} + +int DBGetStringDefault(HANDLE hContact, const char *szModule, const char *szSetting, TCHAR *setting, int size, const TCHAR *defaultValue) +{ + DBVARIANT dbv; + if(!DBGetContactSettingTString(hContact, szModule, szSetting, &dbv)) + { + _tcsncpy(setting, dbv.ptszVal, size); + DBFreeVariant(&dbv); + return 0; + } + + _tcsncpy(setting, defaultValue, size); + return 1; +} + +void HigherLower(int maxValue, int minValue) +{ + TCHAR str[64] = { 0 }; + wsprintf(str, TranslateT("You cannot specify a value lower than %d and higher than %d."), minValue, maxValue); +} + +void ShowLog(TCHAR *file) +{ + int res = (int)ShellExecute(NULL, _T("open"), file, NULL, NULL, SW_SHOW); + if (res <= 32) // error + MessageBox(0, TranslateT("Can't open the log file!"), TranslateT("NewXstatusNotify"), MB_OK | MB_ICONERROR); +} + +int ProtoServiceExists(const char *szModule, const char *szService) +{ + char str[MAXMODULELABELLENGTH]; + if (szModule == NULL || szService == NULL) + return 0; + + strcpy(str,szModule); + strcat(str,szService); + return ServiceExists(str); +} + +BOOL StatusHasAwayMessage(char *szProto, int status) +{ + if (szProto != NULL) + { + unsigned long iSupportsSM = (unsigned long)CallProtoService(szProto, PS_GETCAPS, (WPARAM)PFLAGNUM_3, (LPARAM)0); + return (iSupportsSM & Proto_Status2Flag(status)) ? TRUE : FALSE; + } + else + { + switch (status) + { + case ID_STATUS_AWAY: + case ID_STATUS_NA: + case ID_STATUS_OCCUPIED: + case ID_STATUS_DND: + case ID_STATUS_FREECHAT: + case ID_STATUS_ONTHEPHONE: + case ID_STATUS_OUTTOLUNCH: + return TRUE; + default: + return FALSE; + } + } +} + +void LogToFile(TCHAR *stzText) +{ + FILE *fp = _tfopen(opt.LogFilePath, _T("a+b, ccs=UTF-8")); + if (fp) + { + char *encodedText = mir_utf8encodeT(stzText); + if (encodedText) + { + fprintf(fp, encodedText); + mir_free(encodedText); + } + fclose(fp); + } +} \ No newline at end of file diff --git a/plugins/NewXstatusNotify/utils.h b/plugins/NewXstatusNotify/utils.h new file mode 100644 index 0000000000..0ff5c93e23 --- /dev/null +++ b/plugins/NewXstatusNotify/utils.h @@ -0,0 +1,33 @@ +/* + NewXstatusNotify YM - Plugin for Miranda IM + Copyright (c) 2001-2004 Luca Santarelli + Copyright (c) 2005-2007 Vasilich + Copyright (c) 2007-2011 yaho + + 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 UTILS_H +#define UTILS_H + +TCHAR *db2t(DBVARIANT *dbv); +int DBGetStringDefault(HANDLE hContact, const char *szModule, const char *szSetting, TCHAR *setting, int size, const TCHAR *defaultValue); +void HigherLower(int maxValue, int minValue); +void ShowLog(TCHAR *file); +int ProtoServiceExists(const char *szModule, const char *szService); +BOOL StatusHasAwayMessage(char *szProto, int status); +void LogToFile(TCHAR *stzText); + +#endif \ No newline at end of file diff --git a/plugins/NewXstatusNotify/version.h b/plugins/NewXstatusNotify/version.h new file mode 100644 index 0000000000..10ac34a753 --- /dev/null +++ b/plugins/NewXstatusNotify/version.h @@ -0,0 +1,4 @@ +#define __FILEVERSION_STRING 1,4,0,9 +#define __VERSION_STRING "1.4.0.9" +#define __VERSION_DWORD PLUGIN_MAKE_VERSION(1, 4, 0, 9) + diff --git a/plugins/NewXstatusNotify/version.rc b/plugins/NewXstatusNotify/version.rc new file mode 100644 index 0000000000..1c99a26dab --- /dev/null +++ b/plugins/NewXstatusNotify/version.rc @@ -0,0 +1,37 @@ + +#include +#include "version.h" + +VS_VERSION_INFO VERSIONINFO + FILEVERSION __FILEVERSION_STRING + PRODUCTVERSION __FILEVERSION_STRING + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "Author", "Luca Santarelli, Vasilich, yaho" + VALUE "CompanyName", "yaho" + VALUE "FileDescription", "Notifies you when a contact changes his/her (X)status" + VALUE "FileVersion", __VERSION_STRING + VALUE "InternalName", "NewXstatusNotify YM" + VALUE "LegalCopyright", "© 2001-2004 Luca Santarelli, 2005-2007 Vasilich, 2007-2011 yaho" + VALUE "OriginalFilename", "NewXstatusNotify.dll" + VALUE "ProductName", "NewXstatusNotify YM" + VALUE "ProductVersion", __VERSION_STRING + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1200 + END +END diff --git a/plugins/NewXstatusNotify/xstatus.cpp b/plugins/NewXstatusNotify/xstatus.cpp new file mode 100644 index 0000000000..ed875c7fe0 --- /dev/null +++ b/plugins/NewXstatusNotify/xstatus.cpp @@ -0,0 +1,524 @@ +/* + NewXstatusNotify YM - Plugin for Miranda IM + Copyright (c) 2007-2011 yaho + + 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 "options.h" +#include "popup.h" +#include "utils.h" +#include "xstatus.h" + +extern SortedList *eventList; +extern OPTIONS opt; +extern TEMPLATES templates; + +XSTATUSCHANGE *NewXSC(HANDLE hContact, char *szProto, int xstatusType, int action, TCHAR *stzTitle, TCHAR *stzText) +{ + XSTATUSCHANGE *xsc = (XSTATUSCHANGE *)mir_alloc(sizeof(XSTATUSCHANGE)); + xsc->hContact = hContact; + xsc->szProto = szProto; + xsc->type = xstatusType; + xsc->action = action; + xsc->stzTitle = stzTitle; + xsc->stzText = stzText; + return xsc; +} + +void FreeXSC(XSTATUSCHANGE *xsc) +{ + if (xsc) + { + if (xsc->stzTitle) mir_free(xsc->stzTitle); + if (xsc->stzText) mir_free(xsc->stzText); + mir_free(xsc); + xsc = NULL; + } +} + +void RemoveLoggedEvents(HANDLE hContact) +{ + for (int i = eventList->realCount-1; i >= 0; i--) + { + DBEVENT *dbevent = (DBEVENT *)eventList->items[i]; + if (dbevent->hContact == hContact) + { + CallService(MS_DB_EVENT_DELETE, (WPARAM)dbevent->hContact, (LPARAM)dbevent->hDBEvent); + li.List_Remove(eventList, i); + mir_free(dbevent); + } + } +} + +TCHAR *GetStatusTypeAsString(int type, TCHAR *buff) +{ + switch (type) + { + case TYPE_JABBER_MOOD: + _tcscpy(buff, TranslateT("Mood")); break; + case TYPE_JABBER_ACTIVITY: + _tcscpy(buff, TranslateT("Activity")); break; + case TYPE_ICQ_XSTATUS: + _tcscpy(buff, TranslateT("Xstatus")); break; + default: + _tcscpy(buff, TranslateT("")); + } + + return buff; +} + +void ReplaceVars(XSTATUSCHANGE *xsc , TCHAR *Template, TCHAR *delimiter, TCHAR *buff) +{ + buff[0] = 0; + TCHAR *pch = _tcschr(Template, _T('%')); + while (pch != NULL) + { + size_t len = _tcslen(buff); + _tcsncat(buff, Template, pch - Template); + buff[len + pch - Template] = 0; + + if (pch[1] == _T('N') || pch[1] == _T('T') || pch[1] == _T('I') || pch[1] == _T('D') || pch[1] == _T('B')) + { + switch (pch[1]) + { + case _T('N'): + { + TCHAR stzType[32]; + _tcscat(buff, GetStatusTypeAsString(xsc->type, stzType)); + break; + } + case _T('T'): + { + if (xsc->stzTitle) + _tcscat(buff, xsc->stzTitle); + break; + } + case _T('I'): + { + if (xsc->stzText) + _tcscat(buff, xsc->stzText); + break; + } + case _T('D'): + { + if (xsc->stzText) + { + if (_tcscmp(delimiter, _T("%B")) == 0) + _tcscat(buff, _T("\r\n")); + else + _tcscat(buff, delimiter); + } + break; + } + case _T('B'): + { + _tcscat(buff, _T("\r\n")); + break; + } + } + + Template = pch + 2; + } + else + { + _tcscat(buff, _T("%")); + Template = pch + 1; + } + + pch = _tcschr(Template, _T('%')); + } + + // append rest of the text + if (Template != NULL) + _tcscat(buff, Template); +} + +void ShowPopup(XSTATUSCHANGE *xsc) +{ + DBVARIANT dbv; + char szSetting[64]; + + POPUPDATAT ppd = {0}; + ppd.lchContact = xsc->hContact; + + switch(xsc->type) + { + case TYPE_JABBER_MOOD: + case TYPE_JABBER_ACTIVITY: + { + mir_snprintf(szSetting, SIZEOF(szSetting), "%s/%s/%s", xsc->szProto, (xsc->type == TYPE_JABBER_MOOD) ? "mood" : "activity", "icon"); + if (!DBGetContactSettingString(xsc->hContact, "AdvStatus", szSetting, &dbv)) + { + ppd.lchIcon = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)dbv.pszVal); + DBFreeVariant(&dbv); + } + break; + } + case TYPE_ICQ_XSTATUS: + { + int statusId = DBGetContactSettingByte(xsc->hContact, xsc->szProto, "XStatusId", 0); + ppd.lchIcon = (HICON)CallProtoService(xsc->szProto, PS_ICQ_GETCUSTOMSTATUSICON, statusId, LR_SHARED); + } + } + + if (ppd.lchIcon == NULL) + ppd.lchIcon = LoadSkinnedProtoIcon(xsc->szProto, DBGetContactSettingWord(xsc->hContact, xsc->szProto, "Status", ID_STATUS_ONLINE)); + + switch (opt.Colors) + { + case POPUP_COLOR_OWN: + ppd.colorBack = DBGetContactSettingDword(0, MODULE, "40081bg", COLOR_BG_AVAILDEFAULT); + ppd.colorText = DBGetContactSettingDword(0, MODULE, "40081tx", COLOR_TX_DEFAULT); + break; + case POPUP_COLOR_WINDOWS: + ppd.colorBack = GetSysColor(COLOR_BTNFACE); + ppd.colorText = GetSysColor(COLOR_WINDOWTEXT); + break; + case POPUP_COLOR_POPUP: + ppd.colorBack = ppd.colorText = 0; + break; + } + + + _tcscpy(ppd.lptzContactName, (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)xsc->hContact, GSMDF_TCHAR)); + if (opt.ShowGroup) //add group name to popup title + { + if (!DBGetContactSettingTString(xsc->hContact, "CList", "Group", &dbv)) + { + _tcscat(ppd.lptzContactName, _T(" (")); + _tcscat(ppd.lptzContactName, dbv.ptszVal); + _tcscat(ppd.lptzContactName, _T(")")); + DBFreeVariant(&dbv); + } + } + + // cut message if needed + if (opt.PTruncateMsg && (opt.PMsgLen > 0) && xsc->stzText && (_tcslen(xsc->stzText) > opt.PMsgLen)) + { + TCHAR buff[MAX_TEXT_LEN + 3]; + _tcsncpy(buff, xsc->stzText, opt.PMsgLen); + buff[opt.PMsgLen] = 0; + _tcscat(buff, _T("...")); + mir_free(xsc->stzText); + xsc->stzText = mir_tstrdup(buff); + } + + TCHAR *Template; + switch (xsc->action) + { + case NOTIFY_NEW_XSTATUS: + Template = templates.PopupNewXstatus; break; + case NOTIFY_NEW_MESSAGE: + Template = templates.PopupNewMsg; break; + case NOTIFY_REMOVE: + Template = templates.PopupRemove; break; + } + + TCHAR stzPopupText[2*MAX_TEXT_LEN]; + ReplaceVars(xsc, Template, templates.PopupDelimiter, stzPopupText); + _tcsncpy(ppd.lptzText, stzPopupText, SIZEOF(ppd.lptzText)); + ppd.lptzText[SIZEOF(ppd.lptzText) - 1] = 0; + + ppd.PluginWindowProc = (WNDPROC)PopupDlgProc; + ppd.iSeconds = opt.PopupTimeout; + PUAddPopUpT(&ppd); +} + +void PlayXStatusSound(int action) +{ + switch (action) + { + case NOTIFY_NEW_XSTATUS: + SkinPlaySound(XSTATUS_SOUND_CHANGED); break; + case NOTIFY_NEW_MESSAGE: + SkinPlaySound(XSTATUS_SOUND_MSGCHANGED); break; + case NOTIFY_REMOVE: + SkinPlaySound(XSTATUS_SOUND_REMOVED); break; + } +} + +void LogToMessageWindow(XSTATUSCHANGE *xsc, BOOL opening) +{ + // cut message if needed + if (opt.LTruncateMsg && (opt.LMsgLen > 0) && xsc->stzText && (_tcslen(xsc->stzText) > opt.LMsgLen)) + { + TCHAR buff[MAX_TEXT_LEN + 3]; + _tcsncpy(buff, xsc->stzText, opt.LMsgLen); + buff[opt.LMsgLen] = 0; + _tcscat(buff, _T("...")); + mir_free(xsc->stzText); + xsc->stzText = mir_tstrdup(buff); + } + + TCHAR *Template; + switch (xsc->action) + { + case NOTIFY_NEW_XSTATUS: + Template = templates.LogNewXstatus; break; + case NOTIFY_NEW_MESSAGE: + Template = templates.LogNewMsg; break; + case NOTIFY_REMOVE: + Template = templates.LogRemove; break; + case NOTIFY_OPENING_ML: + Template = templates.LogOpening; break; + } + + TCHAR stzLogText[2*MAX_TEXT_LEN]; + TCHAR stzLastLog[2*MAX_TEXT_LEN]; + ReplaceVars(xsc, Template, templates.LogDelimiter, stzLogText); + DBGetStringDefault(xsc->hContact, MODULE, DB_LASTLOG, stzLastLog, SIZEOF(stzLastLog), _T("")); + + if (!opt.KeepInHistory || !(opt.PreventIdentical && _tcscmp(stzLastLog, stzLogText) == 0)) + { + DBWriteContactSettingTString(xsc->hContact, MODULE, DB_LASTLOG, stzLogText); + + char *blob; +#ifdef _UNICODE + blob = mir_utf8encodeT(stzLogText); +#else + blob = mir_strdup(stzLogText); +#endif + + DBEVENTINFO dbei = {0}; + dbei.cbSize = sizeof(dbei); + dbei.cbBlob = (DWORD)strlen(blob) + 1; + dbei.pBlob = (PBYTE) blob; + dbei.eventType = EVENTTYPE_STATUSCHANGE; + dbei.flags = DBEF_READ; +#ifdef _UNICODE + dbei.flags |= DBEF_UTF; +#endif + dbei.timestamp = (DWORD)time(NULL); + dbei.szModule = xsc->szProto; + HANDLE hDBEvent = (HANDLE)CallService(MS_DB_EVENT_ADD, (WPARAM)xsc->hContact, (LPARAM)&dbei); + mir_free(blob); + + if (!opt.KeepInHistory) + { + DBEVENT *dbevent = (DBEVENT *)mir_alloc(sizeof(DBEVENT)); + dbevent->hContact = xsc->hContact; + dbevent->hDBEvent = hDBEvent; + li.List_Insert(eventList, dbevent, eventList->realCount); + } + } +} + +void LogChangeToFile(XSTATUSCHANGE *xsc) +{ + TCHAR stzName[256], stzType[32]; + TCHAR stzDate[32], stzTime[32]; + TCHAR stzText[MAX_TEXT_LEN]; + + GetStatusTypeAsString(xsc->type, stzType); + + _tcscpy(stzName, (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)xsc->hContact, GCDNF_TCHAR)); + GetTimeFormat(LOCALE_USER_DEFAULT, 0, NULL,_T("HH':'mm"), stzTime, SIZEOF(stzTime)); + GetDateFormat(LOCALE_USER_DEFAULT, 0, NULL,_T("dd/MM/yyyy"), stzDate, SIZEOF(stzDate)); + + if (xsc->action == NOTIFY_REMOVE) + mir_sntprintf(stzText, SIZEOF(stzText), TranslateT("%s, %s. %s removed %s.\r\n"), stzDate, stzTime, stzName, stzType); + else + mir_sntprintf(stzText, SIZEOF(stzText), TranslateT("%s, %s. %s changed %s to: %s.\r\n"), stzDate, stzTime, stzName, stzType, xsc->stzTitle); + + LogToFile(stzText); +} + +void ExtraStatusChanged(XSTATUSCHANGE *xsc) +{ + BOOL bEnablePopup = true, bEnableSound = true; + char buff[12] = {0}; + + wsprintfA(buff, "%d", ID_STATUS_EXTRASTATUS); + + if ((DBGetContactSettingByte(0, MODULE, buff, 1) == 0) || + (DBGetContactSettingWord(xsc->hContact, xsc->szProto, "Status", ID_STATUS_OFFLINE) == ID_STATUS_OFFLINE) || + (!opt.HiddenContactsToo && DBGetContactSettingByte(xsc->hContact, "CList", "Hidden", 0)) || + (opt.TempDisabled)) + { + return; + } + + char statusIDs[12], statusIDp[12]; + if (opt.AutoDisable) + { + WORD myStatus = (WORD)CallProtoService(xsc->szProto, PS_GETSTATUS, 0, 0); + wsprintfA(statusIDs, "s%d", myStatus); + wsprintfA(statusIDp, "p%d", myStatus); + bEnableSound = DBGetContactSettingByte(0, MODULE, statusIDs, 1) ? FALSE : TRUE; + bEnablePopup = DBGetContactSettingByte(0, MODULE, statusIDp, 1) ? FALSE : TRUE; + } + + if (!(templates.PopupFlags & xsc->action)) + bEnableSound = bEnablePopup = false; + + int xstatusID = DBGetContactSettingByte(xsc->hContact, xsc->szProto, "XStatusId", 0); + if (opt.PDisableForMusic && xsc->type == TYPE_ICQ_XSTATUS && xstatusID == XSTATUS_MUSIC) + bEnableSound = bEnablePopup = false; + + if (bEnablePopup && DBGetContactSettingByte(xsc->hContact, MODULE, "EnableXStatusNotify", 1) && TimeoutCheck()) + ShowPopup(xsc); + + if (bEnableSound && DBGetContactSettingByte(xsc->hContact, MODULE, "EnableXStatusNotify", 1)) + PlayXStatusSound(xsc->action); + + BYTE enableLog = opt.EnableLogging; + if (opt.LDisableForMusic && xsc->type == TYPE_ICQ_XSTATUS && xstatusID == XSTATUS_MUSIC) + enableLog = FALSE; + + if (!(templates.LogFlags & xsc->action)) + enableLog = FALSE; + + if (enableLog && DBGetContactSettingByte(xsc->hContact, MODULE, "EnableLogging", 1) && + CallService(MS_MSG_MOD_MESSAGEDIALOGOPENED, (WPARAM)xsc->hContact, 0)) + { + LogToMessageWindow(xsc, FALSE); + } + + if (opt.Log) + LogChangeToFile(xsc); +} + +TCHAR *GetDefaultXstatusName(int statusID, char *szProto, TCHAR *buff, int bufflen) +{ + TCHAR nameBuff[64]; + buff[0] = 0; + + ICQ_CUSTOM_STATUS xstatus = {0}; + xstatus.cbSize = sizeof(ICQ_CUSTOM_STATUS); + xstatus.flags = CSSF_MASK_NAME | CSSF_DEFAULT_NAME | CSSF_TCHAR; + xstatus.ptszName = nameBuff; + xstatus.wParam = (WPARAM *)&statusID; + if (!CallProtoService(szProto, PS_ICQ_GETCUSTOMSTATUSEX, 0, (LPARAM)&xstatus)) + { + _tcsncpy(buff, TranslateTS(nameBuff), bufflen); + buff[bufflen - 1] = 0; + } + + return buff; +} + +TCHAR *GetIcqXStatus(HANDLE hContact, char *szProto, char *szValue, TCHAR *buff, int bufflen) +{ + DBVARIANT dbv; + buff[0] = 0; + + int statusID = DBGetContactSettingByte(hContact, szProto, "XStatusId", -1); + if (statusID != -1) + { + if (!DBGetContactSettingTString(hContact, szProto, szValue, &dbv)) + { + if ((strcmp(szValue, "XStatusName") == 0) && dbv.ptszVal[0] == 0) + GetDefaultXstatusName(statusID, szProto, buff, bufflen); + else + _tcsncpy(buff, dbv.ptszVal, bufflen); + + buff[bufflen - 1] = 0; + DBFreeVariant(&dbv); + } + } + + return buff; +} + +TCHAR *GetJabberAdvStatusText(HANDLE hContact, char *szProto, char *szSlot, char *szValue, TCHAR *buff, int bufflen) +{ + DBVARIANT dbv; + char szSetting[128]; + buff[0] = 0; + + mir_snprintf(szSetting, SIZEOF(szSetting), "%s/%s/%s", szProto, szSlot, szValue); + if (!DBGetContactSettingTString(hContact, "AdvStatus", szSetting, &dbv)) + { + _tcsncpy(buff, dbv.ptszVal, bufflen); + buff[bufflen - 1] = 0; + DBFreeVariant(&dbv); + } + + return buff; +} + +void LogXstatusChange(HANDLE hContact, char *szProto, int xstatusType, TCHAR *stzTitle, TCHAR *stzText) +{ + XSTATUSCHANGE *xsc = + NewXSC( + hContact, + szProto, + xstatusType, + NOTIFY_OPENING_ML, + stzTitle[0] ? mir_tstrdup(stzTitle): NULL, + stzText[0] ? mir_tstrdup(stzText) : NULL + ); + + LogToMessageWindow(xsc, TRUE); + FreeXSC(xsc); +} + +void AddEventThread(void *arg) +{ + HANDLE hContact = (HANDLE)arg; + TCHAR stzTitle[MAX_TITLE_LEN], stzText[MAX_TEXT_LEN]; + + char *szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + if (szProto == NULL) return; + + if (ProtoServiceExists(szProto, JS_PARSE_XMPP_URI)) + { + GetJabberAdvStatusText(hContact, szProto, "mood", "title", stzTitle, SIZEOF(stzTitle)); + if (stzTitle[0]) + { + GetJabberAdvStatusText(hContact, szProto, "mood", "text", stzText, SIZEOF(stzText)); + LogXstatusChange(hContact, szProto, TYPE_JABBER_MOOD, stzTitle, stzText); + } + + GetJabberAdvStatusText(hContact, szProto, "activity", "title", stzTitle, SIZEOF(stzTitle)); + if (stzTitle[0]) + { + GetJabberAdvStatusText(hContact, szProto, "activity", "text", stzText, SIZEOF(stzText)); + LogXstatusChange(hContact, szProto, TYPE_JABBER_ACTIVITY, stzTitle, stzText); + } + } + else + { + GetIcqXStatus(hContact, szProto, "XStatusName", stzTitle, SIZEOF(stzTitle)); + if (stzTitle[0]) + { + GetIcqXStatus(hContact, szProto, "XStatusMsg", stzText, SIZEOF(stzText)); + LogXstatusChange(hContact, szProto, TYPE_ICQ_XSTATUS, stzTitle, stzText); + } + } +} + +int OnWindowEvent(WPARAM wParam, LPARAM lParam) +{ + MessageWindowEventData *mwed = (MessageWindowEventData *)lParam; + + if (mwed->uType == MSG_WINDOW_EVT_CLOSE && !opt.KeepInHistory) + { + RemoveLoggedEvents(mwed->hContact); + return 0; + } + + if (opt.EnableLogging && + (mwed->uType == MSG_WINDOW_EVT_OPEN) && + (templates.LogFlags & NOTIFY_OPENING_ML) && + (DBGetContactSettingByte(mwed->hContact, MODULE, "EnableLogging", 1) == 1)) + { + mir_forkthread(AddEventThread, mwed->hContact); + } + + return 0; +} diff --git a/plugins/NewXstatusNotify/xstatus.h b/plugins/NewXstatusNotify/xstatus.h new file mode 100644 index 0000000000..a26b5fbc60 --- /dev/null +++ b/plugins/NewXstatusNotify/xstatus.h @@ -0,0 +1,106 @@ +/* + NewXstatusNotify YM - Plugin for Miranda IM + Copyright (c) 2007-2011 yaho + + 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 XSTATUS_H +#define XSTATUS_H + +#define NOTIFY_NEW_XSTATUS 1 +#define NOTIFY_NEW_MESSAGE 2 +#define NOTIFY_REMOVE 4 +#define NOTIFY_OPENING_ML 8 + +#define TYPE_ICQ_XSTATUS 1 +#define TYPE_JABBER_MOOD 2 +#define TYPE_JABBER_ACTIVITY 3 + +#define XSTATUS_MUSIC 11 + +#define MAX_TITLE_LEN 256 +#define MAX_TEXT_LEN 2048 + +// Database setting names +#define DB_LASTLOG "LastLog" + +// Sounds +#define XSTATUS_SOUND_CHANGED "XStatusChanged" +#define XSTATUS_SOUND_MSGCHANGED "XStatusMsgChanged" +#define XSTATUS_SOUND_REMOVED "XStatusRemove" + +// tabSRMM stuff (logging to message window) +#define EVENTTYPE_STATUSCHANGE 25368 +#define MS_MSG_MOD_MESSAGEDIALOGOPENED "SRMsg_MOD/MessageDialogOpened" + +// Default templates +#define DEFAULT_POPUP_DELIMITER _T("%B") +#define DEFAULT_POPUP_NEW TranslateT("changed %N to: %T%D%I") +#define DEFAULT_POPUP_CHANGEMSG TranslateT("changed %N message to:%D%I") +#define DEFAULT_POPUP_REMOVE TranslateT("removed %N") +#define DEFAULT_POPUP_STATUSMESSAGE "changed his/her status message to %n" + +#define DEFAULT_LOG_DELIMITER _T(": ") +#define DEFAULT_LOG_NEW TranslateT("changed %N @ %T%D%I") +#define DEFAULT_LOG_CHANGEMSG TranslateT("changed %N message @ %I") +#define DEFAULT_LOG_REMOVE TranslateT("removed %N") +#define DEFAULT_LOG_OPENING TranslateT("has %N @ %T%D%I") + +// Variables help text +#define VARIABLES_HELP_TEXT TranslateT("These variables are available:\r\n\r\n\ +%N\textra status name (Xstatus, Mood, Activity)\r\n\ +%T\textra status title\r\n\ +%I\textra status text\r\n\ +%D\tdelimiter\r\n\ +%B\tline break (can be used as delimiter)") + +#define VARIABLES_SM_HELP_TEXT TranslateT("These variables are available:\r\n\r\n\ +%n\tNew Status Message\r\n\ +%o\tOld Status Message\r\n\ +%c\tCustom Nickname\r\n\ +\\n\tline break\r\n\ +\\t\ttab stop") + +typedef struct tagXSTATUSCHANGE +{ + HANDLE hContact; + char *szProto; + int type; + int action; + TCHAR *stzTitle; + TCHAR *stzText; +} XSTATUSCHANGE; + +typedef struct tagDBEVENT +{ + HANDLE hContact; + HANDLE hDBEvent; +} DBEVENT; + +typedef struct tagPROTOTAMPLATE +{ + TCHAR *ProtoName; + TCHAR ProtoTamplate[MAX_PATH]; +} PROTOTAMPLATE; + +TCHAR *GetDefaultXstatusName(int statusID, char *szProto, TCHAR *buff, int bufflen); +XSTATUSCHANGE *NewXSC(HANDLE hContact, char *szProto, int xstatusType, int action, TCHAR *stzTitle, TCHAR *stzText); +void FreeXSC(XSTATUSCHANGE *xsc); +void ExtraStatusChanged(XSTATUSCHANGE *xsc); +int OnWindowEvent(WPARAM wParam, LPARAM lParam); +BOOL TimeoutCheck(); + +#endif \ No newline at end of file -- cgit v1.2.3