From cb4a46e7fbe62d788e66ed6121c717a2d22a4d7c Mon Sep 17 00:00:00 2001 From: watcherhd Date: Thu, 21 Apr 2011 14:14:52 +0000 Subject: svn.miranda.im is moving to a new home! git-svn-id: http://miranda-plugins.googlecode.com/svn/trunk@7 e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb --- newstatusnotify/Docs/NewStatusNotify_readme.txt | 231 ++ newstatusnotify/Docs/NewStatusNotify_translate.txt | 148 ++ newstatusnotify/ExternalAPI/m_metacontacts.h | 162 ++ newstatusnotify/ExternalAPI/m_updater.h | 117 + newstatusnotify/NewStatusNotify_6.dsp | 311 +++ newstatusnotify/NewStatusNotify_6.dsw | 29 + newstatusnotify/NewStatusNotify_7.sln | 27 + newstatusnotify/NewStatusNotify_7.vcproj | 376 ++++ newstatusnotify/NewStatusNotify_8.sln | 26 + newstatusnotify/NewStatusNotify_8.vcproj | 522 +++++ newstatusnotify/NewStatusNotify_9.sln | 25 + newstatusnotify/NewStatusNotify_9.vcproj | 504 +++++ newstatusnotify/commonheaders.h | 73 + newstatusnotify/indiv_sounds.c | 677 ++++++ newstatusnotify/main.c | 2378 ++++++++++++++++++++ newstatusnotify/newstatusnotify.h | 118 + newstatusnotify/res/NewStatusNotify.rc | 309 +++ newstatusnotify/res/main_off.ico | Bin 0 -> 2550 bytes newstatusnotify/res/main_on.ico | Bin 0 -> 2550 bytes newstatusnotify/res/popup.ico | Bin 0 -> 2038 bytes newstatusnotify/res/resource.h | 123 + newstatusnotify/res/resource.rc | 2 + newstatusnotify/res/sound.ico | Bin 0 -> 2038 bytes newstatusnotify/res/version.h | 41 + newstatusnotify/res/version.rc | 36 + 25 files changed, 6235 insertions(+) create mode 100644 newstatusnotify/Docs/NewStatusNotify_readme.txt create mode 100644 newstatusnotify/Docs/NewStatusNotify_translate.txt create mode 100644 newstatusnotify/ExternalAPI/m_metacontacts.h create mode 100644 newstatusnotify/ExternalAPI/m_updater.h create mode 100644 newstatusnotify/NewStatusNotify_6.dsp create mode 100644 newstatusnotify/NewStatusNotify_6.dsw create mode 100644 newstatusnotify/NewStatusNotify_7.sln create mode 100644 newstatusnotify/NewStatusNotify_7.vcproj create mode 100644 newstatusnotify/NewStatusNotify_8.sln create mode 100644 newstatusnotify/NewStatusNotify_8.vcproj create mode 100644 newstatusnotify/NewStatusNotify_9.sln create mode 100644 newstatusnotify/NewStatusNotify_9.vcproj create mode 100644 newstatusnotify/commonheaders.h create mode 100644 newstatusnotify/indiv_sounds.c create mode 100644 newstatusnotify/main.c create mode 100644 newstatusnotify/newstatusnotify.h create mode 100644 newstatusnotify/res/NewStatusNotify.rc create mode 100644 newstatusnotify/res/main_off.ico create mode 100644 newstatusnotify/res/main_on.ico create mode 100644 newstatusnotify/res/popup.ico create mode 100644 newstatusnotify/res/resource.h create mode 100644 newstatusnotify/res/resource.rc create mode 100644 newstatusnotify/res/sound.ico create mode 100644 newstatusnotify/res/version.h create mode 100644 newstatusnotify/res/version.rc (limited to 'newstatusnotify') diff --git a/newstatusnotify/Docs/NewStatusNotify_readme.txt b/newstatusnotify/Docs/NewStatusNotify_readme.txt new file mode 100644 index 0000000..e97e434 --- /dev/null +++ b/newstatusnotify/Docs/NewStatusNotify_readme.txt @@ -0,0 +1,231 @@ + NewStatusNotify readme file + +This plugin is just my first try to do something for miranda, and is further de- +velopment of NewStatusNotify plugin v1.1.2.2 from Luka Santarelli (aka hrk, +Hrk@users.sourceforge.net). + +Requirements:------------------------------------------------------------------- + - MirandaIM 0.6.2+ for Unicode (since 1.1.2.6b1), 0.4.3+ for ANSI + - Popup Plugin (Popup+ (2.0.3.96 or higher, 2.1.0.5+ recommended), or YAPP) + - for unicode version: unicode MirandaIM version (at least core and CList). + +Hidden settings (which have no GUI. Use DBE++ to set/edit these keys in DB under +"NewStatusNotify" entry in "Settings" branch):---------------------------------- + "ConnectionTimeoutXXX" as DWORD - timeout in miliseconds after "XXX" protocol + connected before starting to notify ( e.g. "ConnectionTimeoutSkype" for + proto named "Skype"). If not defined -then "ConnectionTimeout" (see under) + will be used; + "ConnectionTimeout" as DWORD - timeout in miliseconds after protocol connected + before starting to notify. General for all protos, default is 10000, i.e. + 10 seconds); + "ShowMirVer" as byte - if = 1 then show Miranda Client version in Popup. + +ChangeLog:---------------------------------------------------------------------- +1.1.3.0 (18.09.2009) + * minor code reformatting + - remove SmallDot icon - now requires core 0.7.0.2+ + + Log file name is unicode-aware and supports core variables + ! fixed popup preview statuses + ! minor translation fixes + * new default popup colors defined + +1.1.2.7 beta3 (28.06.2008) + * changed logic in status message request and display (still broken); + * changed "N/A"->"NA" also in resources; + +1.1.2.6 beta2 (09.05.2007) + ! fixed bug which can lead to MIM crash in Clist module (double mem freeing) + ! finally fixed rightclick on popup; + * made unload with destroying created services ("clean exit"); + + prepare to core 0.8 (use also PluginInfoEx); + ! corrected unicode path using for individual sounds; + ! fixed user-defined "out to lunch" and "on the phone" popup text colors; + * emulate behavior of core - do not blink tray icon (if used) when contact + went offline; + +1.1.2.6 beta1 (07.03.2007) + ! fixed bug with icons in Options - Events - Status Notify for MIM<0.7.0.2; + * made paths to individual sounds unicode-safe. This is supported since MIM + 0.6.2, so support of versions below is dropped for Unicode; + * disable any notifications for chatrooms; + ! fix showing test popup for "from offline" event; + * reworked Popup options page a bit: + changed test popup text - from now it really shows choosen info; + fixed possibility to show only status messages; + +1.1.2.6 alpha2 (21.02.2007) + * added request status messages only if subcontact have it for given status + for given meta; + * changed behavior of status descriptions showing - now it is always shown + if "show status descriptions" setting is checked, and no more dependent + from "show status messages" setting; + ! hopefully fixed reason of crashes (wrong string allocation); + +1.1.2.6 alpha1 (15.02.2007) + * "Plugin Disable/Enable" Menu Item moved from popup submenu to main menu + (reason - it controls whole plugin functionality, not only popups). Thx to + Faith Helaer for icons; + ! implemented support of metacontacts, as from v0.12.2.3 Metacontacts plugin + behaves different than other protos. Issues like lot of popups on startup + and going offline should be gone now. Please test; + * changed detection behavior of statuses supported by the protocol - now if + it returns 0 - then it will be translated as "support all statuses". Used + for Metacontacts and Weather Protos who return 0 in certain cases; + * switched to standard m_popup.h (as Nullbie finally made support for TCHAR + in it, and now this header is in standard codebase); + + added support of Updater for ANSI beta version; + * changed order of statuses in "user options" - "status notify" list; + + added hidden DWORD setting "ConnectionTimeoutXXX" per proto, where XXX is + a proto name (e.g."ConnectionTimeoutSkype"). If not found - then general + "ConnectionTimeout" setting (see description of 1.1.2.5b3) will be taken. + ! corrected reading of DWORD values from "ConnectionTimeout" setting to get + rid of thousands of popups when connecting to Skype; + ! fixed individual sounds previewing and playing when using SecureDB driver + (though that driver still has a bug with destroying of relative paths when + calling *_PATHTORELATIVE function with relative path as 1st param). Thanks + to LEM for pointing out to that bug and testing of fixed version. + +1.1.2.5 (20.11.2006) + ! fixed some DB memory leaks (thanks to Borkra); + + added show Miranda Client version (hidden option: "ShowMirVer" = 1 as byte + in DB)[FR:Thief]; + + added showing of contact's group name after contact's name in popup title + [FR:Wombat]; + * if left click on popup is configured to open message window - then it does + this also for contacts went offline (before it just did popup dismiss for + offline status popup) [FR:Wombat]; + +1.1.2.5RC2 (10.08.2006) + * click on popup settings are moved to popup settings page; + ! fixed: context menu on rightclick did not work (there are some issues + though due to bugs in other plugins: + -with CList_Modern message window will always appear when you select smth + from rightclick popup context menu [beside that selected item] + (EDIT: seems to be fixed since CList Modern 0.4.3.54); + -with popup plugin you will not get any icons in context menu; + -YAPP just hangs when you select certain items from context menu ); + ! fixed: settings for ignoring sounds depending on your status for that pro- + tocol, were not saved; + * small change in status name ("N/A"->"NA", as it was before); + * double click on a contact in Options - Events - Status Notify now selects + appropriate page in user details even when UserInfoEx is installed + (requires UInfoEx 0.1.2.18+); + +1.1.2.5RC1 (19.07.2006) + ! fixed stupid bug causing miranda crash when previewing individual "from + offline" sound and no sound was defined + ! fixed bug when "show from offline" popup setting was not shown properly + after Miranda restart + * changed behavior of popup events - now if they were not configured before, + they are enabled by default (on first start of new version only) + * code cleaning and optimization (removed unneeded resources, functions, + unreachable code, optimized some checks, and so on) + * try to fix miranda crash when using LastSeen plugin + +1.1.2.5b3 (6.07.2006) + + implemented updater support (as there is still no releases on FileListing, + it just checks builds from my site) + + show "User details" dialog with opened "Status notify" page instead of + opening message window when doubleclicking on a contact in Options - + Events - Status notify + + plugin now tries to use new PlaySoundEx service if available, making pos- + sible to control volume of Individual sounds also (requires SoundVolume + plugin, and changes in core. Will talk to GHazan about implementing that + patch in new (0.6) core codebase) + + added ability to disable popups for certain contact status changes (check + Popup settings). So for now it is possible to configure popups and sounds + SEPARATELY for each status change. Global enabling / disabling of status + notification events on main options page is still available. + + added hidden DWORD parameter "ConnectionTimeout" - if defined in DB, then + will wait X miliseconds after protocol connected before starting to notify + (default is 10000, i.e 10 seconds) + +1.1.2.5b2 (5.07.2006) + * completely rewritten sound management routine. Consequences: + 1. if FromOffline sound defined, but contact changed NOT from offline to + any status, appropriate sound will be played if defined (old variant: + if FromOffline sound was defined, then no sound was played when chan- + ging from NOT offline to any other status even with defined sound). + 2. Speaker sound plays exactly the same events as when using soundcard + (old behavior - just default sounds). Does anyone still use that PC + speaker (I believe my PC even has no speaker at all...)? + + added FromOffline event to Individual sounds (FR:DeeMaxX) + + added option to disable sound and popup notifications for a contact from + "Status Notify" (renamed from "Individual sounds") page in "User Details" + dialog (idea: Freak_TheMighty). And that option page doesn't disappear + anymore when individual sounds are disabled - I just disable unneeded + elements. + +1.1.2.5b1 (4.07.2006) + + changed blinking tray icon tooltip in tray to unicode, and text - to show + new status (instead of old "xxx is online" for all statuses) + ! fixed "Use Status icon" option to blink appropriate proto status icon + instead of global online icon in tray + ! fixed "Auto Turn off popups on status change" was dependant on (and has + changed) "Disable icon blinking" option in CList (!!!) + * changed behavior of autodisabling popups and sounds - now it depends on + that proto status, from which contact status change notification has came + (also removed one hook - should work a bit faster ;) ) + ! fixed assigning and deleting of individual sound filenames - now should + work properly even if Langpack_CP != CP_ACP + + introduced ability to disable sound and popup notifications "per contact" + (check "Status notify" settings page under "Events" in Miranda options) + - disabled that ugly "Sounds (individual statuses)" option page (noone + probably has ever used it). + +1.1.2.4a (24.06.2006) + * changed icons (thx FaithHealer) + * all registered sounds are separated in category "Status Notify" (idea: + Freak_TheMighty) + +1.1.2.4 (23.06.2006) + + added registered sound "User: from offline", which has priority to all + other registered status sounds + * try to fix popup (and Miranda) hang when displaying status message + +1.1.2.3a (20.05.2006) + * changed behavior of not retrieving status messages for ICQ in invisible + mode - now it checks not own global status, but only own ICQ status. + +1.1.2.3 (08.05.2006) + ! fixed bug with wrong displaying of individual sound file paths + ! changed "use individual sounds" internal checking routine, so now it + should play default sounds if disabled + * option "log statuses to file" was moved to general options page, so - no + Log page anymore + +1.1.2.2 (15.11.2005) Unicode mod; differences from original NSN v1.1.2.2: + + Unicode aware. i.e. all dialogs and popups support unicode + 1. unicode nicks on popups work only if you have unicode clist (so far + in nightlies all contactlist plugins are unicode-aware) + 2. as status messages in Miranda are nonunicode, plugin tries to convert + it to unicode using: + a. TabSRMM codepage setting for contact; + b. if message comes from ICQ client, then setting of codepage per: + i. ICQ codepage defined for a contact; if failed - then + ii. ICQ codepage defined globally; + c. codepage of languagepack installed; + if all of these settings are not defined, then status message is con- + verted using system codepage. + ! Removed Miranda crash when clicking on a contact with unloaded protocol + (usually named as "(Unknown contact)" ) and trying to look at individual + sounds. + * changed status list to read status messages from - now it depends on + protocol capabilities (so now it's possible to read status messages from + "online" status (e.g. for MSN, Jabber etc.) ). + + added checkbox to switch off using of individual sounds (idea: Thief). +-------------------------------------------------------------------------------- +ToDo: + + make "long notify" (for "from offline"-in contact menu, and for every status + - configurable per user); + + support of Idle Status change; + + add statuschange event to DB; + + write LastSeen-compatible data in DB; + +-------------------------------------------------------------------------------- + +Send your suggestons and found bugs to +email: abakumoff [at] mail [dot] ru +ICQ: 78611589 +jabber: IG_Vasilich [at] jabber [dot] ru +MSN: igorabakumov [at] hotmail [dot] com \ No newline at end of file diff --git a/newstatusnotify/Docs/NewStatusNotify_translate.txt b/newstatusnotify/Docs/NewStatusNotify_translate.txt new file mode 100644 index 0000000..916f4b8 --- /dev/null +++ b/newstatusnotify/Docs/NewStatusNotify_translate.txt @@ -0,0 +1,148 @@ +;------------------ general strings +[You cannot specify a value lower than %d and higher than %d.] +[] +[] +[%s is now %s] +[%s, %s. %s changed to: %s (was: %s).\r\n] + +[Status Notify] +[Notify] +[PopUps] +[Status] +[Sounds] +[Events] + +[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] + +;-------------------- NSN options +[Notify when a contact changes to one of these statuses] + +[Plugin activation] +[Automatically turn off PopUps and Sounds on status change] +[Configure] + +[Temporarily disable NewStatusNotify (disables popups and sounds)] +[Put an item in the main menu to easily enable/disable the plugin] +[Use individual sounds] +[Show PopUps when I connect] +[Do not warn me for people not in my Contact List] +[Blink icon in the system tray] +[Use status icon] + +[Log] +[&Log status changes to file] + +[Sound options] +[Use Internal &Speaker] +[&Avoid clipping] +[To select the sounds to play, click on \"Sounds\" in the menu on the left.] + +;-------------------- Events enabling +[Contact status change notifications] +[Enable sound notifications for this contact] +[Enable popup notifications for this contact] +[** All contacts **] + +;---------------------- autodisable options +[Automatically disable sounds or popups when I change to:] + +;------------------------- user options page +[Sound for the status] +[(default sound)] + +[&Change] +[&Preview] +[&Delete] +[with sounds] +[with popups] +[Individual sounds are disabled.\n\nTo enable them, go to Options - Status - Notify, enable \n""Use individual sounds"" checkbox, and then reopen this dialog.] + +;------------------------- popup option page +[Popups on contact status change to:] +[Colours] +[Back] +[Text] + +[Use cus&tom colors] +[Use Pop&up colours] +[Use &Windows colours] + +[Timeout] +[&From PopUp plugin] +[&Custom] +[P&ermanent] + +[Popup title] +[Show contact &group name] + +[Use standard &descriptions] +[Use &alternative descriptions] +[Show &previous status too] +[Read status &message] + +[On left click] +[On right click] +[Dismiss] +[Open message] +[Open user menu] + +[Prev&iew] +[This is \"from offline\" status message] diff --git a/newstatusnotify/ExternalAPI/m_metacontacts.h b/newstatusnotify/ExternalAPI/m_metacontacts.h new file mode 100644 index 0000000..1da12b9 --- /dev/null +++ b/newstatusnotify/ExternalAPI/m_metacontacts.h @@ -0,0 +1,162 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright © 2004 Universite Louis PASTEUR, STRASBOURG. +Copyright © 2004 Scott Ellis (www.scottellis.com.au mail@scottellis.com.au) + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef M_METACONTACTS_H__ +#define M_METACONTACTS_H__ 1 + +//get the handle for a contact's parent metacontact +//wParam=(HANDLE)hSubContact +//lParam=0 +//returns a handle to the parent metacontact, or null if this contact is not a subcontact +#define MS_MC_GETMETACONTACT "MetaContacts/GetMeta" + +//gets the handle for the default contact +//wParam=(HANDLE)hMetaContact +//lParam=0 +//returns a handle to the default contact, or null on failure +#define MS_MC_GETDEFAULTCONTACT "MetaContacts/GetDefault" + +//gets the contact number for the default contact +//wParam=(HANDLE)hMetaContact +//lParam=0 +//returns a DWORD contact number, or -1 on failure +#define MS_MC_GETDEFAULTCONTACTNUM "MetaContacts/GetDefaultNum" + +//gets the handle for the 'most online' contact +//wParam=(HANDLE)hMetaContact +//lParam=0 +//returns a handle to the 'most online' contact +#define MS_MC_GETMOSTONLINECONTACT "MetaContacts/GetMostOnline" + +//gets the number of subcontacts for a metacontact +//wParam=(HANDLE)hMetaContact +//lParam=0 +//returns a DWORD representing the number of subcontacts for the given metacontact +#define MS_MC_GETNUMCONTACTS "MetaContacts/GetNumContacts" + +//gets the handle of a subcontact, using the subcontact's number +//wParam=(HANDLE)hMetaContact +//lParam=(DWORD)contact number +//returns a handle to the specified subcontact +#define MS_MC_GETSUBCONTACT "MetaContacts/GetSubContact" + +//sets the default contact, using the subcontact's contact number +//wParam=(HANDLE)hMetaContact +//lParam=(DWORD)contact number +//returns 0 on success +#define MS_MC_SETDEFAULTCONTACTNUM "MetaContacts/SetDefault" + +//sets the default contact, using the subcontact's handle +//wParam=(HANDLE)hMetaContact +//lParam=(HANDLE)hSubcontact +//returns 0 on success +#define MS_MC_SETDEFAULTCONTACT "MetaContacts/SetDefaultByHandle" + +//forces the metacontact to send using a specific subcontact, using the subcontact's contact number +//wParam=(HANDLE)hMetaContact +//lParam=(DWORD)contact number +//returns 0 on success +#define MS_MC_FORCESENDCONTACTNUM "MetaContacts/ForceSendContact" + +//forces the metacontact to send using a specific subcontact, using the subcontact's handle +//wParam=(HANDLE)hMetaContact +//lParam=(HANDLE)hSubcontact +//returns 0 on success (will fail if 'force default' is in effect) +#define MS_MC_FORCESENDCONTACT "MetaContacts/ForceSendContactByHandle" + +//'unforces' the metacontact to send using a specific subcontact +//wParam=(HANDLE)hMetaContact +//lParam=0 +//returns 0 on success (will fail if 'force default' is in effect) +#define MS_MC_UNFORCESENDCONTACT "MetaContacts/UnforceSendContact" + +//'forces' or 'unforces' (i.e. toggles) the metacontact to send using it's default contact +// overrides (and clears) 'force send' above, and will even force use of offline contacts +// will send ME_MC_FORCESEND or ME_MC_UNFORCESEND event +//wParam=(HANDLE)hMetaContact +//lParam=0 +//returns 1(true) or 0(false) representing new state of 'force default' +#define MS_MC_FORCEDEFAULT "MetaContacts/ForceSendDefault" + +// method to get state of 'force' for a metacontact +// wParam=(HANDLE)hMetaContact +// lParam= (DWORD)&contact_number or NULL +// +// if lparam supplied, the contact_number of the contatct 'in force' will be copied to the address it points to, +// or if none is in force, the value (DWORD)-1 will be copied +// (v0.8.0.8+ returns 1 if 'force default' is true with *lParam == default contact number, else returns 0 with *lParam as above) +#define MS_MC_GETFORCESTATE "MetaContacts/GetForceState" + +// fired when a metacontact's default contact changes (fired upon creation of metacontact also, when default is initially set) +// wParam=(HANDLE)hMetaContact +// lParam=(HANDLE)hDefaultContact +#define ME_MC_DEFAULTTCHANGED "MetaContacts/DefaultChanged" + +// fired when a metacontact's subcontacts change (fired upon creation of metacontact, when contacts are added or removed, and when +// contacts are reordered) - a signal to re-read metacontact data +// wParam=(HANDLE)hMetaContact +// lParam=0 +#define ME_MC_SUBCONTACTSCHANGED "MetaContacts/SubcontactsChanged" + +// fired when a metacontact is forced to send using a specific subcontact +// wParam=(HANDLE)hMetaContact +// lParam=(HANDLE)hForceContact +#define ME_MC_FORCESEND "MetaContacts/ForceSend" + +// fired when a metacontact is 'unforced' to send using a specific subcontact +// wParam=(HANDLE)hMetaContact +// lParam=0 +#define ME_MC_UNFORCESEND "MetaContacts/UnforceSend" + +// method to get protocol name - used to be sure you're dealing with a "real" metacontacts plugin :) +// wParam=lParam=0 +#define MS_MC_GETPROTOCOLNAME "MetaContacts/GetProtoName" + + +// added 0.9.5.0 (22/3/05) +// wParam=(HANDLE)hContact +// lParam=0 +// convert a given contact into a metacontact +#define MS_MC_CONVERTTOMETA "MetaContacts/ConvertToMetacontact" + +// added 0.9.5.0 (22/3/05) +// wParam=(HANDLE)hContact +// lParam=(HANDLE)hMeta +// add an existing contact to a metacontact +#define MS_MC_ADDTOMETA "MetaContacts/AddToMetacontact" + +// added 0.9.5.0 (22/3/05) +// wParam=0 +// lParam=(HANDLE)hContact +// remove a contact from a metacontact +#define MS_MC_REMOVEFROMMETA "MetaContacts/RemoveFromMetacontact" + + +// added 0.9.13.2 (6/10/05) +// wParam=(BOOL)disable +// lParam=0 +// enable/disable the 'hidden group hack' - for clists that support subcontact hiding using 'IsSubcontact' setting +// should be called once in the clist 'onmodulesloaded' event handler (which, since it's loaded after the db, will be called +// before the metacontact onmodulesloaded handler where the subcontact hiding is usually done) +#define MS_MC_DISABLEHIDDENGROUP "MetaContacts/DisableHiddenGroup" + +#endif diff --git a/newstatusnotify/ExternalAPI/m_updater.h b/newstatusnotify/ExternalAPI/m_updater.h new file mode 100644 index 0000000..c83b8a4 --- /dev/null +++ b/newstatusnotify/ExternalAPI/m_updater.h @@ -0,0 +1,117 @@ +#ifndef _M_UPDATER_H +#define _M_UPDATER_H + +// if you set Update::szUpdateURL to the following value when registering, as well as setting your beta site and version data, +// updater will ignore szVersionURL and pbVersionPrefix, and attempt to find the file listing URL's from the backend XML data. +// for this to work, the plugin name in pluginInfo.shortName must match the file listing exactly (except for case) +#define UPDATER_AUTOREGISTER "UpdaterAUTOREGISTER" + +typedef struct Update_tag { + int cbSize; + char *szComponentName; // component name as it will appear in the UI (will be translated before displaying) + + char *szVersionURL; // URL where the current version can be found (NULL to disable) + BYTE *pbVersionPrefix; // bytes occuring in VersionURL before the version, used to locate the version information within the URL data + // (not that this URL could point at a binary file - dunno why, but it could :) + int cpbVersionPrefix; // number of bytes pionted to by pbVersionPrefix + char *szUpdateURL; // URL where dll/zip is located + // set to UPDATER_AUTOREGISTER if you want updater to find the file listing URLs (ensure plugin shortName matches file listing!) + + char *szBetaVersionURL; // URL where the beta version can be found (NULL to disable betas) + BYTE *pbBetaVersionPrefix; // bytes occuring in VersionURL before the version, used to locate the version information within the URL data + int cpbBetaVersionPrefix; // number of bytes pionted to by pbVersionPrefix + char *szBetaUpdateURL; // URL where dll/zip is located + + BYTE *pbVersion; // bytes of current version, used for comparison with those in VersionURL + int cpbVersion; // number of bytes pionted to by pbVersion + + char *szBetaChangelogURL; // url for displaying changelog for beta versions +} Update; + +// register a comonent with the updater +// +// wparam = 0 +// lparam = (LPARAM)&Update +#define MS_UPDATE_REGISTER "Update/Register" + +// utility functions to create a version string from a DWORD or from pluginInfo +// point buf at a buffer at least 16 chars wide - but note the version string returned may be shorter +// +__inline static char *CreateVersionString(DWORD version, char *buf) { + mir_snprintf(buf, 16, "%d.%d.%d.%d", (version >> 24) & 0xFF, (version >> 16) & 0xFF, (version >> 8) & 0xFF, version & 0xFF); + return buf; +} + +__inline static char *CreateVersionStringPlugin(PLUGININFO *pluginInfo, char *buf) { + return CreateVersionString(pluginInfo->version, buf); +} + + +// register the 'easy' way - use this method if you have no beta URL and the plugin is on the miranda file listing +// NOTE: the plugin 'short name' in pluginInfo must match the name of the plugin on the file listing, exactly (not including case) +// AND the plugin version string on the file listing must be the string version of the version in pluginInfo (i.e. 0.0.0.1, +// so no letters, brackets, etc.) +// +// wParam = (int)fileID - this is the file ID from the file listing (i.e. the number at the end of the download link) +// lParam = (PLUGININFO*)&pluginInfo +#define MS_UPDATE_REGISTERFL "Update/RegisterFL" + +// this event is fired when the startup process is complete, but NOT if a restart is imminent +// it is designed for status managment plugins to use as a trigger for beggining their own startup process +// wParam = lParam = 0 (unused) +// (added in version 0.1.6.0) +#define ME_UPDATE_STARTUPDONE "Update/StartupDone" + +// this service can be used to enable/disable Updater's global status control +// it can be called from the StartupDone event handler +// wParam = (BOOL)enable +// lParam = 0 +// (added in version 0.1.6.0) +#define MS_UPDATE_ENABLESTATUSCONTROL "Update/EnableStatusControl" + +// An description of usage of the above service and event: +// Say you are a status control plugin that normally sets protocol or global statuses in your ModulesLoaded event handler. +// In order to make yourself 'updater compatible', you would move the status control code from ModulesLoaded to another function, +// say DoStartup. Then, in ModulesLoaded you would check for the existence of the MS_UPDATE_ENABLESTATUSCONTROL service. +// If it does not exist, call DoStartup. If it does exist, hook the ME_UPDATE_STARTUPDONE event and call DoStartup from there. You may +// also wish to call MS_UPDATE_ENABLESTATUSCONTROL with wParam == FALSE at this time, to disable Updater's own status control feature. + +#endif + + +/////////////// Usage Example /////////////// + +#ifdef EXAMPLE_CODE + +// you need to #include "m_updater.h" and HookEvent(ME_SYSTEM_MODULESLOADED, OnModulesLoaded) in your Load function... + +int OnModulesLoaded(WPARAM wParam, LPARAM lParam) { + + Update update = {0}; // for c you'd use memset or ZeroMemory... + char szVersion[16]; + + update.cbSize = sizeof(Update); + + update.szComponentName = pluginInfo.shortName; + update.pbVersion = (BYTE *)CreateVersionString(&pluginInfo, szVersion); + update.cpbVersion = strlen((char *)update.pbVersion); + + // these are the three lines that matter - the archive, the page containing the version string, and the text (or data) + // before the version that we use to locate it on the page + // (note that if the update URL and the version URL point to standard file listing entries, the backend xml + // data will be used to check for updates rather than the actual web page - this is not true for beta urls) + update.szUpdateURL = "http://scottellis.com.au:81/test/updater.zip"; + update.szVersionURL = "http://scottellis.com.au:81/test/updater_test.html"; + update.pbVersionPrefix = (BYTE *)"Updater version "; + + update.cpbVersionPrefix = strlen((char *)update.pbVersionPrefix); + + CallService(MS_UPDATE_REGISTER, 0, (WPARAM)&update); + + // Alternatively, to register a plugin with e.g. file ID 2254 on the file listing... + // CallService(MS_UPDATE_REGISTERFL, (WPARAM)2254, (LPARAM)&pluginInfo); + + return 0; +} + +#endif diff --git a/newstatusnotify/NewStatusNotify_6.dsp b/newstatusnotify/NewStatusNotify_6.dsp new file mode 100644 index 0000000..70a0436 --- /dev/null +++ b/newstatusnotify/NewStatusNotify_6.dsp @@ -0,0 +1,311 @@ +# Microsoft Developer Studio Project File - Name="NewStatusNotify" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=NewStatusNotify - Win32 Release Unicode +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "NewStatusNotify_6.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "NewStatusNotify_6.mak" CFG="NewStatusNotify - Win32 Release Unicode" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "NewStatusNotify - Win32 Release Unicode" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "NewStatusNotify - Win32 Debug Unicode" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "NewStatusNotify - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "NewStatusNotify - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "NewStatusNotify - Win32 Release Unicode" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release Unicode" +# PROP BASE Intermediate_Dir "Release Unicode" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release Unicode" +# PROP Intermediate_Dir "Release Unicode" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /Ox /Os /Gy /I "..\..\include" /D "_UNICODE" /GF /TC /c +# ADD CPP /nologo /MD /W3 /GX /Ox /Og /Os /Gy /I "..\..\include" /D "_UNICODE" /D "UNICODE" /GF /TC /c +# SUBTRACT CPP /Oa /Ow /Oi /Gf /Fr +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x0 /d "NDEBUG" +# ADD RSC /l 0x0 /fo"resource.res" /i ".\res" /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib winmm.lib /nologo /dll /machine:IX86 /release +# ADD LINK32 user32.lib comdlg32.lib comctl32.lib winmm.lib /nologo /subsystem:windows /dll /pdb:none /machine:IX86 /force /out:"../../bin/release unicode/plugins/NewStatusNotify.dll" /opt:ref /opt:icf /release +# SUBTRACT LINK32 /debug /nodefaultlib + +!ELSEIF "$(CFG)" == "NewStatusNotify - Win32 Debug Unicode" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "..\..\bin\$(ConfigurationName)\Plugins" +# PROP BASE Intermediate_Dir "..\..\bin\$(ConfigurationName)\Obj\$(ProjectName)" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug Unicode" +# PROP Intermediate_Dir "Debug Unicode" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /GX /ZI /Od /I "..\..\include" /D "_UNICODE" /TC /GZ /c +# ADD CPP /nologo /MDd /W3 /GX /ZI /Od /I "..\..\include" /D "_UNICODE" /D "UNICODE" /D "_DEBUG" /TC /GZ /c +# SUBTRACT CPP /Fr +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x0 /d "NDEBUG" +# ADD RSC /l 0x0 /fo"resource.res" /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib winmm.lib /nologo /subsystem:windows /dll /debug /machine:IX86 /out:"..\..\bin\$(ConfigurationName)\Plugins\$(ProjectName).dll" /implib:"$(TargetDir)$(TargetName).lib" /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib comdlg32.lib comctl32.lib winmm.lib /nologo /subsystem:windows /dll /pdb:"../../bin/debug unicode/plugins/NewStatusNotify.pdb" /debug /machine:IX86 /out:"../../bin/debug unicode/plugins/NewStatusNotify.dll" /pdbtype:sept +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "NewStatusNotify - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "..\..\bin\$(ConfigurationName)\Plugins" +# PROP BASE Intermediate_Dir "..\..\bin\$(ConfigurationName)\Obj\$(ProjectName)" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /GX /ZI /Od /I "..\..\include" /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D "NewStatusNotify_EXPORTS" /D "_MBCS" /TC /GZ /c +# ADD CPP /nologo /MDd /W3 /GX /ZI /Od /I "..\..\include" /D "_MBCS" /D "_DEBUG" /TC /GZ /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x0 /d "NDEBUG" +# ADD RSC /l 0x0 /fo"resource.res" /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib winmm.lib /nologo /subsystem:windows /dll /debug /machine:IX86 /out:"..\..\bin\$(ConfigurationName)\Plugins\$(ProjectName).dll" /implib:"$(TargetDir)$(TargetName).lib" /pdbtype:sept /version:1.1.2.5 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib winmm.lib /nologo /subsystem:windows /dll /pdb:"../../bin/debug/plugins/NewStatusNotify.pdb" /debug /machine:IX86 /out:"../../bin/debug/plugins/NewStatusNotify.dll" /implib:"$(TargetDir)$(TargetName).lib" /pdbtype:sept /version:1.1.2.5 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "NewStatusNotify - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /Ox /Os /Gy /I "..\..\include" /D "_MBCS" /GF /TC /c +# ADD CPP /nologo /MD /W3 /GX /Ox /Os /Gy /I "..\..\include" /D "_MBCS" /GF /TC /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x0 /d "NDEBUG" +# ADD RSC /l 0x0 /fo"resource.res" /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib winmm.lib /nologo /subsystem:windows /dll /debug /machine:IX86 /out:"../../bin/release/plugins/NewStatusNotify.dll" /pdbtype:sept /opt:ref /opt:icf /release +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib winmm.lib /nologo /subsystem:windows /dll /pdb:"../../bin/release/plugins/NewStatusNotify.pdb" /debug /machine:IX86 /out:"../../bin/release/plugins/NewStatusNotify.dll" /pdbtype:sept /opt:ref /opt:icf /release +# SUBTRACT LINK32 /pdb:none + +!ENDIF + +# Begin Target + +# Name "NewStatusNotify - Win32 Release Unicode" +# Name "NewStatusNotify - Win32 Debug Unicode" +# Name "NewStatusNotify - Win32 Debug" +# Name "NewStatusNotify - Win32 Release" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\indiv_sounds.c +DEP_CPP_INDIV=\ + "..\..\include\m_awaymsg.h"\ + "..\..\include\m_clc.h"\ + "..\..\include\m_clist.h"\ + "..\..\include\m_clui.h"\ + "..\..\include\m_database.h"\ + "..\..\include\m_genmenu.h"\ + "..\..\include\m_ignore.h"\ + "..\..\include\m_langpack.h"\ + "..\..\include\m_message.h"\ + "..\..\include\m_metacontacts.h"\ + "..\..\include\m_options.h"\ + "..\..\include\m_plugins.h"\ + "..\..\include\m_popup.h"\ + "..\..\include\m_protocols.h"\ + "..\..\include\m_protosvc.h"\ + "..\..\include\m_skin.h"\ + "..\..\include\m_system.h"\ + "..\..\include\m_updater.h"\ + "..\..\include\m_userinfo.h"\ + "..\..\include\m_utils.h"\ + "..\..\include\newpluginapi.h"\ + "..\..\include\statusmodes.h"\ + "..\..\include\win2k.h"\ + ".\commonheaders.h"\ + ".\newstatusnotify.h"\ + +# End Source File +# Begin Source File + +SOURCE=.\main.c +DEP_CPP_MAIN_=\ + "..\..\include\m_awaymsg.h"\ + "..\..\include\m_clc.h"\ + "..\..\include\m_clist.h"\ + "..\..\include\m_clui.h"\ + "..\..\include\m_database.h"\ + "..\..\include\m_genmenu.h"\ + "..\..\include\m_ignore.h"\ + "..\..\include\m_langpack.h"\ + "..\..\include\m_message.h"\ + "..\..\include\m_metacontacts.h"\ + "..\..\include\m_options.h"\ + "..\..\include\m_plugins.h"\ + "..\..\include\m_popup.h"\ + "..\..\include\m_protocols.h"\ + "..\..\include\m_protosvc.h"\ + "..\..\include\m_skin.h"\ + "..\..\include\m_system.h"\ + "..\..\include\m_updater.h"\ + "..\..\include\m_userinfo.h"\ + "..\..\include\m_utils.h"\ + "..\..\include\newpluginapi.h"\ + "..\..\include\statusmodes.h"\ + "..\..\include\win2k.h"\ + ".\commonheaders.h"\ + ".\newstatusnotify.h"\ + ".\res\version.h"\ + +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\commonheaders.h +# End Source File +# Begin Source File + +SOURCE=.\newstatusnotify.h +# End Source File +# Begin Source File + +SOURCE=.\res\resource.h +# End Source File +# Begin Source File + +SOURCE=.\res\version.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\res\main_off.ico +# End Source File +# Begin Source File + +SOURCE=.\res\main_on.ico +# End Source File +# Begin Source File + +SOURCE=.\res\NewStatusNotify.rc +# PROP Exclude_From_Build 1 +# End Source File +# Begin Source File + +SOURCE=.\res\popup.ico +# End Source File +# Begin Source File + +SOURCE=.\res\resource.rc + +!IF "$(CFG)" == "NewStatusNotify - Win32 Release Unicode" + +!ELSEIF "$(CFG)" == "NewStatusNotify - Win32 Debug Unicode" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "NewStatusNotify - Win32 Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "NewStatusNotify - Win32 Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\res\sound.ico +# End Source File +# Begin Source File + +SOURCE=.\res\version.rc + +!IF "$(CFG)" == "NewStatusNotify - Win32 Release Unicode" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "NewStatusNotify - Win32 Debug Unicode" + +!ELSEIF "$(CFG)" == "NewStatusNotify - Win32 Debug" + +!ELSEIF "$(CFG)" == "NewStatusNotify - Win32 Release" + +!ENDIF + +# End Source File +# End Group +# Begin Source File + +SOURCE=.\Docs\NewStatusNotify_readme.txt +# End Source File +# Begin Source File + +SOURCE=.\Docs\NewStatusNotify_translate.txt +# End Source File +# End Target +# End Project diff --git a/newstatusnotify/NewStatusNotify_6.dsw b/newstatusnotify/NewStatusNotify_6.dsw new file mode 100644 index 0000000..527a5bf --- /dev/null +++ b/newstatusnotify/NewStatusNotify_6.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "NewStatusNotify"=NewStatusNotify_6.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/newstatusnotify/NewStatusNotify_7.sln b/newstatusnotify/NewStatusNotify_7.sln new file mode 100644 index 0000000..3aa0f6a --- /dev/null +++ b/newstatusnotify/NewStatusNotify_7.sln @@ -0,0 +1,27 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NewStatusNotify_7", "NewStatusNotify_7.vcproj", "{78E0E6B0-2D7E-4B4D-899A-DA244FBBEC73}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Debug_Unicode = Debug_Unicode + Release = Release + Release_Unicode = Release_Unicode + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {78E0E6B0-2D7E-4B4D-899A-DA244FBBEC73}.Debug.ActiveCfg = Debug|Win32 + {78E0E6B0-2D7E-4B4D-899A-DA244FBBEC73}.Debug.Build.0 = Debug|Win32 + {78E0E6B0-2D7E-4B4D-899A-DA244FBBEC73}.Debug_Unicode.ActiveCfg = Debug_Unicode|Win32 + {78E0E6B0-2D7E-4B4D-899A-DA244FBBEC73}.Debug_Unicode.Build.0 = Debug_Unicode|Win32 + {78E0E6B0-2D7E-4B4D-899A-DA244FBBEC73}.Release.ActiveCfg = Release|Win32 + {78E0E6B0-2D7E-4B4D-899A-DA244FBBEC73}.Release.Build.0 = Release|Win32 + {78E0E6B0-2D7E-4B4D-899A-DA244FBBEC73}.Release_Unicode.ActiveCfg = Release_Unicode|Win32 + {78E0E6B0-2D7E-4B4D-899A-DA244FBBEC73}.Release_Unicode.Build.0 = Release_Unicode|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/newstatusnotify/NewStatusNotify_7.vcproj b/newstatusnotify/NewStatusNotify_7.vcproj new file mode 100644 index 0000000..bce1fd1 --- /dev/null +++ b/newstatusnotify/NewStatusNotify_7.vcproj @@ -0,0 +1,376 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/newstatusnotify/NewStatusNotify_8.sln b/newstatusnotify/NewStatusNotify_8.sln new file mode 100644 index 0000000..35deb56 --- /dev/null +++ b/newstatusnotify/NewStatusNotify_8.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NewStatusNotify_8", "NewStatusNotify_8.vcproj", "{78E0E6B0-2D7E-4B4D-899A-DA244FBBEC73}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug_Unicode|Win32 = Debug_Unicode|Win32 + Debug|Win32 = Debug|Win32 + Release_Unicode|Win32 = Release_Unicode|Win32 + Release|Win32 = Release|Win32 + 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|Win32.ActiveCfg = Debug|Win32 + {78E0E6B0-2D7E-4B4D-899A-DA244FBBEC73}.Debug|Win32.Build.0 = Debug|Win32 + {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|Win32.ActiveCfg = Release|Win32 + {78E0E6B0-2D7E-4B4D-899A-DA244FBBEC73}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/newstatusnotify/NewStatusNotify_8.vcproj b/newstatusnotify/NewStatusNotify_8.vcproj new file mode 100644 index 0000000..131f926 --- /dev/null +++ b/newstatusnotify/NewStatusNotify_8.vcproj @@ -0,0 +1,522 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/newstatusnotify/NewStatusNotify_9.sln b/newstatusnotify/NewStatusNotify_9.sln new file mode 100644 index 0000000..67e6071 --- /dev/null +++ b/newstatusnotify/NewStatusNotify_9.sln @@ -0,0 +1,25 @@ +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NewStatusNotify", "NewStatusNotify_9.vcproj", "{78E0E6B0-2D7E-4B4D-899A-DA244FBBEC73}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug_Unicode|Win32 = Debug_Unicode|Win32 + Debug|Win32 = Debug|Win32 + Release_Unicode|Win32 = Release_Unicode|Win32 + Release|Win32 = Release|Win32 + 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|Win32.ActiveCfg = Debug|Win32 + {78E0E6B0-2D7E-4B4D-899A-DA244FBBEC73}.Debug|Win32.Build.0 = Debug|Win32 + {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|Win32.ActiveCfg = Release|Win32 + {78E0E6B0-2D7E-4B4D-899A-DA244FBBEC73}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/newstatusnotify/NewStatusNotify_9.vcproj b/newstatusnotify/NewStatusNotify_9.vcproj new file mode 100644 index 0000000..5f98aa8 --- /dev/null +++ b/newstatusnotify/NewStatusNotify_9.vcproj @@ -0,0 +1,504 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/newstatusnotify/commonheaders.h b/newstatusnotify/commonheaders.h new file mode 100644 index 0000000..4e95d32 --- /dev/null +++ b/newstatusnotify/commonheaders.h @@ -0,0 +1,73 @@ +/* +=============================================================================== + NewStatusNotify plugin + +This plugin notifies you when a contact changes his/hers status with a PopUp. +You can customize its look (style of popup, font, text...) and behaviour (the +position in the screen, the time to live, the action on a mouse click). + +This file has the purpose of becoming a precompiled header common to every +project file. + +Written by: Hrk (Luca Santarelli) (2002-2004), Vasilich (2005-2008) + +Miranda IM can be found here: +http://miranda-im.org/ + +=============================================================================== +*/ + +#ifndef COMMONHEADERS_H +#define COMMONHEADERS_H +#define _WIN32_WINNT 0x0500 +#define WINVER 0x0500 +#define MIRANDA_VER 0x0800 +#define _CRT_SECURE_NO_DEPRECATE +#define _USE_32BIT_TIME_T +#define STRICT +#define WIN32_LEAN_AND_MEAN + +//Standard Windows "libraries" +#include +#include +#include +#include +#include +#include +#include + +#include "newpluginapi.h" +#include "m_system.h" +#include "m_utils.h" +#include "m_plugins.h" +#include "m_clist.h" +#include "m_options.h" +#include "m_clui.h" +#include "m_clc.h" +#include "m_genmenu.h" +#include "m_skin.h" +#include "m_langpack.h" +#include "m_database.h" +#include "m_ignore.h" +#include "m_message.h" +#include "m_protocols.h" +#include "m_protosvc.h" +#include "m_userinfo.h" +#include "m_updater.h" +#include "win2k.h" +#include "m_popup.h" +#include "m_metacontacts.h" +#include "m_awaymsg.h" + + +#define WIDEN2(x) L ## x +#define WIDEN(x) WIDEN2(x) +#define __WFILE__ WIDEN(__FILE__) +#ifdef _UNICODE +#define __TFILE__ __WFILE__ +#else +#define __TFILE__ __FILE__ +#endif + + +#endif //COMMONHEADERS_H \ No newline at end of file diff --git a/newstatusnotify/indiv_sounds.c b/newstatusnotify/indiv_sounds.c new file mode 100644 index 0000000..6b549dc --- /dev/null +++ b/newstatusnotify/indiv_sounds.c @@ -0,0 +1,677 @@ +/* +=============================================================================== + NewStatusNotify plugin + +This plugin notifies you when a contact changes his/hers status with a PopUp. +You can customize its look (style of popup, font, text...) and behaviour (the +position in the screen, the time to live, the action on a mouse click). + +File name: "indiv_sounds.c" +This file contains the code for individual sound support. + +Written by: Hrk (Luca Santarelli) (2002-2004), Vasilich (2005-2008) + +Miranda IM can be found here: +http://miranda-im.org/ + +=============================================================================== +*/ + +#include "newstatusnotify.h" + +#define NICK_COLUMN 140 +#define STATUS_COLUMN 110 + +extern const char* ModuleName; +extern aStatus StatusesList[]; +extern void Log(char*); +extern MYOPTIONS MyOptions; +extern HINSTANCE hInst; + +static void ResetListOptions(HWND); + +//Declarations +BOOL CALLBACK DlgProcSoundOpts(HWND, UINT, WPARAM, LPARAM); +BOOL CALLBACK DlgProcSoundUIPage(HWND, UINT, WPARAM, LPARAM); +int UserInfoInitialise(WPARAM, LPARAM); +static BOOL RemoveSoundFromList(HWND); +static BOOL SelectSound(HWND); +static BOOL PreviewSound(HWND, int); +HIMAGELIST GetStatusIconsImgList(char*); + +//NewKindOfOptionsPage +static void ResetListOptions(HWND); +HWND hCListClone = NULL; + +//Definitions +static BOOL PreviewSound(HWND hList, int status) + { + int iSel = ListView_GetSelectionMark(hList); + if ( iSel > -1 ) + { + TCHAR str[MAX_PATH] = { 0 }; + //Let's read the file name: + ListView_GetItemText(hList, ListView_GetNextItem(hList, -1, LVNI_SELECTED), 1, str, sizeof(str)); + //If the string is "(default sound)", we want to hear the default sound indeed ;-) + if (lstrcmp(str, TranslateT("(default sound)")) == 0) + { + if (status==1) + SkinPlaySound("UserFromOffline"); + else + SkinPlaySound(StatusesList[Index(status)].lpzSkinSoundName); + } + else { //We have a configured sound. +// char szSoundFile[MAX_PATH] = { 0 }; + TCHAR tszTranslatedSoundFile[MAX_PATH] = { 0 }; +/*#ifdef UNICODE + WideCharToMultiByte(CP_ACP,0,str,-1,szSoundFile,MAX_PATH,0,0); + CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)szSoundFile, (LPARAM)tszTranslatedSoundFile); +#else + CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)str, (LPARAM)tszTranslatedSoundFile); +#endif +*/ + CallService(MS_UTILS_PATHTOABSOLUTET, (WPARAM)str, (LPARAM)tszTranslatedSoundFile); +#ifdef MS_SKIN_PLAYSOUNDEX + if (ServiceExists(MS_SKIN_PLAYSOUNDEX)) + { + SkinPlaySoundEx(tszTranslatedSoundFile); + } + else +#endif +#ifdef RegIndivSounds + SkinPlaySound(tszTranslatedSoundFile); +#else + { + if (MyOptions.AvoidClipping) + PlaySound(tszTranslatedSoundFile, NULL, SND_ASYNC | SND_FILENAME | SND_NOSTOP); + else + PlaySound(tszTranslatedSoundFile, NULL, SND_ASYNC | SND_FILENAME); + } +#endif + } + } + return TRUE; +} + +//Returns TRUE on sound change, FALSE on error. +static BOOL RemoveSoundFromList(HWND hList) +{ + int iSel = ListView_GetNextItem(hList, -1, LVNI_SELECTED); + if (iSel > -1) + { + LVITEM lvitem = { 0 }; + TCHAR str[MAX_PATH] = { 0 }; + + lvitem.mask = LVIF_PARAM; + lvitem.iItem = iSel; + + ListView_GetItemText(hList,iSel,1,str,sizeof(str)); + if (lstrcmp(str, TranslateT("(default sound)"))==0) + return FALSE; + else + { //We cycle on the selected items. + iSel = -1; + while ((iSel = ListView_GetNextItem(hList, iSel, LVNI_SELECTED)) != -1) + //ListView_SetItemText(hList, iSel, 1, Translate("(default sound)")); + { + LV_ITEM _ms_lvi; + _ms_lvi.iSubItem = 1; + _ms_lvi.pszText = TranslateT("(default sound)"); + SNDMSG(hList, LVM_SETITEMTEXT, (WPARAM)iSel, (LPARAM)(LV_ITEM *)&_ms_lvi); + } + return TRUE; + } + } + else //There is no contact selected. + return FALSE; +} + +//Returns TRUE on sound change, FALSE on error. +static BOOL SelectSound(HWND hwndDlg) { + TCHAR str[MAX_PATH] = { 0 }; + OPENFILENAME ofn = { 0 }; + HWND hList = GetDlgItem(hwndDlg, IDC_INDSNDLIST); + + int iSel = ListView_GetNextItem(hList, -1, LVNI_SELECTED); + if (iSel <= -1) return FALSE; + + ListView_GetItemText(hList,ListView_GetNextItem(hList,-1,LVNI_SELECTED),1,str,sizeof(str)); + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = GetParent(hwndDlg); + ofn.hInstance = NULL; + ofn.lpstrFilter = _T("Wave Files (*.wav)\0*.WAV\0All Files (*)\0*\0"); + ofn.lpstrFile = str; + ofn.Flags = OFN_FILEMUSTEXIST; + ofn.nMaxFile = sizeof(str); + ofn.nMaxFileTitle = MAX_PATH; + ofn.lpstrDefExt = _T("wav"); + if(!GetOpenFileName(&ofn)) return FALSE; + //Now let's change the text in the listview. We cycle on the selected items (so that people may choose more than one status) + iSel = -1; + while ((iSel = ListView_GetNextItem(hList, iSel, LVNI_SELECTED)) != -1) { + ListView_SetItemText(hList, iSel,1,str); + } + return TRUE; +} + +HIMAGELIST GetStatusIconsImgList(char * lpzProto) { + HIMAGELIST hList = NULL; + hList = ImageList_Create(GetSystemMetrics(SM_CXSMICON), //cx + GetSystemMetrics(SM_CYSMICON), //cy + ((LOBYTE(LOWORD(GetVersion()))>=5 && LOWORD(GetVersion())!=5)?ILC_COLOR32:ILC_COLOR16)|ILC_MASK, //flags + 10, //cInitial: the number of initial images: the statuses are 10! + 0); //cGrow: we'll not add any other icon to the list. + + if (hList != NULL && lpzProto != NULL) { //The list was made, add the icons to it. + int i = 0; + for (i = ID_STATUS_MIN; i <= ID_STATUS_MAX; i++) { + ImageList_AddIcon(hList, LoadSkinnedProtoIcon(lpzProto, StatusesList[Index(i)].ID)); + } + } + return hList; +} + +//========== Individual Sounds: UserInfo page ========== +BOOL CALLBACK DlgProcSoundUIPage(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { + static HANDLE hContact = NULL; + switch (msg) { + case WM_INITDIALOG: + { + LV_COLUMN lvc = { 0 }; + HWND hList = GetDlgItem(hwndDlg, IDC_INDSNDLIST); + RECT aRect = { 0 }; + int i; + char* lpzProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)lParam,0); + + //Let's get an image list with the status icons. + HIMAGELIST hImgList = GetStatusIconsImgList(lpzProto); + + hContact = (HANDLE)lParam; + ListView_SetImageList(hList, hImgList, LVSIL_SMALL); + ImageList_AddIcon(hImgList, LoadSkinnedIcon(SKINICON_OTHER_USERONLINE)); // icon for UserFromOffline sound + GetClientRect(hList, &aRect); + lvc.mask = LVCF_WIDTH | LVCF_TEXT; + ListView_SetExtendedListViewStyleEx(hList, + LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP, + LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP); + lvc.cx = STATUS_COLUMN; + lvc.pszText = TranslateT("Status"); + SNDMSG((hList), LVM_INSERTCOLUMN, 0, (LPARAM)(const LV_COLUMN *)(&lvc)); + lvc.cx = aRect.right - STATUS_COLUMN - GetSystemMetrics(SM_CXVSCROLL); + lvc.pszText = TranslateT("Sound for the status"); + SNDMSG((hList), LVM_INSERTCOLUMN, 1, (LPARAM)(const LV_COLUMN *)(&lvc)); + if ( lpzProto!=NULL) + { + // -----------------------------------------------------------------add all status sounds + for (i = ID_STATUS_MAX; i >= ID_STATUS_MIN; i--) + { int Pflags2 = CallProtoService(lpzProto,PS_GETCAPS,PFLAGNUM_2,0); + if (Pflags2 == 0) Pflags2 = PF2_ONLINE|PF2_INVISIBLE|PF2_SHORTAWAY|PF2_LONGAWAY|PF2_LIGHTDND|PF2_HEAVYDND|PF2_FREECHAT|PF2_OUTTOLUNCH|PF2_ONTHEPHONE; + if ((Proto_Status2Flag(i) != 0 && Pflags2&Proto_Status2Flag(i)) + || i == ID_STATUS_OFFLINE) + { //Offline has not a PF value, so we workaround it :/ + LV_ITEM _ms_lvi; + LV_ITEM lvi = { 0 }; + DBVARIANT dbv = { 0 }; + lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE; + lvi.iItem = 0; + lvi.iSubItem = 0; + lvi.iImage = Index(i); //We've already associated an image list to the listview. + lvi.lParam = (LPARAM)i; + lvi.pszText = TranslateTS(StatusesList[Index(i)].lpzStandardText); + //lvi.iItem = ListView_InsertItem(GetDlgItem(hwndDlg, IDC_INDSNDLIST),&lvi); + lvi.iItem = SNDMSG(GetDlgItem(hwndDlg, IDC_INDSNDLIST), LVM_INSERTITEM, 0, (LPARAM)(const LV_ITEM *)(&lvi)); + if (DBGetContactSettingTString(hContact, ModuleName, StatusesList[Index(i)].lpzSkinSoundName, &dbv) == DB_READ_SUCCESS) + { + lvi.pszText = dbv.ptszVal; + DBFreeVariant(&dbv); + } + else + lvi.pszText = TranslateT("(default sound)"); + + _ms_lvi.iSubItem = 1; + _ms_lvi.pszText = lvi.pszText; + SNDMSG((GetDlgItem(hwndDlg, IDC_INDSNDLIST)), LVM_SETITEMTEXT, (WPARAM)lvi.iItem, (LPARAM)(LV_ITEM *)&_ms_lvi); + } + } + // ---------------- add "user from offline" sound settting + { + LV_ITEM _ms_lvi; + LV_ITEM lvi = { 0 }; + DBVARIANT dbv = { 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)1; + lvi.pszText = TranslateT("From offline"); + lvi.iItem = SNDMSG(GetDlgItem(hwndDlg, IDC_INDSNDLIST), LVM_INSERTITEM, 0, (LPARAM)(const LV_ITEM *)(&lvi)); + if (DBGetContactSettingTString(hContact, ModuleName, "UserFromOffline", &dbv) == DB_READ_SUCCESS) + { + lvi.pszText = dbv.ptszVal; + DBFreeVariant(&dbv); + } + else + lvi.pszText = TranslateT("(default sound)"); + //ListView_SetItemText(GetDlgItem(hwndDlg, IDC_INDSNDLIST),lvi.iItem,1,lvi.pszText); + _ms_lvi.iSubItem = 1; + _ms_lvi.pszText = lvi.pszText; + SNDMSG((GetDlgItem(hwndDlg, IDC_INDSNDLIST)), LVM_SETITEMTEXT, (WPARAM)lvi.iItem, (LPARAM)(LV_ITEM *)&_ms_lvi); + } + //------------------------------------------end "fromoffline"--- + } + { //checkboxes for contact to disable popups and sounds + BYTE EnableSounds = DBGetContactSettingByte(hContact,ModuleName,"EnableSounds",1); + BYTE EnablePopups = DBGetContactSettingByte(hContact,ModuleName,"EnablePopups",1); + CheckDlgButton(hwndDlg, IDC_CHECK_NOTIFYSOUNDS, EnableSounds?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_CHECK_NOTIFYPOPUPS, EnablePopups?BST_CHECKED:BST_UNCHECKED); + } + if (MyOptions.UseIndSnd) // if individual sounds are used, then activate all controls + { + ShowWindow(GetDlgItem(hwndDlg, IDC_INDSNDLIST), SW_SHOW); + ShowWindow(GetDlgItem(hwndDlg,IDC_TEXT_ENABLE_IS), SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_CHANGE), SW_SHOW); + ShowWindow(GetDlgItem(hwndDlg, IDC_PREVIEW), SW_SHOW); + ShowWindow(GetDlgItem(hwndDlg, IDC_DELETE), SW_SHOW); + } + else + { + ShowWindow(GetDlgItem(hwndDlg, IDC_INDSNDLIST), SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg,IDC_TEXT_ENABLE_IS), SW_SHOW); + ShowWindow(GetDlgItem(hwndDlg, IDC_CHANGE), SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_PREVIEW), SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_DELETE), SW_HIDE); + } + TranslateDialogDefault(hwndDlg); + return TRUE; //End of WM_INITDIALOG + } + case WM_COMMAND: { + //Who sent us a WM_COMMAND? + switch (LOWORD(wParam)) { + case IDC_PREVIEW: { + //We want to hear the sound. + HWND hList = GetDlgItem(hwndDlg, IDC_INDSNDLIST); + int nSel = ListView_GetSelectionMark(hList); + if ( nSel > -1 ) { //There's something selected. + LVITEM lvitem = { 0 }; + lvitem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE; + lvitem.iItem = ListView_GetNextItem(hList,-1,LVNI_SELECTED); + ListView_GetItem(hList, &lvitem); + PreviewSound(hList, lvitem.lParam); + } + break; + } //End of IDC_PREVIEW + case IDC_CHANGE: + if (SelectSound(hwndDlg) == TRUE) + SendMessage(GetParent(hwndDlg), PSM_CHANGED,0,0); + break; + case IDC_DELETE: + if (RemoveSoundFromList(GetDlgItem(hwndDlg, IDC_INDSNDLIST))==TRUE) + SendMessage(GetParent(hwndDlg), PSM_CHANGED,0,0); + break; + case IDC_CHECK_NOTIFYSOUNDS: + if (IsDlgButtonChecked(hwndDlg, IDC_CHECK_NOTIFYSOUNDS)) + DBDeleteContactSetting(hContact,ModuleName,"EnableSounds"); + else + DBWriteContactSettingByte(hContact,ModuleName,"EnableSounds",0); + break; + case IDC_CHECK_NOTIFYPOPUPS: + if (IsDlgButtonChecked(hwndDlg, IDC_CHECK_NOTIFYPOPUPS)) + DBDeleteContactSetting(hContact,ModuleName,"EnablePopups"); + else + DBWriteContactSettingByte(hContact,ModuleName,"EnablePopups",0); + break; + default: + break; + } //End of SWITCH on WM_COMMAND + break; //End of WM_COMMAND + } + case WM_NOTIFY: + switch(((LPNMHDR)lParam)->idFrom) { + case 0: + switch (((LPNMHDR)lParam)->code) { + case PSN_APPLY: { + //We have to write to the DB: let's find out what. + TCHAR str[MAX_PATH] = { 0 }; + HWND hList = GetDlgItem(hwndDlg, IDC_INDSNDLIST); + LVITEM lvitem = { 0 }; + + lvitem.mask = LVIF_PARAM; + //Cycle through the list reading the text associated to each status. + for(lvitem.iItem = ListView_GetItemCount(hList)-1; lvitem.iItem>=0; lvitem.iItem--) { + ListView_GetItem(hList,&lvitem); + ListView_GetItemText(hList,lvitem.iItem,1,str,sizeof(str)); + //If the filename is "(default sound)", delete the setting from the DB, else write the new setting. + if (lstrcmp(str, TranslateT("(default sound)"))==0) + { + if (lvitem.lParam==1) + DBDeleteContactSetting((HANDLE)hContact,ModuleName, "UserFromOffline"); + else + DBDeleteContactSetting((HANDLE)hContact,ModuleName, StatusesList[Index(lvitem.lParam)].lpzSkinSoundName); + } + else { + TCHAR szTranslatedPath[MAX_PATH] = { 0 }; +/*#ifdef UNICODE + char cPath[MAX_PATH] = {0}; + WideCharToMultiByte(CP_ACP,0,str,-1,cPath,MAX_PATH,0,0); + CallService(MS_UTILS_PATHTORELATIVE, (WPARAM)cPath, (LPARAM)szTranslatedPath); +#else + CallService(MS_UTILS_PATHTORELATIVE, (WPARAM)str, (LPARAM)szTranslatedPath); +#endif +*/ + CallService(MS_UTILS_PATHTORELATIVET, (WPARAM)str, (LPARAM)szTranslatedPath); + if (lvitem.lParam==1) + DBWriteContactSettingTString((HANDLE)hContact,ModuleName, "UserFromOffline",szTranslatedPath); + else + DBWriteContactSettingTString((HANDLE)hContact,ModuleName, StatusesList[Index(lvitem.lParam)].lpzSkinSoundName, szTranslatedPath); + } + } //End of for, we have written every setting. + return TRUE; + } + } + } + //Various actions. + { + LPNMHDR pParam = (LPNMHDR)lParam; + + if (pParam == NULL) return TRUE; + + switch ((int)wParam) { + case IDC_INDSNDLIST: { + switch (pParam->code) { + case NM_DBLCLK: { + if (SelectSound(hwndDlg) == TRUE) + SendMessage(GetParent(hwndDlg), PSM_CHANGED,0,0); + return TRUE; + } + case LVN_KEYDOWN: { + LPNMLVKEYDOWN pnkd = (LPNMLVKEYDOWN)lParam; + if (pnkd->wVKey == VK_DELETE) + RemoveSoundFromList(GetDlgItem(hwndDlg, IDC_INDSNDLIST)); + break; + } //End of KEYDOWN + } + } //End of IDC_INDSNDLIST + } //end int wParam + break ; + } //End of WM_NOTIFY + default: + break; + } + return FALSE; +} + +//========== UserInfo page : Initialization ========== +int UserInfoInitialise(WPARAM wParam, LPARAM lParam) +{ + { + //Individual Sounds UserInfo details page + OPTIONSDIALOGPAGE odp = { 0 }; + + if((HANDLE)lParam == NULL) return 0; + odp.cbSize = sizeof(odp); + odp.position = 100000000; + odp.hInstance = hInst; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_INFO_SOUNDS); + odp.pszTitle = _strdup(NAME_OF_UIPAGE); + odp.pfnDlgProc = DlgProcSoundUIPage; + + CallService(MS_USERINFO_ADDPAGE,wParam,(LPARAM)&odp); + } + return 0; +} + +static void ResetListOptions(HWND hwndList) +{ + int i; + SendMessage(hwndList,CLM_SETBKBITMAP,0,(LPARAM)(HBITMAP)NULL); + SendMessage(hwndList,CLM_SETBKCOLOR,GetSysColor(COLOR_WINDOW),0); + SendMessage(hwndList,CLM_SETGREYOUTFLAGS,0,0); + SendMessage(hwndList,CLM_SETLEFTMARGIN,4,0); + SendMessage(hwndList,CLM_SETINDENT,10,0); + for(i=0;i<=FONTID_MAX;i++) + SendMessage(hwndList,CLM_SETTEXTCOLOR,i,GetSysColor(COLOR_WINDOWTEXT)); + SetWindowLong(hwndList,GWL_STYLE,GetWindowLong(hwndList,GWL_STYLE)|CLS_SHOWHIDDEN); +} + +static void SetAllContactIcons(HWND hwndList) +{ + HANDLE hContact,hItem; + char *szProto; + DWORD flags; + BYTE EnableSounds, EnablePopups; + + hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0); + do + { + hItem=(HANDLE)SendMessage(hwndList,CLM_FINDCONTACT,(WPARAM)hContact,0); + if(hItem) + { + szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,(WPARAM)hContact,0); + if (szProto == NULL) { flags = 0; EnableSounds =EnablePopups = 0;} + else + { + flags = CallProtoService(szProto,PS_GETCAPS,PFLAGNUM_1,0); //Status flags + EnableSounds = DBGetContactSettingByte(hContact,ModuleName,"EnableSounds",1); + EnablePopups = DBGetContactSettingByte(hContact,ModuleName,"EnablePopups",1); + } + //if(PF1_INDIVSTATUS) + { + if(SendMessage(hwndList,CLM_GETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(0,0))==0xFF) + SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(0,EnableSounds==TRUE?1:0)); + if(SendMessage(hwndList,CLM_GETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(1,0))==0xFF) + SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(1,EnablePopups==TRUE?2:0)); + } + } + } + while(hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0)); +} + +static void SetListGroupIcons(HWND hwndList,HANDLE hFirstItem,HANDLE hParentItem,int *groupChildCount) +{ + int typeOfFirst; + int iconOn[2]={1,1}; + int childCount[2]={0,0},i; + int iImage; + HANDLE hItem,hChildItem; + + typeOfFirst=SendMessage(hwndList,CLM_GETITEMTYPE,(WPARAM)hFirstItem,0); + //check groups + 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) SetListGroupIcons(hwndList,hChildItem,hItem,childCount); + for( i=0; i < SIZEOF(iconOn); i++) + if(iconOn[i] && SendMessage(hwndList,CLM_GETEXTRAIMAGE,(WPARAM)hItem,i)==0) 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 ( i=0; i < SIZEOF(iconOn); i++) { + iImage=SendMessage(hwndList,CLM_GETEXTRAIMAGE,(WPARAM)hItem,i); + if(iconOn[i] && iImage==0) iconOn[i]=0; + if(iImage!=0xFF) childCount[i]++; + } + hItem=(HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_NEXTCONTACT,(LPARAM)hItem); + } + //set icons + for( i=0; i < SIZEOF(iconOn); i++) { + SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hParentItem,MAKELPARAM(i,childCount[i]?(iconOn[i]?i+1:0):0xFF)); + if(groupChildCount) groupChildCount[i]+=childCount[i]; + } +} + +static void SetAllChildIcons(HWND hwndList,HANDLE hFirstItem,int iColumn,int iImage) +{ + int typeOfFirst,iOldIcon; + HANDLE hItem,hChildItem; + + typeOfFirst=SendMessage(hwndList,CLM_GETITEMTYPE,(WPARAM)hFirstItem,0); + //check groups + 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) SetAllChildIcons(hwndList,hChildItem,iColumn,iImage); + 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) { + iOldIcon=SendMessage(hwndList,CLM_GETEXTRAIMAGE,(WPARAM)hItem,iColumn); + if(iOldIcon!=0xFF && iOldIcon!=iImage) SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(iColumn,iImage)); + hItem=(HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_NEXTCONTACT,(LPARAM)hItem); + } +} + +BOOL CALLBACK DlgProcSoundOpts2(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { + + static HICON hSoundIcon,hPopupIcon; + static HANDLE hItemAll; + HANDLE hList = GetDlgItem(hWnd, IDC_INDSNDLIST); + hCListClone=(HWND)hList; + //{char str[100];wsprintf (str, L"msg value is %#x", msg);MessageBox(NULL,str,L"soundopts2",0);} + //printf("msg = %#x", msg); + switch (msg) { + case WM_INITDIALOG: { + TranslateDialogDefault(hWnd); + { HIMAGELIST hImageList; + hImageList=ImageList_Create(GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),(IsWinVerXPPlus()?ILC_COLOR32:ILC_COLOR16)|ILC_MASK,3,3); + ImageList_AddIcon(hImageList,(LoadSkinnedIcon(SKINICON_OTHER_SMALLDOT))); + ImageList_AddIcon(hImageList,LoadIcon(hInst,MAKEINTRESOURCE(IDI_SOUND))); + ImageList_AddIcon(hImageList,LoadIcon(hInst,MAKEINTRESOURCE(IDI_POPUP))); + SendDlgItemMessage(hWnd,IDC_INDSNDLIST,CLM_SETEXTRAIMAGELIST,0,(LPARAM)hImageList); + hSoundIcon=ImageList_GetIcon(hImageList,1,ILD_NORMAL); + SendDlgItemMessage(hWnd,IDC_SOUNDICON,STM_SETICON,(WPARAM)hSoundIcon,0); + hPopupIcon=ImageList_GetIcon(hImageList,2,ILD_NORMAL); + SendDlgItemMessage(hWnd,IDC_POPUPICON,STM_SETICON,(WPARAM)hPopupIcon,0); + } + ResetListOptions((HWND)hList); + SendDlgItemMessage(hWnd,IDC_INDSNDLIST,CLM_SETEXTRACOLUMNS,2,0); + + { CLCINFOITEM cii={0}; + cii.cbSize=sizeof(cii); + cii.flags=CLCIIF_GROUPFONT; + cii.pszText=TranslateT("** All contacts **"); + hItemAll=(HANDLE)SendDlgItemMessage(hWnd,IDC_INDSNDLIST,CLM_ADDINFOITEM,0,(LPARAM)&cii); + } + + SetAllContactIcons((HWND)hList); + SetListGroupIcons((HWND)hList,(HANDLE)SendDlgItemMessage(hWnd,IDC_INDSNDLIST,CLM_GETNEXTITEM,CLGN_ROOT,0),hItemAll,NULL); + return TRUE; + } + case WM_SETFOCUS: + SetFocus((HWND)hList); + break; + case WM_NOTIFY: +/* {wchar_t str[100]; + wsprintf(str, L"wm notify value %#x", ((LPNMHDR)lParam)->idFrom); + MessageBox(NULL,str,L"NSN 123456789",0); + } +*/ switch(((LPNMHDR)lParam)->idFrom) { + case IDC_INDSNDLIST: + switch (((LPNMHDR)lParam)->code) + { + case CLN_NEWCONTACT: + case CLN_LISTREBUILT: + SetAllContactIcons((HWND)hList); + //fall through + case CLN_CONTACTMOVED: + SetListGroupIcons((HWND)hList,(HANDLE)SendMessage((HWND)hList,CLM_GETNEXTITEM,CLGN_ROOT,0),hItemAll,NULL); + break; + case CLN_OPTIONSCHANGED: + ResetListOptions((HWND)hList); + break; + case NM_CLICK: + { + HANDLE hItem; + NMCLISTCONTROL *nm=(NMCLISTCONTROL*)lParam; + DWORD hitFlags; + int iImage; + int itemType; + // Make sure we have an extra column + if(nm->iColumn==-1) break; + // Find clicked item + hItem=(HANDLE)SendMessage((HWND)hList,CLM_HITTEST,(WPARAM)&hitFlags,MAKELPARAM(nm->pt.x,nm->pt.y)); + // Nothing was clicked + if(hItem==NULL) break; + // It was not a sound or popup icon + if(!(hitFlags&CLCHT_ONITEMEXTRA)) break; + itemType=SendMessage((HWND)hList,CLM_GETITEMTYPE,(WPARAM)hItem,0); + // Get image in clicked column (0=none, 1=sound, 2=popup) + iImage=SendMessage((HWND)hList,CLM_GETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(nm->iColumn,0)); + if(iImage==0) iImage=nm->iColumn+1; + else if(iImage==1 || iImage==2) iImage=0; + // Get item type (contact, group, etc...) + // Update list + if(itemType==CLCIT_CONTACT) + { + SendMessage((HWND)hList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(nm->iColumn,iImage)); + } + else if(itemType==CLCIT_INFO) //must be 'all contacts' + { + SetAllChildIcons((HWND)hList,hItem,nm->iColumn,iImage); + } + else if(itemType==CLCIT_GROUP) { + hItem=(HANDLE)SendMessage((HWND)hList,CLM_GETNEXTITEM,CLGN_CHILD,(LPARAM)hItem); + if(hItem) + { + SetAllChildIcons((HWND)hList,hItem,nm->iColumn,iImage); + } + } + // Update the all/none icons + SetListGroupIcons((HWND)hList,(HANDLE)SendMessage((HWND)hList,CLM_GETNEXTITEM,CLGN_ROOT,0),hItemAll,NULL); + // Activate Apply button + SendMessage(GetParent(hWnd), PSM_CHANGED, 0, 0); + break; + } + } + break; + case 0: + switch (((LPNMHDR)lParam)->code) + { + case PSN_APPLY: { + HANDLE hContact,hItem; + int iImage; + hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0); + do + { + hItem=(HANDLE)SendMessage((HWND)hList,CLM_FINDCONTACT,(WPARAM)hContact,0); + if(hItem) + { + iImage=SendMessage((HWND)hList,CLM_GETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(0,0)); + if(iImage==1) + DBDeleteContactSetting(hContact,ModuleName,"EnableSounds"); + else + DBWriteContactSettingByte(hContact,ModuleName,"EnableSounds",0); + iImage=SendMessage((HWND)hList,CLM_GETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(1,0)); + if(iImage==2) + DBDeleteContactSetting(hContact,ModuleName,"EnablePopups"); + else + DBWriteContactSettingByte(hContact,ModuleName,"EnablePopups",0); + + } + } + while(hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0)); + return TRUE; + } + } + break; + } + break; + case WM_DESTROY: + { + HIMAGELIST hIml = (HIMAGELIST)SendMessage((HWND)hList,CLM_GETEXTRAIMAGELIST,0,0); + DestroyIcon(hSoundIcon); + DestroyIcon(hPopupIcon); + ImageList_Destroy(hIml); + break; + } + default: + break; + } + return FALSE; +} diff --git a/newstatusnotify/main.c b/newstatusnotify/main.c new file mode 100644 index 0000000..3885d73 --- /dev/null +++ b/newstatusnotify/main.c @@ -0,0 +1,2378 @@ +/* +=============================================================================== + NewStatusNotify plugin + +This plugin notifies you when a contact changes his/hers status with a PopUp. +You can customize its look (style of popup, font, text...) and behaviour (the +position in the screen, the time to live, the action on a mouse click). + +File name: "main.c" + +Written by: Hrk (Luca Santarelli) (2002-2004), Vasilich (2005-2008) + +Miranda IM can be found here: +http://miranda-im.org/ + +=============================================================================== +*/ + +#define _MERGE_RDATA_ +#include "newstatusnotify.h" +#include "res\version.h" + +//extern int CallServiceSync(const char *name, WPARAM wParam, LPARAM lParam); + +/* +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" + +//malloc functions +//#define malloc(size) GlobalAlloc(GMEM_ZEROINIT | GMEM_FIXED, size) +//#define free(something) GlobalFree(something) + +const char* ModuleName = "NewStatusNotify"; +//const char *ModuleIndSounds = "NewStatusNotifyIS"; + +#define POPUPCOLOR_BG_40071 RGB(0x80, 0x80, 0x80) +#define POPUPCOLOR_TX_40071 RGB(0xFF, 0xFF, 0xFF) +#define POPUPCOLOR_BG_40072 RGB(0x95, 0x95, 0xFF) +#define POPUPCOLOR_TX_40072 RGB(0x00, 0x00, 0xFF) +#define POPUPCOLOR_BG_40073 RGB(0x00, 0x40, 0x80) +#define POPUPCOLOR_TX_40073 RGB(0xFF, 0xFF, 0xFF) +#define POPUPCOLOR_BG_40074 RGB(0x00, 0x00, 0x00) +#define POPUPCOLOR_TX_40074 RGB(0xFF, 0x00, 0x00) +#define POPUPCOLOR_BG_40075 RGB(0x00, 0x00, 0x80) +#define POPUPCOLOR_TX_40075 RGB(0xFF, 0xFF, 0xFF) +#define POPUPCOLOR_BG_40076 RGB(0xFF, 0x80, 0x80) +#define POPUPCOLOR_TX_40076 RGB(0x00, 0x00, 0x00) +#define POPUPCOLOR_BG_40077 RGB(0xFF, 0xFF, 0x00) +#define POPUPCOLOR_TX_40077 RGB(0x00, 0x00, 0x00) +#define POPUPCOLOR_BG_40078 RGB(0xC0, 0xC0, 0xC0) +#define POPUPCOLOR_TX_40078 RGB(0x60, 0x60, 0x60) +#define POPUPCOLOR_BG_40079 RGB(0x00, 0x80, 0x00) +#define POPUPCOLOR_TX_40079 RGB(0xFF, 0xFF, 0xFF) +#define POPUPCOLOR_BG_40080 RGB(0x00, 0xFF, 0x00) +#define POPUPCOLOR_TX_40080 RGB(0x00, 0x00, 0x00) + +//Actions +#define ACTION_OPENMSG 0x01 +#define ACTION_DISMISS 0x02 +#define ACTION_USERMENU 0x03 + +#define BEEP_DURATION_DEFAULT 155 +#define BEEP_HZ_DEFAULT 155 + +#define UM_SETDLGITEMINT 5674 + +#define PROTO_POPUPS_ON 1 +#define PROTO_POPUPS_OFF 0 + +#define UM_SETCONTACT (WM_USER + 452) +#define UM_PROCESS (WM_USER + 453) + +#define TIMEOUT_POPUP 1 +#define TIMEOUT_CUSTOM 2 +#define TIMEOUT_PERMANENT 3 +#define TIMEOUT_MINVALUE 1 +#define TIMEOUT_MAXVALUE 60 + +//Defaults +#define DEFAULT_PROTO_POPUPS PROTO_POPUPS_ON +#define DEFAULT_USEWINCOLORS 0 +#define DEFAULT_USEDULLTEXT 0 +#define DEFAULT_TEMPDISABLE 0 +#define DEFAULT_AUTODISABLE 0 +#define DEFAULT_FROMOFFLINE 1 +#define DEFAULT_ENABLESOUNDS 1 +#define DEFAULT_USESPEAKER 0 +#define DEFAULT_AVOIDCLIPPING 1 +#define DEFAULT_HIDDENCONTACTSTOO 0 +#define DEFAULT_SHOWONCONNECTION 0 +#define DEFAULT_SHOWDISABLEMENU 1 +#define DEFAULT_NOTIFYWITHPOPUP 1 +#define DEFAULT_NOTIFYWITHSOUND 1 +#define DEFAULT_READAWAYMSG 0 +#define DEFAULT_SHOWPREVIOUSSTATUS 0 +#define DEFAULT_LOG 0 +#define DEFAULT_LOGFILE _T("NewStatusNotify.log") +#define DEFAULT_BLINKICON FALSE +#define DEFAULT_BLINKICON_STATUS FALSE +#define DEFAULT_TIMEOUT TIMEOUT_POPUP +#define DEFAULT_TIMEOUT_VALUE 7 +#define DEFAULT_USE_IND_SOUNDS 1 +#define DEFAULT_SHOWGROUP 0 + +#define STRING_SHOWPREVIOUSSTATUS _T("(was %s)") +/*This is needed to send a message with safe multithreading. +We'll create a private hook and we'll call it via NotifyEventHooks, which brings execution +back to the main thread. +What we'll need is: +- hHookSendMessage, the handle to the created hook. +- hSendMessage, the hook we'll use (i.e.: the hook which will be notified) +- ME_NSN_CONTACTSENDMESSAGE, the service name +- ContactSendMessage(WPARAM, LPARAM) which will do the job +- (finally) move the send code to ContactSendMessage and put a NotifyEventHooks inside WM_COMMAND. +*/ + +#define ME_NSN_CONTACTSENDMESSAGE "NewStatusNotify/ContactSendMessage" + +#define WM_AWAYMSG (WM_USER + 0x0192) +//===== PopUp ===== +LRESULT CALLBACK PopupDlgProc(HWND, UINT, WPARAM, LPARAM); +//===== DB functions ===== +BYTE GetGender(HANDLE); +//===== MessageBoxes ===== +void Log(TCHAR*); //This one is used to notify the user + +static int ModulesLoaded(WPARAM wParam,LPARAM lParam); +//===== Options ===== +void LoadOptions(); +void installMainMenuItem(); +static int OptionsInitialize(WPARAM,LPARAM); +static BOOL CALLBACK DlgProcGeneralOpts(HWND, UINT, WPARAM, LPARAM); +static BOOL CALLBACK DlgProcPopUpOpts(HWND, UINT, WPARAM, LPARAM); +extern BOOL CALLBACK DlgProcSoundOpts2(HWND, UINT, WPARAM, LPARAM); +extern BOOL CALLBACK DlgProcSoundUIPage(HWND, UINT, WPARAM, LPARAM); +static BOOL CALLBACK DlgProcAutoDisableOpts(HWND, UINT, WPARAM, LPARAM); +static int OpenUserDetails(WPARAM, LPARAM); +extern int UserInfoInitialise(WPARAM, LPARAM); +//===== Plugin specific ===== +static int ContactSettingChanged(WPARAM,LPARAM); +static int ContactStatusChanged(WPARAM, LPARAM); +static int EnableDisableMenuCommand(WPARAM,LPARAM); +static int ProtoAck(WPARAM,LPARAM); +static int ContactSendMessage(WPARAM, LPARAM); +static BOOL StatusHasAwayMessage(char *szProto, int status); +void PlaySpeakerBeep(void); +int SortPUWinList(void* it1, void * it2); + +//===== Initializations ===== +void InitStatusList(); +void InitPopUpFont(); + +//HANDLE hhkProtoAck = NULL; +HANDLE hPopupList = NULL; +void CALLBACK ConnectionTimerProc(HWND,UINT,UINT,DWORD); +void ReceivedAwayMessage(HWND, LPARAM , PLUGINDATA *); +void ReceivedStatusMessage (HANDLE, BOOL); +BOOL QueryAwayMessage(HWND , PLUGINDATA *); + +//===== Global variables ===== +//===== General Plugin ===== +HINSTANCE hInst; +PLUGINLINK *pluginLink; +//CLISTMENUITEM mi; +int hEnableDisableMenu; +BOOL IsOptionsOpened=FALSE; +//===== Event Handles ===== +HANDLE hOptionsInitialize, hModulesLoaded, hOpenUserDetails; +HANDLE hUserInfoInitialise; +HANDLE hContactSettingChanged, hHookContactStatusChanged, hContactStatusChanged; +//HANDLE hEventStatusModeChange; +HANDLE hProtoAck; +HANDLE hHookSendMessage, hSendMessage; //Internal "private" event. +//HANDLE hHookMenuProcessCommand, hMenuProcessCommand; //Internal "private" event. +HANDLE hServiceMenu; +extern HWND hCListClone; +HWND SecretWnd; +//HWND hRightClickWnd; //This is needed to bring menu commands back to the main Miranda thread. +//static LRESULT CALLBACK RightClickWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); +//===== Other stuff... ===== +BYTE count = 0; +int uniqueEventId = 0; +#define ID_STATUS_ALLSTATUSES 40070 +#define STATUSES 11 +aStatus StatusesList[STATUSES]; +MYOPTIONS MyOptions = { 0 }; +struct MM_INTERFACE mmi = { 0 }; +struct LIST_INTERFACE li = { 0 }; +SortedList *PopupList = NULL; + +//===== Plugin informations struct ===== +PLUGININFO pluginInfo={ + sizeof(PLUGININFO), + __PLUGIN_NAME, + PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM), + __DESC, + __AUTHOR, + __AUTHOREMAIL, + __COPYRIGHT, + __AUTHORWEB, + UNICODE_AWARE, + DEFMOD_RNDUSERONLINE //Replaces UserOnline functionality +}; + +//===== New Plugin informations struct ===== +PLUGININFOEX pluginInfoEx={ + sizeof(PLUGININFOEX), + __PLUGIN_NAME, + PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM), + __DESC, + __AUTHOR, + __AUTHOREMAIL, + __COPYRIGHT, + __AUTHORWEB, + UNICODE_AWARE, + DEFMOD_RNDUSERONLINE, //Replaces UserOnline functionality + MIID_NSN +}; + +//===== Basic plugin (template) functions ===== +//=== DllMain ===== +BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved) { + hInst=hinstDLL; + DisableThreadLibraryCalls(hInst); + return TRUE; +} + +//===== MirandaPluginInfo ===== +//extern "C" +__declspec(dllexport) PLUGININFO* MirandaPluginInfo(DWORD mirandaVersion) { + return &pluginInfo; +} + +//extern "C" +__declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion) { + return &pluginInfoEx; +} + +static const MUUID interfaces[] = { MIID_USERONLINE, MIID_LAST }; + +__declspec(dllexport) const MUUID *MirandaPluginInterfaces(void) { + return interfaces; +} + +//===== Load ===== +//extern "C" +int __declspec(dllexport) Load(PLUGINLINK *link) { + int i = 0; + pluginLink=link; + mir_getMMI(&mmi); + mir_getLI(&li); + + //Hooks + //"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); + //Protocol status: we use this for "PopUps on Connection". + hProtoAck = HookEvent(ME_PROTO_ACK,ProtoAck); + //This is needed for "NoSound"-like routines. +// hEventStatusModeChange = HookEvent(ME_CLIST_STATUSMODECHANGE,StatusModeChanged); + //open user details dialog on proper page when clicking on contact in our SOUNDS2 options page + hOpenUserDetails=HookEvent(ME_CLIST_DOUBLECLICKED, OpenUserDetails); + //Internal hooks used to bring the send dialog to the main thread. + hHookSendMessage = CreateHookableEvent(ME_NSN_CONTACTSENDMESSAGE); + hSendMessage = HookEvent(ME_NSN_CONTACTSENDMESSAGE, ContactSendMessage); +// hHookMenuProcessCommand = CreateHookableEvent(ME_NSN_CONTACTMENUPROCESSCOMMAND); +// hMenuProcessCommand = HookEvent(ME_NSN_CONTACTMENUPROCESSCOMMAND, ContactMenuProcessCommand); + //Menu item + if (DBGetContactSettingByte(NULL,ModuleName,"ShowDisableMenu",DEFAULT_SHOWDISABLEMENU)==TRUE) + installMainMenuItem(); +/* { + CLISTMENUITEM mi = { 0 }; + CreateServiceFunction("NewStatusNotify/EnableDisableMenuCommand",EnableDisableMenuCommand); + mi.cbSize = sizeof(mi); + //mi.position=-0x7FFFFFFF; + mi.flags=0; + if (DBGetContactSettingByte(NULL,ModuleName,"TempDisable",DEFAULT_TEMPDISABLE)==TRUE) + { + //If Miranda is 0.1.2.1-, we can't change both text and icon. + //If it's 0.1.2.2+, we can and we do. + mi.pszName = Translate("Enable status ¬ification"); + //if (CallService(MS_SYSTEM_GETVERSION,(WPARAM)0,(LPARAM)0) >= 0x00010202) + mi.hIcon = LoadIcon(hInst,MAKEINTRESOURCE(IDI_NOPOPUP)); + } + else + { + mi.pszName = Translate("Disable status ¬ification"); + //if (CallService(MS_SYSTEM_GETVERSION,(WPARAM)0,(LPARAM)0) >= 0x00010202) + mi.hIcon = LoadIcon(hInst,MAKEINTRESOURCE(IDI_POPUP)); + } + mi.pszService="NewStatusNotify/EnableDisableMenuCommand"; + mi.pszPopupName = NULL; //Translate("PopUps"); + hEnableDisableMenu = CallService(MS_CLIST_ADDMAINMENUITEM,0,(LPARAM)&mi); + } +*/ + InitStatusList(); + for (i = ID_STATUS_MIN; i <= ID_STATUS_MAX; i++) + SkinAddNewSoundEx( StatusesList[Index(i)].lpzSkinSoundName, "Status Notify", StatusesList[Index(i)].lpzSkinSoundDesc); + + SkinAddNewSoundEx("UserFromOffline", "Status Notify", "User: from offline (has priority!)"); + count = 0; + + LoadOptions(); + CallService(MS_DB_SETSETTINGRESIDENT, (WPARAM)TRUE,(LPARAM)"MetaContacts/LastOnline"); + CallService(MS_DB_SETSETTINGRESIDENT, (WPARAM)TRUE,(LPARAM)"NewStatusNotify/"LASTPOPUPTEXT); + + //if (PopupList == NULL) + PopupList = li.List_Create(0,10); + PopupList->sortFunc = SortPUWinList; + return 0; +} + +//===== Unload ===== +//extern "C" +int __declspec(dllexport) Unload(void) { + li.List_Destroy(PopupList); + //Hooks + UnhookEvent(hContactSettingChanged); + UnhookEvent(hOptionsInitialize); + UnhookEvent(hModulesLoaded); + UnhookEvent(hUserInfoInitialise); + //UnhookEvent(hEventStatusModeChange); + UnhookEvent(hProtoAck); + UnhookEvent(hSendMessage); + UnhookEvent(hOpenUserDetails); + + DestroyHookableEvent(hHookContactStatusChanged); + DestroyHookableEvent(hHookSendMessage); + + if (ServiceExists("NewStatusNotify/EnableDisableMenuCommand")) + DestroyServiceFunction(hServiceMenu); + +// UnhookEvent(hMenuProcessCommand); + return 0; +} +/* +#ifdef _TINYCONFIG +BOOL WINAPI _DllMainCRTStartup(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpReserved) +{ + return DllMain(hinstDLL,fdwReason,lpReserved); +} +#endif +*/ + +//===== Options pages ===== +void LoadOptions() { + //ZeroMemory(&MyOptions, sizeof(MyOptions)); + //PopUp Options + MyOptions.Colors =DBGetContactSettingByte(NULL,ModuleName, "Colors", DEFAULT_COLORS); + MyOptions.UseDullText = DBGetContactSettingByte(NULL, ModuleName, "UseDullText", DEFAULT_USEDULLTEXT); + MyOptions.ReadAwayMsg = DBGetContactSettingByte(NULL, ModuleName, "ReadAwayMsg", DEFAULT_READAWAYMSG); + MyOptions.ShowGroup = DBGetContactSettingByte(NULL, ModuleName, "ShowGroup", DEFAULT_SHOWGROUP); + MyOptions.ShowPreviousStatus = DBGetContactSettingByte(NULL, ModuleName, "ShowPreviousStatus", DEFAULT_SHOWPREVIOUSSTATUS); + MyOptions.FromOfflinePopup = DBGetContactSettingByte(NULL, ModuleName, "FromOfflinePopup", 0); + //General Options + MyOptions.FromOffline = DBGetContactSettingByte(NULL, ModuleName, "FromOffline", DEFAULT_FROMOFFLINE); + MyOptions.TempDisable = DBGetContactSettingByte(NULL, ModuleName, "TempDisable", DEFAULT_TEMPDISABLE); + MyOptions.AutoDisable = DBGetContactSettingByte(NULL, ModuleName, "AutoDisable", DEFAULT_AUTODISABLE); + MyOptions.EnableSoundForMyCurrentStatus = DEFAULT_NOTIFYWITHSOUND; + MyOptions.EnablePopupForMyCurrentStatus = DEFAULT_NOTIFYWITHPOPUP; + MyOptions.UseSpeaker = DBGetContactSettingByte(NULL, ModuleName, "UseSpeaker", DEFAULT_USESPEAKER); + MyOptions.AvoidClipping = DBGetContactSettingByte(NULL, ModuleName, "AvoidClipping", DEFAULT_AVOIDCLIPPING); + MyOptions.HiddenContactsToo = DBGetContactSettingByte(NULL, ModuleName, "HiddenContactsToo", DEFAULT_HIDDENCONTACTSTOO); + MyOptions.Log = DBGetContactSettingByte(NULL, ModuleName, "Log", DEFAULT_LOG); + MyOptions.BlinkIcon = DBGetContactSettingByte(NULL, ModuleName, "BlinkIcon", DEFAULT_BLINKICON); + MyOptions.BlinkIcon_Status = DBGetContactSettingByte(NULL, ModuleName, "BlinkIcon_Status", DEFAULT_BLINKICON_STATUS); + MyOptions.byTimeout = DBGetContactSettingByte(NULL, ModuleName, "byTimeout", DEFAULT_TIMEOUT); + MyOptions.iTimeout = DBGetContactSettingDword(NULL, ModuleName, "iTimeout", DEFAULT_TIMEOUT_VALUE); + MyOptions.UseIndSnd = DBGetContactSettingByte(NULL, ModuleName, "UseIndSounds", DEFAULT_USE_IND_SOUNDS); + return; +} + +static int OptionsInitialize(WPARAM wParam,LPARAM lParam) { + OPTIONSDIALOGPAGE odp = { 0 }; + + odp.cbSize = sizeof(odp); + odp.position = 100000000; + odp.hInstance = hInst; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_NSN_OPT); + odp.pszTitle = "Notify"; + odp.pszGroup = "Status"; + odp.groupPosition = 910000000; + odp.flags=ODPF_BOLDGROUPS; + odp.pfnDlgProc = DlgProcGeneralOpts; + CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp); + + if (ServiceExists(MS_POPUP_ADDPOPUP)) { + ZeroMemory(&odp,sizeof(odp)); + odp.cbSize = sizeof(odp); + odp.position = 100000000; + odp.hInstance = hInst; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_NSN_OPT_POPUP); + odp.pszTitle = "Status Notify"; + odp.pszGroup = "PopUps"; + odp.groupPosition = 910000000; + odp.flags=ODPF_BOLDGROUPS; + odp.pfnDlgProc = DlgProcPopUpOpts; + CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp); + } + ZeroMemory(&odp,sizeof(odp)); + odp.cbSize = sizeof(odp); + odp.position = 100000000; + odp.hInstance = hInst; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_NSN_OPT_EVENTS_ENABLE); + odp.pszTitle = "Status Notify"; + odp.pszGroup = "Events"; + odp.groupPosition = 910000000; + odp.flags=ODPF_BOLDGROUPS; + odp.pfnDlgProc = DlgProcSoundOpts2; + CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp); + return 0; +} + +//===== MessageBoxes ===== +void Log(TCHAR* str) { + MessageBox(NULL, str, _T("NewStatusNotify"), MB_OK | MB_ICONINFORMATION); +} + +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); + Log(str); +} + +//====== list function=== +int SortPUWinList(void* it1, void * it2) { + PUWinItem* item1=(PUWinItem*)it1; + PUWinItem* item2=(PUWinItem*)it2; + return (int)(item1->hContact) - (int)(item2->hContact); +} + +//===== DB Functions ==== +//This function has the purpose of finding out the gender of a given contact. +//Currently only ICQ supports gender, as far as I know, but this could change in +//the future (i.e.: if I make a LAN protocol plugin). +//It works quite easy: it gets the base protocol for the contact and compares it +//with the known protocols. This can't be done automatically because each protocol +//could store gender informations in a different way, so it'a all manual. +//The first comparison which goes fine, checks for the gender and returns. +#define GENDER_UNSPECIFIED 0 +#define GENDER_MALE 1 +#define GENDER_FEMALE 2 + +BYTE GetGender(HANDLE hContact) { + char* lpzProtocol =(char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,(WPARAM)hContact,0); + if (lpzProtocol) { + switch (DBGetContactSettingByte((HANDLE)hContact,lpzProtocol,"Gender",0)) { + case 'M': + case 'm': + return GENDER_MALE; + case 'F': + case 'f': + return GENDER_FEMALE; + default: + return GENDER_UNSPECIFIED; + } + } + else + return GENDER_UNSPECIFIED; +} +// New Status Notify PopUp Window Message Proc +LRESULT CALLBACK PopupDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { + HANDLE hContact = NULL; + PLUGINDATA * pdp = NULL; + char *szProto={0}; + hContact = PUGetContact(hwnd); + + 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)hContact)) + break; + //If we get here, it was not a menu process command, but a click on one of our controls. + if (hContact > 0) { + //Get the plugin data (we need the PopUp service to do it) + pdp = (PLUGINDATA*)PUGetPluginData(hwnd); + if (!pdp || ((int)pdp == -1)) + return 0; // (== -1, == 0); + //If the contact (MS_POPUP_GETCONTACT) is < 0 (wrong) or = 0 (it's us) we do exit. + //Now we can act. + if ((DBGetContactSettingByte(NULL, ModuleName, "LeftClickAction", ACTION_OPENMSG) == ACTION_OPENMSG) + /*&& (pdp->newStatus != ID_STATUS_OFFLINE) */) + NotifyEventHooks(hHookSendMessage, (WPARAM)hContact, 0); + } + //After a click, we destroy it nevertheless: message window or not. + PUDeletePopUp(hwnd); + break; + } + case WM_CONTEXTMENU: { + if (DBGetContactSettingByte(NULL, ModuleName, "RightClickAction", ACTION_DISMISS) == ACTION_DISMISS) + PUDeletePopUp(hwnd); + else { + //What do I do? This: + if (hContact < 0) break; + if (hContact != NULL) { + 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); + } + } + break; + } + case UM_FREEPLUGINDATA: { + PUWinItem PULItem = {0}; + PUWinItem* pPULItem = {0}; + //PLUGINDATA * pdp = {0}; + pdp = (PLUGINDATA*)PUGetPluginData(hwnd); + if (pdp != 0) { +// if (pdp->hAwayMsgHook != NULL) UnhookEvent(pdp->hAwayMsgHook); + mir_free(pdp); + } + PULItem.hContact = hContact; + pPULItem = li.List_Find(PopupList, &PULItem); + if ( (pPULItem != NULL) && (pPULItem->hWnd == hwnd ) ) // if we have item in list for this contact and this window + li.List_RemovePtr(PopupList, pPULItem); + return 0; + //break; + } + case UM_INITPOPUP: { + pdp = (PLUGINDATA*)PUGetPluginData(hwnd); + + if (!PUIsSecondLineShown()) //There is no second line, it's not needed to check for away message. + return 0; + + szProto= (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)(HANDLE)PUGetContact(hwnd),(LPARAM)0); + + if (MyOptions.ReadAwayMsg && StatusHasAwayMessage(szProto, pdp->newStatus)) { +// BOOL bNeedCreateItem; + PUWinItem PULItem = {0}; + PUWinItem* pPULItem = {0}; + PULItem.hContact = hContact; + pPULItem = li.List_Find(PopupList, &PULItem); + if ((pPULItem != NULL) /*&& (pPULItem->hWnd != NULL)*/) // if we have any list item for this contact AND popup already exists +// li.List_RemovePtr(PopupList, pPULItem); // remove item from popupList to have only ONE entry for that contact in list + { + pPULItem->hWnd = hwnd; + time(&(pPULItem->TimeStamp)); + } + + // if we (had any list item for this contact AND popup already exists) OR do not have any item for this contact + /*bNeedCreateItem = ((pPULItem != NULL) && (pPULItem->hWnd != NULL)) || (pPULItem == NULL); + if (bNeedCreateItem) + { + pPULItem = (PUWinItem*)mir_alloc(sizeof(PULItem)); // create new list item + pPULItem->hContact = hContact; + lstrcpyn(pPULItem->StatMsg, _T(""), MAX_SECONDLINE); + } + pPULItem->hWnd = hwnd; + + time(&(pPULItem->TimeStamp)); + pPULItem->Status = pdp->newStatus; + if (bNeedCreateItem) + li.List_Insert(PopupList, (void*)pPULItem, 0); // insert item to list + */ + if (szProto && (strstr(szProto, "ICQ") || strstr(szProto, "AIM")) ) + { //A bit useless (to receive a status change, szProto wasn't NULL in the first place) + WORD myStatus = (WORD)CallProtoService(szProto,PS_GETSTATUS, (WPARAM)0, (LPARAM)0); + if (myStatus != ID_STATUS_INVISIBLE) // do not retrieve status messages when we are in ICQ invisible mode - otherwise it will show us to other side! + QueryAwayMessage(hwnd, pdp); + /*else //not ICQ, query the away message whatever status we're in. + QueryAwayMessage(hwnd, pdp);*/ + } + } + return 0; + } + case WM_AWAYMSG: { //We're here because ME_PROTO_ACK has been hooked to this window (too!). + pdp = (PLUGINDATA*)PUGetPluginData(hwnd); + ReceivedAwayMessage(hwnd, lParam, pdp); + //Since we're in a Hook routine, we need to return 0 or the hook chain will stop. + return FALSE; + } + default: + break; + } + return DefWindowProc(hwnd, message, wParam, lParam); +}; + +//===== Function called when the settings for a contact are changed. +// We'll basically see if the changed setting regards contact's Status: either +// exit from the function to let other modules do their job, or do *our* job. +// A significant part of this code has been copied from Miranda's original code +// by Cyreve, but I have changed something. +static int ContactSettingChanged(WPARAM wParam,LPARAM lParam) { + DBCONTACTWRITESETTING *cws=(DBCONTACTWRITESETTING*)lParam; + WORD newStatus = 0,oldStatus = 0; + DWORD dwStatuses = 0; + + //We need to exit from this function as fast as possible, so we'll first check + //if the setting regards us (exit) or if it's not related to status (exit). + //If we're there, it means it's a status change we *could* notify, so let's see + //if we are ignoring that event. This means if *Miranda* ignores it (ignores every + //notification) and then if *We* ignore the event. + //Lastly, we check if we're offline: this will happen only once per connection, while + //the checks above will happen more frequently. + + //The setting must belong to a contact different from myself (NULL) and needs + //to be related to the status. Otherwise, exit as fast as possible. + if ((HANDLE)wParam != NULL && !lstrcmpA(cws->szSetting,"Status")) { + //Ok, if we're here we have a contact who is changing his status. + //The first thing we need to do is save the new Status in place of the old + //one, then we'll proceed. + //If we don't do this, we may exit from the function without updating the + //UserOnline settings. + DBVARIANT dbvProto = { 0 }; + newStatus = cws->value.wVal; + //--------------------------------need to check if it is really a protocol + if (DBGetContactSettingString((HANDLE)wParam, "Protocol", "p", &dbvProto) == DB_READ_SUCCESS) { + BOOL temp = strcmp(cws->szModule, dbvProto.pszVal) != 0; + DBFreeVariant(&dbvProto); + if ( temp ) { + //MessageBox(0,_T("Not a proto. Return!"), _T("NSN"), 0); + return 0; + } + } + oldStatus = DBGetContactSettingRangedWord((HANDLE)wParam,"UserOnline","OldStatus",ID_STATUS_OFFLINE, ID_STATUS_MIN, ID_STATUS_MAX); + //If they are the same, you don't need to write to the DB or do anything else. + if (oldStatus == newStatus) + return 0; + //If we get here, the two stauses differ, so we can proceed. + DBWriteContactSettingWord((HANDLE)wParam,"UserOnline","OldStatus",(WORD)newStatus); + + //If *Miranda* ignores the UserOnline event, exit! + if(CallService(MS_IGNORE_ISIGNORED,wParam,IGNOREEVENT_USERONLINE)) + return 0; + + //If we get here, we have to notify the Hooks. + dwStatuses = MAKELPARAM(oldStatus, newStatus); + NotifyEventHooks(hHookContactStatusChanged, (WPARAM)wParam, (LPARAM)dwStatuses); + + return 0; + } + if ( ((HANDLE)wParam != NULL) //not our own status message + && MyOptions.ReadAwayMsg //and we should show status message in popup + && !lstrcmpA(cws->szSetting,"StatusMsg")) //and changed DB value is StatusMessage + ReceivedStatusMessage((HANDLE)wParam, TRUE); + + return 0; +} + +static int ContactStatusChanged(WPARAM wParam, LPARAM lParam) { + WORD oldStatus = LOWORD(lParam); + WORD newStatus = HIWORD(lParam); + char str[8] = { 0 }; + WORD myStatus; + char lpszSubProto[MAX_PROTONAMELEN] = { 0 }; + char *lpzProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)wParam,0); + + //------------------------------ if NewStatusNotify has been disabled, exit! + if (MyOptions.TempDisable) + return 0; + + myStatus = (WORD)CallProtoService(lpzProto,PS_GETSTATUS, (WPARAM)0, (LPARAM)0); + + //------------------------------- if it is metacontact - get subcontact and test if its proto is offline or we don't want to be notified at connect + if ( (ServiceExists(MS_MC_GETPROTOCOLNAME)) && + (strcmp(lpzProto,(char*)CallService(MS_MC_GETPROTOCOLNAME,0,0)) == 0) ) //this contact is Meta + { + //get Most Online contact - it is DefContact if DefContact is Online, + // otherwise first online contact in the Subcontacts list + char cMCBaseProto[MAX_PROTONAMELEN] = {0}; + HANDLE hSubContact = (HANDLE)CallService(MS_MC_GETMOSTONLINECONTACT,wParam,0); + // get Proto name from Subcontact + if (hSubContact) + strncpy(cMCBaseProto, (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hSubContact,0), MAX_PROTONAMELEN); + if (cMCBaseProto == NULL) + mir_snprintf(lpszSubProto, MAX_PROTONAMELEN, + "No subcontact returned for given metacontact %d. Probably, this metacontact is corrupted", wParam); + else + { + strncpy(lpszSubProto, cMCBaseProto, sizeof(lpszSubProto)-1 ); + if (newStatus > ID_STATUS_OFFLINE) + // write last online protocol for Metacontact. from MIM 0.6+ this setting is resident + DBWriteContactSettingString((HANDLE)wParam, lpzProto, "LastOnline", lpszSubProto); + else + { + // read last online proto for metaconatct if exists, + // to avoid notifying when meta went offline but default contact's proto still online + DBVARIANT dbvProto = { 0 }; + if (DBGetContactSettingString((HANDLE)wParam, lpzProto, "LastOnline", &dbvProto) == DB_READ_SUCCESS) + { + //strcpy(lpzSubProto, dbvProto.pszVal); + //lpszSubProto = (char*)_malloca( strlen(dbvProto.pszVal)+1 ); + strncpy( lpszSubProto, dbvProto.pszVal, sizeof(lpszSubProto)-1 ); + DBFreeVariant(&dbvProto); + } + } + /* + { //debug out for metas + char outtxt[200]; + WORD mySubStatus; + // get Proto Status from Subcontact + mySubStatus = (WORD)CallProtoService(lpzSubProto,PS_GETSTATUS, (WPARAM)0, (LPARAM)0); + mir_snprintf(outtxt,sizeof(outtxt), "Main Proto: %s\nMain Status: %d\nSubProto: %s\nSubStatus: %d",lpzProto, myStatus, lpzSubProto, mySubStatus); + PUShowMessage(outtxt, SM_NOTIFY); + } */ + + // check if Subcontact's proto is offline and we shouldn't notify about status change on connect + if ( (DBGetContactSettingByte(NULL, ModuleName, lpszSubProto, DEFAULT_PROTO_POPUPS) == PROTO_POPUPS_OFF && + DBGetContactSettingByte(NULL, ModuleName, "ShowOnConnection", DEFAULT_SHOWONCONNECTION) == FALSE) ) + return(0); + } + } + //------------------------------- end of meta -- + else + { + //------------------------------ if we're offline (=> we've just switched to offline), exit as fast as possible. + if (myStatus == ID_STATUS_OFFLINE) + return 0; + //------------------------------ if the user doesn't want sounds on connect, exit. (If this was a popup after a connection 8)) + if (DBGetContactSettingByte(NULL, ModuleName, lpzProto, DEFAULT_PROTO_POPUPS) == PROTO_POPUPS_OFF && + DBGetContactSettingByte(NULL, ModuleName, "ShowOnConnection", DEFAULT_SHOWONCONNECTION) == FALSE) + //ShowOnConnection must be FALSE to get here. + //lpzProto must be FALSE (0) (PROTO_POPUPS_OFF) to get here (value for that proto in NSN settings is 0(=disable notifications)). + //It means that we don't want to be notified at startup/connection and we're at startup/connection. + return 0; + } + //If *we* ignore the event, exit as fast as possible, but if the previous status was Offline, there's the chance + //we want to be notified. + if ( !(MyOptions.FromOffline && (oldStatus == ID_STATUS_OFFLINE)) ) + { // Either it wasn't a change from Offline or we didn't enable that. + wsprintfA(str, "%d", newStatus); + if (DBGetContactSettingByte(NULL, ModuleName, str,0) == 1) + return 0; // "Notify when a contact changes to one of..." is unchecked + } + //If the contact is hidden (i.e.: not in Contact List), exit. + //This is here because it's a read from the DB and it has lesser chances to be called than the others. + //I mean: it's easier that the user disabled something, than a hidden contact is changing status. + if ((!MyOptions.HiddenContactsToo) && (DBGetContactSettingByte((HANDLE)wParam, "CList", "Hidden", 0) == 1)) + return 0; + // we don't want to be notified if new chatroom comes online + if (DBGetContactSettingByte((HANDLE)wParam, lpzProto, "ChatRoom", 0) == 1) + return 0; + //Ok, we want to be notified. :-) + + { // check if that proto from which we received statuschange notification, isn't in autodisable list + char statusIDs[12] = { 0 }, statusIDp[12] = { 0 }; //2 (my) + 5 (40078) + 1 (\0) = 8; 12 - 8 = 4 free bytes, you never can tell. + + if (MyOptions.AutoDisable == TRUE) + { + wsprintfA(statusIDs,"s%d", myStatus); + wsprintfA(statusIDp,"p%d", myStatus); + //Now statusIDs contains "s40078", "s40072" or whatever. + //DBGetContactSettingByte(NULL, ModuleName, statusIDs,xx) will give me one of these two values: + // 1 (TRUE) meaning that we want sounds and popups + // 0 (FALSE) meaning that we don't want them. + MyOptions.EnableSoundForMyCurrentStatus = DBGetContactSettingByte(NULL, ModuleName, statusIDs, DEFAULT_NOTIFYWITHSOUND) ? TRUE : FALSE; + MyOptions.EnablePopupForMyCurrentStatus = DBGetContactSettingByte(NULL, ModuleName, statusIDp, DEFAULT_NOTIFYWITHPOPUP) ? TRUE : FALSE; + } + } + + //-------------------------------------------------===== Status PopUp =====--------------------------------------------------------- + if ( MyOptions.EnablePopupForMyCurrentStatus && DBGetContactSettingByte((HANDLE)wParam, ModuleName, "EnablePopups",1) ) //DBGetContactSettingByte(NULL, "CList", "DisableTrayFlash", FALSE) == FALSE) + { + // Create the window, add its corresponding structure to our list of visible NSN windows, show the list. + BOOL NotifyMe = FALSE; + BOOL bIsICQ = FALSE; + POPUPDATAT ppd = { 0 }; + PLUGINDATA * pdp = (PLUGINDATA*)mir_alloc(sizeof(PLUGINDATA)); + TCHAR lptzStatusText[MAX_SECONDLINE] = { 0 }; + BOOL bReadAwayMsg = TRUE; + //implementation of contact status event filtering + if (MyOptions.FromOfflinePopup && (oldStatus == ID_STATUS_OFFLINE) ) + NotifyMe = TRUE; + + if (NotifyMe == FALSE) + { // Either it wasn't a change from Offline or we didn't enable that. + wsprintfA(str, "%dp", newStatus); + if (DBGetContactSettingByte(NULL, ModuleName, str,0) == 1) + NotifyMe=TRUE; // "Notify when a contact changes to one of..." is checked + } + + if (NotifyMe == TRUE) + { + ppd.lchContact = (HANDLE)wParam; //You need to give me a valid hContact, because I don't check its existance. + ppd.lchIcon = LoadSkinnedProtoIcon(lpzProto, newStatus); + lstrcpyn(ppd.lptzContactName, (TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)wParam, GCMDF_TCHAR), SIZEOF(ppd.lptzContactName)-1); + + if (MyOptions.ShowGroup) + {//add group name to popup title + DBVARIANT dbv = { 0 }; + if ((DBGetContactSettingTString((HANDLE)wParam, "CList", "Group", &dbv)) == DB_READ_SUCCESS) + { + mir_sntprintf(ppd.lptzContactName, SIZEOF(ppd.lptzContactName)-1, _T("%s (%s)"), ppd.lptzContactName, dbv.ptszVal); + DBFreeVariant(&dbv); + } + } + if (lpzProto) + { //A bit useless (to receive a status change, szProto wasn't NULL in the first place) + if (strstr(lpzProto, "ICQ")) + { + bIsICQ = TRUE; + if (myStatus == ID_STATUS_INVISIBLE) + // do not retrieve status messages when we are in ICQ invisible mode - otherwise it will show us to other side! + bReadAwayMsg = FALSE; + } + } + + if (lpszSubProto[0] != '\0') +// if ( assign lpszSubProto) + { + if (StatusHasAwayMessage(lpszSubProto, newStatus) == FALSE) + bReadAwayMsg = FALSE; + } + + bReadAwayMsg = bReadAwayMsg && MyOptions.ReadAwayMsg && StatusHasAwayMessage(lpzProto, newStatus); + //-------------- + { + if (MyOptions.UseDullText == 1) + lstrcpyn(lptzStatusText,StatusesList[Index(newStatus)].lpzStandardText, MAX_STATUSTEXT); + else if (MyOptions.UseDullText == 2) + { + //Get gender and load status text. + switch (GetGender((HANDLE)wParam)) + { + case GENDER_MALE: + lstrcpyn(lptzStatusText,StatusesList[Index(newStatus)].lpzMStatusText, MAX_STATUSTEXT); + break; + case GENDER_FEMALE: + lstrcpyn(lptzStatusText,StatusesList[Index(newStatus)].lpzFStatusText, MAX_STATUSTEXT); + break; + case GENDER_UNSPECIFIED: + lstrcpyn(lptzStatusText,StatusesList[Index(newStatus)].lpzUStatusText, MAX_STATUSTEXT); + break; + } + } + //Now we add the old status. + if (MyOptions.ShowPreviousStatus && ((oldStatus>=ID_STATUS_OFFLINE)||(oldStatus<=ID_STATUS_OUTTOLUNCH) )) + { + TCHAR szAux[MAX_STATUSTEXT] = { 0 }; + wsprintf(szAux, TranslateTS(STRING_SHOWPREVIOUSSTATUS), StatusesList[Index(oldStatus)].lpzStandardText); + lstrcat(lstrcat(lptzStatusText, _T(" ")), szAux); + } + } + + if (DBGetContactSettingByte(NULL, ModuleName, "ShowMirVer",0)) + {//add MirVer Text if key is set + DBVARIANT dbv = { 0 }; + if ((DBGetContactSettingTString((HANDLE)wParam, lpzProto, "MirVer", &dbv)) == DB_READ_SUCCESS) + { + lstrcat(ppd.lptzText, dbv.ptszVal); + lstrcat(ppd.lptzText, _T("\n")); + DBFreeVariant(&dbv); + } + else + lstrcpy(ppd.lptzText, _T("")); + } + //-------------- + if (bReadAwayMsg) + { + PUWinItem PULItem = {0}; + PUWinItem* pPULItem = {0}; + DBVARIANT dbv = { 0 }; + TCHAR sztDBStatMes[MAX_SECONDLINE] = {0}; + time_t now; + time(&now); + PULItem.hContact = (HANDLE)wParam; + pPULItem = li.List_Find(PopupList, &PULItem); + if ((pPULItem != NULL) /*&& ( ((pPULItem->TimeStamp + 1) < now) || (pPULItem->hWnd != NULL) )*/ ) + { + //li.List_RemovePtr(PopupList, pPULItem); // remove record from popupList if we have any for this contact + if (pPULItem->hWnd != NULL) + { + pPULItem->hWnd = NULL; + PUDeletePopUp(pPULItem->hWnd); + } + } + + DBWriteContactSettingTString((HANDLE)wParam, ModuleName, LASTPOPUPTEXT, lptzStatusText); + if ((DBGetContactSettingTString((HANDLE)wParam, "Clist", "StatusMsg", &dbv)) == DB_READ_SUCCESS) + { + lstrcpyn(sztDBStatMes, dbv.ptszVal, MAX_SECONDLINE); + DBFreeVariant(&dbv); + } + else + lstrcpyn(sztDBStatMes, _T(""), MAX_SECONDLINE); + + mir_sntprintf(lptzStatusText, MAX_SECONDLINE, _T("%s\n%s"), lptzStatusText, + (pPULItem != NULL) ? pPULItem->StatMsg : ( bIsICQ ? TranslateT("") : sztDBStatMes ) ); + } + //-------------- + lstrcat(ppd.lptzText, lptzStatusText); + + switch (MyOptions.Colors) + { + case byCOLOR_OWN: + ppd.colorBack = StatusesList[Index(newStatus)].colorBack; + ppd.colorText = StatusesList[Index(newStatus)].colorText; + break; + case byCOLOR_WINDOWS: + ppd.colorBack = GetSysColor(COLOR_BTNFACE); + ppd.colorText = GetSysColor(COLOR_WINDOWTEXT); + break; + case byCOLOR_POPUP: + ppd.colorBack = ppd.colorText = 0; + break; + } + ppd.PluginWindowProc = (WNDPROC)PopupDlgProc; + //Now the "additional" data. + pdp->oldStatus = oldStatus; + pdp->newStatus = newStatus; + //Now that the plugin data has been filled, we add it to the PopUpData. + ppd.PluginData = pdp; + switch (MyOptions.byTimeout) + { + case TIMEOUT_CUSTOM: + ppd.iSeconds = MyOptions.iTimeout; + break; + case TIMEOUT_PERMANENT: + ppd.iSeconds = -1; + break; + case TIMEOUT_POPUP: + default: + ppd.iSeconds = 0; + break; + } + PUAddPopUpT(&ppd); + } + } + //-------------------------------------------------===== Blinking Icon section =====--------------------------------------------------- + if ((MyOptions.BlinkIcon) && (newStatus > ID_STATUS_OFFLINE)) //emulate behavior of core - don't show tray icon when contact went offline + { + CLISTEVENT cle = { 0 }; + TCHAR szTooltip[256]; + + cle.cbSize = sizeof(cle); + cle.flags = CLEF_ONLYAFEW|CLEF_TCHAR; + cle.hContact = (HANDLE)wParam; + cle.hDbEvent = (HANDLE)wParam; + if (MyOptions.BlinkIcon_Status) + cle.hIcon = LoadSkinnedProtoIcon(lpzProto, newStatus); + else + cle.hIcon = LoadSkinnedIcon(SKINICON_OTHER_USERONLINE); + cle.pszService = "UserOnline/Description"; + wsprintf(szTooltip, TranslateT("%s is now %s"), (TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, wParam, GCDNF_TCHAR), + StatusesList[Index(newStatus)].lpzStandardText); + cle.ptszTooltip = szTooltip; + CallService(MS_CLIST_ADDEVENT, 0, (LPARAM)&cle); + } + //-------------------------------------------------===== Log to file section =====------------------------------------------------------ + if (MyOptions.Log) { + HANDLE hFile = NULL; + DBVARIANT dbv = { 0 }; + SECURITY_ATTRIBUTES sa = { 0 }; + BOOL bResult = FALSE; + TCHAR szName[1024] = { 0 }, szStatus[MAX_STATUSTEXT] = { 0 }, szOldStatus[MAX_STATUSTEXT] = { 0 }; + TCHAR szDate[MAX_STATUSTEXT] = { 0 }, szTime[MAX_STATUSTEXT] = { 0 }; + TCHAR szFile[MAX_PATH] = { 0 }, szFileRel[MAX_PATH] = { 0 }; + REPLACEVARSDATA dat = {0}; + TCHAR *pszText = NULL, *res; + DWORD dwBytes = 0, dwWritten = 0; + + if (DBGetContactSettingTString(NULL, ModuleName, "Logfile", &dbv) == 0) { + lstrcpyn(szFileRel, dbv.ptszVal, MAX_PATH); + DBFreeVariant(&dbv); + } + else + lstrcpyn(szFileRel, DEFAULT_LOGFILE, MAX_PATH); + + dat.cbSize = sizeof(dat); + dat.dwFlags = RVF_TCHAR; + + res = (TCHAR*)CallService(MS_UTILS_REPLACEVARS, (WPARAM)szFileRel, (LPARAM)&dat); + if (res) { + _tcscpy(szFileRel, res); + mir_free(res); + } + + CallService(MS_UTILS_PATHTOABSOLUTET, (WPARAM)szFileRel, (LPARAM)szFile); + + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.lpSecurityDescriptor = NULL; + sa.bInheritHandle = TRUE; + + hFile = CreateFile(szFile, + GENERIC_WRITE, FILE_SHARE_READ, &sa, + OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + + if (hFile != INVALID_HANDLE_VALUE) { // The file was successfully opened + DWORD FilePos = SetFilePointer(hFile, 0, NULL, FILE_END); + if (FilePos != INVALID_SET_FILE_POINTER) { // and positioned. +#ifdef _UNICODE + if (FilePos == 0) + fputwc((const wchar_t)"\xFF\xFE", hFile); // newly created file - write UTF-16 LE BOM +#endif + lstrcpyn(szName, (TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)wParam, GCDNF_TCHAR), SIZEOF(szName)-1); + lstrcpyn(szStatus,StatusesList[Index(newStatus)].lpzStandardText, MAX_STATUSTEXT); + lstrcpyn(szOldStatus,StatusesList[Index(oldStatus)].lpzStandardText, MAX_STATUSTEXT); + GetTimeFormat(LOCALE_USER_DEFAULT, 0, NULL,_T("HH':'mm"),szTime, SIZEOF(szTime)); + GetDateFormat(LOCALE_USER_DEFAULT, 0, NULL,_T("dd'.'MM'.'yyyy"),szDate, SIZEOF(szDate)); + + dwBytes = lstrlen(TranslateT("%s, %s. %s changed to: %s (was: %s).\r\n")) + lstrlen(szDate) + lstrlen(szTime) + + lstrlen(szName) + lstrlen(szStatus) + lstrlen(szOldStatus) + 1; //'\0' + pszText = (TCHAR*)mir_alloc(dwBytes * sizeof(TCHAR)); + wsprintf(pszText, TranslateT("%s, %s. %s changed to: %s (was: %s).\r\n"), szDate, szTime, szName, szStatus, szOldStatus); + bResult = WriteFile(hFile, pszText, lstrlen(pszText)* sizeof(TCHAR), &dwWritten, NULL); + SetEndOfFile(hFile); + mir_free(pszText); + } + CloseHandle(hFile); //This closes the handle both if the write routine worked or not. + } + } + //-------------------------------------------------===== Sound section =====--------------------------------------------------------- + if (DBGetContactSettingByte(NULL, "Skin", "UseSound", TRUE) + && MyOptions.EnableSoundForMyCurrentStatus + && DBGetContactSettingByte((HANDLE)wParam,ModuleName,"EnableSounds",1) ) { + // We want to hear something, ok. Every status has a sound associated, + // and we get it via the StatusesList[Index(newStatus)].lpzSkinSoundName. + // Before we play, however, we check if we have to use the sound card or the speaker: + // we'll add here individual sounds too, with a check for a group and contact specific sound. + // Since speaker and individual sounds don't get played automatically by the skin module, + // we have to check manually if they're enabled or disabled. + + // Check for individualized sounds. + if (MyOptions.UseIndSnd) { // -----------------------------Individual sounds are enabled----------------------- + TCHAR stzSound[MAX_PATH] = { 0 }; + DBVARIANT dbvDefIndStatus = { 0 }, dbvDefIndFO = { 0 }; + if (oldStatus == ID_STATUS_OFFLINE) { + if (DBGetContactSettingTString((HANDLE)wParam, ModuleName, "UserFromOffline", &dbvDefIndFO)==DB_READ_SUCCESS) { + // individual FromOffline sound defined and contact came from offline + lstrcpyn(stzSound, dbvDefIndFO.ptszVal, SIZEOF(stzSound)-1); + DBFreeVariant(&dbvDefIndFO); + } + } + else // check other individual sounds + if (DBGetContactSettingTString((HANDLE)wParam, ModuleName, StatusesList[Index(newStatus)].lpzSkinSoundName, &dbvDefIndStatus) == DB_READ_SUCCESS) { + lstrcpyn(stzSound, dbvDefIndStatus.ptszVal, SIZEOF(stzSound)-1); + DBFreeVariant(&dbvDefIndStatus); + } + if (stzSound[0] != 0) { // check if any of above checks is succeed and we need to play sound + if (MyOptions.UseSpeaker) + PlaySpeakerBeep(); + else { // play through soundcard + // Now make path to IndSound absolute, as it isn't registered + TCHAR stzTranslatedSound[MAX_PATH] = { 0 }; + CallService(MS_UTILS_PATHTOABSOLUTET, (WPARAM)stzSound, (LPARAM)stzTranslatedSound); + #ifdef DEBUG + if (!szTranslatedSound) PUShowMessage("ToAbsolutePath failed.", SM_WARNING); + #endif + //finally play Individual sound and return +#ifdef MS_SKIN_PLAYSOUNDEX + if (ServiceExists(MS_SKIN_PLAYSOUNDEX)) + { + SkinPlaySoundEx(szTranslatedSound); + } + else +#endif +#ifdef RegIndivSounds + SkinPlaySound(szTranslatedSound); +#else + if (MyOptions.AvoidClipping) + PlaySound(stzTranslatedSound, NULL, SND_ASYNC | SND_FILENAME | SND_NOSTOP); + else + PlaySound(stzTranslatedSound, NULL, SND_ASYNC | SND_FILENAME); +#endif + } + return 0; //sound is played - exit + } + } + //----------------------------------------------------check global sounds -------------------------------- + // Here there's the automatic check by Skin module, and this is right: + // if a user hasn't a specific sound, he is a "default" user, withstanding the rules of Skin module. + { + char szSoundFile[MAX_PATH] = { 0 }; + DBVARIANT dbvSound = { 0 }; + + if ( ( DBGetContactSettingByte(NULL, "SkinSoundsOff", "UserFromOffline",FALSE) == FALSE) + && (DBGetContactSettingString(NULL,"SkinSounds", "UserFromOffline",&dbvSound) == DB_READ_SUCCESS) + && (oldStatus == ID_STATUS_OFFLINE )) //The "UserFromOffline" sound isn't disabled, is defined and old status is offline + lstrcpyA(szSoundFile, "UserFromOffline"); + else if ( (DBGetContactSettingByte(NULL, "SkinSoundsOff", StatusesList[Index(newStatus)].lpzSkinSoundName,FALSE) == FALSE) + && (DBGetContactSettingString(NULL,"SkinSounds", StatusesList[Index(newStatus)].lpzSkinSoundName,&dbvSound) == DB_READ_SUCCESS) ) + lstrcpynA(szSoundFile, StatusesList[Index(newStatus)].lpzSkinSoundName, SIZEOF(szSoundFile)-1); + DBFreeVariant(&dbvSound); + if (szSoundFile[0]!=0) { // check if any of above checks is succeed and we need to play sound + if (MyOptions.UseSpeaker) PlaySpeakerBeep(); + else SkinPlaySound(szSoundFile); + } + } //end of global sounds + } // End of sound playing + return 0; +} //--------------------------------------------------============End of ContactStatusChanged=======------------------------------ + +//This is for the PopUp Options: style, position, color, font... +static BOOL CALLBACK DlgProcPopUpOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { + WORD i = 0; + char str[8] = {0}; + + switch (msg) { + +/************************************************************************ + case WM_CONTEXTMENU: + { + POINT pt = { 0 }; + HMENU hMenu=(HMENU)CallService(MS_CLIST_MENUBUILDCONTACT,214849,0); + GetCursorPos(&pt); + TrackPopupMenu(hMenu,0,pt.x,pt.y,0,hwndDlg,NULL); + DestroyMenu(hMenu); + break; + } +*///------------------------------------------------------------------------- + + + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + //Colours. + if (MyOptions.Colors == byCOLOR_OWN) { + CheckDlgButton(hwndDlg, IDC_USEOWNCOLORS, BST_CHECKED); + CheckDlgButton(hwndDlg, IDC_USEPOPUPCOLORS, BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_USEWINCOLORS, BST_UNCHECKED); + //EnableWindow(GetDlgItem(hwndDlg, IDC_USEPOPUPCOLORS), FALSE); + //EnableWindow(GetDlgItem(hwndDlg, IDC_USEWINCOLORS), TRUE); + } + if (MyOptions.Colors == byCOLOR_WINDOWS) { + CheckDlgButton(hwndDlg, IDC_USEOWNCOLORS, BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_USEPOPUPCOLORS, BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_USEWINCOLORS, BST_CHECKED); + //EnableWindow(GetDlgItem(hwndDlg, IDC_USEPOPUPCOLORS), FALSE); + //EnableWindow(GetDlgItem(hwndDlg, IDC_USEWINCOLORS), TRUE); + } + if (MyOptions.Colors == byCOLOR_POPUP) { + CheckDlgButton(hwndDlg, IDC_USEOWNCOLORS, BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_USEPOPUPCOLORS, BST_CHECKED); + CheckDlgButton(hwndDlg, IDC_USEWINCOLORS, BST_UNCHECKED); + //EnableWindow(GetDlgItem(hwndDlg, IDC_USEWINCOLORS), FALSE); + //EnableWindow(GetDlgItem(hwndDlg, IDC_USEPOPUPCOLORS), TRUE); + } + for (i = ID_STATUS_MIN; i <= ID_STATUS_MAX; i++) { + SendDlgItemMessage(hwndDlg,(i+2000),CPM_SETCOLOUR,0,StatusesList[Index(i)].colorBack); + SendDlgItemMessage(hwndDlg,(i+1000),CPM_SETCOLOUR,0,StatusesList[Index(i)].colorText); + EnableWindow(GetDlgItem(hwndDlg, i+2000), (MyOptions.Colors == byCOLOR_OWN)); + EnableWindow(GetDlgItem(hwndDlg, (i+1000)), (MyOptions.Colors == byCOLOR_OWN)); + } + //Ugly dull text... + CheckDlgButton(hwndDlg, IDC_CHK_USEDULLTEXT, MyOptions.UseDullText == 1 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_CHK_SHOWALTDESCS, MyOptions.UseDullText == 2 ? BST_CHECKED : BST_UNCHECKED); + //Away messages + CheckDlgButton(hwndDlg, IDC_READAWAYMSG, MyOptions.ReadAwayMsg?BST_CHECKED:BST_UNCHECKED); + //Previous status + CheckDlgButton(hwndDlg, IDC_SHOWPREVIOUSSTATUS, MyOptions.ShowPreviousStatus?BST_CHECKED:BST_UNCHECKED); + if (MyOptions.UseDullText == 0) + EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWPREVIOUSSTATUS), FALSE); + //Show group name in title + CheckDlgButton(hwndDlg, IDC_SHOWGROUP, MyOptions.ShowGroup?BST_CHECKED:BST_UNCHECKED); + //Timeout + CheckDlgButton(hwndDlg, IDC_TIMEOUT_POPUP, (MyOptions.byTimeout == TIMEOUT_POPUP)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_TIMEOUT_CUSTOM, (MyOptions.byTimeout == TIMEOUT_CUSTOM)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_TIMEOUT_PERMANENT, (MyOptions.byTimeout == TIMEOUT_PERMANENT)?BST_CHECKED:BST_UNCHECKED); + SetDlgItemInt(hwndDlg, IDC_TIMEOUT_VALUE, MyOptions.iTimeout, FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_TIMEOUT_VALUE), MyOptions.byTimeout == TIMEOUT_CUSTOM); + //Mouse actions + switch(DBGetContactSettingByte(NULL, ModuleName, "LeftClickAction",ACTION_OPENMSG)) + { + case ACTION_OPENMSG: + CheckDlgButton(hwndDlg, IDC_LC_OPENMSG, BST_CHECKED); + break; + case ACTION_DISMISS: + CheckDlgButton(hwndDlg, IDC_LC_DISMISS, BST_CHECKED); + break; + } + switch(DBGetContactSettingByte(NULL, ModuleName, "RightClickAction",ACTION_DISMISS)) + { + case ACTION_USERMENU: + CheckDlgButton(hwndDlg, IDC_RC_USERMENU, BST_CHECKED); + break; + case ACTION_DISMISS: + CheckDlgButton(hwndDlg, IDC_RC_DISMISS, BST_CHECKED); + break; + } + //Statuses notified + for (i = ID_STATUS_MIN; i <= ID_STATUS_MAX; i++) + { + wsprintfA(str, "%dp", i); + CheckDlgButton(hwndDlg, i, (DBGetContactSettingByte(NULL, ModuleName, str, 1))?BST_CHECKED:BST_UNCHECKED); + } + //Always notify when changing from offline? + CheckDlgButton(hwndDlg, IDC_CHK_PFROMOFFLINE, (MyOptions.FromOfflinePopup)?BST_CHECKED:BST_UNCHECKED); + return TRUE; + //End WM_INITDIALOG + case WM_COMMAND: + { +//----------------------- +// if(CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(wParam),MPCF_CONTACTMENU),214849)) break; +//------------------------ + WORD idCtrl = LOWORD(wParam), wNotifyCode = HIWORD(wParam); + if (wNotifyCode == EN_KILLFOCUS && idCtrl == IDC_TIMEOUT_VALUE) { //Check if it's in the range. + int newValue, oldValue = GetDlgItemInt(hwndDlg, idCtrl, NULL, FALSE); + int maxValue, minValue; + //newValue gets set in WM_COMMAND to the right value. We only update the edit field. + newValue = MyOptions.iTimeout; + maxValue = TIMEOUT_MAXVALUE; + minValue = TIMEOUT_MINVALUE; + if (oldValue > maxValue || oldValue < minValue) { + HigherLower(maxValue, minValue); + SendMessage(hwndDlg,UM_SETDLGITEMINT,idCtrl,newValue); + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + return TRUE; + } + if(idCtrl == IDC_TIMEOUT_VALUE && (wNotifyCode != EN_CHANGE || (HWND)lParam != GetFocus())) { + return TRUE; + } + if (wNotifyCode == CPN_COLOURCHANGED) { + //It's a colour picker change. idCtrl is the control id. + COLORREF colour = SendDlgItemMessage(hwndDlg,idCtrl,CPM_GETCOLOUR,0,0); + int ctlID = idCtrl; + if ((ctlID > 41070) && (ctlID < 42070) ) //It's 41071 or above => Text colour. + StatusesList[Index(ctlID-1000)].colorText = colour; + else //Background colour. + StatusesList[Index(ctlID-2000)].colorBack = colour; + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + return TRUE; + } + switch(idCtrl) + { + case IDC_USEOWNCOLORS: + { + BOOL bEnableOthers = FALSE; + if (wNotifyCode != BN_CLICKED) + break; + MyOptions.Colors = byCOLOR_OWN; + bEnableOthers = TRUE; + for (i = ID_STATUS_MIN; i <= ID_STATUS_MAX; i++) + { + EnableWindow(GetDlgItem(hwndDlg,( i+2000)), bEnableOthers); //Background + EnableWindow(GetDlgItem(hwndDlg, (i+1000)), bEnableOthers); //Text + } +// EnableWindow(GetDlgItem(hwndDlg, IDC_USEPOPUPCOLORS), bEnableOthers); + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + } + case IDC_USEWINCOLORS: + { + BOOL bEnableOthers = FALSE; + if (wNotifyCode != BN_CLICKED) + break; + //Use Windows colours. + MyOptions.Colors = byCOLOR_WINDOWS; + bEnableOthers = FALSE; + for (i = ID_STATUS_MIN; i <= ID_STATUS_MAX; i++) + { + EnableWindow(GetDlgItem(hwndDlg,( i+2000)), bEnableOthers); //Background + EnableWindow(GetDlgItem(hwndDlg, (i+1000)), bEnableOthers); //Text + } + //EnableWindow(GetDlgItem(hwndDlg, IDC_USEPOPUPCOLORS), bEnableOthers); + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + } + case IDC_USEPOPUPCOLORS: + { + BOOL bEnableOthers = FALSE; + if (wNotifyCode != BN_CLICKED) + break; + //Use Windows colours. + MyOptions.Colors = byCOLOR_POPUP; + bEnableOthers = FALSE; + for (i = ID_STATUS_MIN; i <= ID_STATUS_MAX; i++) + { + EnableWindow(GetDlgItem(hwndDlg, (i+2000)), bEnableOthers); //Background + EnableWindow(GetDlgItem(hwndDlg, (i+1000)), bEnableOthers); //Text + } +// EnableWindow(GetDlgItem(hwndDlg, IDC_USEWINCOLORS), bEnableOthers); + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + } + case IDC_PREVIEW: + {//Declarations and initializations + POPUPDATAT ppd = { 0 }; + PLUGINDATA * pd = NULL; + //int i = 0; + for (i = ID_STATUS_MIN; i <= (ID_STATUS_MAX+1); i++) + {wsprintfA(str, "%dp", i); + lstrcpy(ppd.lptzText, _T("")); + if ( !IsDlgButtonChecked(hwndDlg, i)) continue; // skip unchecked statuses + //ZeroMemory(&ppd, sizeof(POPUPDATAEX)); //Clear the object. + pd = (PLUGINDATA*)mir_alloc(sizeof(PLUGINDATA)); + /* This is my #1 cause of bugs: I always forget to add this malloc!! + Without this malloc, every popup would share the same PLUGINDATA structure, + so the second popup to be destroyed causes a c0000005! */ +// pd->oldStatus =(WORD)(ID_STATUS_OFFLINE + ((i-1)%10)); + pd->oldStatus = (WORD)(i <= ID_STATUS_MAX ? i : ID_STATUS_OFFLINE); +// pd->newStatus = (WORD)(i <= ID_STATUS_MAX ? (pd->oldStatus + 1) : ID_STATUS_ONLINE); + pd->newStatus = (WORD)(i < ID_STATUS_MAX ? (i + 1) : (i == ID_STATUS_MAX ? ID_STATUS_OFFLINE : ID_STATUS_ONLINE)); + ppd.lchIcon = LoadSkinnedIcon(StatusesList[Index(pd->newStatus)].Icon); + lstrcpyn(ppd.lptzContactName, (TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)NULL,GCMDF_TCHAR), SIZEOF(ppd.lptzContactName)-1); + if (MyOptions.UseDullText == 1) + lstrcpy(ppd.lptzText, StatusesList[Index(pd->newStatus)].lpzStandardText); + else if (MyOptions.UseDullText == 2) + lstrcpy(ppd.lptzText, StatusesList[Index(pd->newStatus)].lpzUStatusText); + if (MyOptions.ShowPreviousStatus) + { + TCHAR szAux[MAX_STATUSTEXT]; + wsprintf(szAux, TranslateTS(STRING_SHOWPREVIOUSSTATUS), StatusesList[Index(pd->oldStatus)].lpzStandardText); + lstrcat(lstrcat(ppd.lptzText, _T(" ")), szAux); + } + if (MyOptions.ReadAwayMsg) + { + if (MyOptions.UseDullText > 0) + lstrcat(ppd.lptzText, _T("\n")); + if (i<=ID_STATUS_MAX) + { + char *DefAwayMsg = (char*)CallService(MS_AWAYMSG_GETSTATUSMSG,pd->newStatus,0); + if (DefAwayMsg != NULL) + { +#ifdef UNICODE + WCHAR wsUStatMsg[MAX_SECONDLINE] = { 0 }; + MultiByteToWideChar((unsigned int)CallService(MS_LANGPACK_GETCODEPAGE,0,0),MB_PRECOMPOSED, DefAwayMsg, -1, wsUStatMsg, sizeof(wsUStatMsg)/sizeof(WCHAR)); + lstrcat(ppd.lptzText, wsUStatMsg); +#else + lstrcat(ppd.lptzText, DefAwayMsg); +#endif + mir_free(DefAwayMsg); + } + } + else + lstrcat(ppd.lptzText, TranslateT("This is \"from offline\" status message")); + + } + switch (MyOptions.Colors) + { + case byCOLOR_WINDOWS: + ppd.colorBack = GetSysColor(COLOR_BTNFACE); + ppd.colorText = GetSysColor(COLOR_WINDOWTEXT); + break; + case byCOLOR_OWN: + ppd.colorBack = StatusesList[Index(pd->newStatus)].colorBack; + ppd.colorText = StatusesList[Index(pd->newStatus)].colorText; + break; + case byCOLOR_POPUP: + ppd.colorBack = ppd.colorText = 0; + break; + } + ppd.PluginWindowProc = (WNDPROC)PopupDlgProc; + ppd.PluginData = pd; + switch (MyOptions.byTimeout) + { + case TIMEOUT_CUSTOM: + ppd.iSeconds = MyOptions.iTimeout; break; + case TIMEOUT_PERMANENT: + ppd.iSeconds = -1; break; + case TIMEOUT_POPUP: + default: + ppd.iSeconds = 0; break; + } + PUAddPopUpT(&ppd); + } + break; + } + case IDC_CHK_USEDULLTEXT: + if (wNotifyCode != BN_CLICKED) break; + MyOptions.UseDullText = MyOptions.UseDullText == 1 ? 0 : 1 ; + if (MyOptions.UseDullText == 1) + { + CheckDlgButton(hwndDlg, IDC_CHK_SHOWALTDESCS, BST_UNCHECKED); + EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWPREVIOUSSTATUS), TRUE); + } + else + if (MyOptions.UseDullText == 0) + { + EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWPREVIOUSSTATUS), FALSE); + MyOptions.ShowPreviousStatus = FALSE; + } + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case IDC_CHK_SHOWALTDESCS: + if (wNotifyCode != BN_CLICKED) break; + MyOptions.UseDullText = MyOptions.UseDullText == 2 ? 0 : 2 ; + if (MyOptions.UseDullText == 2) + { + CheckDlgButton(hwndDlg, IDC_CHK_USEDULLTEXT, BST_UNCHECKED); + EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWPREVIOUSSTATUS), TRUE); + } + else + if (MyOptions.UseDullText == 0) + { + EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWPREVIOUSSTATUS), FALSE); + MyOptions.ShowPreviousStatus = FALSE; + } + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case IDC_READAWAYMSG: + if (wNotifyCode != BN_CLICKED) break; + MyOptions.ReadAwayMsg = !MyOptions.ReadAwayMsg; + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case IDC_SHOWGROUP: + if (wNotifyCode != BN_CLICKED) break; + MyOptions.ShowGroup = !MyOptions.ShowGroup; + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case IDC_SHOWPREVIOUSSTATUS: + if (wNotifyCode != BN_CLICKED) break; + MyOptions.ShowPreviousStatus = !MyOptions.ShowPreviousStatus; + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case IDC_TIMEOUT_POPUP: + if (wNotifyCode != BN_CLICKED) break; + MyOptions.byTimeout = TIMEOUT_POPUP; + EnableWindow(GetDlgItem(hwndDlg, IDC_TIMEOUT_VALUE), FALSE); //It has to be disabled. + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case IDC_TIMEOUT_CUSTOM: + if (wNotifyCode != BN_CLICKED) break; + MyOptions.byTimeout = TIMEOUT_CUSTOM; + EnableWindow(GetDlgItem(hwndDlg, IDC_TIMEOUT_VALUE), TRUE); //It has to be enabled. + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case IDC_TIMEOUT_PERMANENT: + if (wNotifyCode != BN_CLICKED) break; + MyOptions.byTimeout = TIMEOUT_PERMANENT; + EnableWindow(GetDlgItem(hwndDlg, IDC_TIMEOUT_VALUE), FALSE); + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case IDC_TIMEOUT_VALUE: + { + if (wNotifyCode == EN_CHANGE) + { + int iTemp = GetDlgItemInt(hwndDlg, IDC_TIMEOUT_VALUE, NULL, FALSE); + if (iTemp > TIMEOUT_MAXVALUE) + MyOptions.iTimeout = TIMEOUT_MAXVALUE; + else if (iTemp < TIMEOUT_MINVALUE) + MyOptions.iTimeout = TIMEOUT_MINVALUE; + else + MyOptions.iTimeout = iTemp; + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + break; + } + case IDC_LC_DISMISS: case IDC_LC_OPENMSG: + case IDC_RC_DISMISS: case IDC_RC_USERMENU: + case IDC_CHK_PONLINE: case IDC_CHK_POFFLINE: case IDC_CHK_PINVISIBLE: + case IDC_CHK_PFREECHAT: case IDC_CHK_PAWAY: case IDC_CHK_PNA: + case IDC_CHK_POCCUPIED: case IDC_CHK_PDND: case IDC_CHK_POUTTOLUNCH: + case IDC_CHK_PONTHEPHONE: + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case IDC_CHK_PFROMOFFLINE: + MyOptions.FromOfflinePopup=!MyOptions.FromOfflinePopup; + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + } //End switch(WM_COMMAND) + break; + //End WM_COMMAND + } + case WM_NOTIFY: { //Here we have pressed either the OK or the APPLY button. + switch(((LPNMHDR)lParam)->idFrom) { + case 0: + switch (((LPNMHDR)lParam)->code) { + case PSN_RESET: + //Restore the options stored in memory. + LoadOptions(); + //We need to reload the status colours too. + InitStatusList(); + return TRUE; + case PSN_APPLY: { + //Text colour + char szSetting[8] = { 0 }; + DWORD ctlColour = 0; + for (i = ID_STATUS_MIN; i <= ID_STATUS_MAX; i++) { + ctlColour = SendDlgItemMessage(hwndDlg,(i+2000),CPM_GETCOLOUR,0,0); + StatusesList[Index(i)].colorBack = ctlColour; + wsprintfA(szSetting, "%ibg", i); + DBWriteContactSettingDword(NULL, ModuleName, szSetting,ctlColour); + ctlColour = SendDlgItemMessage(hwndDlg,(i+1000),CPM_GETCOLOUR,0,0); + StatusesList[Index(i)].colorText = ctlColour; + wsprintfA(szSetting, "%itx", i); + DBWriteContactSettingDword(NULL, ModuleName, szSetting, ctlColour); + } + //Colors + DBWriteContactSettingByte(NULL, ModuleName, "Colors", MyOptions.Colors); + //Use Dull Text + DBWriteContactSettingByte(NULL, ModuleName, "UseDullText", (BYTE)MyOptions.UseDullText); + //Away messages + DBWriteContactSettingByte(NULL, ModuleName, "ReadAwayMsg", (BYTE)MyOptions.ReadAwayMsg); + //Show previous status + DBWriteContactSettingByte(NULL, ModuleName, "ShowPreviousStatus", (BYTE)MyOptions.ShowPreviousStatus); + //Show group name in title + DBWriteContactSettingByte(NULL, ModuleName, "ShowGroup", (BYTE)MyOptions.ShowGroup); + //Timeout. + DBWriteContactSettingByte(NULL, ModuleName, "byTimeout", MyOptions.byTimeout); + DBWriteContactSettingDword(NULL, ModuleName, "iTimeout", MyOptions.iTimeout); + //Left mouse click + DBWriteContactSettingByte(NULL, ModuleName, "LeftClickAction", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_LC_DISMISS)?ACTION_DISMISS:ACTION_OPENMSG)); + //Right mouse click + DBWriteContactSettingByte(NULL, ModuleName, "RightClickAction", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_RC_DISMISS)?ACTION_DISMISS:ACTION_USERMENU)); + //Notified statuses + for (i = ID_STATUS_MIN; i <= ID_STATUS_MAX; i++) { + wsprintfA(str, "%dp", i); + DBWriteContactSettingByte(NULL, ModuleName, str, (BYTE)(BOOL)(IsDlgButtonChecked(hwndDlg, i))); + } + //Always notify when changing from offline + DBWriteContactSettingByte(NULL, ModuleName, "FromOfflinePopup", (BYTE)MyOptions.FromOfflinePopup); + return TRUE; + } //case PSN_APPLY + } // switch code + break; + } //switch idFrom + break; //End WM_NOTIFY + } + case UM_SETDLGITEMINT: + SetDlgItemInt(hwndDlg, (int)wParam, (int)lParam, FALSE); + break; + } //switch message + return FALSE; +} + +static BOOL CALLBACK DlgProcAutoDisableOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { + int i = 0; + char str[8] = { 0 }; + + switch (msg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + //Statuses notified + for (i = ID_STATUS_MIN; i <= ID_STATUS_MAX; i++) { + wsprintfA(str, "p%d", i); + CheckDlgButton(hwndDlg, i, + (DBGetContactSettingByte(NULL, ModuleName, str, DEFAULT_NOTIFYWITHPOPUP))?BST_UNCHECKED:BST_CHECKED); + } + for (i = ID_STATUS_MIN; i <= ID_STATUS_MAX; i++) { + wsprintfA(str, "s%d", i); + CheckDlgButton(hwndDlg, (i+2000), + (DBGetContactSettingByte(NULL, ModuleName, str, DEFAULT_NOTIFYWITHSOUND))?BST_UNCHECKED:BST_CHECKED); + } + return TRUE; + case WM_CLOSE: + DestroyWindow(hwndDlg); + break; + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_OK: + //Notified statuses + for (i = ID_STATUS_MIN; i <= ID_STATUS_MAX; i++) { + wsprintfA(str, "p%d", i); + DBWriteContactSettingByte(NULL, ModuleName, str, (BYTE)(BOOL)(!IsDlgButtonChecked(hwndDlg, i))); + } + for (i = ID_STATUS_MIN; i <= ID_STATUS_MAX; i++) { + wsprintfA(str, "s%d", i); + DBWriteContactSettingByte(NULL, ModuleName, str, (BYTE)(BOOL)(!IsDlgButtonChecked(hwndDlg, (i+2000)))); + } + //Fall through + case IDC_CANCEL: + DestroyWindow(hwndDlg); + break; + default: + break; + } + break; + default: + break; + } + return FALSE; +} + +//===== General options: use sounds? Use internal speaker? When to notify? Temporarily disable? +static BOOL CALLBACK DlgProcGeneralOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { + int i = 0; + char str[8] = { 0 }; + DBVARIANT dbv = { 0 }; + WORD idCtrl = LOWORD(wParam), wNotifyCode = HIWORD(wParam); + + switch (msg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + //Automatically disable + CheckDlgButton(hwndDlg, IDC_AUTODISABLE,MyOptions.AutoDisable?BST_CHECKED:BST_UNCHECKED); + EnableWindow(GetDlgItem(hwndDlg, IDC_CONFIGUREAUTODISABLE), IsDlgButtonChecked(hwndDlg, IDC_AUTODISABLE)); + //Temporary disable + CheckDlgButton(hwndDlg, IDC_TEMPDISABLE,MyOptions.TempDisable?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SHOWONCONNECTION,DBGetContactSettingByte(NULL, ModuleName, "ShowOnConnection", DEFAULT_SHOWONCONNECTION)?BST_CHECKED:BST_UNCHECKED); + //Blink icon. + CheckDlgButton(hwndDlg, IDC_BLINKICON, MyOptions.BlinkIcon?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_BLINKICON_STATUS, MyOptions.BlinkIcon_Status?BST_CHECKED:BST_UNCHECKED); + //Menu item + CheckDlgButton(hwndDlg, IDC_SHOWDISABLEMENU, DBGetContactSettingByte(NULL, ModuleName, "ShowDisableMenu", DEFAULT_SHOWDISABLEMENU)?BST_CHECKED:BST_UNCHECKED); + //HiddenContactsToo + CheckDlgButton(hwndDlg, IDC_HIDDENCONTACTSTOO, MyOptions.HiddenContactsToo?BST_UNCHECKED:BST_CHECKED); + //Sounds + CheckDlgButton(hwndDlg, IDC_SPEAKER,MyOptions.UseSpeaker?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_AVOIDCLIPPING,MyOptions.AvoidClipping?BST_CHECKED:BST_UNCHECKED); + //Individual sounds + CheckDlgButton(hwndDlg, IDC_USEINDIVSOUNDS,MyOptions.UseIndSnd?BST_CHECKED:BST_UNCHECKED); + //Statuses notified + for (i = ID_STATUS_MIN; i <= ID_STATUS_MAX; i++) + { + wsprintfA(str, "%d", i); + CheckDlgButton(hwndDlg, i, (DBGetContactSettingByte(NULL, ModuleName, str, 0))?BST_UNCHECKED:BST_CHECKED); + } + //Always notify when changing from offline? + CheckDlgButton(hwndDlg, IDC_CHK_FROMOFFLINE, (MyOptions.FromOffline)?BST_CHECKED:BST_UNCHECKED); + // Log options + if (DBGetContactSettingTString(NULL, ModuleName, "Logfile", &dbv) == 0) + { + SetDlgItemText(hwndDlg, IDC_LOGFILE, dbv.ptszVal); + DBFreeVariant(&dbv); + } + else + SetDlgItemText(hwndDlg, IDC_LOGFILE, DEFAULT_LOGFILE); + CheckDlgButton(hwndDlg, IDC_LOG, MyOptions.Log?BST_CHECKED:BST_UNCHECKED); + EnableWindow(GetDlgItem(hwndDlg, IDC_LOGFILE), IsDlgButtonChecked(hwndDlg, IDC_LOG)); + + return TRUE; + //End WM_INITDIALOG + case WM_COMMAND: + //These are simple clicks: we don't save, but we tell the Options Page to enable the "Apply" button. + switch(LOWORD(wParam)) { + case IDC_CONFIGUREAUTODISABLE: + CreateDialogA(hInst, MAKEINTRESOURCEA(IDD_AUTODISABLE), hwndDlg, DlgProcAutoDisableOpts); + break; + case IDC_SPEAKER: + MyOptions.UseSpeaker=!MyOptions.UseSpeaker; + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case IDC_USEINDIVSOUNDS: + MyOptions.UseIndSnd=!MyOptions.UseIndSnd; + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + case IDC_AVOIDCLIPPING: + MyOptions.AvoidClipping=!MyOptions.AvoidClipping; + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case IDC_AUTODISABLE: + MyOptions.AutoDisable = !MyOptions.AutoDisable; + EnableWindow(GetDlgItem(hwndDlg, IDC_CONFIGUREAUTODISABLE), IsDlgButtonChecked(hwndDlg, IDC_AUTODISABLE)); + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case IDC_TEMPDISABLE: + EnableDisableMenuCommand(0,0); + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case IDC_HIDDENCONTACTSTOO: + MyOptions.HiddenContactsToo=!MyOptions.HiddenContactsToo; + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case IDC_BLINKICON: + MyOptions.BlinkIcon = !MyOptions.BlinkIcon; + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case IDC_BLINKICON_STATUS: + MyOptions.BlinkIcon_Status = !MyOptions.BlinkIcon_Status; + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case IDC_SHOWDISABLEMENU: + case IDC_SHOWONCONNECTION: + case IDC_CHK_ONLINE: case IDC_CHK_OFFLINE: case IDC_CHK_INVISIBLE: + case IDC_CHK_FREECHAT: case IDC_CHK_AWAY: case IDC_CHK_NA: + case IDC_CHK_OCCUPIED: case IDC_CHK_DND: case IDC_CHK_OUTTOLUNCH: + case IDC_CHK_ONTHEPHONE: + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case IDC_CHK_FROMOFFLINE: + MyOptions.FromOffline=!MyOptions.FromOffline; + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case IDC_LOG: + if (idCtrl == IDC_LOG && wNotifyCode == BN_CLICKED) + { + EnableWindow(GetDlgItem(hwndDlg, IDC_LOGFILE), IsDlgButtonChecked(hwndDlg, IDC_LOG)); + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0,0); + break; + } + if (idCtrl == IDC_LOGFILE && wNotifyCode == EN_CHANGE && (HWND)lParam == GetFocus()) + { + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0,0); + break; + } + default: + break; + }//End switch(WM_COMMAND) + break; + //End WM_COMMAND + case WM_NOTIFY: //Here we have pressed either the OK or the APPLY button. + switch(((LPNMHDR)lParam)->idFrom) { + case 0: + switch (((LPNMHDR)lParam)->code) { + case PSN_RESET: + LoadOptions(); + return TRUE; + case PSN_APPLY: { + TCHAR szFile[MAX_PATH] = { 0 }; + int iResult = GetDlgItemText(hwndDlg, IDC_LOGFILE, szFile, MAX_PATH); + DBWriteContactSettingByte(NULL, ModuleName, "AutoDisable", (BYTE)MyOptions.AutoDisable); + //Temporarily disable NewStatusNotify + DBWriteContactSettingByte(NULL, ModuleName, "TempDisable", (BYTE)MyOptions.TempDisable); + DBWriteContactSettingByte(NULL, ModuleName, "ShowDisableMenu", (BYTE)IsDlgButtonChecked(hwndDlg, IDC_SHOWDISABLEMENU)); + + if (IsDlgButtonChecked(hwndDlg, IDC_SHOWDISABLEMENU)) { //We want the menu item. + if (!hEnableDisableMenu) { //It's not present, so make it. + installMainMenuItem(); + } + // else -> It is present, don't do anything. + } + else { //We don't want the menu item. + if (hEnableDisableMenu) { //It is present, we remove it. + if (ServiceExists(MS_CLIST_REMOVEMAINMENUITEM)) { + CallService(MS_CLIST_REMOVEMAINMENUITEM, (WPARAM)hEnableDisableMenu, (LPARAM)0); + hEnableDisableMenu = (int)(HANDLE)NULL; + } + //else -> the service does not exist, we leave the item there. + } + //else -> it is not present, we don't need to do anything. + } + + DBWriteContactSettingByte(NULL, ModuleName, "ShowOnConnection", (BYTE)IsDlgButtonChecked(hwndDlg, IDC_SHOWONCONNECTION)); + //individual sounds + DBWriteContactSettingByte(NULL, ModuleName, "UseIndSounds", (BYTE)MyOptions.UseIndSnd); + //Speaker + DBWriteContactSettingByte(NULL, ModuleName, "UseSpeaker", (BYTE)MyOptions.UseSpeaker); + //Avoid clipping + DBWriteContactSettingByte(NULL, ModuleName, "AvoidClipping", (BYTE)MyOptions.AvoidClipping); + //HiddenContactsToo + DBWriteContactSettingByte(NULL, ModuleName, "HiddenContactsToo", (BYTE)MyOptions.HiddenContactsToo); + //Blink icon + DBWriteContactSettingByte(NULL, ModuleName, "BlinkIcon", (BYTE)MyOptions.BlinkIcon); + DBWriteContactSettingByte(NULL, ModuleName, "BlinkIcon_Status", (BYTE)MyOptions.BlinkIcon_Status); + //Notified statuses + for (i = ID_STATUS_MIN; i <= ID_STATUS_MAX; i++) { + wsprintfA(str, "%d", i); + DBWriteContactSettingByte(NULL, ModuleName, str, (BYTE)(BOOL)(!IsDlgButtonChecked(hwndDlg, i))); + } + //Always notify when changing from offline + DBWriteContactSettingByte(NULL, ModuleName, "FromOffline", (BYTE)MyOptions.FromOffline); + + // log filename ------------------------- + if (iResult == 0) + { //No file name has been given. Use default one. + SetDlgItemText(hwndDlg, IDC_LOGFILE, DEFAULT_LOGFILE); + lstrcpy(szFile, DEFAULT_LOGFILE); + } + MyOptions.Log = IsDlgButtonChecked(hwndDlg, IDC_LOG)?1:0; + DBWriteContactSettingByte(NULL, ModuleName, "Log", MyOptions.Log); + DBWriteContactSettingTString(NULL, ModuleName, "Logfile", szFile); + //--------------------------- + + return TRUE; + } //case PSN_APPLY + } // switch code + break; + } //switch idFrom + break; //End WM_NOTIFY + } //switch message + return FALSE; +} + +//===== Initializations ===== +void InitStatusList() { + int index = 0; + //Online + index = Index(ID_STATUS_ONLINE); + StatusesList[index].ID = ID_STATUS_ONLINE; + StatusesList[index].Icon = SKINICON_STATUS_ONLINE; + lstrcpyn(StatusesList[index].lpzMStatusText, TranslateT("(M) is back online!"), MAX_STATUSTEXT); + lstrcpyn(StatusesList[index].lpzFStatusText, TranslateT("(F) is back online!"), MAX_STATUSTEXT); + lstrcpyn(StatusesList[index].lpzUStatusText, TranslateT("(U) is back online!"), MAX_STATUSTEXT); + lstrcpyn(StatusesList[index].lpzStandardText, TranslateT("Online"), MAX_STANDARDTEXT); + lstrcpynA(StatusesList[index].lpzSkinSoundName, "UserOnline", MAX_SKINSOUNDNAME); + lstrcpynA(StatusesList[index].lpzSkinSoundDesc, "User: Online", MAX_SKINSOUNDDESC); + lstrcpynA(StatusesList[index].lpzSkinSoundFile, "global.wav", MAX_PATH); +// StatusesList[index].dwProtoFlag = PF2_ONLINE; + StatusesList[index].colorBack = DBGetContactSettingDword(NULL, ModuleName, "40072bg", POPUPCOLOR_BG_40072); + StatusesList[index].colorText = DBGetContactSettingDword(NULL, ModuleName, "40072tx", POPUPCOLOR_TX_40072); + + //Offline + index = Index(ID_STATUS_OFFLINE); + StatusesList[index].ID = ID_STATUS_OFFLINE; + StatusesList[index].Icon = SKINICON_STATUS_OFFLINE; + lstrcpyn(StatusesList[index].lpzMStatusText, TranslateT("(M) went offline! :("), MAX_STATUSTEXT); + lstrcpyn(StatusesList[index].lpzFStatusText, TranslateT("(F) went offline! :("), MAX_STATUSTEXT); + lstrcpyn(StatusesList[index].lpzUStatusText, TranslateT("(U) went offline! :("), MAX_STATUSTEXT); + lstrcpyn(StatusesList[index].lpzStandardText, TranslateT("Offline"), MAX_STANDARDTEXT); + lstrcpynA(StatusesList[index].lpzSkinSoundName, "UserOffline", MAX_SKINSOUNDNAME); + lstrcpynA(StatusesList[index].lpzSkinSoundDesc, "User: Offline", MAX_SKINSOUNDDESC); + lstrcpynA(StatusesList[index].lpzSkinSoundFile, "offline.wav", MAX_PATH); +// StatusesList[index].dwProtoFlag = 0; + StatusesList[index].colorBack = DBGetContactSettingDword(NULL, ModuleName, "40071bg", POPUPCOLOR_BG_40071); + StatusesList[index].colorText = DBGetContactSettingDword(NULL, ModuleName, "40071tx", POPUPCOLOR_TX_40071); + + //Invisible + index = Index(ID_STATUS_INVISIBLE); + StatusesList[index].ID = ID_STATUS_INVISIBLE; + StatusesList[index].Icon = SKINICON_STATUS_INVISIBLE; + lstrcpyn(StatusesList[index].lpzMStatusText, TranslateT("(M) hides in shadows..."), MAX_STATUSTEXT); + lstrcpyn(StatusesList[index].lpzFStatusText, TranslateT("(F) hides in shadows..."), MAX_STATUSTEXT); + lstrcpyn(StatusesList[index].lpzUStatusText, TranslateT("(U) hides in shadows..."), MAX_STATUSTEXT); + lstrcpyn(StatusesList[index].lpzStandardText, TranslateT("Invisible"), MAX_STANDARDTEXT); + lstrcpynA(StatusesList[index].lpzSkinSoundName, "UserInvisible", MAX_SKINSOUNDNAME); + lstrcpynA(StatusesList[index].lpzSkinSoundDesc, "User: Invisible", MAX_SKINSOUNDDESC); + lstrcpynA(StatusesList[index].lpzSkinSoundFile, "invisible.wav", MAX_PATH); +// StatusesList[index].dwProtoFlag = PF2_INVISIBLE; + StatusesList[index].colorBack = DBGetContactSettingDword(NULL, ModuleName, "40078bg", POPUPCOLOR_BG_40078); + StatusesList[index].colorText = DBGetContactSettingDword(NULL, ModuleName, "40078tx", POPUPCOLOR_TX_40078); + + //Free for chat + index = Index(ID_STATUS_FREECHAT); + StatusesList[index].ID = ID_STATUS_FREECHAT; + StatusesList[index].Icon = SKINICON_STATUS_FREE4CHAT; + lstrcpyn(StatusesList[index].lpzMStatusText, TranslateT("(M) feels talkative!"), MAX_STATUSTEXT); + lstrcpyn(StatusesList[index].lpzFStatusText, TranslateT("(F) feels talkative!"), MAX_STATUSTEXT); + lstrcpyn(StatusesList[index].lpzUStatusText, TranslateT("(U) feels talkative!"), MAX_STATUSTEXT); + lstrcpyn(StatusesList[index].lpzStandardText, TranslateT("Free for chat"), MAX_STANDARDTEXT); + lstrcpynA(StatusesList[index].lpzSkinSoundName, "UserFreeForChat", MAX_SKINSOUNDNAME); + lstrcpynA(StatusesList[index].lpzSkinSoundDesc, "User: Free For Chat", MAX_SKINSOUNDDESC); + lstrcpynA(StatusesList[index].lpzSkinSoundFile, "free4chat.wav", MAX_PATH); +// StatusesList[index].dwProtoFlag = PF2_FREECHAT; + StatusesList[index].colorBack = DBGetContactSettingDword(NULL, ModuleName, "40077bg", POPUPCOLOR_BG_40077); + StatusesList[index].colorText = DBGetContactSettingDword(NULL, ModuleName, "40077tx", POPUPCOLOR_TX_40077); + + //Away + index = Index(ID_STATUS_AWAY); + StatusesList[index].ID = ID_STATUS_AWAY; + StatusesList[index].Icon = SKINICON_STATUS_AWAY; + lstrcpyn(StatusesList[index].lpzMStatusText, TranslateT("(M) went Away"), MAX_STATUSTEXT); + lstrcpyn(StatusesList[index].lpzFStatusText, TranslateT("(F) went Away"), MAX_STATUSTEXT); + lstrcpyn(StatusesList[index].lpzUStatusText, TranslateT("(U) went Away"), MAX_STATUSTEXT); + lstrcpyn(StatusesList[index].lpzStandardText, TranslateT("Away"), MAX_STANDARDTEXT); + lstrcpynA(StatusesList[index].lpzSkinSoundName, "UserAway", MAX_SKINSOUNDNAME); + lstrcpynA(StatusesList[index].lpzSkinSoundDesc, "User: Away", MAX_SKINSOUNDDESC); + lstrcpynA(StatusesList[index].lpzSkinSoundFile, "away.wav", MAX_PATH); +// StatusesList[index].dwProtoFlag = PF2_SHORTAWAY; + StatusesList[index].colorBack = DBGetContactSettingDword(NULL, ModuleName, "40073bg", POPUPCOLOR_BG_40073); + StatusesList[index].colorText = DBGetContactSettingDword(NULL, ModuleName, "40073tx", POPUPCOLOR_TX_40073); + + //NA + index = Index(ID_STATUS_NA); + StatusesList[index].ID = ID_STATUS_NA; + StatusesList[index].Icon = SKINICON_STATUS_NA; + lstrcpyn(StatusesList[index].lpzMStatusText, TranslateT("(M) isn't there anymore!"), MAX_STATUSTEXT); + lstrcpyn(StatusesList[index].lpzFStatusText, TranslateT("(F) isn't there anymore!"), MAX_STATUSTEXT); + lstrcpyn(StatusesList[index].lpzUStatusText, TranslateT("(U) isn't there anymore!"), MAX_STATUSTEXT); + lstrcpyn(StatusesList[index].lpzStandardText, TranslateT("NA"), MAX_STANDARDTEXT); + lstrcpynA(StatusesList[index].lpzSkinSoundName, "UserNA", MAX_SKINSOUNDNAME); + lstrcpynA(StatusesList[index].lpzSkinSoundDesc, "User: Not Available", MAX_SKINSOUNDDESC); + lstrcpynA(StatusesList[index].lpzSkinSoundFile, "na.wav", MAX_PATH); +// StatusesList[index].dwProtoFlag = PF2_LONGAWAY; + StatusesList[index].colorBack = DBGetContactSettingDword(NULL, ModuleName, "40075bg", POPUPCOLOR_BG_40075); + StatusesList[index].colorText = DBGetContactSettingDword(NULL, ModuleName, "40075tx", POPUPCOLOR_TX_40075); + + //Occupied + index = Index(ID_STATUS_OCCUPIED); + StatusesList[index].ID = ID_STATUS_OCCUPIED; + StatusesList[index].Icon = SKINICON_STATUS_OCCUPIED; + lstrcpyn(StatusesList[index].lpzMStatusText, TranslateT("(M) has something else to do."), MAX_STATUSTEXT); + lstrcpyn(StatusesList[index].lpzFStatusText, TranslateT("(F) has something else to do."), MAX_STATUSTEXT); + lstrcpyn(StatusesList[index].lpzUStatusText, TranslateT("(U) has something else to do."), MAX_STATUSTEXT); + lstrcpyn(StatusesList[index].lpzStandardText, TranslateT("Occupied"), MAX_STANDARDTEXT); + lstrcpynA(StatusesList[index].lpzSkinSoundName, "UserOccupied", MAX_SKINSOUNDNAME); + lstrcpynA(StatusesList[index].lpzSkinSoundDesc, "User: Occupied", MAX_SKINSOUNDDESC); + lstrcpynA(StatusesList[index].lpzSkinSoundFile, "occupied.wav", MAX_PATH); +// StatusesList[index].dwProtoFlag = PF2_LIGHTDND; + StatusesList[index].colorBack = DBGetContactSettingDword(NULL, ModuleName, "40076bg", POPUPCOLOR_BG_40076); + StatusesList[index].colorText = DBGetContactSettingDword(NULL, ModuleName, "40076tx", POPUPCOLOR_TX_40076); + + //DND + index = Index(ID_STATUS_DND); + StatusesList[index].ID = ID_STATUS_DND; + StatusesList[index].Icon = SKINICON_STATUS_DND; + lstrcpyn(StatusesList[index].lpzMStatusText, TranslateT("(M) doesn't want to be disturbed!"), MAX_STATUSTEXT); + lstrcpyn(StatusesList[index].lpzFStatusText, TranslateT("(F) doesn't want to be disturbed!"), MAX_STATUSTEXT); + lstrcpyn(StatusesList[index].lpzUStatusText, TranslateT("(U) doesn't want to be disturbed!"), MAX_STATUSTEXT); + lstrcpyn(StatusesList[index].lpzStandardText, TranslateT("DND"), MAX_STANDARDTEXT); + lstrcpynA(StatusesList[index].lpzSkinSoundName, "UserDND", MAX_SKINSOUNDNAME); + lstrcpynA(StatusesList[index].lpzSkinSoundDesc, "User: Do Not Disturb", MAX_SKINSOUNDDESC); + lstrcpynA(StatusesList[index].lpzSkinSoundFile, "dnd.wav", MAX_PATH); +// StatusesList[index].dwProtoFlag = PF2_HEAVYDND; + StatusesList[index].colorBack = DBGetContactSettingDword(NULL, ModuleName, "40074bg", POPUPCOLOR_BG_40074); + StatusesList[index].colorText = DBGetContactSettingDword(NULL, ModuleName, "40074tx", POPUPCOLOR_TX_40074); + + //OutToLunch + index = Index(ID_STATUS_OUTTOLUNCH); + StatusesList[index].ID = ID_STATUS_OUTTOLUNCH; + StatusesList[index].Icon = SKINICON_STATUS_OUTTOLUNCH; + lstrcpyn(StatusesList[index].lpzMStatusText, TranslateT("(M) is eating something"), MAX_STATUSTEXT); + lstrcpyn(StatusesList[index].lpzFStatusText, TranslateT("(F) is eating something"), MAX_STATUSTEXT); + lstrcpyn(StatusesList[index].lpzUStatusText, TranslateT("(U) is eating something"), MAX_STATUSTEXT); + lstrcpyn(StatusesList[index].lpzStandardText, TranslateT("Out to lunch"), MAX_STANDARDTEXT); + lstrcpynA(StatusesList[index].lpzSkinSoundName, "UserOutToLunch", MAX_SKINSOUNDNAME); + lstrcpynA(StatusesList[index].lpzSkinSoundDesc, "User: Out To Lunch", MAX_SKINSOUNDDESC); + lstrcpynA(StatusesList[index].lpzSkinSoundFile, "lunch.wav", MAX_PATH); +// StatusesList[index].dwProtoFlag = PF2_OUTTOLUNCH; + StatusesList[index].colorBack = DBGetContactSettingDword(NULL, ModuleName, "40080bg", POPUPCOLOR_BG_40080); + StatusesList[index].colorText = DBGetContactSettingDword(NULL, ModuleName, "40080tx", POPUPCOLOR_TX_40080); + + //OnThePhone + index = Index(ID_STATUS_ONTHEPHONE); + StatusesList[index].ID = ID_STATUS_ONTHEPHONE; + StatusesList[index].Icon = SKINICON_STATUS_ONTHEPHONE; + lstrcpyn(StatusesList[index].lpzMStatusText, TranslateT("(M) had to answer the phone"), MAX_STATUSTEXT); + lstrcpyn(StatusesList[index].lpzFStatusText, TranslateT("(F) had to answer the phone"), MAX_STATUSTEXT); + lstrcpyn(StatusesList[index].lpzUStatusText, TranslateT("(U) had to answer the phone"), MAX_STATUSTEXT); + lstrcpyn(StatusesList[index].lpzStandardText, TranslateT("On the phone"), MAX_STANDARDTEXT); + lstrcpynA(StatusesList[index].lpzSkinSoundName, "UserOnThePhone", MAX_SKINSOUNDNAME); + lstrcpynA(StatusesList[index].lpzSkinSoundDesc, "User: On The Phone", MAX_SKINSOUNDDESC); + lstrcpynA(StatusesList[index].lpzSkinSoundFile, "phone.wav", MAX_PATH); +// StatusesList[index].dwProtoFlag = PF2_ONTHEPHONE; + StatusesList[index].colorBack = DBGetContactSettingDword(NULL, ModuleName, "40079bg", POPUPCOLOR_BG_40079); + StatusesList[index].colorText = DBGetContactSettingDword(NULL, ModuleName, "40079tx", POPUPCOLOR_TX_40079); +} + +//Function which makes the initializations +static int ModulesLoaded(WPARAM wParam,LPARAM lParam) { + //===== Initializations ===== + //UserInfo detail page + hUserInfoInitialise = HookEvent(ME_USERINFO_INITIALISE, UserInfoInitialise); + + //Contact status change: let's try if here. + hContactStatusChanged = HookEvent(ME_STATUSCHANGE_CONTACTSTATUSCHANGED,ContactStatusChanged); + + //I need this window for the "PopUps on connect" routines. + SecretWnd = CreateWindowEx(WS_EX_TOOLWINDOW,_T("static"),_T("ConnectionTimerWindow"),0, + CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,HWND_DESKTOP, + NULL,hInst,NULL); + //I need this window for the Right Click menu actions +/* hRightClickWnd = CreateWindowEx(WS_EX_TOOLWINDOW,_T("static"),_T("NewStatusNotify_RightClickWindow"),0, + CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,HWND_DESKTOP, + NULL,hInst,NULL); +*/ +// SetWindowLong(hRightClickWnd, GWL_WNDPROC, (LONG)(WNDPROC)RightClickWndProc); + + //PopUps on connect. + { + int protoCount = 0, i = 0; + PROTOCOLDESCRIPTOR **protos = NULL; + CallService(MS_PROTO_ENUMPROTOCOLS, (WPARAM)&protoCount, (LPARAM)&protos); + for (i=0; i < protoCount; i++) + { + if (protos[i]->type == PROTOTYPE_PROTOCOL) + DBWriteContactSettingByte(NULL, ModuleName, protos[i]->szName, PROTO_POPUPS_OFF); + } + } + { //----------------updater support--------------- + Update update = {0}; + char szVersion[16]; + update.cbSize = sizeof(Update); + + update.szComponentName = pluginInfo.shortName; + update.pbVersion = (BYTE *)CreateVersionStringPlugin(&pluginInfo, szVersion); + update.cpbVersion = strlen((char *)update.pbVersion); + // these are the three lines that matter - the archive, the page containing the version string, and the text (or data) + // before the version that we use to locate it on the page + // (note that if the update URL and the version URL point to standard file listing entries, the backend xml + // data will be used to check for updates rather than the actual web page - this is not true for beta urls) +/* update.szUpdateURL = "http://vasilich.org/mim/nsn/nsnw.zip"; + update.szVersionURL = "http://vasilich.org/blog/"; + update.pbVersionPrefix = (BYTE *)"NSNw "; + update.cpbVersionPrefix = strlen((char *)update.pbVersionPrefix); +*/ + update.szBetaVersionURL = "http://vasilich.org/mim/nsn/nsn.txt"; + update.pbBetaVersionPrefix = (BYTE *)"NSN "; +#ifdef UNICODE + update.szBetaUpdateURL = "http://vasilich.org/mim/nsn/nsnw.zip"; +#else + update.szBetaUpdateURL = "http://vasilich.org/mim/nsn/nsn.zip"; +#endif + update.cpbBetaVersionPrefix = strlen((char *)update.pbBetaVersionPrefix); + // do the same for the beta versions of the above struct members if you wish to allow beta updates from another URL + if(ServiceExists(MS_UPDATE_REGISTER)) CallService(MS_UPDATE_REGISTER, 0, (LPARAM)&update); + } + // popup window list + return 0; +} + +static int EnableDisableMenuCommand(WPARAM wParam,LPARAM lParam) { + //We're here to change something, so let's read the actual value. + //TempDisable == FALSE means that right now the popups are enabled + //and if we're here, we want to disable them. + //The icon works this way: + //if the notifications are disabled, the icon hasn't the red circle; + //if the notifications are enabled, the icon has the red circle. + + //This is for compatibility purposes. + CLISTMENUITEM mi = { 0 }; + + mi.cbSize = sizeof(mi); + + if (MyOptions.TempDisable == FALSE) + { + DBWriteContactSettingByte(NULL,ModuleName,"TempDisable",TRUE); + mi.ptszName = _T("Enable status ¬ification"); + mi.hIcon = LoadIcon(hInst,MAKEINTRESOURCE(IDI_MAINMENU_OFF));//IDI_NOPOPUP)); + MyOptions.TempDisable = TRUE; + } + else + { + DBWriteContactSettingByte(NULL,ModuleName,"TempDisable",FALSE); + mi.ptszName = _T("Disable status ¬ification"); + mi.hIcon = LoadIcon(hInst,MAKEINTRESOURCE(IDI_MAINMENU_ON));//IDI_POPUP)); + MyOptions.TempDisable = FALSE; + } + mi.flags = CMIM_ICON | CMIM_NAME | CMIF_TCHAR; + CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)hEnableDisableMenu,(LPARAM)&mi); + return 0; +} + +static int ProtoAck(WPARAM wParam,LPARAM lParam) +{ + ACKDATA *ack=(ACKDATA*)lParam; + + if(ack->type == ACKTYPE_STATUS) + { //We get here on a status change, or a status notification (meaning: old status and new status are just like the same) + WORD newStatus = (WORD)ack->lParam; + WORD oldStatus = (WORD)ack->hProcess; + char * szProtocol = (char*)ack->szModule; + //Now we have the statuses and (a pointer to the string representing) the protocol. + if (oldStatus == newStatus) + return 0; //Useless message. + if (newStatus == ID_STATUS_OFFLINE) + { + //The protocol switched to offline. Disable the popups for this protocol + DBWriteContactSettingByte(NULL, ModuleName, szProtocol, PROTO_POPUPS_OFF); + } + 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. + int idTimer = 0; + idTimer = AddAtomA(szProtocol); + if (idTimer) + { + UINT ConnectTimer; + char TimerProtoName[256] = {0}; + mir_snprintf(TimerProtoName,sizeof(TimerProtoName),"ConnectionTimeout%s",szProtocol); + ConnectTimer = DBGetContactSettingDword(0,ModuleName,TimerProtoName,DBGetContactSettingDword(0,ModuleName,"ConnectionTimeout",10000)); + SetTimer(SecretWnd, idTimer,ConnectTimer, ConnectionTimerProc); + } + else + { //AddAtom failed. + DWORD dwError = GetLastError(); + TCHAR szError[1024] = { 0 }; + wsprintf(szError, _T("AddAtom() failed.\r\n%s\r\n%d\nError: %d."), __TFILE__, __LINE__, dwError); + Log(szError); + } + } + else + { + //The protocol changed in a way we don't care. + } + return 0; + } + else if (ack->type == ACKTYPE_AWAYMSG) //It's an away message + { + if ((ack->hContact != 0) && MyOptions.ReadAwayMsg) //not our own status message and we should show status message in popup + switch (ack->result) + { + case ACKRESULT_SUCCESS: //The away message got read. + { + ReceivedStatusMessage(ack->hContact, TRUE); + break; + } + case ACKRESULT_FAILED: //The away message could not be read. + { + ReceivedStatusMessage(ack->hContact, FALSE); + break; + } + default: + break; + } + return 0; + } + else //It's something we don't need. + return 0; +} + +VOID CALLBACK ConnectionTimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime) +{ + if (uMsg != WM_TIMER) return; + else + { + char szProtocol[MAX_PATH] = { 0 }; + DWORD dwResult = 0; + //We've received a timer message: enable the popups for a specified protocol. + KillTimer(hwnd, idEvent); + dwResult = (DWORD)GetAtomNameA((ATOM)idEvent, szProtocol, sizeof(szProtocol)); + if (dwResult) DBWriteContactSettingByte(NULL, ModuleName, szProtocol, PROTO_POPUPS_ON); + } +} + +static int ContactSendMessage(WPARAM wParam, LPARAM lParam) +{ + HANDLE hContact = (HANDLE)wParam; + + if (ServiceExists("SRMsg/LaunchMessageWindow")) //Conversation is enabled. + CallService("SRMsg/LaunchMessageWindow",(WPARAM)hContact,0); + else //SplitMsgDialog or the default one are enabled. + CallService(MS_MSG_SENDMESSAGE,(WPARAM)hContact,0); + + return 0; +} + +#ifndef WM_AWAYMSG +#define WM_AWAYMSG (WM_USER + 0x0054) +#endif + +BOOL QueryAwayMessage(HWND hWnd, PLUGINDATA * pdp) +{ + char *szProto; + //HANDLE hContact = (HANDLE)CallService(MS_POPUP_GETCONTACT,(WPARAM)hWnd,0); + HANDLE hContact = PUGetContact(hWnd); + +/* if (pdp->hAwayMsgHook) + { //We're already asking for it. +//test UnhookEvent(pdp->hAwayMsgHook); + return FALSE; + } +*/ + szProto=(char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,(WPARAM)hContact,0); + if(szProto) + { + if(CallProtoService(szProto,PS_GETCAPS,PFLAGNUM_1,0)&PF1_MODEMSGRECV) + { + if(CallProtoService(szProto,PS_GETCAPS,PFLAGNUM_3,0)&/*StatusesList[Index((pdp->newStatus))].dwProtoFlag*/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); + return TRUE; + //return FALSE; + } + } + } + return FALSE; +} +void ReceivedStatusMessage(HANDLE hContact, BOOL AckSuccess) +{ + TCHAR tStatMes[MAX_SECONDLINE] = {0}; + TCHAR tNewMsg[MAX_SECONDLINE] = {0}; + PUWinItem PULItem = {0}; + PUWinItem* pPULItem = {0}; + time_t now = 0; + if (AckSuccess) //The away message got read. + { + DBVARIANT dbv = {0}; + if (DBGetContactSettingTString(hContact, "CList", "StatusMsg", &dbv ) == DB_READ_SUCCESS) + { //got Status message + lstrcpyn(tStatMes, dbv.ptszVal, MAX_SECONDLINE); + DBFreeVariant(&dbv); + } + } + else //The away message could not be read. + { + lstrcpyn(tStatMes, TranslateT(""), MAX_SECONDLINE); // send "error reading" to popup + } + time(&now); + PULItem.hContact = hContact; + pPULItem = li.List_Find(PopupList, &PULItem); + if (pPULItem == NULL) // item not found: ------------------------------------------- + { + pPULItem = (PUWinItem*)mir_alloc(sizeof(PULItem)); + pPULItem->hContact = hContact; + pPULItem->hWnd = NULL; + time(&(pPULItem->TimeStamp)); + lstrcpyn(pPULItem->StatMsg, tStatMes, MAX_SECONDLINE); + pPULItem->Status = 0; + li.List_Insert(PopupList, (void*)pPULItem, 0); // - insert item to list + } + else + if (pPULItem->hWnd == NULL) // item found, but without popup: ------------------------------ + { + lstrcpyn(pPULItem->StatMsg, tStatMes, MAX_SECONDLINE); // - put new StatusMessage in this item + time(&(pPULItem->TimeStamp)); + } + else // item found with popup: -------------------------------------- +// if ((pPULItem->TimeStamp+1) < now) // and popup timestamp more than 1 second old + { + DBVARIANT dbv = { 0 }; + if ((DBGetContactSettingTString(hContact, ModuleName, LASTPOPUPTEXT, &dbv) == DB_READ_SUCCESS) ) + { + mir_sntprintf(tNewMsg, MAX_SECONDLINE, _T("%s\n%s"), dbv.ptszVal, tStatMes); + PUChangeTextT(pPULItem->hWnd, tNewMsg); // - send TextChange to it + DBFreeVariant(&dbv); + } + } +} + +void ReceivedAwayMessage(HWND hWnd, LPARAM lParam, PLUGINDATA * pdp) { + + //HANDLE hContact = (HANDLE)CallService(MS_POPUP_GETCONTACT, (WPARAM)hWnd, 0); +// PLUGINDATA *pdp = NULL; + HANDLE hPUContact = PUGetContact(hWnd); + ACKDATA *ack=(ACKDATA*)lParam; + + HANDLE hContact = ack->hContact; + if (!hWnd) return; // We haven't requested this ACK... well, or our window has gone... + pdp = (PLUGINDATA *)PUGetPluginData(hWnd); + if (pdp == (PLUGINDATA *)(-1)) return; // something gone wrong in popup + + if (ack->type != ACKTYPE_AWAYMSG) return; + if (ack->hProcess == pdp->hAwayMsgProcess) { //It's my hProcess, so it's ok to continue. + TCHAR szNewText[MAX_SECONDLINE] = { 0 }; + TCHAR szText [MAX_SECONDLINE] = { 0 }; + char * szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact,(LPARAM)0); + //The first thing we go is removing the hook from the chain to avoid useless calls. +// UnhookEvent(pdp->hAwayMsgHook); +// pdp->hAwayMsgHook = NULL; + //Now we proceed. + if (ack->result == ACKRESULT_SUCCESS) + { //We've the new text. + DBVARIANT dbv = { 0 }; + if ((DBGetContactSettingTString(hContact, ModuleName, LASTPOPUPTEXT, &dbv)) == DB_READ_SUCCESS) + { + mir_sntprintf(szText, SIZEOF(szText), _T("%s\n"), dbv.ptszVal); + DBFreeVariant(&dbv); + } + +#ifdef UNICODE + { + //as we have no unicode in status messages, then we are trying to guess which CP has message + unsigned int CodePage; + //char * szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact,(LPARAM)0); + //first check if there is setting for TabSRMM for defining userCP for that contact + CodePage=(unsigned int)DBGetContactSettingDword(hContact, "Tab_SRMsg", "ANSIcodepage", 5); + if ( (!strncmp(szProto, "ICQ", 3)) && (CodePage==5) ) //check for codepage setting if proto is ICQ + { + CodePage=DBGetContactSettingWord(hContact, szProto, "AnsiCodePage", 5); //for contact + if (CodePage==CP_ACP) + CodePage=(unsigned int)DBGetContactSettingDword(NULL, szProto, "AnsiCodePage", 5); //and global setting + } + if (CodePage==5) + CodePage=(unsigned int)CallService(MS_LANGPACK_GETCODEPAGE,0,0); //at the end, if all previous methods failed, check LangPack CP + MultiByteToWideChar(CodePage, MB_PRECOMPOSED,(char*)ack->lParam, -1, szNewText, MAX_SECONDLINE/sizeof(wchar_t)); + } +#else + lstrcpyn(szNewText, (char*)ack->lParam, MAX_SECONDLINE); +#endif + } + else { //We could not get the new text. + lstrcpyn(szNewText, TranslateT(""), MAX_SECONDLINE); + } + //Now that we have the new text, let's procees and change the second line text. + lstrcat(szText,szNewText); + SendMessage(hWnd, WM_SETREDRAW, FALSE, 0); + PUChangeTextT(hWnd, (TCHAR*)szText); + SendMessage(hWnd, WM_SETREDRAW, TRUE, 0); + return; + } + else + return; +} + +static BOOL StatusHasAwayMessage(char * szProto, int status) +{ + if (szProto != NULL) + { + unsigned long iSUpportsSM = (unsigned long)CallProtoService(szProto, PS_GETCAPS, (WPARAM)PFLAGNUM_3,(LPARAM)0); + switch (status) { + case ID_STATUS_AWAY: + return (iSUpportsSM & PF2_SHORTAWAY)?TRUE:FALSE; + break; + case ID_STATUS_NA: + return (iSUpportsSM & PF2_LONGAWAY)?TRUE:FALSE; + break; + case ID_STATUS_OCCUPIED: + return (iSUpportsSM & PF2_LIGHTDND)?TRUE:FALSE; + break; + case ID_STATUS_DND: + return (iSUpportsSM & PF2_HEAVYDND)?TRUE:FALSE; + break; + case ID_STATUS_FREECHAT: + return (iSUpportsSM & PF2_FREECHAT)?TRUE:FALSE; + break; + case ID_STATUS_ONTHEPHONE: + return (iSUpportsSM & PF2_ONTHEPHONE)?TRUE:FALSE; + break; + case ID_STATUS_OUTTOLUNCH: + return (iSUpportsSM & PF2_OUTTOLUNCH)?TRUE:FALSE; + break; + case ID_STATUS_ONLINE: + return (iSUpportsSM & PF2_ONLINE)?TRUE:FALSE; + break; + default: + return 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; + } +} + +/*static LRESULT CALLBACK RightClickWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { + static HANDLE hContact; + switch (uMsg) { + case UM_PROCESS: + CallService(MS_CLIST_MENUPROCESSCOMMAND, wParam, lParam); + return 0; + case UM_SETCONTACT: + hContact = (HANDLE)wParam; + return FALSE; + case WM_COMMAND: + if(CallService(MS_CLIST_MENUPROCESSCOMMAND, + MAKEWPARAM(LOWORD(wParam),MPCF_CONTACTMENU),(LPARAM)hContact)) + break; + return FALSE; + 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); + default: + return DefWindowProc(hWnd, uMsg, wParam, lParam);//FALSE; + } + return DefWindowProc(hWnd, uMsg, wParam, lParam);//FALSE; +} +*/ +void installMainMenuItem() { + CLISTMENUITEM mi = { 0 }; + + hServiceMenu = (HANDLE)CreateServiceFunction("NewStatusNotify/EnableDisableMenuCommand",EnableDisableMenuCommand); + mi.cbSize=sizeof(mi); + //mi.position=-0x7FFFFFFF; + mi.flags = CMIF_TCHAR; + if (DBGetContactSettingByte(NULL,ModuleName,"TempDisable",DEFAULT_TEMPDISABLE)==TRUE) //(MyOptions.TempDisable) + { + mi.ptszName = _T("Enable status ¬ification"); + mi.hIcon = LoadIcon(hInst,MAKEINTRESOURCE(IDI_MAINMENU_OFF)); //IDI_NOPOPUP)); + } + else + { + mi.ptszName = _T("Disable status ¬ification"); + mi.hIcon = LoadIcon(hInst,MAKEINTRESOURCE(IDI_MAINMENU_ON)); //IDI_POPUP)); + } + mi.pszService="NewStatusNotify/EnableDisableMenuCommand"; + //mi.ptszPopupName = NULL; //Translate("PopUps"); + hEnableDisableMenu = CallService(MS_CLIST_ADDMAINMENUITEM,0,(LPARAM)&mi); +} + +void PlaySpeakerBeep(void) +{ + OSVERSIONINFO osvi = { 0 }; + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&osvi); + if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) //We're on an NT platform + Beep(BEEP_HZ_DEFAULT,BEEP_DURATION_DEFAULT); //BEEP_HZ_DEFAULT Hz, BEEP_DURATION_DEFAULT milliseconds + else //We aren't on a NT platform. + MessageBeep(0xFFFFFFFF); //Standard beep through speaker +} + +static int OpenUserDetails(WPARAM wParam, LPARAM lParam) +{ + POINT pMouseCoord = {0}; + if ((GetCursorPos(&pMouseCoord)) && (WindowFromPoint (pMouseCoord)==hCListClone) ) + {//ugly hack to check if dblclick was on our CList Clone. hClistClone is assigned in appropriate Options Proc + //Now that we've changed the "LastTab" info, we can show the dialog. + DBWriteContactSettingTString(NULL,"UserInfo","LastTab", TranslateT(NAME_OF_UIPAGE)); + {//support of stupid settings form of UserInfoEx plugin + TCHAR tBrackets[MAX_PATH] = _T("{"); + _tcscat(tBrackets, TranslateT(NAME_OF_UIPAGE)); + _tcscat(tBrackets, _T("}")); + DBWriteContactSettingTString(NULL,"UserInfoEx","LastItem", tBrackets); + } + CallService(MS_USERINFO_SHOWDIALOG, (WPARAM)(HANDLE)wParam, 0); + return 1; //return nonzero means we don't need to show dialog window + } + else + return 0; // default handler (open dialog window) +} diff --git a/newstatusnotify/newstatusnotify.h b/newstatusnotify/newstatusnotify.h new file mode 100644 index 0000000..a24e94d --- /dev/null +++ b/newstatusnotify/newstatusnotify.h @@ -0,0 +1,118 @@ +/* +=============================================================================== + NewStatusNotify plugin + +This plugin notifies you when a contact changes his/hers status with a PopUp. +You can customize its look (style of popup, font, text...) and behaviour (the +position in the screen, the time to live, the action on a mouse click). + +This file contains: +- definitions, +- structures, +- macros +which can be useful to different modules (example EventNotify) but mainly +useful to me in order to split my Plugin on different files :-) + +Written by: Hrk (Luca Santarelli) (2002-2004), Vasilich (2005-2008) + +Miranda IM can be found here: +http://miranda-im.org/ + +=============================================================================== +*/ + +#ifndef NEWSTATUSNOTIFY_H +#define NEWSTATUSNOTIFY_H + +#include "commonheaders.h" +#include "res\resource.h" + +#define NAME_OF_UIPAGE "Status Notify" + +#define LASTPOPUPTEXT "LastPopupText" +#define MAX_STATUSTEXT 36 +#define MAX_STANDARDTEXT 36 +#define MAX_SKINSOUNDNAME 36 +#define MAX_SKINSOUNDDESC 36 + +#define MAX_PROTONAMELEN 64 + +//=== Objects ===== +//This one is used to easily tie status id, icon, text... +typedef struct tagaStatus{ + 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]; + DWORD dwProtoFlag; + COLORREF colorBack; + COLORREF colorText; +} aStatus; + +#define Index(ID_STATUS) ID_STATUS - 40071 +#define ID_STATUS_MIN ID_STATUS_OFFLINE +#define ID_STATUS_MAX ID_STATUS_OUTTOLUNCH + +#define byCOLOR_OWN 0x1 +#define byCOLOR_WINDOWS 0x2 +#define byCOLOR_POPUP 0x3 +#define DEFAULT_COLORS byCOLOR_OWN + +//===== Options flags +typedef struct tagMYOPTIONS { + BYTE Colors; + //BYTE UseWinColors; + BYTE UseDullText; + BYTE ReadAwayMsg; + BYTE ShowPreviousStatus; + BYTE TempDisable; + BYTE AutoDisable; + BYTE FromOffline; + BYTE FromOfflinePopup; + BYTE EnableSoundForMyCurrentStatus; + BYTE EnablePopupForMyCurrentStatus; + BYTE UseSpeaker; + BYTE AvoidClipping; + BYTE HiddenContactsToo; + BYTE Log; + BYTE UseIndSnd; + BYTE ShowGroup; + BYTE BlinkIcon; + BYTE BlinkIcon_Status; + BYTE byTimeout; + int iTimeout; +} MYOPTIONS; + +#define DB_READ_SUCCESS 0 +#define DB_READ_FAIL -1 + +typedef struct tagPLUGINDATA { + WORD newStatus; + WORD oldStatus; + HANDLE hAwayMsgProcess; + HANDLE hAwayMsgHook; +} PLUGINDATA; + +typedef struct tagPUWinItem +{ + HANDLE hWnd; + TCHAR StatMsg[MAX_SECONDLINE]; + HANDLE hContact; + int Status; + time_t TimeStamp; +} PUWinItem; + +#ifndef MIID_NSN +#ifdef _UNICODE +#define MIID_NSN { 0x481e45c3, 0xde03, 0x4ac6, { 0x80, 0x7b, 0xe3, 0x6d, 0xa2, 0xc8, 0xbb, 0x31 } } // {481E45C3-DE03-4ac6-807B-E36DA2C8BB31} +#else +#define MIID_NSN { 0x90c33425, 0x3bcf, 0x4aeb, { 0xa7, 0xc9, 0x33, 0x64, 0x6b, 0x2f, 0x65, 0xec } } // {90C33425-3BCF-4aeb-A7C9-33646B2F65EC} +#endif +#endif + +#endif //NEWSTATUSNOTIFY_H diff --git a/newstatusnotify/res/NewStatusNotify.rc b/newstatusnotify/res/NewStatusNotify.rc new file mode 100644 index 0000000..d28fc8f --- /dev/null +++ b/newstatusnotify/res/NewStatusNotify.rc @@ -0,0 +1,309 @@ +// 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 + +///////////////////////////////////////////////////////////////////////////// +// Neutral resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU) +#ifdef _WIN32 +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL +#pragma code_page(1251) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_NSN_OPT, DIALOG + BEGIN + LEFTMARGIN, 5 + RIGHTMARGIN, 309 + TOPMARGIN, 5 + BOTTOMMARGIN, 218 + END + + IDD_INFO_SOUNDS, DIALOG + BEGIN + LEFTMARGIN, 5 + RIGHTMARGIN, 217 + BOTTOMMARGIN, 155 + END + + IDD_AUTODISABLE, DIALOG + BEGIN + LEFTMARGIN, 5 + RIGHTMARGIN, 218 + TOPMARGIN, 5 + BOTTOMMARGIN, 159 + END + + IDD_NSN_OPT_EVENTS_ENABLE, DIALOG + BEGIN + VERTGUIDE, 6 + VERTGUIDE, 306 + END + + IDD_NSN_OPT_POPUP, DIALOG + BEGIN + RIGHTMARGIN, 308 + VERTGUIDE, 6 + VERTGUIDE, 163 + VERTGUIDE, 288 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_NSN_OPT DIALOGEX 0, 0, 314, 223 +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,10,4,292,55,WS_GROUP + CONTROL "Online",IDC_CHK_ONLINE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,14,77,10 + CONTROL "Offline",IDC_CHK_OFFLINE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,109,14,77,10 + CONTROL "Invisible",IDC_CHK_INVISIBLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,214,14,77,10 + CONTROL "Free for chat",IDC_CHK_FREECHAT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,24,77,10 + CONTROL "Away",IDC_CHK_AWAY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,109,24,77,10 + CONTROL "NA",IDC_CHK_NA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,214,24,77,10 + CONTROL "Occupied",IDC_CHK_OCCUPIED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,34,77,10 + CONTROL "DND",IDC_CHK_DND,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,109,34,77,10 + CONTROL "Out to lunch",IDC_CHK_OUTTOLUNCH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,214,34,77,10 + CONTROL "On the phone",IDC_CHK_ONTHEPHONE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,44,77,10 + CONTROL "Always when changing from offline",IDC_CHK_FROMOFFLINE, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,109,44,163,10 + GROUPBOX "Plugin activation",IDC_STATIC,10,62,292,89,WS_GROUP + CONTROL "Automatically turn off PopUps and Sounds on status change",IDC_AUTODISABLE, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,72,219,10 + PUSHBUTTON "Configure",IDC_CONFIGUREAUTODISABLE,245,71,50,14 + CONTROL "Temporarily disable NewStatusNotify (disables popups and sounds)",IDC_TEMPDISABLE, + "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,15,85,278,10 + CONTROL "Put an item in the main menu to easily enable/disable the plugin",IDC_SHOWDISABLEMENU, + "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,15,98,278,10 + CONTROL "Show PopUps when I connect",IDC_SHOWONCONNECTION,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,160,111,140,10 + CONTROL "Do not warn me for people not in my Contact List",IDC_HIDDENCONTACTSTOO, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,124,274,10 + CONTROL "Blink icon in the system tray",IDC_BLINKICON,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,137,140,10 + CONTROL "Use status icon",IDC_BLINKICON_STATUS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,159,137,137,10 + GROUPBOX "Sound options",IDC_STATIC,10,175,292,39,WS_GROUP + CONTROL "Use Internal &Speaker",IDC_SPEAKER,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,15,184,99,13 + CONTROL "&Avoid clipping",IDC_AVOIDCLIPPING,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,15,196,99,13 + LTEXT "To select the sounds to play, click on ""Sounds"" in the menu on the left.",IDC_STATIC,161,181,135,28,NOT WS_GROUP + CONTROL "Use individual sounds",IDC_USEINDIVSOUNDS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,111,141,10 + GROUPBOX "Log",IDC_STATIC,9,152,292,22 + CONTROL "&Log status changes to file",IDC_LOG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,161,143,10 + EDITTEXT IDC_LOGFILE,162,159,135,12,ES_AUTOHSCROLL +END + +IDD_INFO_SOUNDS DIALOGEX 0, 0, 222, 156 +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,5,1,212,111,WS_EX_CLIENTEDGE + PUSHBUTTON "&Change",IDC_CHANGE,24,115,50,14 + PUSHBUTTON "&Preview",IDC_PREVIEW,86,115,50,14 + PUSHBUTTON "&Delete",IDC_DELETE,149,115,50,14 + CONTROL "with sounds",IDC_CHECK_NOTIFYSOUNDS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,139,98,10 + CONTROL "with popups",IDC_CHECK_NOTIFYPOPUPS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,113,139,98,10 + GROUPBOX "Status Notify",IDC_STATIC,5,130,212,23 + 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,31,212,56 +END + +IDD_AUTODISABLE DIALOGEX 0, 0, 223, 164 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_NOFAILCREATE | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +CAPTION "NewStatusNotify" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + CONTROL "Online",IDC_CHK_ONLINE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,40,77,10 + CONTROL "Invisible",IDC_CHK_INVISIBLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,50,77,10 + CONTROL "Free for chat",IDC_CHK_FREECHAT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,61,77,10 + CONTROL "Away",IDC_CHK_AWAY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,71,77,10 + CONTROL "NA",IDC_CHK_NA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,81,77,10 + CONTROL "Occupied",IDC_CHK_OCCUPIED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,91,77,10 + CONTROL "DND",IDC_CHK_DND,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,101,77,10 + CONTROL "Out to lunch",IDC_CHK_OUTTOLUNCH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,122,77,10 + CONTROL "On the phone",IDC_CHK_ONTHEPHONE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,111,77,10 + LTEXT "Automatically disable sounds or popups when I change to:",IDC_STATIC,17,10,197,16,SS_NOPREFIX + PUSHBUTTON "OK",IDC_OK,113,145,50,14 + GROUPBOX "PopUps",IDC_STATIC,10,28,92,111 + CONTROL "Online",IDC_CHK_ONLINE2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,130,41,77,10 + CONTROL "Invisible",IDC_CHK_INVISIBLE2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,130,51,77,10 + CONTROL "Free for chat",IDC_CHK_FREECHAT2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,130,62,77,10 + CONTROL "Away",IDC_CHK_AWAY2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,130,72,77,10 + CONTROL "NA",IDC_CHK_NA2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,130,82,77,10 + CONTROL "Occupied",IDC_CHK_OCCUPIED2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,130,92,77,10 + CONTROL "DND",IDC_CHK_DND2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,130,102,77,10 + CONTROL "Out to lunch",IDC_CHK_OUTTOLUNCH2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,130,123,77,10 + CONTROL "On the phone",IDC_CHK_ONTHEPHONE2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,130,112,77,10 + GROUPBOX "Sounds",IDC_STATIC,122,29,92,111 + PUSHBUTTON "Cancel",IDC_CANCEL,168,145,50,14 +END + +IDD_NSN_OPT_EVENTS_ENABLE DIALOGEX 0, 0, 314, 240 +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,6,14,300,188,WS_EX_CLIENTEDGE + LTEXT "Enable sound notifications for this contact",IDC_STATIC,30,209,237,9 + LTEXT "Enable popup notifications for this contact",IDC_STATIC,30,224,235,9 + ICON IDI_SOUND,IDC_SOUNDICON,6,203,21,20,SS_CENTERIMAGE | SS_REALSIZEIMAGE,WS_EX_TRANSPARENT + ICON IDI_POPUP,IDC_POPUPICON,6,218,21,20,SS_CENTERIMAGE | SS_REALSIZEIMAGE,WS_EX_TRANSPARENT + GROUPBOX "Contact status change notifications",IDC_STATIC,0,0,314,240 +END + +IDD_NSN_OPT_POPUP DIALOGEX 0, 0, 309, 238 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + GROUPBOX "Colours",IDC_STATIC,86,9,59,159 + CTEXT "Back",IDC_STATIC,90,17,24,8 + CTEXT "Text",IDC_STATIC,116,17,24,8 + CONTROL "",IDC_OFFLINE_BG,"ColourPicker",WS_TABSTOP,90,26,24,12 + CONTROL "",IDC_OFFLINE_TX,"ColourPicker",WS_TABSTOP,116,26,24,12 + CONTROL "",IDC_ONLINE_BG,"ColourPicker",WS_TABSTOP,90,40,24,12 + CONTROL "",IDC_ONLINE_TX,"ColourPicker",WS_TABSTOP,116,40,24,12 + CONTROL "",IDC_AWAY_BG,"ColourPicker",WS_TABSTOP,90,54,24,12 + CONTROL "",IDC_AWAY_TX,"ColourPicker",WS_TABSTOP,116,54,24,12 + CONTROL "",IDC_NA_BG,"ColourPicker",WS_TABSTOP,90,68,24,12 + CONTROL "",IDC_NA_TX,"ColourPicker",WS_TABSTOP,116,68,24,12 + CONTROL "",IDC_OCCUPIED_BG,"ColourPicker",WS_TABSTOP,90,82,24,12 + CONTROL "",IDC_OCCUPIED_TX,"ColourPicker",WS_TABSTOP,116,82,24,12 + CONTROL "",IDC_DND_BG,"ColourPicker",WS_TABSTOP,90,96,24,12 + CONTROL "",IDC_DND_TX,"ColourPicker",WS_TABSTOP,116,96,24,12 + CONTROL "",IDC_FREEFORCHAT_BG,"ColourPicker",WS_TABSTOP,90,110,24,12 + CONTROL "",IDC_FREEFORCHAT_TX,"ColourPicker",WS_TABSTOP,116,110,24,12 + CONTROL "",IDC_INVISIBLE_BG,"ColourPicker",WS_TABSTOP,90,124,24,12 + CONTROL "",IDC_INVISIBLE_TX,"ColourPicker",WS_TABSTOP,116,124,24,12 + CONTROL "",IDC_OUTTOLUNCH_BG,"ColourPicker",WS_TABSTOP,90,138,24,12 + CONTROL "",IDC_OUTTOLUNCH_TX,"ColourPicker",WS_TABSTOP,116,138,24,12 + CONTROL "",IDC_ONTHEPHONE_BG,"ColourPicker",WS_TABSTOP,90,152,24,12 + CONTROL "",IDC_ONTHEPHONE_TX,"ColourPicker",WS_TABSTOP,116,152,24,12 + GROUPBOX "Colours",IDC_STATIC,0,189,151,46,WS_GROUP + CONTROL "Use cus&tom colors",IDC_USEOWNCOLORS,"Button",BS_AUTORADIOBUTTON | BS_MULTILINE | BS_NOTIFY | WS_TABSTOP,8,196,138,13 + CONTROL "Use &Windows colours",IDC_USEWINCOLORS,"Button",BS_AUTORADIOBUTTON | BS_MULTILINE | BS_NOTIFY | WS_TABSTOP,8,220,138,13 + CONTROL "Use Pop&up colours",IDC_USEPOPUPCOLORS,"Button",BS_AUTORADIOBUTTON | BS_MULTILINE | BS_NOTIFY | WS_TABSTOP,8,208,138,13 + GROUPBOX "Text",IDC_STATIC,155,76,145,59,WS_GROUP + CONTROL "Use standard &descriptions",IDC_CHK_USEDULLTEXT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,163,83,125,13 + CONTROL "Read status &message",IDC_READAWAYMSG,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,163,119,125,13 + CONTROL "Show &previous status too",IDC_SHOWPREVIOUSSTATUS, + "Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,163,107,125,13 + GROUPBOX "Timeout",IDC_STATIC,156,0,146,46 + CONTROL "&From PopUp plugin",IDC_TIMEOUT_POPUP,"Button",BS_AUTORADIOBUTTON,161,9,127,10 + CONTROL "&Custom",IDC_TIMEOUT_CUSTOM,"Button",BS_AUTORADIOBUTTON,161,21,72,10 + EDITTEXT IDC_TIMEOUT_VALUE,267,19,21,14,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "P&ermanent",IDC_TIMEOUT_PERMANENT,"Button",BS_AUTORADIOBUTTON,161,33,127,10 + PUSHBUTTON "Prev&iew",IDC_PREVIEW,200,208,57,12 + GROUPBOX "Popups on contact status change to:",IDC_STATIC,0,0,152,189,WS_GROUP + CONTROL "Online",IDC_CHK_PONLINE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,41,77,10 + CONTROL "Offline",IDC_CHK_POFFLINE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,27,77,10 + CONTROL "Invisible",IDC_CHK_PINVISIBLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,125,77,10 + CONTROL "Free for chat",IDC_CHK_PFREECHAT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,111,77,10 + CONTROL "Away",IDC_CHK_PAWAY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,55,77,10 + CONTROL "NA",IDC_CHK_PNA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,69,77,10 + CONTROL "Occupied",IDC_CHK_POCCUPIED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,83,77,10 + CONTROL "DND",IDC_CHK_PDND,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,97,77,10 + CONTROL "Out to lunch",IDC_CHK_POUTTOLUNCH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,139,77,10 + CONTROL "On the phone",IDC_CHK_PONTHEPHONE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,153,77,10 + CONTROL "Always when changing from offline",IDC_CHK_PFROMOFFLINE, + "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,6,165,81,18 + GROUPBOX "On left click",IDC_STATIC,155,139,70,50,WS_GROUP + CONTROL "Dismiss",IDC_LC_DISMISS,"Button",BS_AUTORADIOBUTTON | BS_LEFT | BS_VCENTER | BS_MULTILINE | BS_NOTIFY | WS_GROUP | WS_TABSTOP,163,147,52,18 + CONTROL "Open message",IDC_LC_OPENMSG,"Button",BS_AUTORADIOBUTTON | BS_LEFT | BS_VCENTER | BS_MULTILINE | BS_NOTIFY | WS_TABSTOP,163,166,52,18 + GROUPBOX "On right click",IDC_STATIC,231,139,70,50,WS_GROUP + CONTROL "Dismiss",IDC_RC_DISMISS,"Button",BS_AUTORADIOBUTTON | BS_LEFT | BS_VCENTER | BS_MULTILINE | BS_NOTIFY | WS_GROUP | WS_TABSTOP,243,147,52,18 + CONTROL "Open user menu",IDC_RC_USERMENU,"Button",BS_AUTORADIOBUTTON | BS_LEFT | BS_VCENTER | BS_MULTILINE | BS_NOTIFY | WS_TABSTOP,243,166,52,18 + GROUPBOX "Popup title",IDC_STATIC,155,48,146,25 + CONTROL "Show contact &group name",IDC_SHOWGROUP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,163,58,125,9 + CONTROL "Use &alternative descriptions",IDC_CHK_SHOWALTDESCS, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,163,95,125,13 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_POPUP ICON "popup.ico" +IDI_SOUND ICON "sound.ico" +IDI_MAINMENU_OFF ICON "main_off.ico" +IDI_MAINMENU_ON ICON "main_on.ico" + +#endif // Neutral resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// German (Germany) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) +#ifdef _WIN32 +LANGUAGE LANG_GERMAN, SUBLANG_GERMAN +#pragma code_page(1252) +#endif //_WIN32 + +#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 // German (Germany) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/newstatusnotify/res/main_off.ico b/newstatusnotify/res/main_off.ico new file mode 100644 index 0000000..c5543f9 Binary files /dev/null and b/newstatusnotify/res/main_off.ico differ diff --git a/newstatusnotify/res/main_on.ico b/newstatusnotify/res/main_on.ico new file mode 100644 index 0000000..6fb625b Binary files /dev/null and b/newstatusnotify/res/main_on.ico differ diff --git a/newstatusnotify/res/popup.ico b/newstatusnotify/res/popup.ico new file mode 100644 index 0000000..da4e6af Binary files /dev/null and b/newstatusnotify/res/popup.ico differ diff --git a/newstatusnotify/res/resource.h b/newstatusnotify/res/resource.h new file mode 100644 index 0000000..d54eefc --- /dev/null +++ b/newstatusnotify/res/resource.h @@ -0,0 +1,123 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by resource.rc +// +#define IDD_INFO_SOUNDS 105 +#define IDD_NSN_OPT 106 +#define IDD_AUTODISABLE 113 +#define IDD_NSN_OPT_EVENTS_ENABLE 114 +#define IDD_NSN_OPT_POPUP 115 +#define IDI_POPUP 117 +#define IDI_SOUND 118 +#define IDI_MAINMENU_OFF 123 +#define IDI_MAINMENU_ON 124 +#define IDC_SOUND 1004 +#define IDC_SPEAKER 1005 +#define IDC_TEMPDISABLE 1006 +#define IDC_USEWINCOLORS 1007 +#define IDC_SHOWDISABLEMENU 1008 +#define IDC_CHK_USEDULLTEXT 1009 +#define IDC_AVOIDCLIPPING 1010 +#define IDC_READAWAYMSG 1011 +#define IDC_SHOWPREVIOUSSTATUS 1012 +#define IDC_USEPOPUPCOLORS 1013 +#define IDC_PREVIEW 1030 +#define IDC_CHANGE 1031 +#define IDC_DELETE 1032 +#define IDC_LC_DISMISS 1033 +#define IDC_RC_DISMISS 1034 +#define IDC_INDSNDLIST 1044 +#define IDC_LC_OPENMSG 1045 +#define IDC_RC_USERMENU 1046 +#define IDC_DEBUG 1050 +#define IDC_SHOWONCONNECTION 1051 +#define IDC_HIDDENCONTACTSTOO 1052 +#define IDC_USEINDIVSOUNDS 1053 +#define IDC_APPLY 1054 +#define IDC_OK 1055 +#define IDC_CANCEL 1056 +#define IDC_CONFIGUREAUTODISABLE 1057 +#define IDC_RESTOREDEFAULTS 1058 +#define IDC_CLCLIST 1059 +#define IDC_AUTODISABLE 1060 +#define IDC_LOG 1061 +#define IDC_LOGFILE 1062 +#define IDC_TIMEOUT_POPUP 1063 +#define IDC_TIMEOUT_CUSTOM 1064 +#define IDC_TIMEOUT_PERMANENT 1065 +#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_NOTIFYPOPUP 1072 +#define IDC_CHECK_NOTIFYPOPUPS 1073 +#define IDC_TEXT_ENABLE_IS 1074 +#define IDC_SHOWGROUP 1075 +#define IDC_USEOWNCOLORS 1076 +#define IDC_CHK_SHOWALTDESCS 1077 +#define IDC_CHK_POFFLINE 40071 +#define IDC_CHK_OFFLINE 40071 +#define IDC_CHK_PONLINE 40072 +#define IDC_CHK_ONLINE 40072 +#define IDC_CHK_PAWAY 40073 +#define IDC_CHK_AWAY 40073 +#define IDC_CHK_PDND 40074 +#define IDC_CHK_DND 40074 +#define IDC_CHK_PNA 40075 +#define IDC_CHK_NA 40075 +#define IDC_CHK_POCCUPIED 40076 +#define IDC_CHK_OCCUPIED 40076 +#define IDC_CHK_PFREECHAT 40077 +#define IDC_CHK_FREECHAT 40077 +#define IDC_CHK_PINVISIBLE 40078 +#define IDC_CHK_INVISIBLE 40078 +#define IDC_CHK_PONTHEPHONE 40079 +#define IDC_CHK_ONTHEPHONE 40079 +#define IDC_CHK_POUTTOLUNCH 40080 +#define IDC_CHK_OUTTOLUNCH 40080 +#define IDC_CHK_PFROMOFFLINE 40081 +#define IDC_CHK_FROMOFFLINE 40081 +#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_OFFLINE_BG 42071 +#define IDC_CHK_OFFLINE2 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_NSN_ICON -1 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 126 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1086 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/newstatusnotify/res/resource.rc b/newstatusnotify/res/resource.rc new file mode 100644 index 0000000..1dc1f7d --- /dev/null +++ b/newstatusnotify/res/resource.rc @@ -0,0 +1,2 @@ +#include "newstatusnotify.rc" +#include "version.rc" diff --git a/newstatusnotify/res/sound.ico b/newstatusnotify/res/sound.ico new file mode 100644 index 0000000..6a9c137 Binary files /dev/null and b/newstatusnotify/res/sound.ico differ diff --git a/newstatusnotify/res/version.h b/newstatusnotify/res/version.h new file mode 100644 index 0000000..7de54b7 --- /dev/null +++ b/newstatusnotify/res/version.h @@ -0,0 +1,41 @@ +// Set the version number here - it will affect the version resource and the version field of the pluginInfo structure +// (Be careful that you don't have the resource file open when you change this and rebuild, otherwise the changes may not +// take effect within the version resource) +#define __MAJOR_VERSION 1 +#define __MINOR_VERSION 1 +#define __RELEASE_NUM 2 +#define __BUILD_NUM 8 + +#define __PROD_MAJOR_VERSION 0 +#define __PROD_MINOR_VERSION 8 +#define __PROD_RELEASE_NUM 0 +#define __PROD_BUILD_NUM 0 + +#define __STRINGIFY_IMPL(x) #x +#define __STRINGIFY(x) __STRINGIFY_IMPL(x) + +#define __FILEVERSION_STRING __MAJOR_VERSION,__MINOR_VERSION,__RELEASE_NUM,__BUILD_NUM +#define __FILEVERSION_STRING_DOTS __MAJOR_VERSION.__MINOR_VERSION.__RELEASE_NUM.__BUILD_NUM +#define __VERSION_STRING __STRINGIFY(__FILEVERSION_STRING_DOTS) + +#define __PRODVERSION_STRING __PROD_MAJOR_VERSION,__PROD_MINOR_VERSION,__PROD_RELEASE_NUM,__PROD_BUILD_NUM +#define __PRODVERSION_STRING_DOTS __PROD_MAJOR_VERSION.__PROD_MINOR_VERSION.__PROD_RELEASE_NUM.__PROD_BUILD_NUM +#define __PROD_VERSION_STRING __STRINGIFY(__PRODVERSION_STRING_DOTS+) + +/* +#ifdef _UNICODE +#define UNICODEAWARE_STR " (Unicode)" +#else +#define UNICODEAWARE_STR "" +#endif +#define __PLUGIN_NAME "NewStatusNotify" UNICODEAWARE_STR +*/ +#define __PLUGIN_NAME "NewStatusNotify" + +#define __FILENAME "NewStatusNotify.dll" + +#define __DESC "Notifies you when a contact changes his/her status." +#define __AUTHOR "Luca Santarelli, Vasilich" +#define __AUTHOREMAIL "abakumoff {at} mail {dot} ru" +#define __AUTHORWEB "http://vasilich.org/blog" +#define __COPYRIGHT "© 2001-2004 Luca Santarelli, 2005-2009 Vasilich" diff --git a/newstatusnotify/res/version.rc b/newstatusnotify/res/version.rc new file mode 100644 index 0000000..203f66d --- /dev/null +++ b/newstatusnotify/res/version.rc @@ -0,0 +1,36 @@ + +#include +#include "version.h" + +VS_VERSION_INFO VERSIONINFO + FILEVERSION __FILEVERSION_STRING + PRODUCTVERSION __PRODVERSION_STRING + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "Author", __AUTHOR + VALUE "FileDescription", __DESC + VALUE "InternalName", __PLUGIN_NAME + VALUE "LegalCopyright", __COPYRIGHT + VALUE "OriginalFilename", __FILENAME + VALUE "FileVersion", __VERSION_STRING + VALUE "ProductName", "Miranda IM" + VALUE "ProductVersion", __PROD_VERSION_STRING + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1200 + END +END -- cgit v1.2.3