diff options
Diffstat (limited to 'message_notify/messagenotify.cpp')
-rw-r--r-- | message_notify/messagenotify.cpp | 372 |
1 files changed, 372 insertions, 0 deletions
diff --git a/message_notify/messagenotify.cpp b/message_notify/messagenotify.cpp new file mode 100644 index 0000000..69595b2 --- /dev/null +++ b/message_notify/messagenotify.cpp @@ -0,0 +1,372 @@ +////////////////////////////////////
+/// This Miranda plugin (http://www.miranda-im.org) is released under the General Public Licence,
+/// available at http://www.gnu.org/copyleft/gpl.html
+/// Copyright Scott Ellis 2005 (mail@scottellis.com.au .. www.scottellis.com.au)
+////////////////////////////////////
+
+#include "common.h"
+#include "options.h"
+#include "popups.h"
+#include <time.h>
+
+HINSTANCE hInst;
+PLUGINLINK *pluginLink;
+
+HANDLE mainThread;
+
+bool metacontacts_installed;
+bool unicode_system;
+
+int code_page = CP_ACP;
+
+HANDLE popupWindowList;
+
+DWORD focusTimerId = 0;
+
+PLUGININFO pluginInfo={
+ sizeof(PLUGININFO),
+ "Message Notify",
+ PLUGIN_MAKE_VERSION(0,1,1,1),
+ "Show a popup when a message is received",
+ "Scott Ellis",
+ "mail@scottellis.com.au",
+ "© 2005 Scott Ellis",
+ "http://www.scottellis.com.au/",
+ 0, //not transient
+ 0 //doesn't replace anything built-in
+};
+
+
+extern "C" BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
+{
+ hInst=hinstDLL;
+ DisableThreadLibraryCalls(hInst);
+ return TRUE;
+}
+
+extern "C" __declspec(dllexport) PLUGININFO* MirandaPluginInfo(DWORD mirandaVersion)
+{
+ return &pluginInfo;
+}
+
+HANDLE hWindowEvent, hEventDbEventAdded, hIdle;
+BOOL bIsIdle = FALSE;
+
+bool window_focussed(HWND hwnd, HANDLE hContact) {
+ HWND parent;
+ while((parent = GetParent(hwnd)) != 0) hwnd = parent; // ensure we have the top level window (need parent window for scriver & tabsrmm)
+
+ // consider minimized window not-focussed
+ WINDOWPLACEMENT wp = {0};
+ wp.length = sizeof(wp);
+ GetWindowPlacement(hwnd, &wp);
+ if(hwnd == GetForegroundWindow() && !(wp.showCmd & SW_SHOWMINIMIZED)) {
+
+ // check message API for focus too
+ if(options.consider_tabs) {
+ MessageWindowInputData mwid = {0};
+ MessageWindowData mwd = {0};
+
+ mwid.cbSize = sizeof(mwid);
+ mwid.hContact = hContact;
+ mwid.uFlags = MSG_WINDOW_UFLAG_MSG_BOTH;
+
+ mwd.cbSize = sizeof(mwd);
+
+ if(!CallService(MS_MSG_GETWINDOWDATA, (WPARAM)&mwid, (LPARAM)&mwd)) {
+ if((mwd.uState & MSG_WINDOW_STATE_VISIBLE) != 0) {
+ return true;
+ }
+ } else
+ return true;
+
+ } else
+ return true;
+ }
+
+ return false;
+}
+
+void __stdcall FocusTimerProc(struct HWND__ *,unsigned int,unsigned int,unsigned long) {
+ if(options.notify_when != NOTIFY_NFORE) return;
+
+ HANDLE hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ while (hContact) {
+ HWND hwnd;
+ if((hwnd = (HWND)DBGetContactSettingDword(hContact, MODULE, "WindowHandle", 0)) != 0) {
+ if(!EmptyList(hContact)) {
+ if(window_focussed(hwnd, hContact))
+ PostMessageWindowList(WMU_CLOSEPOPUP, (WPARAM)hContact, 0); // close popups
+ }
+ }
+ hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0);
+ }
+}
+
+void StartFocusTimer() {
+ if(!focusTimerId)
+ focusTimerId = SetTimer(0, 0, 500, FocusTimerProc);
+}
+
+void StopFocusTimer() {
+ if(focusTimerId) {
+ KillTimer(0, focusTimerId);
+ focusTimerId = 0;
+ }
+}
+
+
+
+//#define CONTROL_GLOBAL_STATUS
+
+#ifdef CONTROL_GLOBAL_STATUS
+WORD saved_status;
+#endif
+
+int OnIdleChanged(WPARAM wParam, LPARAM lParam) {
+#ifdef CONTROL_GLOBAL_STATUS
+ int st;
+#endif
+
+ bIsIdle = (lParam & IDF_ISIDLE);
+
+#ifdef CONTROL_GLOBAL_STATUS
+ st = CallService(MS_CLIST_GETSTATUSMODE, 0, 0);
+ if(bIsIdle && st != ID_STATUS_OFFLINE) {
+ saved_status = st;
+ CallService(MS_CLIST_SETSTATUSMODE, (WPARAM)ID_STATUS_AWAY, 0);
+ } else if(!bIsIdle && saved_status != ID_STATUS_OFFLINE) {
+ CallService(MS_CLIST_SETSTATUSMODE, (WPARAM)saved_status, 0);
+ }
+#endif
+
+ return 0;
+}
+
+typedef struct {
+ HANDLE hContact;
+ BYTE *blob;
+ int blobsize;
+} CheckWindowData;
+
+unsigned int __stdcall sttCheckWindowProc( VOID *dwParam ) {
+ CheckWindowData *cd = (CheckWindowData *)dwParam;
+
+ Sleep(500); // wait for message window to open from event, if it's going to
+
+ HWND hwnd = (HWND)DBGetContactSettingDword(cd->hContact, MODULE, "WindowHandle", 0);
+ bool window_open = (hwnd != 0);
+ bool window_has_focus = window_open && window_focussed(hwnd, cd->hContact);
+
+ if(options.notify_when == NOTIFY_ALWAYS
+ || (options.notify_when == NOTIFY_NFORE && !window_has_focus)
+ || (options.notify_when == NOTIFY_CLOSED && !window_open))
+ {
+ if(IsUnicodePopupsEnabled()) {
+ // get contact display name from clist
+ wchar_t *swzContactDisplayName = 0;
+
+ if(unicode_system)
+ swzContactDisplayName = (wchar_t *) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)cd->hContact, GCDNF_UNICODE);
+ else {
+ char *szCDN = (char *) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)cd->hContact, 0);
+ if(szCDN && szCDN[0]) {
+ int size = MultiByteToWideChar(code_page, 0, (char *) szCDN, -1, 0, 0);
+ swzContactDisplayName = (wchar_t *) malloc(sizeof(wchar_t) * size);
+ MultiByteToWideChar(code_page, 0, (char *) szCDN, -1, swzContactDisplayName, size);
+ } else {
+ swzContactDisplayName = (wchar_t *) malloc(sizeof(wchar_t) * (wcslen(TranslateT("(Unknown)") + 1)));
+ wcscpy(swzContactDisplayName, TranslateT("(Unknown)"));
+ }
+ }
+
+ wchar_t *msg;
+ int msglen = strlen((char *)cd->blob) + 1;
+
+ // does blob contain unicode message?
+ if(msglen != cd->blobsize && wcslen((wchar_t *)(&cd->blob[msglen]))) {
+ // yes
+ msg = (wchar_t *)(&cd->blob[msglen]);
+ ShowPopupW(cd->hContact, swzContactDisplayName, msg);
+ } else if(cd->blobsize) {
+ // no, convert to unciode
+ int size = MultiByteToWideChar(code_page, 0, (char *) cd->blob, -1, 0, 0);
+ msg = (wchar_t *) malloc(sizeof(wchar_t) * size);
+ MultiByteToWideChar(code_page, 0, (char *) cd->blob, -1, msg, size);
+ ShowPopupW(cd->hContact, swzContactDisplayName, msg);
+ free(msg);
+ }
+ if(!unicode_system) free(swzContactDisplayName);
+ } else {
+ char *szCDN = (char *) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)cd->hContact, 0);
+ if(szCDN && szCDN[0]) {
+ char msg[MAX_SECONDLINE];
+ strncpy(msg, (char *)cd->blob, MAX_SECONDLINE - 1);
+ msg[MAX_SECONDLINE - 1] = 0;
+ ShowPopup(cd->hContact, szCDN, (char *)msg);
+ }
+ }
+ }
+
+ delete[] cd->blob;
+ delete cd;
+
+ return 0;
+}
+
+int OnDatabaseEventPreAdd(WPARAM wParam, LPARAM lParam) {
+ DBEVENTINFO *dbei = (DBEVENTINFO *)lParam;
+
+ // safety checks
+
+ if ((dbei == 0) || (wParam == 0) || (dbei->flags & DBEF_SENT) || (dbei->eventType != EVENTTYPE_MESSAGE) || (dbei->flags & DBEF_READ)) {
+ return 0;
+ }
+
+ int status = CallService(MS_CLIST_GETSTATUSMODE, 0, 0);
+ if(status >= ID_STATUS_ONLINE && status <= ID_STATUS_OUTTOLUNCH && options.disable_status[status - ID_STATUS_ONLINE])
+ return 0;
+
+ // messages from this contact ignored
+ if(CallService(MS_IGNORE_ISIGNORED, wParam, (LPARAM)IGNOREEVENT_MESSAGE))
+ return 0;
+
+ // if contact 'not on list', use default ignore setting
+ if(DBGetContactSettingByte((HANDLE)wParam, "CList", "NotOnList", 0) && CallService(MS_IGNORE_ISIGNORED, 0, (LPARAM)IGNOREEVENT_MESSAGE))
+ return 0;
+
+ if(dbei->cbBlob == 0 || dbei->pBlob == 0)
+ return 0; // just to be safe
+
+
+ // copy blob data
+ CheckWindowData *cd = new CheckWindowData;
+ cd->hContact = (HANDLE)wParam;
+ cd->blobsize = dbei->cbBlob;
+ cd->blob = new BYTE[cd->blobsize];
+ memcpy(cd->blob, dbei->pBlob, cd->blobsize);
+
+ // spawn a thread to deal with the copied data
+ CloseHandle((HANDLE)_beginthreadex(0, 0, sttCheckWindowProc, (VOID *)cd, 0, 0));
+ return 0;
+}
+
+int OnWindowEvent(WPARAM wParam, LPARAM lParam) {
+ MessageWindowEventData *mwed = (MessageWindowEventData *)lParam;
+
+ switch(mwed->uType) {
+ case MSG_WINDOW_EVT_OPENING:
+ case MSG_WINDOW_EVT_OPEN:
+ DBWriteContactSettingDword(mwed->hContact, MODULE, "WindowHandle", (DWORD)mwed->hwndWindow);
+ if(options.notify_when == NOTIFY_CLOSED)
+ PostMessageWindowList(WMU_CLOSEPOPUP, (WPARAM)mwed->hContact, 0);
+ break;
+ case MSG_WINDOW_EVT_CLOSING:
+ case MSG_WINDOW_EVT_CLOSE:
+ DBWriteContactSettingDword(mwed->hContact, MODULE, "WindowHandle", 0);
+ break;
+ default:
+ //ShowWarning("Window custom");
+ break;
+ }
+
+ return 0;
+}
+
+int OnModulesLoaded(WPARAM wParam, LPARAM lParam) {
+ InitUtils(); // depends on popup module being loaded already
+
+ 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;
+
+ update.szBetaUpdateURL = "http://www.scottellis.com.au/miranda_plugins/messagenotify.zip";
+ update.szBetaVersionURL = "http://www.scottellis.com.au/miranda_plugins/ver_messagenotify.html";
+ update.pbBetaVersionPrefix = (BYTE *)"Message Notify version ";
+
+ update.cpbBetaVersionPrefix = strlen((char *)update.pbBetaVersionPrefix);
+
+ CallService(MS_UPDATE_REGISTER, 0, (WPARAM)&update);
+ }
+
+ metacontacts_installed = (ServiceExists(MS_MC_GETMETACONTACT) != 0);
+
+ hIdle = HookEvent(ME_IDLE_CHANGED, OnIdleChanged);
+ hWindowEvent = HookEvent(ME_MSG_WINDOWEVENT, OnWindowEvent);
+
+ if(options.notify_when == NOTIFY_NFORE)
+ StartFocusTimer();
+
+ return 0;
+}
+
+int OnPreShutdown(WPARAM wParam, LPARAM lParam) {
+ StopFocusTimer();
+ return 0;
+}
+
+extern "C" int __declspec(dllexport) Load(PLUGINLINK *link)
+{
+ pluginLink = link;
+ DuplicateHandle( GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &mainThread, THREAD_SET_CONTEXT, FALSE, 0 );
+
+ char szVer[128];
+ unicode_system = (CallService(MS_SYSTEM_GETVERSIONTEXT, (WPARAM)sizeof(szVer), (LPARAM)szVer) == 0 && strstr(szVer, "Unicode"));
+
+ INITCOMMONCONTROLSEX icex;
+
+ // Ensure that the common control DLL is loaded (for listview)
+ icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
+ icex.dwICC = ICC_LISTVIEW_CLASSES;
+ InitCommonControlsEx(&icex);
+
+ if(ServiceExists(MS_DB_SETSETTINGRESIDENT)) { // 0.6+
+ CallService(MS_DB_SETSETTINGRESIDENT, TRUE, (LPARAM)(MODULE "/WindowHandle"));
+ }
+
+ HANDLE hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ while (hContact) {
+ if(DBGetContactSettingDword(hContact, MODULE, "WindowHandle", 0) != 0)
+ DBWriteContactSettingDword(hContact, MODULE, "WindowHandle", 0);
+
+ hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0);
+ }
+
+ InitWindowList();
+
+ LoadOptions();
+
+ if(ServiceExists(MS_LANGPACK_GETCODEPAGE))
+ code_page = CallService(MS_LANGPACK_GETCODEPAGE, 0, 0);
+
+ HookEvent(ME_SYSTEM_MODULESLOADED, OnModulesLoaded);
+ HookEvent(ME_SYSTEM_PRESHUTDOWN, OnPreShutdown);
+ HookEvent(ME_OPT_INITIALISE, OptInit);
+
+ popupWindowList = (HANDLE)CallService(MS_UTILS_ALLOCWINDOWLIST, 0, 0);
+
+ hEventDbEventAdded = HookEvent(ME_DB_EVENT_FILTER_ADD, OnDatabaseEventPreAdd);
+
+ return 0;
+}
+
+extern "C" int __declspec(dllexport) Unload(void)
+{
+ UnhookEvent(hIdle);
+ UnhookEvent(hWindowEvent);
+ UnhookEvent(hEventDbEventAdded);
+
+ DeinitUtils();
+ DeinitWindowList();
+
+ return 0;
+}
|