diff options
-rw-r--r-- | yapp/YAPP.mdsp | 109 | ||||
-rw-r--r-- | yapp/common.h | 69 | ||||
-rw-r--r-- | yapp/docs/licence_YAPP.txt | 6 | ||||
-rw-r--r-- | yapp/docs/m_notify.h | 177 | ||||
-rw-r--r-- | yapp/docs/m_popup.h | 339 | ||||
-rw-r--r-- | yapp/docs/m_popup2.h | 29 | ||||
-rw-r--r-- | yapp/message_pump.cpp | 160 | ||||
-rw-r--r-- | yapp/message_pump.h | 22 | ||||
-rw-r--r-- | yapp/notify.h | 7 | ||||
-rw-r--r-- | yapp/notify_imp.cpp | 125 | ||||
-rw-r--r-- | yapp/options.cpp | 394 | ||||
-rw-r--r-- | yapp/options.h | 36 | ||||
-rw-r--r-- | yapp/popup_history.cpp | 393 | ||||
-rw-r--r-- | yapp/popup_history.h | 59 | ||||
-rw-r--r-- | yapp/popups2.cpp | 238 | ||||
-rw-r--r-- | yapp/popups2.h | 12 | ||||
-rw-r--r-- | yapp/popups2.rc | 170 | ||||
-rw-r--r-- | yapp/popups2.sln | 19 | ||||
-rw-r--r-- | yapp/popups2.vcproj | 377 | ||||
-rw-r--r-- | yapp/popwin.cpp | 760 | ||||
-rw-r--r-- | yapp/popwin.h | 27 | ||||
-rw-r--r-- | yapp/resource.h | 68 | ||||
-rw-r--r-- | yapp/resource.rc | 6 | ||||
-rw-r--r-- | yapp/services.cpp | 363 | ||||
-rw-r--r-- | yapp/services.h | 25 | ||||
-rw-r--r-- | yapp/version.h | 23 | ||||
-rw-r--r-- | yapp/version.rc | 34 |
27 files changed, 4047 insertions, 0 deletions
diff --git a/yapp/YAPP.mdsp b/yapp/YAPP.mdsp new file mode 100644 index 0000000..4254ce9 --- /dev/null +++ b/yapp/YAPP.mdsp @@ -0,0 +1,109 @@ +[Project]
+name=YAPP
+type=2
+defaultConfig=0
+
+
+[Debug]
+// compiler
+workingDirectory=
+arguments=
+intermediateFilesDirectory=Debug
+outputFilesDirectory=Debug
+compilerPreprocessor=_UNICODE,UNICODE,POPUPS2_EXPORTS
+extraCompilerOptions=
+compilerIncludeDirectory=..\..\include
+noWarning=0
+defaultWarning=0
+allWarning=1
+extraWarning=0
+isoWarning=0
+warningsAsErrors=0
+debugType=1
+debugLevel=2
+exceptionEnabled=1
+runtimeTypeEnabled=1
+optimizeLevel=0
+
+// linker
+libraryPath=
+outputFilename=Debug\yapp.dll
+libraries=unicows,gdi32,comctl32
+extraLinkerOptions=
+ignoreStartupFile=0
+ignoreDefaultLibs=0
+stripExecutableFile=0
+
+// archive
+extraArchiveOptions=
+
+//resource
+resourcePreprocessor=
+resourceIncludeDirectory=
+extraResourceOptions=
+
+[Release]
+// compiler
+workingDirectory=
+arguments=
+intermediateFilesDirectory=Release
+outputFilesDirectory=Release
+compilerPreprocessor=_UNICODE,UNICODE,POPUPS2_EXPORTS
+extraCompilerOptions=
+compilerIncludeDirectory=..\..\include
+noWarning=0
+defaultWarning=0
+allWarning=1
+extraWarning=0
+isoWarning=0
+warningAsErrors=0
+debugType=0
+debugLevel=1
+exceptionEnabled=1
+runtimeTypeEnabled=1
+optimizeLevel=2
+
+// linker
+libraryPath=
+outputFilename=Release\yapp.dll
+libraries=unicows,gdi32,comctl32
+extraLinkerOptions=
+ignoreStartupFile=0
+ignoreDefaultLibs=0
+stripExecutableFile=1
+
+// archive
+extraArchiveOptions=
+
+//resource
+resourcePreprocessor=
+resourceIncludeDirectory=
+extraResourceOptions=
+
+[Source]
+1=message_pump.cpp
+2=notify_imp.cpp
+3=options.cpp
+4=popups2.cpp
+5=popwin.cpp
+6=services.cpp
+7=popup_history.cpp
+[Header]
+1=message_pump.h
+2=notify.h
+3=options.h
+4=popups2.h
+5=popwin.h
+6=resource.h
+7=services.h
+8=version.h
+9=popup_history.h
+10=common.h
+[Resource]
+1=resource.rc
+[Other]
+1=popups2.rc
+2=version.rc
+[History]
+popwin.cpp,15185
+version.h,175
diff --git a/yapp/common.h b/yapp/common.h new file mode 100644 index 0000000..967aef3 --- /dev/null +++ b/yapp/common.h @@ -0,0 +1,69 @@ +// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+// Modify the following defines if you have to target a platform prior to the ones specified below.
+// Refer to MSDN for the latest info on corresponding values for different platforms.
+#ifndef WINVER // Allow use of features specific to Windows XP or later.
+#define WINVER 0x0501 // Change this to the appropriate value to target other versions of Windows.
+#endif
+
+#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later.
+#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows.
+#endif
+
+#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later.
+#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.
+#endif
+
+#ifndef _WIN32_IE // Allow use of features specific to IE 6.0 or later.
+#define _WIN32_IE 0x0600 // Change this to the appropriate value to target other versions of IE.
+#endif
+
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+// Windows Header Files:
+#include <windows.h>
+#include <commctrl.h>
+#include <malloc.h>
+#include <stdlib.h>
+
+#include <newpluginapi.h>
+#include <statusmodes.h>
+#include <m_database.h>
+#include <m_langpack.h>
+#include <m_options.h>
+#include <m_system.h>
+#include <m_idle.h>
+#include <m_skin.h>
+#include <m_clui.h>
+#include <m_clist.h>
+#include <stdio.h>
+#include <m_utils.h>
+
+#include <m_popup.h>
+
+#include <m_updater.h>
+#include <m_fontservicew.h>
+#include <m_avatars.h>
+
+#include <m_notify.h>
+
+#define MODULE "YAPP"
+
+extern HMODULE hInst;
+extern PLUGINLINK *pluginLink;
+extern HANDLE mainThread;
+
+extern HFONT hFontFirstLine, hFontSecondLine, hFontTime;
+extern COLORREF colFirstLine, colSecondLine, colBg, colTime, colBorder, colSidebar;
+
+extern MNOTIFYLINK *notifyLink;
+
+extern int code_page;
+
+// work around a bug in neweventnotify, possibly httpserver
+// ignore the address passed to the 'get plugin data' service
+extern bool ignore_gpd_passed_addy;
diff --git a/yapp/docs/licence_YAPP.txt b/yapp/docs/licence_YAPP.txt new file mode 100644 index 0000000..a8cbd75 --- /dev/null +++ b/yapp/docs/licence_YAPP.txt @@ -0,0 +1,6 @@ +The YAPP plugin for Miranda-IM is Copyright (c) 2006 Scott Ellis (mail@scottellis.com.au)
+
+http://www.scottellis.com.au
+
+It is released under the General Public Licence, available here:
+http://www.gnu.org/copyleft/gpl.html
\ No newline at end of file diff --git a/yapp/docs/m_notify.h b/yapp/docs/m_notify.h new file mode 100644 index 0000000..f9bce96 --- /dev/null +++ b/yapp/docs/m_notify.h @@ -0,0 +1,177 @@ +#ifndef __m_notify_h__
+#define __m_notify_h__
+
+/*** Miranda Notify Dispatcher ************************************************\
+Notify Dispatcher provides common interface to different notification plugins
+like osd, popup, ticker etc.
+\******************************************************************************/
+
+/* Options UI event and service. The same as for miranda options */
+#define ME_NOTIFY_OPT_INITIALISE "Notify/Opt/Initialise"
+#define MS_NOTIFY_OPT_ADDPAGE "Notify/Opt/AddPage"
+
+typedef struct tagMNOTIFYACTIONINFO {
+ HICON icon;
+ char name[MAXMODULELABELLENGTH];
+ char service[MAXMODULELABELLENGTH];
+ DWORD cookie;
+} MNOTIFYACTIONINFO;
+
+// Just like miranda pluginLink... This should work faster then services,
+// we need some reactivity in notifications.
+typedef struct tagMNNOTIFYLINK
+{
+ /* Create a new notification type */
+ HANDLE (* Register)(const char *name, HICON icon);
+
+ // Create a new notification object
+ HANDLE (* Create)(HANDLE type);
+
+ // Check is handle is a valid notification object
+ int (* IsValid)(HANDLE notify);
+
+ // Set/get information about object, or type defaults
+ int (* Set)(HANDLE notifyORtype, const char *name, DBVARIANT val);
+ int (* Get)(HANDLE notifyORtype, const char *name, DBVARIANT *val);
+
+ // Set/get actions
+ int (* AddAction)(HANDLE notifyORtype, HICON icon, const char *name, const char *service, DWORD cookie);
+ int (* GetActions)(HANDLE notifyORtype, MNOTIFYACTIONINFO *actions);
+
+ // Increment/decrement refer count of notification object. Unreferred objects are destroyed
+ int (* AddRef)(HANDLE notify);
+ int (* Release)(HANDLE notify);
+
+ // Notify user
+ void (* Show)(HANDLE notify);
+ void (* Update)(HANDLE notify);
+ void (* Remove)(HANDLE notify);
+} MNOTIFYLINK;
+
+// Get the MNOTIFYLINK struct
+// result = (LRESULT)(MNOTIFYLINK*)notifyLink
+#define MS_NOTIFY_GETLINK "Notify/GetLink"
+
+// Hook this to process corresponding actions
+#define ME_NOTIFY_SHOW "Notify/Show"
+#define ME_NOTIFY_UPDATE "Notify/Update"
+#define ME_NOTIFY_REMOVE "Notify/Remove"
+
+#if !defined(MNOTIFY_NOEXTERN)
+ extern
+ #ifdef __cpluplus
+ "C"
+ #endif
+ MNOTIFYLINK *notifyLink;
+#endif
+
+#if !defined(MNOTIFY_NOHELPERS) && !defined(MNOTIFY_NOEXTERN)
+ #define MNotifyRegister(a,b) (notifyLink?notifyLink->Register((a),(b)):0)
+ #define MNotifyCreate(a) (notifyLink?notifyLink->Create((a)):0)
+ #define MNotifyIsValid(a) (notifyLink?notifyLink->IsValid((a)):0)
+ #define MNotifySet(a,b,c) (notifyLink?notifyLink->Set((a),(b),(c)):0)
+ #define MNotifyGet(a,b,c) (notifyLink?notifyLink->Get((a),(b),(c)):0)
+ #define MNotifyAddAction(a,b,c) (notifyLink?notifyLink->AddAction((a),(b),(c)):0)
+ #define MNotifyGetActions(a,b) (notifyLink?notifyLink->GetActions((a),(b)):0)
+ #define MNotifyGet(a,b,c) (notifyLink?notifyLink->Get((a),(b),(c)):0)
+ #define MNotifyAddRef(a) (notifyLink?notifyLink->AddRef((a)):0)
+ #define MNotifyRelease(a) (notifyLink?notifyLink->Release((a)):0)
+ #define MNotifyShow(a) (notifyLink?notifyLink->Show(a):0)
+ #define MNotifyUpdate(a) (notifyLink?notifyLink->Update(a):0)
+ #define MNotifyRemove(a) (notifyLink?notifyLink->Remove(a):0)
+
+ static void __inline MNotifyGetLink()
+ {
+ notifyLink = ServiceExists(MS_NOTIFY_GETLINK) ? (MNOTIFYLINK *)CallService(MS_NOTIFY_GETLINK,0,0) : 0;
+ }
+
+ // get helpers
+ static __inline BYTE MNotifyGetByte(HANDLE notifyORtype, const char *name, BYTE defValue)
+ {
+ DBVARIANT dbv;
+ MNotifyGet(notifyORtype, name, &dbv);
+ if (dbv.type != DBVT_BYTE) return defValue;
+ return dbv.bVal;
+ }
+ static __inline WORD MNotifyGetWord(HANDLE notifyORtype, const char *name, WORD defValue)
+ {
+ DBVARIANT dbv;
+ MNotifyGet(notifyORtype, name, &dbv);
+ if (dbv.type != DBVT_WORD) return defValue;
+ return dbv.wVal;
+ }
+ static __inline DWORD MNotifyGetDWord(HANDLE notifyORtype, const char *name, DWORD defValue)
+ {
+ DBVARIANT dbv;
+ MNotifyGet(notifyORtype, name, &dbv);
+ if (dbv.type != DBVT_DWORD) return defValue;
+ return dbv.dVal;
+ }
+ static __inline const char *MNotifyGetString(HANDLE notifyORtype, const char *name, const char *defValue)
+ {
+ DBVARIANT dbv;
+ MNotifyGet(notifyORtype, name, &dbv);
+ if (dbv.type != DBVT_ASCIIZ) return defValue;
+ return dbv.pszVal;
+ }
+ static __inline const WCHAR *MNotifyGetWString(HANDLE notifyORtype, const char *name, const WCHAR *defValue)
+ {
+ DBVARIANT dbv;
+ MNotifyGet(notifyORtype, name, &dbv);
+ if (dbv.type != DBVT_WCHAR) return defValue;
+ return dbv.pwszVal;
+ }
+
+ // set helpers
+ static __inline void MNotifySetByte(HANDLE notifyORtype, const char *name, BYTE value)
+ {
+ DBVARIANT dbv;
+ dbv.type = DBVT_BYTE;
+ dbv.bVal = value;
+ MNotifySet(notifyORtype, name, dbv);
+ }
+ static __inline void MNotifySetWord(HANDLE notifyORtype, const char *name, WORD value)
+ {
+ DBVARIANT dbv;
+ dbv.type = DBVT_WORD;
+ dbv.wVal = value;
+ MNotifySet(notifyORtype, name, dbv);
+ }
+ static __inline void MNotifySetDWord(HANDLE notifyORtype, const char *name, DWORD value)
+ {
+ DBVARIANT dbv;
+ dbv.type = DBVT_DWORD;
+ dbv.dVal = value;
+ MNotifySet(notifyORtype, name, dbv);
+ }
+ static __inline void MNotifySetString(HANDLE notifyORtype, const char *name, const char *value)
+ {
+ DBVARIANT dbv;
+ dbv.type = DBVT_ASCIIZ;
+ dbv.pszVal = (char *)value;
+ MNotifySet(notifyORtype, name, dbv);
+ }
+ static __inline void MNotifySetWString(HANDLE notifyORtype, const char *name, const WCHAR *value)
+ {
+ DBVARIANT dbv;
+ dbv.type = DBVT_WCHAR;
+ dbv.pwszVal = (WCHAR *)value;
+ MNotifySet(notifyORtype, name, dbv);
+ }
+#endif
+
+// Common options for Get/Set actions
+#define NFOPT_TYPENAME "General/TypeName"
+#define NFOPT_ICON "General/Icon"
+#define NFOPT_CONTACT "General/Contact"
+#define NFOPT_EVENT "General/Event"
+#define NFOPT_TEXT "General/Text"
+#define NFOPT_TEXTW "General/TextW"
+#define NFOPT_TITLE "General/Title"
+#define NFOPT_TITLEW "General/TitleW"
+#define NFOPT_BACKCOLOR "General/BackColor"
+#define NFOPT_TEXTCOLOR "General/TextColor"
+#define NFOPT_TIMEOUT "General/Timeout"
+//#define NFOPT_ONDESTROY "General/OnDestroy"
+
+#endif // __m_notify_h__
diff --git a/yapp/docs/m_popup.h b/yapp/docs/m_popup.h new file mode 100644 index 0000000..f0a92a4 --- /dev/null +++ b/yapp/docs/m_popup.h @@ -0,0 +1,339 @@ +/*
+===============================================================================
+ PopUp plugin
+Plugin Name: PopUp
+Plugin authors: Luca Santarelli aka hrk (hrk@users.sourceforge.net)
+ Victor Pavlychko aka zazoo (nullbie@gmail.com)
+===============================================================================
+The purpose of this plugin is to give developers a common "platform/interface"
+to show PopUps. It is born from the source code of NewStatusNotify, another
+plugin I've made.
+
+Remember that users *must* have this plugin enabled, or they won't get any
+popup. Write this in the requirements, do whatever you wish ;-)... but tell
+them!
+===============================================================================
+*/
+
+#ifndef __m_popup_h__
+#define __m_popup_h__
+
+/*
+NOTE! Since Popup 1.0.1.2 there is a main meun group called "PopUps" where I
+have put a "Enable/Disable" item. You can add your own "enable/disable" items
+by adding these lines before you call MS_CLIST_ADDMAINMENUITEM:
+mi.pszPopUpName = Translate("PopUps");
+mi.position = 0; //You don't need it and it's better if you put it to zero.
+*/
+
+#define MAX_CONTACTNAME 2048
+#define MAX_SECONDLINE 2048
+
+// This is the basic data you'll need to fill and pass to the service function.
+typedef struct
+{
+ HANDLE lchContact; // Handle to the contact, can be NULL (main contact).
+ HICON lchIcon; // Handle to a icon to be shown. Cannot be NULL.
+ union
+ {
+ char lptzContactName[MAX_CONTACTNAME]; // This is the contact name or the first line in the plugin. Cannot be NULL.
+ char lpzContactName[MAX_CONTACTNAME];
+ };
+ union
+ {
+ char lptzText[MAX_SECONDLINE]; // This is the second line text. Users can choose to hide it. Cannot be NULL.
+ char lpzText[MAX_SECONDLINE];
+ };
+ COLORREF colorBack; // COLORREF to be used for the background. Can be NULL, default will be used.
+ COLORREF colorText; // COLORREF to be used for the text. Can be NULL, default will be used.
+ WNDPROC PluginWindowProc; // Read below. Can be NULL; default will be used.
+ void * PluginData; // Read below. Can be NULL.
+} POPUPDATA, * LPPOPUPDATA;
+
+// Extended popup data
+typedef struct
+{
+ HANDLE lchContact;
+ HICON lchIcon;
+ union
+ {
+ char lptzContactName[MAX_CONTACTNAME];
+ char lpzContactName[MAX_CONTACTNAME];
+ };
+ union
+ {
+ char lptzText[MAX_SECONDLINE];
+ char lpzText[MAX_SECONDLINE];
+ };
+ COLORREF colorBack;
+ COLORREF colorText;
+ WNDPROC PluginWindowProc;
+ void * PluginData;
+ int iSeconds; // Custom delay time in seconds. -1 means "forever", 0 means "default time".
+ char cZero[16]; // Some unused bytes which may come useful in the future.
+} POPUPDATAEX, *LPPOPUPDATAEX;
+
+// Unicode version of POPUPDATAEX
+typedef struct
+{
+ HANDLE lchContact;
+ HICON lchIcon;
+ union
+ {
+ WCHAR lptzContactName[MAX_CONTACTNAME];
+ WCHAR lpwzContactName[MAX_CONTACTNAME];
+ };
+ union
+ {
+ WCHAR lptzText[MAX_CONTACTNAME];
+ WCHAR lpwzText[MAX_CONTACTNAME];
+ };
+ COLORREF colorBack;
+ COLORREF colorText;
+ WNDPROC PluginWindowProc;
+ void * PluginData;
+ int iSeconds;
+ char cZero[16];
+} POPUPDATAW, *LPPOPUPDATAW;
+
+#if defined(_UNICODE) || defined(UNICODE)
+ typedef POPUPDATAW POPUPDATAT;
+ typedef LPPOPUPDATAW LPPOPUPDATAT;
+#else
+ typedef POPUPDATAEX POPUPDATAT;
+ typedef LPPOPUPDATAEX LPPOPUPDATAT;
+#endif
+
+/* PopUp/AddPopup
+Creates, adds and shows a popup, given a (valid) POPUPDATA structure pointer.
+
+wParam = (WPARAM)(*POPUPDATA)PopUpDataAddress
+lParam = 0
+
+Returns: > 0 on success, 0 if creation went bad, -1 if the PopUpData contained unacceptable values.
+NOTE: it returns -1 if the PopUpData was not valid, if there were already too many popups, if the module was disabled.
+Otherwise, it can return anything else...
+
+Popup Plus 2.0.4.0+
+You may pass additional creation flags via lParam:
+ APF_RETURN_HWND ....... function returns handle to newly created popup window (however this calls are a bit slower)
+ APF_CUSTOM_POPUP ...... new popup is created in hidden state and doesn't obey to popup queue rules.
+ you may control it via UM_* messages and custom window procedure
+*/
+#define APF_RETURN_HWND 0x1
+#define APF_CUSTOM_POPUP 0x2
+
+#define MS_POPUP_ADDPOPUP "PopUp/AddPopUp"
+static int __inline PUAddPopUp(POPUPDATA* ppdp) {
+ return CallService(MS_POPUP_ADDPOPUP, (WPARAM)ppdp,0);
+}
+
+#define MS_POPUP_ADDPOPUPEX "PopUp/AddPopUpEx"
+static int __inline PUAddPopUpEx(POPUPDATAEX* ppdp) {
+ return CallService(MS_POPUP_ADDPOPUPEX, (WPARAM)ppdp,0);
+}
+
+#define MS_POPUP_ADDPOPUPW "PopUp/AddPopUpW"
+static int __inline PUAddPopUpW(POPUPDATAW* ppdp) {
+ return CallService(MS_POPUP_ADDPOPUPW, (WPARAM)ppdp,0);
+}
+
+#if defined(_UNICODE) || defined(UNICODE)
+ #define MS_POPUP_ADDPOPUPT MS_POPUP_ADDPOPUPW
+ #define PUAddPopUpT PUAddPopUpW
+#else
+ #define MS_POPUP_ADDPOPUPT MS_POPUP_ADDPOPUPEX
+ #define PUAddPopUpT PUAddPopUpEx
+#endif
+
+
+/* PopUp/GetContact
+Returns the handle to the contact associated to the specified PopUpWindow.
+
+wParam = (WPARAM)(HWND)hPopUpWindow
+lParam = 0;
+
+Returns: the HANDLE of the contact. Can return NULL, meaning it's the main contact. -1 means failure.
+*/
+#define MS_POPUP_GETCONTACT "PopUp/GetContact"
+static HANDLE __inline PUGetContact(HWND hPopUpWindow) {
+ return (HANDLE)CallService(MS_POPUP_GETCONTACT, (WPARAM)hPopUpWindow,0);
+}
+
+/* PopUp/GetPluginData
+Returns custom plugin date associated with popup
+
+wParam = (WPARAM)(HWND)hPopUpWindow
+lParam = (LPARAM)(PLUGINDATA*)PluginDataAddress;
+
+Returns: the address of the PLUGINDATA structure. Can return NULL, meaning nothing was given. -1 means failure.
+
+IMPORTANT NOTE: it doesn't seem to work if you do:
+CallService(..., (LPARAM)aPointerToAStruct);
+and then use that struct.
+Do this, instead:
+aPointerToStruct = CallService(..., (LPARAM)aPointerToAStruct);
+and it will work. Just look at the example I've written above (PopUpDlgProc).
+
+*/
+#define MS_POPUP_GETPLUGINDATA "PopUp/GetPluginData"
+static void __inline * PUGetPluginData(HWND hPopUpWindow) {
+ long * uselessPointer = NULL;
+ return (void*)CallService(MS_POPUP_GETPLUGINDATA,(WPARAM)hPopUpWindow,(LPARAM)uselessPointer);
+}
+
+/* PopUp/IsSecondLineShown
+Checks if second line is enable
+
+wParam = 0
+lParam = 0
+
+Returns: 0 if the user has chosen not to have the second line, 1 if he choose to have the second line.
+*/
+#define MS_POPUP_ISSECONDLINESHOWN "PopUp/IsSecondLineShown"
+static BOOL __inline PUIsSecondLineShown() {
+ return (BOOL)CallService(MS_POPUP_ISSECONDLINESHOWN,0,0);
+}
+
+/* PopUp/Query
+
+Requests an action or an answer from PopUp module.
+
+wParam = (WPARAM)wpQuery
+
+returns 0 on success, -1 on error, 1 on stupid calls ;-)
+*/
+
+#define PUQS_ENABLEPOPUPS 1 // returns 0 if state was changed, 1 if state wasn't changed
+#define PUQS_DISABLEPOPUPS 2 // " "
+#define PUQS_GETSTATUS 3 //Returns 1 (TRUE) if popups are enabled, 0 (FALSE) if popups are disabled.
+
+#define MS_POPUP_QUERY "PopUp/Query"
+
+/* UM_FREEPLUGINDATA
+Process this message if you have allocated your own memory. (i.e.: POPUPDATA.PluginData != NULL)
+
+wParam = 0
+lParam = 0
+*/
+#define UM_FREEPLUGINDATA (WM_USER + 0x0200)
+
+/* UM_DESTROYPOPUP
+Send this message when you want to destroy the popup, or use the function below.
+
+wParam = 0
+lParam = 0
+*/
+#define UM_DESTROYPOPUP (WM_USER + 0x0201)
+static int __inline PUDeletePopUp(HWND hWndPopUp) {
+ return (int)SendMessage(hWndPopUp, UM_DESTROYPOPUP,0,0);
+}
+
+/* UM_INITPOPUP
+This message is sent to the PopUp when its creation has been finished, so POPUPDATA (and thus your PluginData) is reachable.
+Catch it if you needed to catch WM_CREATE or WM_INITDIALOG, which you'll never ever get in your entire popup-life.
+Return value: if you process this message, return 0. If you don't process it, return 0. Do whatever you like ;-)
+
+wParam = (WPARAM)(HWND)hPopUpWindow (this is useless, you get message inside your popup window)
+lParam = 0
+*/
+#define UM_INITPOPUP (WM_USER + 0x0202)
+
+/* PopUp/Changetext
+Changes the text displayed in the second line of the popup.
+
+wParam = (WPARAM)(HWND)hPopUpWindow
+lParam = (LPARAM)(char*)lpzNewText
+
+returns: > 0 for success, -1 for failure, 0 if the failure is due to second line not being shown. (but you could call
+PUIsSecondLineShown() before changing the text...)
+*/
+#define MS_POPUP_CHANGETEXT "PopUp/Changetext"
+static int __inline PUChangeText(HWND hWndPopUp, LPCTSTR lpzNewText) {
+ return (int)CallService(MS_POPUP_CHANGETEXT, (WPARAM)hWndPopUp, (LPARAM)lpzNewText);
+}
+
+#define MS_POPUP_CHANGETEXTW "PopUp/ChangetextW"
+static int __inline PUChangeTextW(HWND hWndPopUp, LPCWSTR lpwzNewText) {
+ return (int)CallService(MS_POPUP_CHANGETEXTW, (WPARAM)hWndPopUp, (LPARAM)lpwzNewText);
+}
+
+#if defined(_UNICODE) || defined(UNICODE)
+ #define MS_POPUP_CHANGETEXTT MS_POPUP_CHANGETEXTW
+ #define PUChangeTextT PUChangeTextW
+#else
+ #define MS_POPUP_CHANGETEXTT MS_POPUP_CHANGETEXT
+ #define PUChangeTextT PUChangeText
+#endif
+
+/* PopUp/Change
+Changes the entire popup
+
+wParam = (WPARAM)(HWND)hPopUpWindow
+lParam = (LPARAM)(POPUPDATAEX*)newData
+*/
+#define MS_POPUP_CHANGE "PopUp/Change"
+static int __inline PUChange(HWND hWndPopUp, POPUPDATAEX *newData) {
+ return (int)CallService(MS_POPUP_CHANGE, (WPARAM)hWndPopUp, (LPARAM)newData);
+}
+
+#define MS_POPUP_CHANGEW "PopUp/ChangeW"
+static int __inline PUChangeW(HWND hWndPopUp, POPUPDATAW *newData) {
+ return (int)CallService(MS_POPUP_CHANGE, (WPARAM)hWndPopUp, (LPARAM)newData);
+}
+
+#if defined(_UNICODE) || defined(UNICODE)
+ #define MS_POPUP_CHANGET MS_POPUP_CHANGEW
+ #define PUChangeT PUChangeW
+#else
+ #define MS_POPUP_CHANGET MS_POPUP_CHANGE
+ #define PUChangeT PUChange
+#endif
+
+/* UM_CHANGEPOPUP
+This message is triggered by Change/ChangeText services. You also may post it directly :)
+
+wParam = Modification type
+lParam = value of type defined by wParam
+*/
+
+#define CPT_TEXT 1 // lParam = (char *)text
+#define CPT_TEXTW 2 // lParam = (WCHAR *)text
+#define CPT_TITLE 3 // lParam = (char *)title
+#define CPT_TITLEW 4 // lParam = (WCHAR *)title
+#define CPT_DATA 5 // lParam = (POPUPDATA *)data
+#define CPT_DATAEX 6 // lParam = (POPUPDATAEX *)data
+#define CPT_DATAW 7 // lParam = (POPUPDATAW *)data
+
+#define UM_CHANGEPOPUP (WM_USER + 0x0203)
+
+#if defined(_UNICODE) || defined(UNICODE)
+ #define CPT_TEXTT CPT_TEXTW
+ #define CPT_TITLET CPT_TITLEW
+ #define CPT_DATAT CPT_DATAW
+#else
+ #define CPT_TEXTT CPT_TEXT
+ #define CPT_TITLET CPT_TITLE
+ #define CPT_DATAT CPT_DATA
+#endif
+
+/* PopUp/ShowMessage
+This is mainly for developers.
+Shows a warning message in a PopUp. It's useful if you need a "MessageBox" like function, but you don't want a modal
+window (which will interfere with a DialogProcedure. MessageBox steals focus and control, this one not.
+
+wParam = (char *)lpzMessage
+lParam = 0;
+
+Returns: 0 if the popup was shown, -1 in case of failure.
+*/
+#define SM_WARNING 0x01 //Triangle icon.
+#define SM_NOTIFY 0x02 //Exclamation mark icon.
+#define MS_POPUP_SHOWMESSAGE "PopUp/ShowMessage"
+
+static int __inline PUShowMessage(char *lpzText, BYTE kind) {
+ return (int)CallService(MS_POPUP_SHOWMESSAGE, (WPARAM)lpzText,(LPARAM)kind);
+}
+
+#endif // __m_popup_h__
+
diff --git a/yapp/docs/m_popup2.h b/yapp/docs/m_popup2.h new file mode 100644 index 0000000..b23aecf --- /dev/null +++ b/yapp/docs/m_popup2.h @@ -0,0 +1,29 @@ +#ifndef __m_popup2_h__
+#define __m_popup2_h__
+
+#define NFOPT_POPUP2_BACKCOLOR "Popup2/BackColor"
+#define NFOPT_POPUP2_TEXTCOLOR "Popup2/TextColor"
+#define NFOPT_POPUP2_TIMEOUT "Popup2/Timeout"
+#define NFOPT_POPUP2_LCLICKSVC "Popup2/LClickSvc"
+#define NFOPT_POPUP2_LCLICKCOOKIE "Popup2/LClickCookie"
+#define NFOPT_POPUP2_RCLICKSVC "Popup2/RClickSvc"
+#define NFOPT_POPUP2_RCLICKCOOKIE "Popup2/RClickCookie"
+#define NFOPT_POPUP2_STATUSMODE "Popup2/StatusMode"
+#define NFOPT_POPUP2_PLUGINDATA "Popup2/PluginData"
+#define NFOPT_POPUP2_WNDPROC "Popup2/WndProc"
+
+#define NFOPT_POPUP2_BACKCOLOR_S "Popup2/BackColor/Save"
+#define NFOPT_POPUP2_TEXTCOLOR_S "Popup2/TextColor/Save"
+#define NFOPT_POPUP2_TIMEOUT_S "Popup2/Timeout/Save"
+
+#define MS_POPUP2_SHOW "Popup2/Show"
+#define MS_POPUP2_UPDATE "Popup2/Update"
+#define MS_POPUP2_REMOVE "Popup2/Remove"
+
+#ifndef POPUP2_NOHELPERS
+ #define MPopup2Show(a) (CallService(MS_POPUP2_SHOW, 0, (LPARAM)(a)))
+ #define MPopup2Update(a) (CallService(MS_POPUP2_UPDATE, 0, (LPARAM)(a)))
+ #define MPopup2Remove(a) (CallService(MS_POPUP2_REMOVE, 0, (LPARAM)(a)))
+#endif
+
+#endif // __m_popup2_h__
diff --git a/yapp/message_pump.cpp b/yapp/message_pump.cpp new file mode 100644 index 0000000..f5cedd8 --- /dev/null +++ b/yapp/message_pump.cpp @@ -0,0 +1,160 @@ +#include "common.h"
+#include "message_pump.h"
+#include "popwin.h"
+#include "services.h"
+#include "options.h"
+
+DWORD message_pump_thread_id = 0;
+int num_popups = 0;
+
+HANDLE hMPEvent;
+
+#define MUM_FINDWINDOW (WM_USER + 0x050)
+
+#define MAX_POPUPS 100
+
+// from popups, popup2 implementation
+bool is_full_screen() {
+ HWND hWnd = GetForegroundWindow();
+
+ if(!hWnd || !IsWindowVisible(hWnd) || IsIconic(hWnd) || !IsZoomed(hWnd)) return false;
+
+ RECT rc;
+ if(!GetWindowRect(hWnd,&rc)) return false;
+
+ if (rc.right - rc.left < GetSystemMetrics(SM_CXSCREEN) || rc.bottom - rc.top < GetSystemMetrics(SM_CYSCREEN)) return false;
+
+ // at this point, it will return true for full-screen and, unfortunately, maximized windows - so we need to check for maximized
+
+ LONG style = GetWindowLong(hWnd, GWL_STYLE);
+ if(style & WS_MAXIMIZEBOX) return false;
+
+ return true;
+}
+
+bool is_workstation_locked()
+{
+ bool rc = false;
+ HDESK hDesk = OpenDesktop(_T("default"), 0, FALSE, DESKTOP_SWITCHDESKTOP);
+ if(hDesk != 0) {
+ HDESK hDeskInput = OpenInputDesktop(0, FALSE, DESKTOP_SWITCHDESKTOP);
+ if(hDeskInput == 0) {
+ rc = true;
+ } else
+ CloseDesktop(hDeskInput);
+
+ CloseDesktop(hDesk);
+ }
+
+ return rc;
+}
+
+
+DWORD CALLBACK MessagePumpThread(LPVOID param) {
+ CallService(MS_SYSTEM_THREAD_PUSH, 0, 0);
+
+ InitWindowStack();
+
+ if(param) SetEvent((HANDLE)param);
+
+ MSG hwndMsg = {0};
+ while(GetMessage(&hwndMsg, 0, 0, 0) > 0 && !Miranda_Terminated()) {
+ if(!IsDialogMessage(hwndMsg.hwnd, &hwndMsg)) {
+ switch(hwndMsg.message) {
+ case MUM_CREATEPOPUP:
+ {
+ bool enabled = true;
+ int status = CallService(MS_CLIST_GETSTATUSMODE, 0, 0);
+ if(status >= ID_STATUS_OFFLINE && status <= ID_STATUS_OUTTOLUNCH && options.disable_status[status - ID_STATUS_OFFLINE])
+ enabled = false;
+ if(options.disable_full_screen && is_full_screen() || is_workstation_locked())
+ enabled = false;
+ if(enabled && num_popups < MAX_POPUPS) {
+ //HWND hwnd = CreateWindowEx(WS_EX_TOOLWINDOW | WS_EX_TOPMOST, POP_WIN_CLASS, _T("Popup"), WS_POPUP, 0, 0, 0, 0, GetDesktopWindow(), 0, hInst, (LPVOID)hwndMsg.lParam);
+ HWND hwnd = CreateWindowEx(WS_EX_TOOLWINDOW | WS_EX_TOPMOST, POP_WIN_CLASS, _T("Popup"), WS_POPUP, 0, 0, 0, 0, 0, 0, hInst, (LPVOID)hwndMsg.lParam);
+ num_popups++;
+ if(hwndMsg.wParam) // set notifyer handle
+ SendMessage(hwnd, PUM_SETNOTIFYH, hwndMsg.wParam, 0);
+ } else {
+ free((void *)hwndMsg.lParam);
+ }
+ }
+ break;
+
+ case MUM_DELETEPOPUP:
+ {
+ HWND hwnd = (HWND)hwndMsg.lParam;
+ if(IsWindow(hwnd)) {
+ DestroyWindow(hwnd);
+ num_popups--;
+ }
+ }
+ break;
+ case MUM_NMUPDATE:
+ {
+ HANDLE hNotify = (HANDLE)hwndMsg.wParam;
+ BroadcastMessage(PUM_UPDATENOTIFY, (WPARAM)hNotify, 0);
+ }
+ break;
+ case MUM_NMREMOVE:
+ {
+ HANDLE hNotify = (HANDLE)hwndMsg.wParam;
+ BroadcastMessage(PUM_KILLNOTIFY, (WPARAM)hNotify, 0);
+ }
+ break;
+ default:
+ {
+ TranslateMessage(&hwndMsg);
+ DispatchMessage(&hwndMsg);
+ // do this here in case the window has gone
+ if(hwndMsg.message == PUM_CHANGE || hwndMsg.message == PUM_SETTEXT)
+ free((void *)hwndMsg.lParam);
+ }
+ break;
+ }
+ }
+ }
+
+ DeinitWindowStack();
+ num_popups = 0;
+
+ //if(param) SetEvent((HANDLE)param);
+
+ CallService(MS_SYSTEM_THREAD_POP, 0, 0);
+
+ return 0;
+}
+
+void PostMPMessage(UINT msg, WPARAM wParam, LPARAM lParam) {
+ PostThreadMessage(message_pump_thread_id, msg, wParam, lParam);
+}
+
+// given a popup data pointer, and a handle to an event, this function
+// will post a message to the message queue which will set the hwnd value
+// and then set the event...so create an event, call this function and then wait on the event
+// when the event is signalled, the hwnd will be valid
+void FindWindow(POPUPDATAW *pd, HANDLE hEvent, HWND *hwnd);
+
+void InitMessagePump() {
+ WNDCLASS popup_win_class = {0};
+ popup_win_class.style = 0;
+ popup_win_class.lpfnWndProc = PopupWindowProc;
+ popup_win_class.hInstance = hInst;
+ popup_win_class.lpszClassName = POP_WIN_CLASS;
+ popup_win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
+ RegisterClass(&popup_win_class);
+
+ InitServices();
+
+ hMPEvent = CreateEvent(0, TRUE, 0, 0);
+ CloseHandle(CreateThread(0, 0, MessagePumpThread, hMPEvent, 0, &message_pump_thread_id));
+ WaitForSingleObject(hMPEvent, INFINITE);
+ CloseHandle(hMPEvent);
+}
+
+void DeinitMessagePump() {
+
+ PostMPMessage(WM_QUIT, 0, 0);
+
+ DeinitServices();
+}
diff --git a/yapp/message_pump.h b/yapp/message_pump.h new file mode 100644 index 0000000..e57ed55 --- /dev/null +++ b/yapp/message_pump.h @@ -0,0 +1,22 @@ +#ifndef _MESSAGE_PUMP_INC
+#define _MESSAGE_PUMP_INC
+
+extern DWORD message_pump_thread_id;
+void PostMPMessage(UINT msg, WPARAM, LPARAM);
+
+#define MUM_CREATEPOPUP (WM_USER + 0x011)
+#define MUM_DELETEPOPUP (WM_USER + 0x012)
+
+#define MUM_NMUPDATE (WM_USER + 0x013)
+#define MUM_NMREMOVE (WM_USER + 0x014)
+
+// given a popup data pointer, and a handle to an event, this function
+// will post a message to the message queue which will set the hwnd value
+// and then set the event...so create an event, call this function and then wait on the event
+// when the event is signalled, the hwnd will be valid
+void FindWindow(POPUPDATAW *pd, HANDLE hEvent, HWND *hwnd);
+
+void InitMessagePump();
+void DeinitMessagePump();
+
+#endif
diff --git a/yapp/notify.h b/yapp/notify.h new file mode 100644 index 0000000..7f39eb6 --- /dev/null +++ b/yapp/notify.h @@ -0,0 +1,7 @@ +#ifndef _NOTIFY_IMP_INC
+#define _NOTIFY_IMP_INC
+
+void InitNotify();
+void DeinitNotify();
+
+#endif
diff --git a/yapp/notify_imp.cpp b/yapp/notify_imp.cpp new file mode 100644 index 0000000..acb9d36 --- /dev/null +++ b/yapp/notify_imp.cpp @@ -0,0 +1,125 @@ +#include "common.h"
+#include "resource.h"
+#include "notify.h"
+#include "message_pump.h"
+#include "docs/m_popup2.h"
+
+HANDLE hhkShow=0, hhkUpdate=0, hhkRemove=0;
+
+//struct
+
+int Popup2Show(WPARAM wParam, LPARAM lParam) {
+
+ HANDLE hNotify = (HANDLE)lParam;
+
+ POPUPDATAW *pd_out = (POPUPDATAW *)malloc(sizeof(POPUPDATAW));
+ memset(pd_out, 0, sizeof(POPUPDATAW));
+
+ PostMPMessage(MUM_CREATEPOPUP, (WPARAM)hNotify, (LPARAM)pd_out);
+ PostMPMessage(MUM_NMUPDATE, (WPARAM)hNotify, (LPARAM)0);
+ return 0;
+}
+
+int Popup2Update(WPARAM wParam, LPARAM lParam) {
+ HANDLE hNotify = (HANDLE)lParam;
+ PostMPMessage(MUM_NMUPDATE, (WPARAM)hNotify, (LPARAM)0);
+ return 0;
+}
+
+int Popup2Remove(WPARAM wParam, LPARAM lParam) {
+ HANDLE hNotify = (HANDLE)lParam;
+ PostMPMessage(MUM_NMREMOVE, (WPARAM)hNotify, (LPARAM)0);
+ return 0;
+}
+
+int svcPopup2DefaultActions(WPARAM wParam, LPARAM lParam)
+{
+ //PopupWindow *wnd = (PopupWindow *)MNotifyGetDWord((HANDLE)lParam, "Popup2/data", (DWORD)NULL);
+ //if (!wnd) return 0;
+ switch (wParam)
+ {
+ case 0:
+ { // send message
+ //if (wnd->lchContact) CallServiceSync(MS_MSG_SENDMESSAGE, (WPARAM)wnd->lchContact, 0);
+ //SendMessage(wnd->lchMain, UM_DESTROYPOPUP, 0, 0);
+ break;
+ }
+ case 1:
+ { // dismiss popup
+ //SendMessage(wnd->lchMain, UM_DESTROYPOPUP, 0, 0);
+ break;
+ }
+ }
+ return 0;
+}
+
+BOOL CALLBACK DlgProcPopUps(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+/* To change options use MNotifySet*(hNotify, ....) Apply/Cancel is implemented in notify.dll */
+ HANDLE hNotify = (HANDLE)GetWindowLong(hwnd, GWL_USERDATA);
+ switch (msg)
+ {
+ case WM_USER+100:
+ {
+ // This will be extendet to handle array of handles for multiselect lParam
+ // will be HANDLE * and wParam wil; store amount of handles passed
+ hNotify = (HANDLE)lParam;
+ SetWindowLong(hwnd, GWL_USERDATA, lParam);
+ return TRUE;
+ }
+
+ case WM_COMMAND:
+ // This in different from Miranda options!
+ SendMessage(GetParent(GetParent(hwnd)), PSM_CHANGED, 0, 0);
+ break;
+ }
+ return FALSE;
+}
+
+int NotifyOptionsInitialize(WPARAM wParam,LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp = {0};
+ odp.cbSize = sizeof(odp);
+ odp.hInstance = hInst;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_NOTIFY);
+ odp.pszTitle = Translate("YAPP Popups");
+ odp.flags=ODPF_BOLDGROUPS;
+ odp.pfnDlgProc = DlgProcPopUps;
+ CallService(MS_NOTIFY_OPT_ADDPAGE, wParam, (LPARAM)&odp);
+ return 0;
+}
+
+HANDLE hEventNotifyOptInit, hEventNotifyModulesLoaded;
+
+int NotifyModulesLoaded(WPARAM wParam,LPARAM lParam)
+{
+ hEventNotifyOptInit = HookEvent(ME_NOTIFY_OPT_INITIALISE, NotifyOptionsInitialize);
+ return 0;
+}
+
+HANDLE hServicesNotify[4];
+void InitNotify() {
+ hhkShow = HookEvent(ME_NOTIFY_SHOW, Popup2Show);
+ hhkUpdate = HookEvent(ME_NOTIFY_UPDATE, Popup2Update);
+ hhkRemove = HookEvent(ME_NOTIFY_REMOVE, Popup2Remove);
+
+ hServicesNotify[0] = CreateServiceFunction("Popup2/DefaultActions", svcPopup2DefaultActions);
+
+ hServicesNotify[1] = CreateServiceFunction(MS_POPUP2_SHOW, Popup2Show);
+ hServicesNotify[2] = CreateServiceFunction(MS_POPUP2_UPDATE, Popup2Update);
+ hServicesNotify[3] = CreateServiceFunction(MS_POPUP2_REMOVE, Popup2Remove);
+
+ hEventNotifyModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED, NotifyModulesLoaded);
+}
+
+void DeinitNotify() {
+ UnhookEvent(hhkShow);
+ UnhookEvent(hhkUpdate);
+ UnhookEvent(hhkRemove);
+
+ UnhookEvent(hEventNotifyOptInit);
+ UnhookEvent(hEventNotifyModulesLoaded);
+
+ for(int i = 0; i < 4; i++)
+ DestroyServiceFunction(hServicesNotify[i]);
+}
diff --git a/yapp/options.cpp b/yapp/options.cpp new file mode 100644 index 0000000..5f3e0d5 --- /dev/null +++ b/yapp/options.cpp @@ -0,0 +1,394 @@ +#include "common.h"
+#include "options.h"
+#include "resource.h"
+#include "popwin.h"
+#include <commctrl.h>
+
+Options options;
+
+HICON hPopupIcon = 0;
+
+void LoadModuleDependentOptions() {
+ if(ServiceExists(MS_AV_DRAWAVATAR))
+ options.av_layout = (PopupAvLayout)DBGetContactSettingByte(0, MODULE, "AVLayout", PAV_RIGHT);
+ else
+ options.av_layout = PAV_NONE;
+
+ options.time_layout = (PopupTimeLayout)DBGetContactSettingByte(0, MODULE, "TimeLayout", (ServiceExists(MS_AV_DRAWAVATAR) ? PT_WITHAV : PT_RIGHT));
+ if(options.time_layout == PT_WITHAV && !ServiceExists(MS_AV_DRAWAVATAR))
+ options.time_layout = PT_RIGHT;
+}
+
+void LoadOptions() {
+ options.default_timeout = DBGetContactSettingDword(0, MODULE, "DefaultTimeout", 7);
+ options.win_width = DBGetContactSettingDword(0, MODULE, "WinWidth", 220);
+ options.win_max_height = DBGetContactSettingDword(0, MODULE, "WinMaxHeight", 400);
+ options.location = (PopupLocation)DBGetContactSettingByte(0, MODULE, "Location", (BYTE)PL_BOTTOMRIGHT);
+ options.opacity = DBGetContactSettingByte(0, MODULE, "Opacity", 75);
+ options.border = (DBGetContactSettingByte(0, MODULE, "Border", 1) == 1);
+ options.round = (DBGetContactSettingByte(0, MODULE, "RoundCorners", 1) == 1);
+ options.av_round = (DBGetContactSettingByte(0, MODULE, "AvatarRoundCorners", 1) == 1);
+ options.animate = (DBGetContactSettingByte(0, MODULE, "Animate", 1) == 1);
+ options.trans_bg = (DBGetContactSettingByte(0, MODULE, "TransparentBg", 0) == 1);
+ options.use_mim_monitor = (DBGetContactSettingByte(0, MODULE, "UseMimMonitor", 1) == 1);
+ options.right_icon = (DBGetContactSettingByte(0, MODULE, "RightIcon", 0) == 1);
+ options.av_layout = PAV_NONE; // corrected in LoadModuleDependentOptions function above
+ options.av_size = DBGetContactSettingDword(0, MODULE, "AVSize", 40); //tweety
+ options.text_indent = DBGetContactSettingDword(0, MODULE, "TextIndent", 22);
+ options.global_hover = (DBGetContactSettingByte(0, MODULE, "GlobalHover", 1) == 1);
+ options.time_layout = PT_RIGHT; // corrected in LoadModuleDependentOptions function above
+
+ char buff[128];
+ for(int i = 0; i < 10; i++) {
+ sprintf(buff, "DisableStatus%d", i - 1); // -1 because i forgot offline status earlier!
+ options.disable_status[i] = (DBGetContactSettingByte(0, MODULE, buff, 0) == 1);
+ }
+
+ options.disable_full_screen = (DBGetContactSettingByte(0, MODULE, "DisableFullScreen", 1) == 1);
+ options.drop_shadow = (DBGetContactSettingByte(0, MODULE, "DropShadow", 0) == 1);
+ options.sb_width = DBGetContactSettingDword(0, MODULE, "SidebarWidth", 22);
+ options.padding = DBGetContactSettingDword(0, MODULE, "Padding", 4);
+ options.av_padding = DBGetContactSettingDword(0, MODULE, "AvatarPadding", 4);
+}
+
+void SaveOptions() {
+ DBWriteContactSettingDword(0, MODULE, "DefaultTimeout", options.default_timeout);
+ DBWriteContactSettingDword(0, MODULE, "WinWidth", options.win_width);
+ DBWriteContactSettingDword(0, MODULE, "WinMaxHeight", options.win_max_height);
+ DBWriteContactSettingByte(0, MODULE, "Location", (BYTE)options.location);
+ DBWriteContactSettingByte(0, MODULE, "Opacity", (BYTE)options.opacity);
+ DBWriteContactSettingByte(0, MODULE, "Border", (options.border ? 1 : 0));
+ DBWriteContactSettingByte(0, MODULE, "RoundCorners", (options.round ? 1 : 0));
+ DBWriteContactSettingByte(0, MODULE, "AvatarRoundCorners", (options.av_round ? 1 : 0));
+ DBWriteContactSettingByte(0, MODULE, "Animate", (options.animate ? 1 : 0));
+ DBWriteContactSettingByte(0, MODULE, "TransparentBg", (options.trans_bg ? 1 : 0));
+ DBWriteContactSettingByte(0, MODULE, "UseMimMonitor", (options.use_mim_monitor ? 1 : 0));
+ DBWriteContactSettingByte(0, MODULE, "RightIcon", (options.right_icon ? 1 : 0));
+ if(ServiceExists(MS_AV_DRAWAVATAR))
+ DBWriteContactSettingByte(0, MODULE, "AVLayout", (BYTE)options.av_layout);
+ DBWriteContactSettingDword(0, MODULE, "AVSize", options.av_size);
+ DBWriteContactSettingDword(0, MODULE, "TextIndent", options.text_indent);
+ DBWriteContactSettingByte(0, MODULE, "GlobalHover", (options.global_hover ? 1 : 0));
+ DBWriteContactSettingByte(0, MODULE, "TimeLayout", (BYTE)options.time_layout);
+
+ char buff[128];
+ for(int i = 0; i < 9; i++) {
+ sprintf(buff, "DisableStatus%d", i - 1);
+ DBWriteContactSettingByte(0, MODULE, buff, options.disable_status[i] ? 1 : 0);
+ }
+ DBWriteContactSettingByte(0, MODULE, "DisableFullScreen", (options.disable_full_screen ? 1 : 0));
+ DBWriteContactSettingByte(0, MODULE, "DropShadow", (options.drop_shadow ? 1 : 0));
+ DBWriteContactSettingDword(0, MODULE, "SidebarWidth", options.sb_width);
+ DBWriteContactSettingDword(0, MODULE, "Padding", options.padding);
+ DBWriteContactSettingDword(0, MODULE, "AvatarPadding", options.av_padding);
+}
+
+void ShowExamplePopups() {
+ POPUPDATAW pd = {0};
+ pd.lchIcon = hPopupIcon;
+
+ wcscpy(pd.lpwzContactName, TranslateT("Example"));
+ wcscpy(pd.lpwzText, TranslateT("The quick brown fox jumped over the lazy dog."));
+ CallService(MS_POPUP_ADDPOPUPW, (WPARAM)&pd, 0);
+ wcscpy(pd.lpwzContactName, TranslateT("Example With a Long Title"));
+ wcscpy(pd.lpwzText, TranslateT("The quick brown fox jumped over the lazy dog."));
+ CallService(MS_POPUP_ADDPOPUPW, (WPARAM)&pd, 0);
+ wcscpy(pd.lpwzContactName, TranslateT("Example"));
+ wcscpy(pd.lpwzText, TranslateT("Thequickbrownfoxjumpedoverthelazydog."));
+ CallService(MS_POPUP_ADDPOPUPW, (WPARAM)&pd, 0);
+
+ HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ while(hContact) {
+ if(options.av_layout != PAV_NONE && ServiceExists(MS_AV_DRAWAVATAR)) {
+ AVATARCACHEENTRY *ace = (AVATARCACHEENTRY *)CallService(MS_AV_GETAVATARBITMAP, (WPARAM)hContact, 0);
+ if(ace && ace->dwFlags & AVS_BITMAP_VALID) {
+ pd.lchContact = hContact;
+ wcscpy(pd.lpwzText, TranslateT("An avatar."));
+ CallService(MS_POPUP_ADDPOPUPW, (WPARAM)&pd, 0);
+ break;
+ }
+ }
+
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0);
+ }
+}
+
+static BOOL CALLBACK DlgProcOpts1(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
+
+ switch ( msg ) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault( hwndDlg );
+
+ SendDlgItemMessage(hwndDlg, IDC_CMB_PLACEMENT, CB_ADDSTRING, 0, (LPARAM)TranslateT("Bottom right"));
+ SendDlgItemMessage(hwndDlg, IDC_CMB_PLACEMENT, CB_ADDSTRING, 0, (LPARAM)TranslateT("Bottom left"));
+ SendDlgItemMessage(hwndDlg, IDC_CMB_PLACEMENT, CB_ADDSTRING, 0, (LPARAM)TranslateT("Top right"));
+ SendDlgItemMessage(hwndDlg, IDC_CMB_PLACEMENT, CB_ADDSTRING, 0, (LPARAM)TranslateT("Top left"));
+ SendDlgItemMessage(hwndDlg, IDC_CMB_PLACEMENT, CB_SETCURSEL, (int)options.location, 0);
+
+ SendDlgItemMessage(hwndDlg, IDC_CMB_ICON, CB_ADDSTRING, 0, (LPARAM)TranslateT("Icon on left"));
+ SendDlgItemMessage(hwndDlg, IDC_CMB_ICON, CB_ADDSTRING, 0, (LPARAM)TranslateT("Icon on right"));
+ SendDlgItemMessage(hwndDlg, IDC_CMB_ICON, CB_SETCURSEL, (options.right_icon ? 1 : 0), 0);
+
+ SendDlgItemMessage(hwndDlg, IDC_CMB_TIME, CB_ADDSTRING, 0, (LPARAM)TranslateT("No time"));
+ SendDlgItemMessage(hwndDlg, IDC_CMB_TIME, CB_ADDSTRING, 0, (LPARAM)TranslateT("Time on left"));
+ SendDlgItemMessage(hwndDlg, IDC_CMB_TIME, CB_ADDSTRING, 0, (LPARAM)TranslateT("Time on right"));
+ if(ServiceExists(MS_AV_DRAWAVATAR))
+ SendDlgItemMessage(hwndDlg, IDC_CMB_TIME, CB_ADDSTRING, 0, (LPARAM)TranslateT("Time above avatar"));
+ SendDlgItemMessage(hwndDlg, IDC_CMB_TIME, CB_SETCURSEL, (int)options.time_layout, 0);
+
+ SendDlgItemMessage(hwndDlg, IDC_CMB_AV, CB_ADDSTRING, 0, (LPARAM)TranslateT("No avatar"));
+ if(ServiceExists(MS_AV_DRAWAVATAR)) {
+ SendDlgItemMessage(hwndDlg, IDC_CMB_AV, CB_ADDSTRING, 0, (LPARAM)TranslateT("Left avatar"));
+ SendDlgItemMessage(hwndDlg, IDC_CMB_AV, CB_ADDSTRING, 0, (LPARAM)TranslateT("Right avatar"));
+ } else {
+ HWND hw = GetDlgItem(hwndDlg, IDC_CMB_AV);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_SPIN_AVSIZE);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_ED_AVSIZE);
+ EnableWindow(hw, FALSE);
+ }
+ SendDlgItemMessage(hwndDlg, IDC_CMB_AV, CB_SETCURSEL, (int)options.av_layout, 0);
+
+ CheckDlgButton(hwndDlg, IDC_CHK_GLOBALHOVER, options.global_hover ? TRUE : FALSE);
+
+ {
+ // initialise and fill listbox
+ HWND hwndList = GetDlgItem(hwndDlg, IDC_LST_STATUS);
+ ListView_DeleteAllItems(hwndList);
+
+ SendMessage(hwndList,LVM_SETEXTENDEDLISTVIEWSTYLE, 0,LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES);
+
+ LVCOLUMN lvc = {0};
+ // Initialize the LVCOLUMN structure.
+ // The mask specifies that the format, width, text, and
+ // subitem members of the structure are valid.
+ lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
+ lvc.fmt = LVCFMT_LEFT;
+
+ lvc.iSubItem = 0;
+ lvc.pszText = TranslateT("Status");
+ lvc.cx = 200; // width of column in pixels
+ ListView_InsertColumn(hwndList, 0, &lvc);
+
+
+ LVITEM lvI = {0};
+
+ // Some code to create the list-view control.
+ // Initialize LVITEM members that are common to all
+ // items.
+ lvI.mask = LVIF_TEXT;
+
+ char *strptr;
+ wchar_t buff[256];
+ int i = 0;
+ for(; i < 10; i++) {
+ strptr = (char *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, (WPARAM)(ID_STATUS_OFFLINE + i), (LPARAM)0);
+ int cp = CP_ACP;
+ if(ServiceExists(MS_LANGPACK_GETCODEPAGE))
+ cp = (int)CallService(MS_LANGPACK_GETCODEPAGE, 0, 0);
+ MultiByteToWideChar(cp, 0, strptr, -1, buff, 256);
+ lvI.pszText = buff;
+ lvI.iItem = i;
+ ListView_InsertItem(hwndList, &lvI);
+ ListView_SetCheckState(hwndList, i, options.disable_status[i]);
+ }
+ lvI.pszText = TranslateT("Full-screen app running");
+ lvI.iItem = i;
+ ListView_InsertItem(hwndList, &lvI);
+ ListView_SetCheckState(hwndList, i, options.disable_full_screen);
+ }
+
+ SendDlgItemMessage(hwndDlg, IDC_SPIN_TIMEOUT, UDM_SETRANGE, 0, (LPARAM)MAKELONG(360, 1));
+ SendDlgItemMessage(hwndDlg, IDC_SPIN_WIDTH, UDM_SETRANGE, 0, (LPARAM)MAKELONG(2048, 16));
+ SendDlgItemMessage(hwndDlg, IDC_SPIN_MAXHEIGHT, UDM_SETRANGE, 0, (LPARAM)MAKELONG(2048, 16));
+ SendDlgItemMessage(hwndDlg, IDC_SPIN_TRANS, UDM_SETRANGE, 0, (LPARAM)MAKELONG(100, 1));
+ SendDlgItemMessage(hwndDlg, IDC_SPIN_AVSIZE, UDM_SETRANGE, 0, (LPARAM)MAKELONG(100, 16));
+ SendDlgItemMessage(hwndDlg, IDC_SPIN_INDENT, UDM_SETRANGE, 0, (LPARAM)MAKELONG(400, 0));
+ SendDlgItemMessage(hwndDlg, IDC_SPIN_SBWIDTH, UDM_SETRANGE, 0, (LPARAM)MAKELONG(2048, 0));
+ SendDlgItemMessage(hwndDlg, IDC_SPIN_PADDING, UDM_SETRANGE, 0, (LPARAM)MAKELONG(400, 0));
+
+ if(options.default_timeout == -1) {
+ CheckDlgButton(hwndDlg, IDC_RAD_NOTIMEOUT, TRUE);
+ HWND hw = GetDlgItem(hwndDlg, IDC_ED_TIMEOUT);
+ EnableWindow(hw, FALSE);
+ SetDlgItemInt(hwndDlg, IDC_ED_TIMEOUT, 7, FALSE);
+ } else {
+ CheckDlgButton(hwndDlg, IDC_RAD_TIMEOUT, TRUE);
+ SetDlgItemInt(hwndDlg, IDC_ED_TIMEOUT, options.default_timeout, FALSE);
+ }
+ if(options.right_icon) CheckDlgButton(hwndDlg, IDC_RAD_RIGHTICON, TRUE);
+ else CheckDlgButton(hwndDlg, IDC_RAD_LEFTICON, TRUE);
+
+ if(ServiceExists(MS_AV_DRAWAVATAR)) {
+ switch(options.av_layout) {
+ case PAV_NONE: CheckDlgButton(hwndDlg, IDC_RAD_NOAV, TRUE); break;
+ case PAV_RIGHT: CheckDlgButton(hwndDlg, IDC_RAD_RIGHTAV, TRUE); break;
+ case PAV_LEFT: CheckDlgButton(hwndDlg, IDC_RAD_LEFTAV, TRUE); break;
+ }
+ } else {
+ CheckDlgButton(hwndDlg, IDC_RAD_NOAV, TRUE);
+ HWND hw = GetDlgItem(hwndDlg, IDC_RAD_RIGHTAV);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_RAD_LEFTAV);
+ EnableWindow(hw, FALSE);
+ }
+
+ SetDlgItemInt(hwndDlg, IDC_ED_WIDTH, options.win_width, FALSE);
+ SetDlgItemInt(hwndDlg, IDC_ED_MAXHEIGHT, options.win_max_height, FALSE);
+ SetDlgItemInt(hwndDlg, IDC_ED_AVSIZE, options.av_size, FALSE);
+ SetDlgItemInt(hwndDlg, IDC_ED_INDENT, options.text_indent, FALSE);
+ SetDlgItemInt(hwndDlg, IDC_ED_SBWIDTH, options.sb_width, FALSE);
+ SetDlgItemInt(hwndDlg, IDC_ED_PADDING, options.padding, FALSE);
+
+ switch(options.location) {
+ case PL_BOTTOMRIGHT: CheckDlgButton(hwndDlg, IDC_RAD_BOTTOMRIGHT, TRUE); break;
+ case PL_BOTTOMLEFT: CheckDlgButton(hwndDlg, IDC_RAD_BOTTOMLEFT, TRUE); break;
+ case PL_TOPRIGHT: CheckDlgButton(hwndDlg, IDC_RAD_TOPRIGHT, TRUE); break;
+ case PL_TOPLEFT: CheckDlgButton(hwndDlg, IDC_RAD_TOPLEFT, TRUE); break;
+ }
+
+ SetDlgItemInt(hwndDlg, IDC_ED_TRANS, options.opacity, FALSE);
+ CheckDlgButton(hwndDlg, IDC_CHK_BORDER, options.border);
+ CheckDlgButton(hwndDlg, IDC_CHK_ROUNDCORNERS, options.round);
+ CheckDlgButton(hwndDlg, IDC_CHK_ROUNDCORNERSAV, options.av_round);
+
+ CheckDlgButton(hwndDlg, IDC_CHK_ANIMATE, options.animate);
+ CheckDlgButton(hwndDlg, IDC_CHK_TRANSBG, options.trans_bg);
+
+ return FALSE;
+ case WM_COMMAND:
+ if ( HIWORD( wParam ) == CBN_SELCHANGE) {
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ } else if ( HIWORD( wParam ) == EN_CHANGE && ( HWND )lParam == GetFocus()) {
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ } else if ( HIWORD( wParam ) == BN_CLICKED ) {
+ if(LOWORD(wParam) == IDC_BTN_PREVIEW) {
+ ShowExamplePopups();
+ } else {
+ switch( LOWORD( wParam )) {
+ case IDC_RAD_NOTIMEOUT:
+ {
+ HWND hw = GetDlgItem(hwndDlg, IDC_ED_TIMEOUT);
+ EnableWindow(hw, IsDlgButtonChecked(hwndDlg, IDC_RAD_TIMEOUT));
+ }
+ break;
+ case IDC_RAD_TIMEOUT:
+ {
+ HWND hw = GetDlgItem(hwndDlg, IDC_ED_TIMEOUT);
+ EnableWindow(hw, IsDlgButtonChecked(hwndDlg, IDC_RAD_TIMEOUT));
+ }
+ break;
+ }
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+ }
+ break;
+ case WM_NOTIFY:
+ if(IsWindowVisible(hwndDlg) && ((LPNMHDR) lParam)->hwndFrom == GetDlgItem(hwndDlg, IDC_LST_STATUS)) {
+ switch (((LPNMHDR) lParam)->code) {
+
+ case LVN_ITEMCHANGED:
+ {
+ NMLISTVIEW *nmlv = (NMLISTVIEW *)lParam;
+ if((nmlv->uNewState ^ nmlv->uOldState) & LVIS_STATEIMAGEMASK) {
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ }
+ }
+ break;
+ }
+ } else
+ if (((LPNMHDR)lParam)->code == (unsigned)PSN_APPLY ) {
+ BOOL trans;
+ int new_val;
+ if(IsDlgButtonChecked(hwndDlg, IDC_RAD_NOTIMEOUT))
+ options.default_timeout = -1;
+ else {
+ new_val = GetDlgItemInt(hwndDlg, IDC_ED_TIMEOUT, &trans, FALSE);
+ if(trans) options.default_timeout = new_val;
+ }
+ if(options.default_timeout == 0) {
+ SetDlgItemInt(hwndDlg, IDC_ED_TIMEOUT, options.default_timeout, FALSE);
+ MessageBox(hwndDlg, TranslateT("You cannot set a default timeout of 0.\nValue has been reset."), TranslateT("Error"), MB_OK | MB_ICONWARNING);
+ options.default_timeout = 7; // prevent instant timeout
+ }
+
+ new_val = GetDlgItemInt(hwndDlg, IDC_ED_WIDTH, &trans, FALSE);
+ if(trans) options.win_width = new_val;
+ new_val = GetDlgItemInt(hwndDlg, IDC_ED_MAXHEIGHT, &trans, FALSE);
+ if(trans) options.win_max_height = new_val;
+ new_val = GetDlgItemInt(hwndDlg, IDC_ED_AVSIZE, &trans, FALSE);
+ if(trans) options.av_size = new_val;
+ new_val = GetDlgItemInt(hwndDlg, IDC_ED_INDENT, &trans, FALSE);
+ if(trans) options.text_indent = new_val;
+ new_val = GetDlgItemInt(hwndDlg, IDC_ED_SBWIDTH, &trans, FALSE);
+ if(trans) options.sb_width = new_val;
+ new_val = GetDlgItemInt(hwndDlg, IDC_ED_PADDING, &trans, FALSE);
+ if(trans) options.padding = new_val;
+
+ options.location = (PopupLocation)SendDlgItemMessage(hwndDlg, IDC_CMB_PLACEMENT, CB_GETCURSEL, 0, 0);
+ options.right_icon = (SendDlgItemMessage(hwndDlg, IDC_CMB_ICON, CB_GETCURSEL, 0, 0) == 1);
+ options.av_layout = (PopupAvLayout)SendDlgItemMessage(hwndDlg, IDC_CMB_AV, CB_GETCURSEL, 0, 0);
+ options.time_layout = (PopupTimeLayout)SendDlgItemMessage(hwndDlg, IDC_CMB_TIME, CB_GETCURSEL, 0, 0);
+
+ new_val = GetDlgItemInt(hwndDlg, IDC_ED_TRANS, &trans, FALSE);
+ if(trans) options.opacity = new_val;
+ options.border = IsDlgButtonChecked(hwndDlg, IDC_CHK_BORDER) && IsWindowEnabled(GetDlgItem(hwndDlg, IDC_CHK_BORDER)) ? true : false;
+ options.round = IsDlgButtonChecked(hwndDlg, IDC_CHK_ROUNDCORNERS) && IsWindowEnabled(GetDlgItem(hwndDlg, IDC_CHK_ROUNDCORNERS)) ? true : false;
+ options.av_round = IsDlgButtonChecked(hwndDlg, IDC_CHK_ROUNDCORNERSAV) && IsWindowEnabled(GetDlgItem(hwndDlg, IDC_CHK_ROUNDCORNERSAV)) ? true : false;
+ options.animate = IsDlgButtonChecked(hwndDlg, IDC_CHK_ANIMATE) ? true : false;
+ options.trans_bg = IsDlgButtonChecked(hwndDlg, IDC_CHK_TRANSBG) ? true : false;
+ options.global_hover = IsDlgButtonChecked(hwndDlg, IDC_CHK_GLOBALHOVER) ? true : false;
+
+ int i = 0;
+ for(; i < 10; i++)
+ options.disable_status[i] = (ListView_GetCheckState(GetDlgItem(hwndDlg, IDC_LST_STATUS), i) == 1);
+ options.disable_full_screen = (ListView_GetCheckState(GetDlgItem(hwndDlg, IDC_LST_STATUS), i) == 1);
+
+ SaveOptions();
+ return TRUE;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+int OptInit(WPARAM wParam, LPARAM lParam) {
+#define OPTIONPAGE_OLD_SIZE2 60
+
+ OPTIONSDIALOGPAGE odp = { 0 };
+ //odp.cbSize = sizeof(odp);
+ odp.cbSize = OPTIONPAGE_OLD_SIZE2;
+ odp.flags = ODPF_BOLDGROUPS;
+ //odp.flags |= ODPF_UNICODE;
+ odp.position = -790000000;
+ odp.hInstance = hInst;
+
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT1);
+ odp.pszTitle = Translate("PopUps");
+ //odp.pszTitle = Translate("General");
+ //odp.pszGroup = Translate("PopUps");
+ //odp.ptszTitle = TranslateT("Updater");
+ //odp.ptszGroup = TranslateT("Plugins");
+ odp.nIDBottomSimpleControl = 0;
+ odp.pfnDlgProc = DlgProcOpts1;
+ CallService( MS_OPT_ADDPAGE, wParam,( LPARAM )&odp );
+
+ return 0;
+}
+
+HANDLE hEventOptInit;
+void InitOptions() {
+ hEventOptInit = HookEvent(ME_OPT_INITIALISE, OptInit);
+
+ // an icon for preview popups
+ hPopupIcon = LoadSkinnedIcon(SKINICON_EVENT_MESSAGE);
+
+ LoadOptions();
+}
+
+void DeinitOptions() {
+ UnhookEvent(hEventOptInit);
+ DestroyIcon(hPopupIcon);
+}
diff --git a/yapp/options.h b/yapp/options.h new file mode 100644 index 0000000..55b94d1 --- /dev/null +++ b/yapp/options.h @@ -0,0 +1,36 @@ +#ifndef _OPTIONS_INC
+#define _OPTIONS_INC
+
+typedef enum {PL_BOTTOMRIGHT=0, PL_BOTTOMLEFT=1, PL_TOPRIGHT=2, PL_TOPLEFT=3} PopupLocation;
+typedef enum {PAV_NONE=0, PAV_LEFT=1, PAV_RIGHT=2} PopupAvLayout;
+typedef enum {PT_NONE=0, PT_LEFT=1, PT_RIGHT=2, PT_WITHAV=3} PopupTimeLayout;
+typedef struct {
+ int win_width, win_max_height, av_size; //tweety
+ int default_timeout;
+ PopupLocation location;
+ int opacity;
+ bool border;
+ bool round, av_round;
+ bool animate;
+ bool trans_bg;
+ bool use_mim_monitor;
+ bool right_icon;
+ PopupAvLayout av_layout;
+ bool disable_status[10];
+ int text_indent;
+ bool global_hover;
+ PopupTimeLayout time_layout;
+ bool disable_full_screen;
+ bool drop_shadow;
+ int sb_width;
+ int padding, av_padding;
+} Options;
+
+extern Options options;
+
+void InitOptions();
+void LoadOptions();
+void LoadModuleDependentOptions();
+void DeinitOptions();
+
+#endif
diff --git a/yapp/popup_history.cpp b/yapp/popup_history.cpp new file mode 100644 index 0000000..6e9b59e --- /dev/null +++ b/yapp/popup_history.cpp @@ -0,0 +1,393 @@ +#define STRICT +#define WIN32_LEAN_AND_MEAN + +#include "common.h" +#include "resource.h" +#include "popup_history.h" +#include <time.h> + +#define POPUPMENU_TITLE 100 +#define POPUPMENU_MESSAGE 101 +#define POPUPMENU_TIMESTAMP 102 + +HWND hHistoryWindow = 0; //the history window +PopupHistoryList lstPopupHistory; //defined in main.cpp + +WNDPROC oldPopupsListProc = NULL; + +PopupHistoryList::PopupHistoryList() +{ + size = HISTORY_SIZE; //fixed size (at least for now) + historyData = (PopupHistoryData *) malloc(size * sizeof(PopupHistoryData)); //alloc space for data + count = 0; +} + +PopupHistoryList::~PopupHistoryList() +{ + Clear(); //clear the data strings + free(historyData); //deallocate the data list +} + +void PopupHistoryList::Clear() +{ + int i; + for (i = 0; i < count; i++) + { + DeleteData(i); + } + count = 0; +} + +int PopupHistoryList::Count() +{ + return count; +} + +int PopupHistoryList::Size() +{ + return size; +} + +void PopupHistoryList::RemoveItem(int index) +{ + int i; + DeleteData(index); //free the mem for that particular item + for (i = index + 1; i < count; i++) + { + historyData[i - 1] = historyData[i]; //shift all items to the left + } +} + +void PopupHistoryList::DeleteData(int index) +{ + PopupHistoryData *item = &historyData[index]; + if (item->flags && PHDF_UNICODE) //strings are dupped(), we need to free them + { + free(item->titleW); + free(item->messageW); + } + else{ + free(item->title); + free(item->message); + } + item->timestamp = 0; //invalidate item + item->title = NULL; + item->message = NULL; + item->flags = 0; +} + +void PopupHistoryList::AddItem(PopupHistoryData item) +{ + if (count >= size) + { + RemoveItem(0); //remove first element - the oldest + count--; //it will be inc'ed later + } + historyData[count++] = item; //item has it's relevant strings dupped() + RefreshPopupHistory(hHistoryWindow); +} + +void PopupHistoryList::Add(char *title, char *message, time_t timestamp) +{ + PopupHistoryData item = {0}; //create a history item + item.timestamp = timestamp; + item.title = strdup(title); + item.message = strdup(message); + AddItem(item); //add it (flags = 0) +} + +void PopupHistoryList::Add(wchar_t *title, wchar_t *message, time_t timestamp) +{ + PopupHistoryData item = {0}; //create an unicode history item + item.flags = PHDF_UNICODE; //mark it as unicode + item.timestamp = timestamp; + item.titleW = _wcsdup(title); + item.messageW = _wcsdup(message); + AddItem(item); //add it +} + +PopupHistoryData *PopupHistoryList::Get(int index) +{ + if ((index < 0) || (index >= count)) //a bit of sanity check + { + return NULL; + } + + return &historyData[index]; +} + +//Stucture passed to list sort function +struct SortParams{ + HWND hList; + int column; +}; + +static int lastColumn = -1; //last sort column + +int CALLBACK PopupsCompare(LPARAM lParam1, LPARAM lParam2, LPARAM myParam) +{ + SortParams params = *(SortParams *) myParam; + const int MAX_SIZE = 512; + TCHAR text1[MAX_SIZE]; + TCHAR text2[MAX_SIZE]; + int res; + + ListView_GetItemText(params.hList, (int) lParam1, params.column, text1, MAX_SIZE); + ListView_GetItemText(params.hList, (int) lParam2, params.column, text2, MAX_SIZE); + + res = _tcsicmp(text1, text2); + + res = (params.column == lastColumn) ? -res : res; //do reverse search on second click on same column + + return res; +} + +void RefreshPopupHistory(HWND hWnd) +{ + if (!hWnd) + { + return; + } + HWND hHistoryList = GetDlgItem(hWnd, IDC_LST_HISTORY); + ListView_DeleteAllItems(hHistoryList); + + int i; + LVITEM item = {0}; + item.mask = LVIF_TEXT; + wchar_t buffer[1024]; + struct tm *myTime; + for (i = 0; i < lstPopupHistory.Count(); i++) + { + item.iItem = i; + PopupHistoryData *popupItem = lstPopupHistory.Get(i); + item.pszText = popupItem->titleW; + ListView_InsertItem(hHistoryList, &item); + ListView_SetItemText(hHistoryList, i, 1, popupItem->messageW); + myTime = localtime(&popupItem->timestamp); + wcsftime(buffer, 1024, L"%c", myTime); + ListView_SetItemText(hHistoryList, i, 2, buffer); + } + + SortParams params = {0}; + params.hList = hHistoryList; + params.column = lastColumn; + + ListView_SortItemsEx(hHistoryList, PopupsCompare, ¶ms); +} + +void CopyPopupDataToClipboard(HWND hList, int selection) +{ + if (!selection) + { + return; + } + + if (!GetOpenClipboardWindow()) + { + if (OpenClipboard(hList)) + { + TCHAR buffer[2048]; + buffer[0] = _T('\0'); + TCHAR *clipboard; + int i; + int found = 0; + int count = ListView_GetItemCount(hList); + int textType; +#ifdef _UNICODE + textType = CF_UNICODETEXT; +#else + textType = CF_TEXT; +#endif + + for (i = 0; i < count; i++) + { + if (ListView_GetItemState(hList, i, LVIS_SELECTED)) + { + ListView_GetItemText(hList, i, selection - 100, buffer, 2048); + found = 1; + break; + } + } + if (found) + { + EmptyClipboard(); + int len = _tcslen(buffer); + + HANDLE hData = GlobalAlloc(GMEM_MOVEABLE, (len + 2) * sizeof(TCHAR)); + clipboard = (TCHAR *) GlobalLock(hData); + _tcsncpy(clipboard, buffer, len); + clipboard[len] = _T('\0'); + GlobalUnlock(hData); + if (!SetClipboardData(textType, hData)) + { + PUShowMessage("Could not set clipboard data", SM_WARNING); + } + } + CloseClipboard(); + } + else{ + PUShowMessage("Could not open clipboard", SM_WARNING); + } + } + else{ + PUShowMessage("The clipboard is not available", SM_WARNING); + } +} + +//subclass proc for the list view +BOOL CALLBACK PopupsListSubclassProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + case WM_CONTEXTMENU: + { + int x = LOWORD(lParam); + int y = HIWORD(lParam); + int selection; + + HMENU hMenu = CreatePopupMenu(); + AppendMenu(hMenu, MF_STRING, POPUPMENU_TITLE, TranslateT("Copy title to clipboard")); + AppendMenu(hMenu, MF_STRING, POPUPMENU_MESSAGE, TranslateT("Copy message to clipboard")); + AppendMenu(hMenu, MF_STRING, POPUPMENU_TIMESTAMP, TranslateT("Copy timestamp to clipboard")); + selection = TrackPopupMenu(hMenu, TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, x, y, 0, hWnd, NULL); + DestroyMenu(hMenu); + if (selection) + { + CopyPopupDataToClipboard(hWnd, selection); + } + + break; + } + + case WM_KEYUP: + { + switch (wParam) + { + case 'C': + { + if (GetKeyState(VK_CONTROL)) + { + CopyPopupDataToClipboard(hWnd, POPUPMENU_MESSAGE); + } + + break; + } + + case VK_ESCAPE: + { + SendMessage(GetParent(hWnd), WM_CLOSE, 0, 0); + + break; + } + + } + + break; + } + + case WM_SYSKEYDOWN: + { + if (wParam == 'X') + { + SendMessage(GetParent(hWnd), WM_CLOSE, 0, 0); + } + + break; + } + } + + return CallWindowProc(oldPopupsListProc, hWnd, msg, wParam, lParam); +} + +//this is the history list window handler +BOOL CALLBACK DlgProcHistLst(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + case WM_INITDIALOG: + { + TranslateDialogDefault(hWnd); + HWND hHistoryList = GetDlgItem(hWnd, IDC_LST_HISTORY); + + ListView_SetExtendedListViewStyleEx (hHistoryList, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT); + + oldPopupsListProc = (WNDPROC) SetWindowLong(hHistoryList, GWL_WNDPROC, (LONG) PopupsListSubclassProc); + + LVCOLUMN col; + col.mask = LVCF_TEXT | LVCF_WIDTH; + col.pszText = L"Title"; + col.cx = 100; + ListView_InsertColumn(hHistoryList, 0, &col); + col.pszText = L"Message"; + col.cx = 450; + ListView_InsertColumn(hHistoryList, 1, &col); + col.pszText = L"Timestamp"; + col.cx = 115; + ListView_InsertColumn(hHistoryList, 2, &col); + RefreshPopupHistory(hWnd); + + return TRUE; + } + + case WM_DESTROY: + { + hHistoryWindow = NULL; + + break; + } + + case WM_CLOSE: + { + DestroyWindow(hWnd); + + break; + } + + case WM_COMMAND: + { + switch (LOWORD(wParam)) + { + case IDC_CLOSE: + { + SendMessage(hWnd, WM_CLOSE, 0, 0); + + break; + } + } + + break; + } + + case WM_NOTIFY: + { + switch(((LPNMHDR)lParam)->idFrom) + { + case IDC_LST_HISTORY: + { + switch (((LPNMHDR)lParam)->code) + { + case LVN_COLUMNCLICK: + { + LPNMLISTVIEW lv = (LPNMLISTVIEW) lParam; + int column = lv->iSubItem; + SortParams params = {0}; + params.hList = GetDlgItem(hWnd, IDC_LST_HISTORY); + params.column = column; + + ListView_SortItemsEx(params.hList, PopupsCompare, (LPARAM) ¶ms); + lastColumn = (params.column == lastColumn) ? -1 : params.column; + + break; + } + } + + break; + } + } + + break; + } + } + + return 0; +} diff --git a/yapp/popup_history.h b/yapp/popup_history.h new file mode 100644 index 0000000..8bb6c7b --- /dev/null +++ b/yapp/popup_history.h @@ -0,0 +1,59 @@ +#ifndef __popup_history_h__ +#define __popup_history_h__ + +#define HISTORY_SIZE 200 //number of popup history items + +#define PHDF_UNICODE 1 + +struct PopupHistoryData{ + DWORD flags; //PHDF_* flags + union{ + char *message; + wchar_t *messageW; + }; + union{ + char *title; + wchar_t *titleW; + }; + time_t timestamp; +}; + +class PopupHistoryList{ + protected: + private: + PopupHistoryData *historyData; //historyData[0] - oldest, historyData[size - 1] - newest + int count; + int size; + + void DeleteData(int index); + void AddItem(PopupHistoryData item); //adds a PopupHistoryData item + void RemoveItem(int index); + + public: + PopupHistoryList(); + ~PopupHistoryList(); + + void Add(char *title, char *message, time_t timestamp); + void Add(wchar_t *title, wchar_t *message, time_t timestamp); + + PopupHistoryData *Get(int index); + + void Clear(); + int Count(); + int Size(); +}; + +/*Shows a history with the last popups. +Useful if you've missed a popup when it appeared. +wParam - 0 +lParam - 0 +*/ +#define MS_POPUP_SHOWHISTORY "PopUp/ShowHistory" + +extern PopupHistoryList lstPopupHistory; //defined in main.cpp +extern HWND hHistoryWindow; //the history window +void RefreshPopupHistory(HWND hWnd); + +BOOL CALLBACK DlgProcHistLst(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); + +#endif //__popup_history_h__ diff --git a/yapp/popups2.cpp b/yapp/popups2.cpp new file mode 100644 index 0000000..3439832 --- /dev/null +++ b/yapp/popups2.cpp @@ -0,0 +1,238 @@ +// popups2.cpp : Defines the entry point for the DLL application.
+//
+
+#include "common.h"
+#include "popups2.h"
+#include "version.h"
+#include "message_pump.h"
+#include "options.h"
+#include "popwin.h"
+#include "notify.h"
+
+HMODULE hInst = 0;
+HANDLE mainThread = 0;
+
+MNOTIFYLINK *notifyLink = 0;
+
+int code_page = CP_ACP;
+
+// used to work around a bug in neweventnotify and others with the address passed in the GetPluginData function
+bool ignore_gpd_passed_addy = false;
+
+FontIDW font_id_firstline = {0}, font_id_secondline = {0}, font_id_time = {0};
+ColourIDW colour_id_bg = {0}, colour_id_border = {0}, colour_id_sidebar = {0};
+COLORREF colBg = GetSysColor(COLOR_3DSHADOW);
+HFONT hFontFirstLine = 0, hFontSecondLine = 0, hFontTime = 0;
+COLORREF colFirstLine = RGB(255, 0, 0), colSecondLine = 0, colTime = RGB(0, 0, 255), colBorder = RGB(0, 0, 0), colSidebar = RGB(128, 128, 128);
+
+
+// hooked here so it's in the main thread
+HANDLE hAvChangeEvent = 0;
+
+PLUGININFO pluginInfo={
+ sizeof(PLUGININFO),
+ __PLUGIN_NAME,
+ PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
+ __DESC,
+ __AUTHOR,
+ __AUTHOREMAIL,
+ __COPYRIGHT,
+ __AUTHORWEB,
+ 0, //not transient
+ 0 //doesn't replace anything built-in
+};
+
+PLUGINLINK *pluginLink = 0;
+
+extern "C" BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
+{
+ hInst = hModule;
+ //DisableThreadLibraryCalls(hInst);
+ return TRUE;
+}
+
+extern "C" POPUPS2_API PLUGININFO* MirandaPluginInfo(DWORD mirandaVersion)
+{
+ return &pluginInfo;
+}
+
+int ReloadFont(WPARAM wParam, LPARAM lParam) {
+ LOGFONT log_font;
+
+ if(hFontFirstLine) DeleteObject(hFontFirstLine);
+ colFirstLine = CallService(MS_FONT_GETW, (WPARAM)&font_id_firstline, (LPARAM)&log_font);
+ hFontFirstLine = CreateFontIndirect(&log_font);
+ if(hFontSecondLine) DeleteObject(hFontSecondLine);
+ colSecondLine = CallService(MS_FONT_GETW, (WPARAM)&font_id_secondline, (LPARAM)&log_font);
+ hFontSecondLine = CreateFontIndirect(&log_font);
+ if(hFontTime) DeleteObject(hFontTime);
+ colTime = CallService(MS_FONT_GETW, (WPARAM)&font_id_time, (LPARAM)&log_font);
+ hFontTime = CreateFontIndirect(&log_font);
+
+ colBg = CallService(MS_COLOUR_GETW, (WPARAM)&colour_id_bg, 0);
+ colBorder = CallService(MS_COLOUR_GETW, (WPARAM)&colour_id_border, 0);
+ colSidebar = CallService(MS_COLOUR_GETW, (WPARAM)&colour_id_sidebar, 0);
+
+ return 0;
+}
+
+HANDLE hEventReloadFont = 0;
+
+int ModulesLoaded(WPARAM wParam, LPARAM lParam) {
+ MNotifyGetLink();
+
+ if(ServiceExists(MS_UPDATE_REGISTER)) {
+ // register with updater
+ Update update = {0};
+ char szVersion[16];
+
+ update.cbSize = sizeof(Update);
+
+ update.szComponentName = pluginInfo.shortName;
+ update.pbVersion = (BYTE *)CreateVersionString(pluginInfo.version, szVersion);
+ update.cpbVersion = strlen((char *)update.pbVersion);
+
+ update.szUpdateURL = UPDATER_AUTOREGISTER;
+
+ // 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.szBetaUpdateURL = "http://www.scottellis.com.au/miranda_plugins/yapp.zip";
+ update.szBetaVersionURL = "http://www.scottellis.com.au/miranda_plugins/ver_yapp.html";
+ update.pbBetaVersionPrefix = (BYTE *)"YAPP version ";
+
+ update.cpbBetaVersionPrefix = strlen((char *)update.pbBetaVersionPrefix);
+
+ CallService(MS_UPDATE_REGISTER, 0, (WPARAM)&update);
+ }
+
+ if(ServiceExists(MS_FONT_REGISTERW)) {
+ font_id_firstline.cbSize = sizeof(FontIDW);
+ font_id_firstline.flags = FIDF_ALLOWEFFECTS;
+ wcscpy(font_id_firstline.group, TranslateT("Popups"));
+ wcscpy(font_id_firstline.name, TranslateT("First Line"));
+ strcpy(font_id_firstline.dbSettingsGroup, MODULE);
+ strcpy(font_id_firstline.prefix, "FontFirst");
+ font_id_firstline.order = 0;
+
+ font_id_secondline.cbSize = sizeof(FontIDW);
+ font_id_secondline.flags = FIDF_ALLOWEFFECTS;
+ wcscpy(font_id_secondline.group, TranslateT("Popups"));
+ wcscpy(font_id_secondline.name, TranslateT("Second Line"));
+ strcpy(font_id_secondline.dbSettingsGroup, MODULE);
+ strcpy(font_id_secondline.prefix, "FontSecond");
+ font_id_secondline.order = 1;
+
+ font_id_time.cbSize = sizeof(FontIDW);
+ font_id_time.flags = FIDF_ALLOWEFFECTS;
+ wcscpy(font_id_time.group, TranslateT("Popups"));
+ wcscpy(font_id_time.name, TranslateT("Time"));
+ strcpy(font_id_time.dbSettingsGroup, MODULE);
+ strcpy(font_id_time.prefix, "FontTime");
+ font_id_time.order = 2;
+
+ CallService(MS_FONT_REGISTERW, (WPARAM)&font_id_firstline, 0);
+ CallService(MS_FONT_REGISTERW, (WPARAM)&font_id_secondline, 0);
+ CallService(MS_FONT_REGISTERW, (WPARAM)&font_id_time, 0);
+
+ colour_id_bg.cbSize = sizeof(ColourIDW);
+ wcscpy(colour_id_bg.group, TranslateT("Popups"));
+ wcscpy(colour_id_bg.name, TranslateT("Background"));
+ strcpy(colour_id_bg.dbSettingsGroup, MODULE);
+ strcpy(colour_id_bg.setting, "ColourBg");
+ colour_id_bg.defcolour = GetSysColor(COLOR_3DSHADOW);
+ colour_id_bg.order = 0;
+
+ colour_id_border.cbSize = sizeof(ColourIDW);
+ wcscpy(colour_id_border.group, TranslateT("Popups"));
+ wcscpy(colour_id_border.name, TranslateT("Border"));
+ strcpy(colour_id_border.dbSettingsGroup, MODULE);
+ strcpy(colour_id_border.setting, "ColourBorder");
+ colour_id_border.defcolour = RGB(0, 0, 0);
+ colour_id_border.order = 1;
+
+ colour_id_sidebar.cbSize = sizeof(ColourIDW);
+ wcscpy(colour_id_sidebar.group, TranslateT("Popups"));
+ wcscpy(colour_id_sidebar.name, TranslateT("Sidebar"));
+ strcpy(colour_id_sidebar.dbSettingsGroup, MODULE);
+ strcpy(colour_id_sidebar.setting, "ColourSidebar");
+ colour_id_sidebar.defcolour = RGB(128, 128, 128);
+ colour_id_sidebar.order = 2;
+
+ CallService(MS_COLOUR_REGISTERW, (WPARAM)&colour_id_bg, 0);
+ CallService(MS_COLOUR_REGISTERW, (WPARAM)&colour_id_border, 0);
+ CallService(MS_COLOUR_REGISTERW, (WPARAM)&colour_id_sidebar, 0);
+
+ ReloadFont(0, 0);
+
+ hEventReloadFont = HookEvent(ME_FONT_RELOAD, ReloadFont);
+ } else {
+ LOGFONT lf = {0};
+ lf.lfCharSet = DEFAULT_CHARSET;
+ lf.lfHeight = -14;
+ lf.lfWeight = FW_BOLD;
+ hFontFirstLine = CreateFontIndirect(&lf);
+
+ lf.lfHeight = -12;
+ lf.lfWeight = 0;
+ hFontSecondLine = CreateFontIndirect(&lf);
+
+ lf.lfHeight = -8;
+ lf.lfWeight = 0;
+ hFontTime = CreateFontIndirect(&lf);
+ }
+
+ hAvChangeEvent = HookEvent(ME_AV_AVATARCHANGED, AvatarChanged);
+
+ LoadModuleDependentOptions();
+
+ if(GetModuleHandle(_T("neweventnotify")))
+ {
+ ignore_gpd_passed_addy = true;
+ }
+
+ return 0;
+}
+
+int PreShutdown(WPARAM wParam, LPARAM lParam) {
+ if(hAvChangeEvent) UnhookEvent(hAvChangeEvent);
+ DeinitMessagePump();
+ return 0;
+}
+
+HANDLE hEventPreShutdown, hEventModulesLoaded;
+
+extern "C" int POPUPS2_API Load(PLUGINLINK *link) {
+ pluginLink = link;
+ DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &mainThread, THREAD_SET_CONTEXT, FALSE, 0);
+
+ INITCOMMONCONTROLSEX icex;
+
+ // Ensure that the common control DLL is loaded (for listview)
+ icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
+ icex.dwICC = ICC_LISTVIEW_CLASSES;
+ InitCommonControlsEx(&icex);
+
+ InitMessagePump();
+ InitOptions();
+ InitNotify();
+
+ hEventPreShutdown = HookEvent(ME_SYSTEM_PRESHUTDOWN, PreShutdown);
+ hEventModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED, ModulesLoaded);
+
+ return 0;
+}
+
+extern "C" int POPUPS2_API Unload() {
+ if(hEventReloadFont) UnhookEvent(hEventReloadFont);
+ UnhookEvent(hEventPreShutdown);
+ UnhookEvent(hEventModulesLoaded);
+ DeinitNotify();
+ if(ServiceExists(MS_FONT_REGISTERW)) {
+ DeleteObject(hFontFirstLine);
+ DeleteObject(hFontSecondLine);
+ DeleteObject(hFontTime);
+ } // otherwise, no need to delete the handle
+ return 0;
+}
diff --git a/yapp/popups2.h b/yapp/popups2.h new file mode 100644 index 0000000..59e4f89 --- /dev/null +++ b/yapp/popups2.h @@ -0,0 +1,12 @@ +// The following ifdef block is the standard way of creating macros which make exporting
+// from a DLL simpler. All files within this DLL are compiled with the POPUPS2_EXPORTS
+// symbol defined on the command line. this symbol should not be defined on any project
+// that uses this DLL. This way any other project whose source files include this file see
+// POPUPS2_API functions as being imported from a DLL, whereas this DLL sees symbols
+// defined with this macro as being exported.
+#ifdef POPUPS2_EXPORTS
+#define POPUPS2_API __declspec(dllexport)
+#else
+#define POPUPS2_API __declspec(dllimport)
+#endif
+
diff --git a/yapp/popups2.rc b/yapp/popups2.rc new file mode 100644 index 0000000..9ffafcd --- /dev/null +++ b/yapp/popups2.rc @@ -0,0 +1,170 @@ +// 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
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#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 // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// English (Australia) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENA)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_AUS
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_LST_HISTORY DIALOGEX 0, 0, 467, 303
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Popup history"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ PUSHBUTTON "Close",IDC_CLOSE,413,285,50,14
+ CONTROL "",IDC_LST_HISTORY,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,4,3,459,278
+END
+
+IDD_OPT1 DIALOGEX 0, 0, 297, 218
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ GROUPBOX "Default Timeout",IDC_STATIC,4,7,153,36
+ CONTROL "Never timeout",IDC_RAD_NOTIMEOUT,"Button",BS_AUTORADIOBUTTON | BS_LEFTTEXT | WS_GROUP,10,16,77,10,WS_EX_RIGHT
+ CONTROL "Set timeout:",IDC_RAD_TIMEOUT,"Button",BS_AUTORADIOBUTTON | BS_LEFTTEXT,10,28,77,10,WS_EX_RIGHT
+ EDITTEXT IDC_ED_TIMEOUT,93,26,40,14,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER,WS_EX_RIGHT
+ CONTROL "",IDC_SPIN_TIMEOUT,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,131,26,12,14
+ EDITTEXT IDC_ED_WIDTH,238,84,39,14,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER,WS_EX_RIGHT
+ CONTROL "",IDC_SPIN_WIDTH,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,270,84,12,14
+ EDITTEXT IDC_ED_MAXHEIGHT,238,102,39,14,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER,WS_EX_RIGHT
+ CONTROL "",IDC_SPIN_MAXHEIGHT,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,270,102,12,14
+ RTEXT "Width:",IDC_STATIC,174,87,60,8,0,WS_EX_RIGHT
+ RTEXT "Maximum height:",IDC_STATIC,174,104,60,8,0,WS_EX_RIGHT
+ GROUPBOX "Options",IDC_STATIC,4,116,153,94
+ EDITTEXT IDC_ED_TRANS,97,183,33,12,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER,WS_EX_RIGHT
+ CONTROL "",IDC_SPIN_TRANS,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,126,183,13,12
+ RTEXT "Opacity(%):",IDC_STATIC,11,186,84,8,0,WS_EX_RIGHT
+ CONTROL "Border",IDC_CHK_BORDER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,25,127,121,10
+ CONTROL "Round corners (window)",IDC_CHK_ROUNDCORNERS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,25,138,121,10
+ PUSHBUTTON "Preview",IDC_BTN_PREVIEW,161,194,130,17
+ CONTROL "Animate",IDC_CHK_ANIMATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,25,160,121,10
+ CONTROL "Transparent background",IDC_CHK_TRANSBG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,25,199,121,10
+ GROUPBOX "Layout",IDC_STATIC,161,7,129,184
+ RTEXT "Avatar size:",IDC_STATIC,174,122,60,8,0,WS_EX_RIGHT
+ EDITTEXT IDC_ED_AVSIZE,238,120,39,14,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER,WS_EX_RIGHT
+ CONTROL "",IDC_SPIN_AVSIZE,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,270,120,12,14
+ GROUPBOX "Disable when",IDC_STATIC,4,44,153,70
+ CONTROL "",IDC_LST_STATUS,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_NOLABELWRAP | LVS_ALIGNLEFT | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,54,148,56
+ COMBOBOX IDC_CMB_PLACEMENT,165,19,120,68,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ COMBOBOX IDC_CMB_ICON,165,36,120,69,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ COMBOBOX IDC_CMB_AV,165,53,120,76,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ CONTROL "Global hover",IDC_CHK_GLOBALHOVER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,25,171,121,10
+ COMBOBOX IDC_CMB_TIME,165,69,120,76,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ EDITTEXT IDC_ED_SBWIDTH,238,138,39,14,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER,WS_EX_RIGHT
+ CONTROL "",IDC_SPIN_SBWIDTH,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,270,138,11,14
+ RTEXT "Sidebar width:",IDC_STATIC,174,141,60,8
+ EDITTEXT IDC_ED_INDENT,238,156,39,14,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER,WS_EX_RIGHT
+ CONTROL "",IDC_SPIN_INDENT,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,269,156,12,14
+ RTEXT "Text indent:",IDC_STATIC,174,160,60,8
+ EDITTEXT IDC_ED_PADDING,238,173,39,14,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER,WS_EX_RIGHT
+ CONTROL "",IDC_SPIN_PADDING,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,270,173,12,14
+ RTEXT "Padding:",IDC_STATIC,174,176,60,8
+ CONTROL "Round corners (avatar)",IDC_CHK_ROUNDCORNERSAV,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,25,149,121,10
+END
+
+IDD_OPT_NOTIFY DIALOGEX 0, 0, 187, 91
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_OPT1, DIALOG
+ BEGIN
+ LEFTMARGIN, 4
+ RIGHTMARGIN, 290
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 211
+ END
+
+ IDD_OPT_NOTIFY, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 180
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 84
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+#endif // English (Australia) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/yapp/popups2.sln b/yapp/popups2.sln new file mode 100644 index 0000000..cefe976 --- /dev/null +++ b/yapp/popups2.sln @@ -0,0 +1,19 @@ +Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "popups2", "popups2.vcproj", "{B6FC188B-8E54-4197-9444-8BADE9AA75E2}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {B6FC188B-8E54-4197-9444-8BADE9AA75E2}.Debug|Win32.ActiveCfg = Debug|Win32
+ {B6FC188B-8E54-4197-9444-8BADE9AA75E2}.Debug|Win32.Build.0 = Debug|Win32
+ {B6FC188B-8E54-4197-9444-8BADE9AA75E2}.Release|Win32.ActiveCfg = Release|Win32
+ {B6FC188B-8E54-4197-9444-8BADE9AA75E2}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/yapp/popups2.vcproj b/yapp/popups2.vcproj new file mode 100644 index 0000000..400b8cd --- /dev/null +++ b/yapp/popups2.vcproj @@ -0,0 +1,377 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="popups2"
+ ProjectGUID="{B6FC188B-8E54-4197-9444-8BADE9AA75E2}"
+ RootNamespace="popups2"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ CharacterSet="1"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;POPUPS2_EXPORTS;_UNICODE;UNICODE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderThrough="common.h"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="4"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="unicows.lib comctl32.lib"
+ OutputFile="..\..\bin\$(ConfigurationName)\plugins\yapp.dll"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ ImportLibrary="$(IntDir)/$(TargetName).lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ FavorSizeOrSpeed="2"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;POPUPS2_EXPORTS;_UNICODE;UNICODE;MICROSOFT_LAYER_FOR_UNICODE=1"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderThrough="common.h"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="unicows.lib comctl32.lib"
+ OutputFile="..\..\bin\$(ConfigurationName)\plugins\yapp.dll"
+ LinkIncremental="1"
+ GenerateManifest="false"
+ IgnoreDefaultLibraryNames="Kernel32.lib Advapi32.lib User32.lib Gdi32.lib Shell32.lib Comdlg32.lib Version.lib Mpr.lib Rasapi32.lib Winmm.lib Winspool.lib Vfw32.lib Secur32.lib Oleacc.lib Oledlg.lib Sensapi.lib"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ ImportLibrary="$(IntDir)/$(TargetName).lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\message_pump.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;POPUPS2_EXPORTS;_UNICODE;UNICODE"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;POPUPS2_EXPORTS;_UNICODE;UNICODE"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\notify_imp.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\options.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\popup_history.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;POPUPS2_EXPORTS;_UNICODE;UNICODE"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;POPUPS2_EXPORTS;_UNICODE;UNICODE;MICROSOFT_LAYER_FOR_UNICODE=1"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\popups2.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\popwin.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\services.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\common.h"
+ >
+ </File>
+ <File
+ RelativePath=".\message_pump.h"
+ >
+ </File>
+ <File
+ RelativePath=".\notify.h"
+ >
+ </File>
+ <File
+ RelativePath=".\options.h"
+ >
+ </File>
+ <File
+ RelativePath=".\popup_history.h"
+ >
+ </File>
+ <File
+ RelativePath=".\popups2.h"
+ >
+ </File>
+ <File
+ RelativePath=".\popwin.h"
+ >
+ </File>
+ <File
+ RelativePath=".\resource.h"
+ >
+ </File>
+ <File
+ RelativePath=".\services.h"
+ >
+ </File>
+ <File
+ RelativePath=".\version.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath=".\popups2.rc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\resource.rc"
+ >
+ </File>
+ <File
+ RelativePath=".\version.rc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <File
+ RelativePath=".\ReadMe.txt"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/yapp/popwin.cpp b/yapp/popwin.cpp new file mode 100644 index 0000000..9915961 --- /dev/null +++ b/yapp/popwin.cpp @@ -0,0 +1,760 @@ +#include "common.h"
+#include "popwin.h"
+#include "message_pump.h"
+#include "options.h"
+
+HMODULE hUserDll;
+BOOL (WINAPI *MySetLayeredWindowAttributes)(HWND,COLORREF,BYTE,DWORD) = 0;
+BOOL (WINAPI *MyAnimateWindow)(HWND hWnd,DWORD dwTime,DWORD dwFlags) = 0;
+
+#define ID_CLOSETIMER 0x0101
+#define ID_MOVETIMER 0x0102
+
+DWORD pop_start_x, pop_start_y;
+int global_mouse_in = 0;
+
+void SetStartValues() {
+ RECT wa_rect;
+ if(options.use_mim_monitor) {
+ RECT clr;
+ HMONITOR hMonitor;
+ GetWindowRect((HWND)CallService(MS_CLUI_GETHWND, 0, 0), &clr);
+ hMonitor = MonitorFromRect(&clr, MONITOR_DEFAULTTONEAREST);
+
+ MONITORINFO mi;
+ mi.cbSize = sizeof(mi);
+ GetMonitorInfo(hMonitor, &mi);
+
+ wa_rect = mi.rcWork;
+
+ } else
+ SystemParametersInfo(SPI_GETWORKAREA, 0, &wa_rect, 0);
+
+ if(options.location == PL_BOTTOMRIGHT || options.location == PL_TOPRIGHT)
+ pop_start_x = wa_rect.right - options.win_width - 1;
+ else
+ pop_start_x = wa_rect.left + 1;
+
+ if(options.location == PL_BOTTOMRIGHT || options.location == PL_BOTTOMLEFT)
+ pop_start_y = wa_rect.bottom - 1;
+ else
+ pop_start_y = wa_rect.top + 1;
+}
+
+struct HWNDStackNode {
+ HWND hwnd;
+ struct HWNDStackNode *next;
+};
+
+HWNDStackNode *hwnd_stack_top = 0;
+int stack_size = 0;
+
+void RepositionWindows() {
+ HWNDStackNode *current;
+ int x = pop_start_x, y = pop_start_y;
+ int height;//, total_height = 0;
+
+ /*
+ current = hwnd_stack_top;
+ while(current) {
+ SendMessage(current->hwnd, PUM_GETHEIGHT, (WPARAM)&height, 0);
+ total_height += height;
+ current = current->next;
+ }
+ */
+
+ current = hwnd_stack_top;
+ while(current) {
+ SendMessage(current->hwnd, PUM_GETHEIGHT, (WPARAM)&height, 0);
+ if(options.location == PL_BOTTOMRIGHT || options.location == PL_BOTTOMLEFT) y -= height + 1;
+ SendMessage(current->hwnd, PUM_MOVE, (WPARAM)x, (LPARAM)y);
+ if(options.location == PL_TOPRIGHT || options.location == PL_TOPLEFT) y += height + 1;
+
+ current = current->next;
+ }
+}
+
+void AddWindowToStack(HWND hwnd) {
+ SetStartValues();
+
+ HWNDStackNode *new_node = (HWNDStackNode *)malloc(sizeof(HWNDStackNode));
+ new_node->hwnd = hwnd;
+ new_node->next = hwnd_stack_top;
+ hwnd_stack_top = new_node;
+
+ int height;
+ SendMessage(hwnd, PUM_GETHEIGHT, (WPARAM)&height, 0);
+
+ int x = pop_start_x, y = pop_start_y;
+ if(options.location == PL_BOTTOMRIGHT || options.location == PL_TOPRIGHT)
+ x += options.win_width;
+ else
+ x -= options.win_width;
+
+ if(options.location == PL_BOTTOMRIGHT || options.location == PL_BOTTOMLEFT) y -= height;
+ SetWindowPos(hwnd, 0, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
+ if(options.location == PL_TOPRIGHT || options.location == PL_TOPLEFT) y += height;
+
+ stack_size++;
+
+ RepositionWindows();
+}
+
+void RemoveWindowFromStack(HWND hwnd) {
+ HWNDStackNode *current = hwnd_stack_top, *prev = 0;
+ while(current) {
+ if(current->hwnd == hwnd) {
+ if(prev) {
+ prev->next = current->next;
+ } else {
+ hwnd_stack_top = current->next;
+ }
+ free(current);
+ stack_size--;
+ break;
+ }
+
+ prev = current;
+ current = current->next;
+ }
+
+ if(hwnd_stack_top) RepositionWindows();
+}
+
+void ClearStack() {
+ while(hwnd_stack_top) {
+ DestroyWindow(hwnd_stack_top->hwnd);
+ }
+}
+
+void BroadcastMessage(UINT msg, WPARAM wParam, LPARAM lParam) {
+ HWNDStackNode *current = hwnd_stack_top;
+ while(current) {
+ SendMessage(current->hwnd, msg, wParam, lParam);
+ current = current->next;
+ }
+}
+
+struct PopupWindowData {
+ POPUPDATAW *pd;
+ int new_x, new_y;
+ bool is_round, av_is_round, mouse_in, close_on_leave;
+ bool custom_col;
+ HBRUSH bkBrush, barBrush;
+ HPEN bPen;
+ TCHAR tbuff[128];
+ int tb_height, av_height, text_height, time_height, time_width;
+ int real_av_width, real_av_height;
+ bool have_av;
+ HANDLE hNotify;
+};
+
+void trim(TCHAR *str) {
+ int len = _tcslen(str), pos;
+ // trim whitespace (e.g. from OTR detection)
+ for(pos = len - 1; pos >= 0; pos--) {
+ if(str[pos] == _T(' ') || str[pos] == _T('\t') || str[pos] == _T('\r') || str[pos] == _T('\n')) str[pos] = 0;
+ else break;
+ }
+
+ // remove tabs
+ for(pos = len - 1; pos >= 0; pos--)
+ if(str[pos] == _T('\t')) str[pos] = _T(' ');
+}
+
+LRESULT CALLBACK PopupWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
+ PopupWindowData *pwd = (PopupWindowData *)GetWindowLong(hwnd, GWL_USERDATA);
+ POPUPDATAW *pd = 0;
+ if(pwd) pd = pwd->pd;
+
+ switch(uMsg) {
+ case WM_CREATE:
+ {
+ CREATESTRUCT *cs = (CREATESTRUCT *)lParam;
+ pwd = (PopupWindowData *)malloc(sizeof(PopupWindowData));
+ pd = (POPUPDATAW *)cs->lpCreateParams;
+ pwd->pd = pd;
+ pwd->hNotify = 0;
+
+ trim(pwd->pd->lpwzContactName);
+ trim(pwd->pd->lpwzText);
+
+ pwd->is_round = options.round;
+ pwd->av_is_round = options.av_round;
+ pwd->mouse_in = pwd->close_on_leave = false;
+ pwd->custom_col = (pd->colorBack != pd->colorText);
+
+ pwd->tb_height = pwd->av_height = pwd->text_height = pwd->time_height = pwd->time_width = 0;
+ pwd->have_av = false;
+
+ if(pwd->custom_col) {
+ pwd->bkBrush = CreateSolidBrush(pd->colorBack);
+
+ //pwd->barBrush = CreateSolidBrush(pd->colorBack / 2); // make sidebar a dark version of the bg
+ //DWORD darkBg = (((pd->colorBack & 0xff0000) >> 1) & 0xff0000) + (((pd->colorBack & 0xff00) >> 1) & 0xff00) + (((pd->colorBack & 0xff) >> 1) & 0xff);
+ //DWORD darkBg = (pdColorBack >> 1) & 0x7f7f7f; // equivalent to above :)
+
+ DWORD darkBg = pd->colorBack - ((pd->colorBack >> 2) & 0x3f3f3f); // 3/4 of current individual RGB components
+ pwd->barBrush = CreateSolidBrush(darkBg); // make sidebar a dark version of the bg
+ } else {
+ pwd->bkBrush = CreateSolidBrush(colBg);
+ pwd->barBrush = CreateSolidBrush(colSidebar); + }
+
+ if(options.border) pwd->bPen = (HPEN)CreatePen(PS_SOLID, 1, colBorder);
+ else pwd->bPen = CreatePen(PS_SOLID, 1, pwd->custom_col ? pd->colorBack : colBg);
+
+ SYSTEMTIME st;
+ GetLocalTime(&st);
+ GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, 0, pwd->tbuff, 128);
+
+ SetWindowLong(hwnd, GWL_USERDATA, (LONG)pwd);
+
+ if(pd->iSeconds == -1 || (pd->iSeconds == 0 && options.default_timeout == -1)) {
+ // make a really long timeout - say 7 days? ;)
+ SetTimer(hwnd, ID_CLOSETIMER, 7 * 24 * 60 * 60 * 1000, 0);
+ } else {
+ if(pd->iSeconds == 0) {
+ SetTimer(hwnd, ID_CLOSETIMER, options.default_timeout * 1000, 0);
+ } else {
+ SetTimer(hwnd, ID_CLOSETIMER, pd->iSeconds * 1000, 0);
+ }
+ }
+
+ AddWindowToStack(hwnd); // this updates our size
+ }
+
+ // transparency
+#ifdef WS_EX_LAYERED
+ SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
+#endif
+ +#ifdef CS_DROPSHADOW + if (options.drop_shadow) { + SetClassLong(hwnd, GCL_STYLE, CS_DROPSHADOW); + } +#endif +
+#ifdef LWA_ALPHA
+ if(MySetLayeredWindowAttributes) {
+ MySetLayeredWindowAttributes(hwnd, RGB(0,0,0), (int)(options.opacity / 100.0 * 255), LWA_ALPHA);
+ if(options.trans_bg) {
+ COLORREF bg;
+ if(pd->colorBack == pd->colorText)
+ bg = colBg;
+ else
+ bg = pd->colorBack;
+ MySetLayeredWindowAttributes(hwnd, bg, 0, LWA_COLORKEY);
+ }
+ }
+#endif
+ PostMessage(hwnd, UM_INITPOPUP, (WPARAM)hwnd, 0);
+ return 0;
+ case WM_MOUSEMOVE:
+ if(pwd && !pwd->mouse_in) {
+ pwd->mouse_in = true;
+ global_mouse_in++;
+ TRACKMOUSEEVENT tme = { sizeof(tme) };
+ tme.dwFlags = TME_LEAVE;
+ tme.hwndTrack = hwnd;
+ TrackMouseEvent(&tme);
+ }
+ break;
+ case WM_MOUSELEAVE:
+ if(pwd && pwd->mouse_in) {
+ pwd->mouse_in = false;
+ global_mouse_in--;
+ }
+ return 0;
+ case WM_LBUTTONUP:
+ // fake STN_CLICKED notification
+ SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(0, STN_CLICKED), 0);
+ break;
+ case WM_TIMER:
+ if(wParam == ID_CLOSETIMER) {
+ KillTimer(hwnd, ID_CLOSETIMER);
+ if(pwd->mouse_in || (options.global_hover && global_mouse_in))
+ SetTimer(hwnd, ID_CLOSETIMER, 800, 0); // reset timer if mouse in window - allow another 800 ms
+ else {
+ PostMessage(hwnd, UM_DESTROYPOPUP, 0, 0);
+ }
+ return TRUE;
+ } else if(wParam == ID_MOVETIMER) {
+ RECT r;
+ GetWindowRect(hwnd, &r);
+
+ if(r.left == pwd->new_x && r.top == pwd->new_y) {
+ KillTimer(hwnd, ID_MOVETIMER);
+ return TRUE;
+ }
+ int adj_x = (pwd->new_x - r.left) / 4, adj_y = (pwd->new_y - r.top) / 4;
+ if(adj_x == 0) adj_x = (pwd->new_x - r.left);
+ if(adj_y == 0) adj_y = (pwd->new_y - r.top);
+
+ int x = r.left + adj_x, y = r.top + adj_y;
+ //SetWindowPos(hwnd, 0, x, y, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOCOPYBITS);
+ SetWindowPos(hwnd, 0, x, y, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
+
+
+ /*
+ // clip to monitor bounds (paints badly!)
+ //HDC hdc = GetDC(hwnd);
+ HMONITOR hMonitor = MonitorFromRect(&r, MONITOR_DEFAULTTONEAREST);
+ MONITORINFO mi;
+ mi.cbSize = sizeof(mi);
+ GetMonitorInfo(hMonitor, &mi);
+
+ POINT p[2];
+ p[0].x = mi.rcWork.left; p[0].y = mi.rcWork.top; p[1].x = mi.rcWork.right; p[1].y = mi.rcWork.bottom;
+ //LPtoDP(hdc, p, 2);
+ ScreenToClient(hwnd, &p[0]); ScreenToClient(hwnd, &p[1]);
+
+ HRGN hMonRgn = CreateRectRgn(p[0].x, p[0].y, p[1].x, p[1].y);
+ //ReleaseDC(hwnd, hdc);
+
+ RECT cr; GetClientRect(hwnd, &cr);
+ HRGN hWndRgn = CreateRectRgn(cr.left, cr.top, cr.right + 3, cr.bottom + 3);
+ CombineRgn(hMonRgn, hMonRgn, hWndRgn, RGN_AND);
+
+ // round corners
+ if(options.round) {
+ HRGN hRgn1;
+ int v,h, w=10;
+ h=(r.right-r.left)>(w*2)?w:(r.right-r.left);
+ v=(r.bottom-r.top)>(w*2)?w:(r.bottom-r.top);
+ h=(h<v)?h:v;
+ hRgn1=CreateRoundRectRgn(0,0,(r.right-r.left+1),(r.bottom-r.top+1),h,h);
+ CombineRgn(hMonRgn, hMonRgn, hRgn1, RGN_AND);
+ DeleteObject(hRgn1);
+ }
+
+ SetWindowRgn(hwnd, hMonRgn, TRUE);
+
+ DeleteObject(hWndRgn);
+
+ InvalidateRect(hwnd, 0, TRUE);
+ */
+
+ if(!IsWindowVisible(hwnd)) {
+ ShowWindow(hwnd, SW_SHOWNOACTIVATE);
+ UpdateWindow(hwnd);
+ }
+ return TRUE;
+ }
+ break;
+ case WM_ERASEBKGND:
+ {
+ HDC hdc = (HDC) wParam; + RECT r, r_bar; + GetClientRect(hwnd, &r); + + // bg + FillRect(hdc, &r, pwd->bkBrush); + // sidebar + r_bar = r; + r_bar.right = r.left + options.sb_width; + FillRect(hdc, &r_bar, pwd->barBrush); + // border + if(options.border) { + + HBRUSH hOldBrush = (HBRUSH)SelectObject(hdc, GetStockObject(NULL_BRUSH)); + HPEN hOldPen = (HPEN)SelectObject(hdc, pwd->bPen); + + int h = 0; + if(options.round) { + int v; + int w=14; + h=(r.right-r.left)>(w*2)?w:(r.right-r.left); + v=(r.bottom-r.top)>(w*2)?w:(r.bottom-r.top); + h=(h<v)?h:v; + //} else { + // Rectangle(hdc, r.left, r.top, (r.right - r.left), (r.bottom - r.top)); + } + RoundRect(hdc, 0, 0, (r.right - r.left), (r.bottom - r.top), h, h); + + SelectObject(hdc, hOldBrush); + SelectObject(hdc, hOldPen); + } +
+ }
+ return TRUE;
+ case WM_PAINT:
+ {
+ RECT r;
+ //if(GetUpdateRect(hwnd, &r, TRUE)) {
+ PAINTSTRUCT ps;
+ BeginPaint(hwnd, &ps);
+ HDC hdc = ps.hdc;
+ GetClientRect(hwnd, &r);
+
+ // text background
+ //if(pwd->custom_col) SetBkColor(ps.hdc, pd->colorBack);
+ //else SetBkColor(ps.hdc, colBg);
+ SetBkMode(hdc, TRANSPARENT);
+
+ // avatar & time if with avatar
+ if(options.av_layout != PAV_NONE && (pwd->have_av || options.time_layout == PT_WITHAV)) {
+ RECT avr;
+ avr.top = options.av_padding;
+
+ if(options.av_layout == PAV_LEFT) {
+ avr.left = r.left + options.av_padding;
+ if(pwd->have_av && options.time_layout == PT_WITHAV) avr.right = avr.left + max(pwd->real_av_width, pwd->time_width);
+ else if(pwd->have_av) avr.right = avr.left + pwd->real_av_width;
+ else avr.right = avr.left + pwd->time_width;
+ r.left = avr.right;
+ } else if(options.av_layout == PAV_RIGHT) {
+ avr.right = r.right - options.av_padding;
+ if(pwd->have_av && options.time_layout == PT_WITHAV) avr.left = avr.right - max(pwd->real_av_width, pwd->time_width);
+ else if(pwd->have_av) avr.left = avr.right - pwd->real_av_width;
+ else avr.left = avr.right - pwd->time_width;
+ r.right = avr.left;
+ }
+
+ if(options.time_layout == PT_WITHAV) {
+ avr.top = options.padding;
+ avr.bottom = avr.top + pwd->time_height;
+ if(pwd->custom_col) SetTextColor(ps.hdc, pd->colorText);
+ else SetTextColor(ps.hdc, colTime);
+ if(hFontTime) SelectObject(hdc, (HGDIOBJ)hFontTime);
+ DrawText(ps.hdc, pwd->tbuff, wcslen(pwd->tbuff), &avr, DT_VCENTER | DT_CENTER | DT_LEFT | DT_SINGLELINE | DT_NOPREFIX);
+ avr.top = avr.bottom + options.av_padding;
+ }
+
+ if(pwd->have_av) {
+ // correct for wider time
+ if(options.time_layout == PT_WITHAV && pwd->time_width > options.av_size) {
+ avr.left = avr.left + (pwd->time_width - pwd->real_av_width) / 2;
+ avr.right = avr.left + pwd->real_av_width;
+ }
+ avr.bottom = avr.top + pwd->real_av_height;
+
+ AVATARDRAWREQUEST adr = {0};
+ adr.cbSize = sizeof(adr);
+ adr.hContact = pd->lchContact;
+ adr.hTargetDC = ps.hdc;
+ adr.rcDraw = avr;
+ adr.dwFlags = (pwd->is_round ? AVDRQ_ROUNDEDCORNER : 0);
+ adr.radius = (pwd->av_is_round ? 5 : 0);
+
+ CallService(MS_AV_DRAWAVATAR, 0, (LPARAM)&adr);
+ }
+ }
+
+ // title icon
+ int iconx, textxmin = r.left + options.padding, textxmax = r.right - options.padding;
+ if(pd->lchIcon) {
+ if(options.right_icon) {
+ iconx = r.right - (16 + options.padding);
+ textxmax -= 16 + options.padding;
+ } else {
+ iconx = r.left + options.padding;
+ textxmin += 16 + options.padding;
+ }
+ DrawIconEx(ps.hdc, iconx, options.padding + (pwd->tb_height - 16) / 2, pd->lchIcon, 16, 16, 0, NULL, DI_NORMAL);
+ }
+
+ // title time
+ if(options.time_layout == PT_LEFT || options.time_layout == PT_RIGHT) {
+ RECT ttr;
+ ttr.top = r.top + options.padding; ttr.bottom = ttr.top + pwd->tb_height;
+ if(pwd->custom_col) SetTextColor(ps.hdc, pd->colorText);
+ else SetTextColor(ps.hdc, colTime);
+ if(hFontTime) SelectObject(hdc, (HGDIOBJ)hFontTime);
+ switch(options.time_layout) {
+ case PT_LEFT:
+ ttr.left = textxmin; ttr.right = ttr.left + pwd->time_width;
+ textxmin += pwd->time_width + options.padding;
+ DrawText(ps.hdc, pwd->tbuff, wcslen(pwd->tbuff), &ttr, DT_VCENTER | DT_LEFT | DT_SINGLELINE | DT_NOPREFIX);
+ break;
+ case PT_RIGHT:
+ ttr.right = textxmax; ttr.left = ttr.right - pwd->time_width;
+ textxmax -= pwd->time_width + options.padding;
+ DrawText(ps.hdc, pwd->tbuff, wcslen(pwd->tbuff), &ttr, DT_VCENTER | DT_LEFT | DT_SINGLELINE | DT_NOPREFIX);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if(textxmin < options.sb_width) textxmin = options.sb_width + options.padding / 2;
+
+ // title text
+ if(hFontFirstLine) SelectObject(ps.hdc, (HGDIOBJ)hFontFirstLine);
+ RECT tr;
+ tr.left = textxmin; tr.right = textxmax; tr.top = r.top + options.padding; tr.bottom = tr.top + pwd->tb_height;
+
+ if(pwd->custom_col) SetTextColor(ps.hdc, pd->colorText);
+ else SetTextColor(ps.hdc, colFirstLine);
+ DrawText(ps.hdc, pd->lpwzContactName, wcslen(pd->lpwzContactName), &tr, DT_VCENTER | DT_LEFT | DT_END_ELLIPSIS | DT_SINGLELINE | DT_NOPREFIX);
+
+ // second line(s)
+ int len_second = wcslen(pd->lpwzText);
+ if(len_second) {
+ if(hFontSecondLine) SelectObject(ps.hdc, (HGDIOBJ)hFontSecondLine);
+ if(!pwd->custom_col)
+ SetTextColor(ps.hdc, colSecondLine);
+
+ // expand text if no avatar and the time isn't too large
+ if(options.av_layout != PAV_NONE && options.time_layout == PT_WITHAV && pwd->time_height <= pwd->tb_height && !pwd->have_av)
+ GetClientRect(hwnd, &r);
+
+ tr.left = r.left + options.padding + options.text_indent; tr.right = r.right - options.padding; tr.top = tr.bottom + options.padding; tr.bottom = r.bottom - options.padding;
+ DrawText(ps.hdc, pd->lpwzText, len_second, &tr, DT_NOPREFIX | DT_WORDBREAK | DT_EXTERNALLEADING | DT_TOP | DT_LEFT | DT_WORD_ELLIPSIS);
+ }
+
+ EndPaint(hwnd, &ps);
+ //}
+ }
+ return 0;
+ case WM_DESTROY:
+ if(pwd->mouse_in) global_mouse_in--;
+
+ ShowWindow(hwnd, SW_HIDE);
+
+ DeleteObject(pwd->bkBrush);
+ DeleteObject(pwd->bPen);
+ DeleteObject(pwd->barBrush); + KillTimer(hwnd, ID_MOVETIMER);
+ KillTimer(hwnd, ID_CLOSETIMER);
+
+ RemoveWindowFromStack(hwnd);
+
+ SendMessage(hwnd, UM_FREEPLUGINDATA, 0, 0);
+
+ free(pd); pd = 0;
+ free(pwd); pwd = 0;
+ SetWindowLong(hwnd, GWL_USERDATA, 0);
+
+ break;
+ case PUM_UPDATERGN:
+ // round corners
+ if(pwd->is_round) {
+ HRGN hRgn1;
+ RECT r;
+
+ int v,h;
+ int w=11;
+ GetWindowRect(hwnd,&r);
+ h=(r.right-r.left)>(w*2)?w:(r.right-r.left);
+ v=(r.bottom-r.top)>(w*2)?w:(r.bottom-r.top);
+ h=(h<v)?h:v;
+ hRgn1=CreateRoundRectRgn(0,0,(r.right-r.left) + 1,(r.bottom-r.top) + 1,h,h);
+ SetWindowRgn(hwnd,hRgn1,FALSE);
+ }
+ return TRUE;
+
+ case PUM_MOVE:
+ {
+ if(options.animate) {
+ KillTimer(hwnd, ID_MOVETIMER);
+ pwd->new_x = (int)wParam;
+ pwd->new_y = (int)lParam;
+ SetTimer(hwnd, ID_MOVETIMER, 10, 0);
+ } else {
+ SetWindowPos(hwnd, 0, (int)wParam, (int)lParam, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
+ if(!IsWindowVisible(hwnd)) {
+ ShowWindow(hwnd, SW_SHOWNOACTIVATE);
+ UpdateWindow(hwnd);
+ }
+ }
+ }
+ return TRUE;
+ case PUM_SETTEXT:
+ {
+ wcscpy(pd->lpwzText, (wchar_t *)lParam);
+ // free((void *)lParam); // freed in message pump in case the window has gone
+ InvalidateRect(hwnd, 0, TRUE);
+ RepositionWindows();
+ }
+ return TRUE;
+
+ case PUM_GETCONTACT:
+ {
+ HANDLE *phContact = (HANDLE *)wParam;
+ *phContact = pd->lchContact;
+ if(lParam) SetEvent((HANDLE)lParam);
+ }
+ return TRUE;
+ case PUM_GETHEIGHT:
+ {
+ int *pHeight = (int *)wParam;
+ HDC hdc = GetDC(hwnd);
+ SIZE size;
+
+ // time_height + width
+ if(options.time_layout != PT_NONE) {
+ SIZE size_t;
+ if(hFontTime) SelectObject(hdc, (HGDIOBJ)hFontTime);
+ GetTextExtentPoint32(hdc, pwd->tbuff, wcslen(pwd->tbuff), &size_t);
+ pwd->time_height = size_t.cy;
+ pwd->time_width = size_t.cx;
+ }
+
+ // titlebar height
+ if(hFontFirstLine) SelectObject(hdc, (HGDIOBJ)hFontFirstLine);
+ GetTextExtentPoint32(hdc, pd->lpwzContactName, wcslen(pd->lpwzContactName), &size);
+ pwd->tb_height = size.cy;
+ if(options.time_layout == PT_LEFT || options.time_layout == PT_RIGHT) {
+ if(pwd->tb_height < pwd->time_height) pwd->tb_height = pwd->time_height;
+ }
+ if(pwd->tb_height < 16) pwd->tb_height = 16;
+
+ // avatar height
+ if(options.av_layout != PAV_NONE && ServiceExists(MS_AV_DRAWAVATAR)) {
+ AVATARCACHEENTRY *ace = (AVATARCACHEENTRY *)CallService(MS_AV_GETAVATARBITMAP, (WPARAM)pd->lchContact, 0);
+ if(ace && (ace->dwFlags & AVS_BITMAP_VALID) && !(ace->dwFlags & AVS_HIDEONCLIST)) {
+ if(ace->bmHeight >= ace->bmWidth) { + pwd->real_av_height = options.av_size; + pwd->real_av_width = (int)(options.av_size * (ace->bmWidth / (double)ace->bmHeight)); + } else { + pwd->real_av_height = (int)(options.av_size * (ace->bmHeight / (double)ace->bmWidth)); + pwd->real_av_width = options.av_size; + } + pwd->have_av = true;
+ pwd->av_height = pwd->real_av_height;
+ }
+ }
+
+ // text height
+ int len_second = wcslen(pd->lpwzText);
+ if(len_second) {
+ RECT r;
+ r.left = r.top = 0;
+ r.right = options.win_width - 2 * options.padding - options.text_indent;
+ if(pwd->have_av && options.time_layout == PT_WITHAV)
+ r.right -= (max(options.av_size, pwd->time_width) + options.padding);
+ else if(pwd->have_av)
+ r.right -= (options.av_size + options.padding);
+ else if(options.av_layout != PAV_NONE && options.time_layout == PT_WITHAV && pwd->time_height >= pwd->tb_height)
+ r.right -= pwd->time_width + options.padding;
+
+ if(hFontSecondLine) SelectObject(hdc, (HGDIOBJ)hFontSecondLine);
+ DrawText(hdc, pd->lpwzText, len_second, &r, DT_CALCRECT | DT_NOPREFIX | DT_WORDBREAK | DT_EXTERNALLEADING | DT_TOP | DT_LEFT | DT_WORD_ELLIPSIS);
+ pwd->text_height = r.bottom;
+ }
+
+ ReleaseDC(hwnd, hdc);
+
+ if(options.time_layout == PT_WITHAV && options.av_layout != PAV_NONE)
+ *pHeight = max(pwd->tb_height + pwd->text_height + 3 * options.padding, pwd->av_height + pwd->time_height + options.padding + 2 * options.av_padding);
+ else
+ *pHeight = max(pwd->tb_height + pwd->text_height + 3 * options.padding, pwd->av_height + 2 * options.av_padding);
+
+ if(*pHeight > options.win_max_height) *pHeight = options.win_max_height;
+
+ RECT r;
+ GetWindowRect(hwnd, &r);
+ if(r.right - r.left != options.win_width || r.bottom - r.top != *pHeight) {
+ SetWindowPos(hwnd, 0, 0, 0, options.win_width, *pHeight, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
+ SendMessage(hwnd, PUM_UPDATERGN, 0, 0);
+ InvalidateRect(hwnd, 0, TRUE);
+ }
+ }
+ return TRUE;
+ case PUM_GETPLUGINDATA:
+ {
+ void **pData = (void **)wParam;
+ if(pd) *pData = pd->PluginData;
+ if(lParam) SetEvent((HANDLE)lParam);
+ }
+ return TRUE;
+ case PUM_CHANGE:
+ {
+ KillTimer(hwnd, ID_CLOSETIMER);
+ free(pd);
+ pwd->pd = pd = (POPUPDATAW *)malloc(sizeof(POPUPDATAW));
+ memcpy(pd, (void *)lParam, sizeof(POPUPDATAW)); // the passed in value is freed in the message pump, in case the window has gone
+
+ if(pd->iSeconds != -1) {
+ if(pd->iSeconds == 0) {
+ SetTimer(hwnd, ID_CLOSETIMER, 7 * 1000, 0);
+ } else {
+ SetTimer(hwnd, ID_CLOSETIMER, pd->iSeconds * 1000, 0);
+ }
+ } else {
+ // make a really long timeout - say 7 days? ;)
+ SetTimer(hwnd, ID_CLOSETIMER, 7 * 24 * 60 * 60 * 1000, 0);
+ }
+
+ InvalidateRect(hwnd, 0, TRUE);
+ RepositionWindows();
+ }
+ return TRUE;
+
+ case PUM_SETNOTIFYH:
+ pwd->hNotify = (HANDLE)wParam;
+ return TRUE;
+
+ case PUM_UPDATENOTIFY:
+ if(pwd->hNotify == (HANDLE)wParam) {
+ pd->colorBack = MNotifyGetDWord(pwd->hNotify, NFOPT_BACKCOLOR, colBg);
+ pd->colorText = MNotifyGetDWord(pwd->hNotify, NFOPT_TEXTCOLOR, colSecondLine);
+ pd->iSeconds = MNotifyGetDWord(pwd->hNotify, NFOPT_TIMEOUT, options.default_timeout);
+ pd->lchContact = (HANDLE)MNotifyGetDWord(pwd->hNotify, NFOPT_CONTACT, 0);
+ pd->lchIcon = (HICON)MNotifyGetDWord(pwd->hNotify, NFOPT_ICON, 0);
+ const wchar_t *swzName = MNotifyGetWString(pwd->hNotify, NFOPT_TITLEW, 0);
+ if(swzName) {
+ wcsncpy(pd->lpwzContactName, swzName, MAX_CONTACTNAME);
+ } else {
+ const char *szName = MNotifyGetString(pwd->hNotify, NFOPT_TITLE, 0);
+ if(szName) MultiByteToWideChar(code_page, 0, szName, -1, pd->lpwzContactName, MAX_CONTACTNAME);
+ else pd->lpwzContactName[0] = 0;
+ }
+ pd->lpwzContactName[MAX_CONTACTNAME - 1] = 0;
+
+ const wchar_t *swzText = MNotifyGetWString(pwd->hNotify, NFOPT_TEXTW, 0);
+ if(swzText) {
+ wcsncpy(pd->lpwzText, swzText, MAX_SECONDLINE);
+ } else {
+ const char *szText = MNotifyGetString(pwd->hNotify, NFOPT_TEXT, 0);
+ if(szText) MultiByteToWideChar(code_page, 0, szText, -1, pd->lpwzText, MAX_SECONDLINE);
+ else pd->lpwzText[0] = 0;
+ }
+ pd->lpwzText[MAX_SECONDLINE - 1] = 0;
+ InvalidateRect(hwnd, 0, TRUE);
+ RepositionWindows();
+ }
+
+ return TRUE;
+ case PUM_KILLNOTIFY:
+ if(pwd->hNotify != (HANDLE)wParam)
+ return TRUE;
+ // drop through
+
+ case UM_DESTROYPOPUP:
+ PostMPMessage(MUM_DELETEPOPUP, 0, (LPARAM)hwnd);
+ return TRUE;
+ }
+
+
+ if(pd && pd->PluginWindowProc)
+ return CallWindowProc(pd->PluginWindowProc, hwnd, uMsg, wParam, lParam);
+ else {
+ // provide a way to close popups, if no PluginWindowProc is provided
+ if(uMsg == WM_CONTEXTMENU) {
+ SendMessage(hwnd, UM_DESTROYPOPUP, 0, 0);
+ return TRUE;
+ } else
+ return DefWindowProc(hwnd, uMsg, wParam, lParam);
+ }
+}
+
+int AvatarChanged(WPARAM wParam, LPARAM lParam) {
+ RepositionWindows();
+ return 0;
+}
+
+void InitWindowStack() {
+ hUserDll = LoadLibrary(_T("user32.dll"));
+ if (hUserDll) {
+ MySetLayeredWindowAttributes = (BOOL (WINAPI *)(HWND,COLORREF,BYTE,DWORD))GetProcAddress(hUserDll, "SetLayeredWindowAttributes");
+ MyAnimateWindow=(BOOL (WINAPI*)(HWND,DWORD,DWORD))GetProcAddress(hUserDll,"AnimateWindow");
+ }
+}
+
+void DeinitWindowStack() {
+ ClearStack();
+ if(hUserDll) FreeLibrary(hUserDll);
+}
+
diff --git a/yapp/popwin.h b/yapp/popwin.h new file mode 100644 index 0000000..951a6ba --- /dev/null +++ b/yapp/popwin.h @@ -0,0 +1,27 @@ +#ifndef _POPWIN_INC
+#define _POPWIN_INC
+
+#define POP_WIN_CLASS _T(MODULE) _T("WinClass")
+
+#define PUM_SETTEXT (WM_USER + 0x020)
+#define PUM_GETCONTACT (WM_USER + 0x021)
+#define PUM_GETPLUGINDATA (WM_USER + 0x022)
+#define PUM_CHANGE (WM_USER + 0x023)
+#define PUM_MOVE (WM_USER + 0x024)
+#define PUM_GETHEIGHT (WM_USER + 0x025)
+#define PUM_UPDATERGN (WM_USER + 0x026)
+
+#define PUM_SETNOTIFYH (WM_USER + 0x030)
+#define PUM_KILLNOTIFY (WM_USER + 0x031)
+#define PUM_UPDATENOTIFY (WM_USER + 0x032)
+
+void InitWindowStack();
+void DeinitWindowStack();
+
+void BroadcastMessage(UINT msg, WPARAM wParam, LPARAM lParam);
+int AvatarChanged(WPARAM wParam, LPARAM lParam); // exposed so hook/unhook is in main thread
+
+LRESULT CALLBACK PopupWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+
+#endif
diff --git a/yapp/resource.h b/yapp/resource.h new file mode 100644 index 0000000..2ba26c1 --- /dev/null +++ b/yapp/resource.h @@ -0,0 +1,68 @@ +//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by popups2.rc
+//
+#define IDD_OPT1 101
+#define IDD_DIALOG1 102
+#define IDD_OPT_NOTIFY 103
+#define IDD_LST_HISTORY 104
+#define IDC_RAD_NOTIMEOUT 1001
+#define IDC_RAD_TIMEOUT 1002
+#define IDC_ED_TIMEOUT 1003
+#define IDC_SPIN_TIMEOUT 1004
+#define IDC_ED_WIDTH 1005
+#define IDC_ED_MAXHEIGHT 1006
+#define IDC_SPIN_WIDTH 1007
+#define IDC_SPIN3 1008
+#define IDC_SPIN_MAXHEIGHT 1009
+#define IDC_RAD_BOTTOMRIGHT 1010
+#define IDC_ED_INDENT 1011
+#define IDC_RAD_BOTTOMLEFT 1012
+#define IDC_ED_SBWIDTH 1012
+#define IDC_SPIN_INDENT 1013
+#define IDC_RAD_TOPRIGHT 1014
+#define IDC_SPIN_SBWIDTH 1014
+#define IDC_RAD_TOPLEFT 1015
+#define IDC_ED_PADDING 1015
+#define IDC_ED_TRANS 1016
+#define IDC_SPIN_TRANS 1017
+#define IDC_CHK_BORDER 1018
+#define IDC_CHK_ROUNDCORNERS 1019
+#define IDC_BTN_PREVIEW 1020
+#define IDC_CHK_ANIMATE 1021
+#define IDC_CHK_TRANSBG 1022
+#define IDC_RAD_RIGHTICON 1023
+#define IDC_SPIN_INDENT2 1023
+#define IDC_SPIN_PADDING 1023
+#define IDC_CHK_GLOBALHOVER 1024
+#define IDC_RAD_LEFTICON 1025
+#define IDC_CHK_ROUNDCORNERSAV 1025
+#define IDC_RAD_NOAV 1026
+#define IDC_RAD_RIGHTAV 1027
+#define IDC_RAD_NOAV3 1028
+#define IDC_RAD_LEFTAV 1029
+#define IDC_ED_MAXHEIGHT2 1030
+#define IDC_ED_AVSIZE 1031
+#define IDC_SPIN_AVSIZE 1032
+#define IDC_LST_STATUS 1033
+#define IDC_CMB_PLACEMENT 1034
+#define IDC_CMB_ICON 1035
+#define IDC_CMB_AV 1036
+#define IDC_CMB_AV2 1037
+#define IDC_CMB_TIME 1038
+#define IDC_CUSTOM1 1039
+#define IDC_BORDERCOLOUR 1040
+#define IDC_CLOSE 1041
+#define IDC_LIST3 1042
+#define IDC_LST_HISTORY 1043
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 105
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1044
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/yapp/resource.rc b/yapp/resource.rc new file mode 100644 index 0000000..f39a424 --- /dev/null +++ b/yapp/resource.rc @@ -0,0 +1,6 @@ +
+// this makes our dependencies work better
+#include "version.h"
+
+#include "popups2.rc"
+#include "version.rc"
diff --git a/yapp/services.cpp b/yapp/services.cpp new file mode 100644 index 0000000..28f2b5b --- /dev/null +++ b/yapp/services.cpp @@ -0,0 +1,363 @@ +#include "common.h" +#include "services.h" +#include "popwin.h" +#include "message_pump.h" +#include "resource.h" +#include "popup_history.h" +#include <time.h> + +#define NUM_SERVICES 13 +HANDLE hService[NUM_SERVICES]; +HANDLE hMenuShowHistory, hMenuToggleOnOff; + +void StripBBCodesInPlace(wchar_t *text) { + if(!DBGetContactSettingByte(0, MODULE, "StripBBCodes", 1)) + return; + + int read = 0, write = 0; + int len = wcslen(text); + + while(read <= len) { // copy terminating null too + while(read <= len && text[read] != L'[') { + if(text[read] != text[write]) text[write] = text[read]; + read++; write++; + } + if(read == len) break; + + if(len - read >= 3 && (wcsnicmp(text + read, L"[b]", 3) == 0 || wcsnicmp(text + read, L"[i]", 3) == 0)) + read += 3; + else if(len - read >= 4 && (wcsnicmp(text + read, L"[/b]", 4) == 0 || wcsnicmp(text + read, L"[/i]", 4) == 0)) + read += 4; + else if(len - read >= 6 && (wcsnicmp(text + read, L"[color", 6) == 0)) { + while(read < len && text[read] != L']') read++; + read++;// skip the ']' + } else if(len - read >= 8 && (wcsnicmp(text + read, L"[/color]", 8) == 0)) + read += 8; + else { + if(text[read] != text[write]) text[write] = text[read]; + read++; write++; + } + } +} + +int CreatePopupA(WPARAM wParam, LPARAM lParam) { + if(!DBGetContactSettingByte(0, MODULE, "Enabled", 1)) return 0; + + POPUPDATA *pd_in = (POPUPDATA *)wParam; + POPUPDATAW *pd_out = (POPUPDATAW *)malloc(sizeof(POPUPDATAW)); + + MultiByteToWideChar(code_page, 0, pd_in->lpzContactName, -1, pd_out->lpwzContactName, MAX_CONTACTNAME); + MultiByteToWideChar(code_page, 0, pd_in->lpzText, -1, pd_out->lpwzText, MAX_SECONDLINE); + pd_out->lpwzContactName[MAX_CONTACTNAME - 1] = 0; + pd_out->lpwzText[MAX_SECONDLINE - 1] = 0; + StripBBCodesInPlace(pd_out->lpwzContactName); + StripBBCodesInPlace(pd_out->lpwzText); + + pd_out->lchContact = pd_in->lchContact; + pd_out->lchIcon = pd_in->lchIcon; + if(pd_in->colorBack == 0xffffffff) // that's the old #define for 'skinned bg' + pd_out->colorBack = pd_out->colorText = 0; + else { + pd_out->colorBack = pd_in->colorBack & 0xFFFFFF; + pd_out->colorText = pd_in->colorText & 0xFFFFFF; + } + pd_out->PluginWindowProc = pd_in->PluginWindowProc; + pd_out->PluginData = pd_in->PluginData; + pd_out->iSeconds = 0; + + lstPopupHistory.Add(pd_out->lpwzContactName, pd_out->lpwzText, time(0)); + + if(!DBGetContactSettingByte(0, MODULE, "Enabled", 1)) { + free(pd_out); + return 0; + } + + //MessageBox(0, pd_out->lpwzContactName, _T("CreatePopupA"), MB_OK); + PostMPMessage(MUM_CREATEPOPUP, 0, (LPARAM)pd_out); + return 0; +} + +int CreatePopupExA(WPARAM wParam, LPARAM lParam) { + + POPUPDATAEX *pd_in = (POPUPDATAEX *)wParam; + POPUPDATAW *pd_out = (POPUPDATAW *)malloc(sizeof(POPUPDATAW)); + + MultiByteToWideChar(code_page, 0, pd_in->lpzContactName, -1, pd_out->lpwzContactName, MAX_CONTACTNAME); + MultiByteToWideChar(code_page, 0, pd_in->lpzText, -1, pd_out->lpwzText, MAX_SECONDLINE); + pd_out->lpwzContactName[MAX_CONTACTNAME - 1] = 0; + pd_out->lpwzText[MAX_SECONDLINE - 1] = 0; + StripBBCodesInPlace(pd_out->lpwzContactName); + StripBBCodesInPlace(pd_out->lpwzText); + + pd_out->lchContact = pd_in->lchContact; + pd_out->lchIcon = pd_in->lchIcon; + if(pd_in->colorBack == 0xffffffff) // that's the old #define for 'skinned bg' + pd_out->colorBack = pd_out->colorText = 0; + else { + pd_out->colorBack = pd_in->colorBack & 0xFFFFFF; + pd_out->colorText = pd_in->colorText & 0xFFFFFF; + } + pd_out->PluginWindowProc = pd_in->PluginWindowProc; + pd_out->PluginData = pd_in->PluginData; + pd_out->iSeconds = pd_in->iSeconds; + + lstPopupHistory.Add(pd_out->lpwzContactName, pd_out->lpwzText, time(0)); + if(!DBGetContactSettingByte(0, MODULE, "Enabled", 1)) { + free(pd_out); + return 0; + } + + //MessageBox(0, pd_out->lpwzContactName, _T("CreatePopupExA"), MB_OK); + PostMPMessage(MUM_CREATEPOPUP, 0, (LPARAM)pd_out); + return 0; +} + +int CreatePopupW(WPARAM wParam, LPARAM lParam) { + + POPUPDATAW *pd_in = (POPUPDATAW *)wParam; + POPUPDATAW *pd_out = (POPUPDATAW *)malloc(sizeof(POPUPDATAW)); + memcpy(pd_out, pd_in, sizeof(POPUPDATAW)); + pd_out->lpwzContactName[MAX_CONTACTNAME - 1] = 0; + pd_out->lpwzText[MAX_SECONDLINE - 1] = 0; + StripBBCodesInPlace(pd_out->lpwzContactName); + StripBBCodesInPlace(pd_out->lpwzText); + + if(pd_in->colorBack == 0xffffffff) // that's the old #define for 'skinned bg' + pd_out->colorBack = pd_out->colorText = 0; + else { + pd_out->colorBack &= 0xFFFFFF; + pd_out->colorText &= 0xFFFFFF; + } + + lstPopupHistory.Add(pd_out->lpwzContactName, pd_out->lpwzText, time(0)); + if(!DBGetContactSettingByte(0, MODULE, "Enabled", 1)) { + free(pd_out); + return 0; + } + + //MessageBox(0, pd_out->lpwzContactName, _T("CreatePopupW"), MB_OK); + PostMPMessage(MUM_CREATEPOPUP, 0, (LPARAM)pd_out); + return 0; +} + +int ChangeTextW(WPARAM wParam, LPARAM lParam) { + HWND hwndPop = (HWND)wParam; + wchar_t *newText = wcsdup((wchar_t *)lParam); + StripBBCodesInPlace(newText); + + if(IsWindow(hwndPop)) + PostMessage(hwndPop, PUM_SETTEXT, 0, (LPARAM)newText); + return 0; +} + +int ChangeTextA(WPARAM wParam, LPARAM lParam) { + HWND hwndPop = (HWND)wParam; + char *newText = (char *)lParam; + wchar_t buff[MAX_SECONDLINE]; + MultiByteToWideChar(code_page, 0, newText, -1, buff, MAX_SECONDLINE); + buff[MAX_SECONDLINE - 1] = 0; + StripBBCodesInPlace(buff); + + if(IsWindow(hwndPop)) + PostMessage(hwndPop, PUM_SETTEXT, 0, (LPARAM)wcsdup(buff)); + return 0; +} + +int GetContact(WPARAM wParam, LPARAM lParam) { + HWND hwndPop = (HWND)wParam; + HANDLE hContact; + if(GetCurrentThreadId() == message_pump_thread_id) { + SendMessage(hwndPop, PUM_GETCONTACT, (WPARAM)&hContact, 0); + } else { + HANDLE hEvent = CreateEvent(0, 0, 0, 0); + PostMessage(hwndPop, PUM_GETCONTACT, (WPARAM)&hContact, (LPARAM)hEvent); + //WaitForSingleObject(hEvent, INFINITE); + MsgWaitForMultipleObjectsEx(1, &hEvent, INFINITE, 0, 0); + CloseHandle(hEvent); + } + + return (int)hContact; +} + +int GetPluginData(WPARAM wParam, LPARAM lParam) { + HWND hwndPop = (HWND)wParam; + void *data = 0; + if(GetCurrentThreadId() == message_pump_thread_id) { + SendMessage(hwndPop, PUM_GETPLUGINDATA, (WPARAM)&data, 0); + } else { + HANDLE hEvent = CreateEvent(0, 0, 0, 0); + PostMessage(hwndPop, PUM_GETPLUGINDATA, (WPARAM)&data, (LPARAM)hEvent); + //WaitForSingleObject(hEvent, INFINITE); + MsgWaitForMultipleObjectsEx(1, &hEvent, INFINITE, 0, 0); + CloseHandle(hEvent); + } + + if(lParam && !ignore_gpd_passed_addy) { + void **pData = (void **)lParam; + *pData = data; + } + + return (int)data; +} + +int IsSecondLineShown(WPARAM wParam, LPARAM lParam) { + return TRUE; +} + +int PopupQuery(WPARAM wParam, LPARAM lParam) { + switch(wParam) { + case PUQS_ENABLEPOPUPS: + { + bool enabled = (DBGetContactSettingByte(0, MODULE, "Enabled", 1) == 1); + if(!enabled) DBWriteContactSettingByte(0, MODULE, "Enabled", 1); + return enabled ? 0: 1; + } + break; + case PUQS_DISABLEPOPUPS: + { + bool enabled = (DBGetContactSettingByte(0, MODULE, "Enabled", 1) == 1); + if(enabled) DBWriteContactSettingByte(0, MODULE, "Enabled", 0); + DBWriteContactSettingByte(0, MODULE, "Enabled", 0); + return enabled ? 1 : 0; + } + break; + case PUQS_GETSTATUS: + return DBGetContactSettingByte(0, MODULE, "Enabled", 1); + default: + return 1; + } + return 0; +} + +int TogglePopups(WPARAM wParam, LPARAM lParam) { + CLISTMENUITEM menu; + menu.cbSize = sizeof(CLISTMENUITEM); + // just write to db - the rest is handled in the Meta_SettingChanged function + if(DBGetContactSettingByte(0, MODULE, "Enabled", 1)) { + DBWriteContactSettingByte(0, MODULE, "Enabled", 0); + // modify main menu item + menu.flags = CMIM_NAME;// | CMIM_ICON; + menu.hIcon=0; //LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MCMENUOFF)); + menu.pszName = (char *)Translate("Enable Popups"); + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuToggleOnOff, (LPARAM)&menu); + } else { + DBWriteContactSettingByte(0, MODULE, "Enabled", 1); + // modify main menu item + menu.flags = CMIM_NAME;// | CMIM_ICON; + menu.hIcon=0;//LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MCMENU)); + menu.pszName = (char *)Translate("Disable Popups"); + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuToggleOnOff, (LPARAM)&menu); + } + return 0; +} + +int PopupChange(WPARAM wParam, LPARAM lParam) { + HWND hwndPop = (HWND)wParam; + POPUPDATAEX *pd_in = (POPUPDATAEX *)lParam; + + if(IsWindow(hwndPop)) { + POPUPDATAW *pd_out = (POPUPDATAW *)malloc(sizeof(POPUPDATAW)); + + MultiByteToWideChar(code_page, 0, pd_in->lpzContactName, -1, pd_out->lpwzContactName, MAX_CONTACTNAME); + MultiByteToWideChar(code_page, 0, pd_in->lpzText, -1, pd_out->lpwzText, MAX_SECONDLINE); + + pd_out->lchContact = pd_in->lchContact; + pd_out->lchIcon = pd_in->lchIcon; + if(pd_in->colorBack == 0xffffffff) // that's the old #define for 'skinned bg' + pd_out->colorBack = pd_out->colorText = 0; + else { + pd_out->colorBack = pd_in->colorBack & 0xFFFFFF; + pd_out->colorText = pd_in->colorText & 0xFFFFFF; + } + pd_out->colorBack = pd_in->colorBack; + pd_out->colorText = pd_in->colorText; + pd_out->PluginWindowProc = pd_in->PluginWindowProc; + pd_out->PluginData = pd_in->PluginData; + pd_out->iSeconds = pd_in->iSeconds; + + lstPopupHistory.Add(pd_out->lpwzContactName, pd_out->lpwzText, time(0)); + + PostMessage(hwndPop, PUM_CHANGE, 0, (LPARAM)pd_out); + } + return 0; +} + +int ShowMessage(WPARAM wParam, LPARAM lParam) { + if(!DBGetContactSettingByte(0, MODULE, "Enabled", 1)) return 0; + + POPUPDATAW pd = {0}; + wcscpy(pd.lpwzContactName, lParam == SM_WARNING ? _T("Warning") : _T("Notification")); + pd.lchIcon = LoadIcon(0, lParam == SM_WARNING ? IDI_WARNING : IDI_INFORMATION); + wchar_t buff[MAX_SECONDLINE]; + MultiByteToWideChar(code_page, 0, (char *)wParam, -1, buff, MAX_SECONDLINE); + wcscpy(pd.lpwzText, buff); + + CallService(MS_POPUP_ADDPOPUPW, (WPARAM)&pd, 0); + + return 0; +} + +//=====PopUp/ShowHistory +//extern BOOL CALLBACK DlgProcHistLstOpts(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); +int PopUp_ShowHistory(WPARAM wParam, LPARAM lParam) +{ + if (!hHistoryWindow) { + hHistoryWindow = CreateDialog(hInst, MAKEINTRESOURCE(IDD_LST_HISTORY), NULL, DlgProcHistLst); + } + ShowWindow(hHistoryWindow, SW_SHOW); + return 0; +} + +int PrebuildMenu(WPARAM wParam, LPARAM lParam) { + return 0; +} + +HANDLE hEventBuildMenu; + +void InitServices() { + int i = 0; + hService[i++] = CreateServiceFunction(MS_POPUP_ADDPOPUP, CreatePopupA); + hService[i++] = CreateServiceFunction(MS_POPUP_ADDPOPUPEX, CreatePopupExA); + hService[i++] = CreateServiceFunction(MS_POPUP_ADDPOPUPW, CreatePopupW); + hService[i++] = CreateServiceFunction(MS_POPUP_CHANGETEXTW, ChangeTextW); + hService[i++] = CreateServiceFunction(MS_POPUP_CHANGETEXT, ChangeTextA); + hService[i++] = CreateServiceFunction(MS_POPUP_CHANGE, PopupChange); + hService[i++] = CreateServiceFunction(MS_POPUP_GETCONTACT, GetContact); + hService[i++] = CreateServiceFunction(MS_POPUP_GETPLUGINDATA, GetPluginData); + hService[i++] = CreateServiceFunction(MS_POPUP_ISSECONDLINESHOWN, IsSecondLineShown); + hService[i++] = CreateServiceFunction(MS_POPUP_QUERY, PopupQuery); + + hService[i++] = CreateServiceFunction(MS_POPUP_SHOWMESSAGE, ShowMessage); + + hService[i++] = CreateServiceFunction(MS_POPUP_SHOWHISTORY, PopUp_ShowHistory); + hService[i++] = CreateServiceFunction("PopUp/ToggleEnabled", TogglePopups); + + CLISTMENUITEM menu = {0}; + + menu.cbSize=sizeof(menu); + menu.flags = CMIM_ALL; + + menu.hIcon=0; + menu.position = 500010000; + menu.pszPopupName = Translate("PopUps"); + + menu.pszService= MS_POPUP_SHOWHISTORY; + menu.pszName = Translate("Popup History"); + hMenuShowHistory = (HANDLE)CallService(MS_CLIST_ADDMAINMENUITEM, 0, (LPARAM)&menu); + + menu.pszService= "PopUp/ToggleEnabled"; + menu.pszName = (DBGetContactSettingByte(0, MODULE, "Enabled", 1) == 1 ? Translate("Disable Popups") : Translate("Enable Popups")); + hMenuToggleOnOff = (HANDLE)CallService(MS_CLIST_ADDMAINMENUITEM, 0, (LPARAM)&menu); + + hEventBuildMenu = HookEvent(ME_CLIST_PREBUILDCONTACTMENU, PrebuildMenu); + + if(ServiceExists(MS_LANGPACK_GETCODEPAGE)) + code_page = CallService(MS_LANGPACK_GETCODEPAGE, 0, 0); +} + +void DeinitServices() { + UnhookEvent(hEventBuildMenu); + + for(int i = 0; i < NUM_SERVICES; i++) + if(hService[i]) DestroyServiceFunction(hService[i]); +} diff --git a/yapp/services.h b/yapp/services.h new file mode 100644 index 0000000..35f6285 --- /dev/null +++ b/yapp/services.h @@ -0,0 +1,25 @@ +#ifndef _SERVICES_INC
+#define _SERVICES_INC
+
+void InitServices();
+void DeinitServices();
+
+/*
+int CreatePopupA(WPARAM wParam, LPARAM lParam);
+int CreatePopupExA(WPARAM wParam, LPARAM lParam);
+int CreatePopupW(WPARAM wParam, LPARAM lParam);
+int ChangeTextW(WPARAM wParam, LPARAM lParam);
+int ChangeTextA(WPARAM wParam, LPARAM lParam);
+int GetContact(WPARAM wParam, LPARAM lParam);
+int GetPluginData(WPARAM wParam, LPARAM lParam);
+int IsSecondLineShown(WPARAM wParam, LPARAM lParam);
+int PopupQuery(WPARAM wParam, LPARAM lParam);
+int PopupChange(WPARAM wParam, LPARAM lParam);
+int ShowMessage(WPARAM wParam, LPARAM lParam);
+
+int PopUp_ShowHistory(WPARAM wParam, LPARAM lParam);
+
+int TogglePopups(WPARAM wParam, LPARAM lParam);
+*/
+
+#endif
diff --git a/yapp/version.h b/yapp/version.h new file mode 100644 index 0000000..c02ba06 --- /dev/null +++ b/yapp/version.h @@ -0,0 +1,23 @@ +#ifndef __VERSION_H_INCLUDED
+#define __VERSION_H_INCLUDED
+
+#define __MAJOR_VERSION 0
+#define __MINOR_VERSION 1
+#define __RELEASE_NUM 4
+#define __BUILD_NUM 3
+
+#define __FILEVERSION_STRING __MAJOR_VERSION,__MINOR_VERSION,__RELEASE_NUM,__BUILD_NUM
+#define __FILEVERSION_STRING_DOTS __MAJOR_VERSION.__MINOR_VERSION.__RELEASE_NUM.__BUILD_NUM
+#define __STRINGIFY(x) #x
+#define __VERSION_STRING __STRINGIFY(__FILEVERSION_STRING_DOTS)
+
+#define __DESC "Yet Another Popup Plugin - provides popup notification window services (unicode and ansi) to other plugins"
+#define __AUTHOR "Scott Ellis"
+#define __AUTHOREMAIL "mail@scottellis.com.au"
+#define __COPYRIGHT "© 2005,2006 Scott Ellis"
+#define __AUTHORWEB "http://www.scottellis.com.au"
+
+#define __PLUGIN_NAME "YAPP"
+#define __FILENAME "yapp.dll"
+
+#endif //__VERSION_H_INCLUDED
diff --git a/yapp/version.rc b/yapp/version.rc new file mode 100644 index 0000000..842659d --- /dev/null +++ b/yapp/version.rc @@ -0,0 +1,34 @@ +
+#include <windows.h>
+#include "version.h"
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION __FILEVERSION_STRING
+ PRODUCTVERSION __FILEVERSION_STRING
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "000004b0"
+ BEGIN
+ VALUE "Author", __AUTHOR
+ VALUE "FileDescription", __DESC
+ VALUE "FileVersion", __VERSION_STRING
+ VALUE "InternalName", __PLUGIN_NAME
+ VALUE "LegalCopyright", __COPYRIGHT
+ VALUE "OriginalFilename", __FILENAME
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0, 1200
+ END
+END
|