diff options
Diffstat (limited to 'kbdnotify/main.c')
-rw-r--r-- | kbdnotify/main.c | 1487 |
1 files changed, 0 insertions, 1487 deletions
diff --git a/kbdnotify/main.c b/kbdnotify/main.c deleted file mode 100644 index 8e9fdff..0000000 --- a/kbdnotify/main.c +++ /dev/null @@ -1,1487 +0,0 @@ - -/* - KeyboardNotify plugin v1.5 for Miranda IM - _________________________________________ - - Copyright (C) 2002,2003 Martin Öberg - Copyright (C) 2004 Std - Copyright (C) 2005,2006 TioDuke (tioduke@yahoo.ca) - - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - - Description - ----------- - This plugin for Miranda-IM notifies user of specified events (as incoming messages, - incoming files, incoming URLs or other events). This plugin is based on the original one - by Martin Öberg (aka strickz) and Std's modifications (mainly the idea of using direct - port handling using a driver). - It has many options allowing: - a) To select on which events to react - b) Under which conditions (eg: fullscreen mode, ScreenSaver running, workstation locked) - c) To act only if the protocol receiving the event is under specified status - d) For message events you can choose to be notified if the message window is open or not - e) A notification feature allowing to be notified of pending events (unopen events) - after specified period of time - f) To select method for stopping the blinking (after x secs, if Miranda is re-attended, - if Windows is re-attended, if all notified events are opened or when the notify conditions - end) - g) And several flashing options: select leds to blink, effects (all at the same time, - in turn, in sequence and like KITT!), preview button - It was designed to be flexible and performing several different tasks. It can be - configured to act like the original one and has several functions from other Miranda's - keyboard notifier plugins. - It also provides a service to allow third party plugins use its notifier abilities. - - Options - ------- - Options page Options->Plugins->Keyboard Flash. Tabbed: Protocols, Rules (when), Flashing (how), Themes and Ignore. - - Thanks - ------ - - Pete for the numerous patches he sent, actively helping to improve the code and - functionality - - UnregistereD for great help in solving problem with Windows activity detection - - Slacktarn, Sir_qwerty and Tweety for giving great help with ideas (most of the new - features included in this plugin were suggested by them) and testing - - The authors of AAA, PopUp+, KeyScrollNotify, original KeyboardNotify, Neweventnotify, - IEView, NGEventNotify for part of their code used in this plugin. - - Vampik fot the InTurn flashing option - - Miranda IM developers for this amazing program - - all other people from Miranda community - - History - ------- - 1.5.7.7:
- [!] Added support for Miranda 0.8.x.x.
- 1.5.7.6:
- [!] Fixed bug in Ignore module.
- 1.5.7.5:
- [!] Updated TriggerPlugin support for latest version.
- 1.5.7.4:
- [*] Updated screenshot
- [*] Minor code cleaning
- 1.5.7.3: - [+] Added xstatus support - 1.5.7.2: - [+] Added per contact Ignore options - 1.5.7.1: - [!] Fix in Options for themes under WinXP+ (really essential feature) - 1.5.7.0: - [+] Added support for Trigger plugin - 1.5.6.3: - [-] Removed device presence validation: it is not needed now that the plugin works on USB (thanks Nick, aka Aestetic) - [+] Added a new service to the API for 'normalizing' a custom flashing sequence string - [-] Simplified the API (the extended version of the start blink service is no longer needed). - 1.5.6.2: - [!] Fixed problem while trying to detect if message window is in foreground. - 1.5.6.1: - [!] Fixed bug with keypress emulation and "until Windows is re-attended" option. - 1.5.6.0: - [+] Option to emulate keypresses (for the USB people) - [*] Changed the emergency key (to make it stop with PAUSE instead of SCROLL LOCK key). - 1.5.5.4: - [*] Improved ListView control handling - [*] Changed the default values (for the sake of new users). - 1.5.5.3: - [*] More code optimization. - 1.5.5.2: - [+] Support for Update plugin. - 1.5.5.1: - [!] Minor source fixes. - 1.5.5.0: - [+] New 'notify when' option: while defined programs are running (just like gamerstatus) - [+] Extended the API to add two new services to disable and re-enable keyboard notifications (for use by bosskey plugin). - 1.5.4.4: - [!] Fixed (hopefully) problems with some system configurations (with PS2 keyboards) where the KeyboardClass0 device was not the apropriate one (thanks pete!) - [+] Extended the plugin API (requested bt tweety). - 1.5.4.3: - [!] Fixed some compatibility issues with nconvers++ (thank you donatas for your help). - 1.5.4.2: - [!] Fixed problem with Windows' activity detection under Win9X when using other plugins that do the same. - [!] Fixed crash caused by incoming authorisation requests when metacontacts was enabled. - 1.5.4.1: - [!] Some corrections on third party plugins events handling (now they are more assimilated to the 'other events') - [*] Some code cleaning - [!] Fixed problem with first message in Metacontacts recognition while checking for pending events (thank you again NirG) - 1.5.4.0: - [+] New plugin API (thank you CriS for your ideas and great help) - [!] Added Offline status to status check list (thank you Slaktarn for finding it). - 1.5.3.4: - [!] Fixed Metacontacts recognition in checking and counting of pending events (thank you NirG for finding the problem) - [!] Fixed problems with multiple instances of the plugin running (thank you tweety for reporting and testing). - 1.5.3.3: - [!] Changed behaviour of Preview button to make it independent of the rules' options. - 1.5.3.2: - [+] New dialog to asign leds to specific events for the trillian-like sequences. - 1.5.3.1: - [!] Fixed bug of loosing any other until setting when selecting 'Events are opened'. - 1.5.3.0: - [+] Applied pete's patches (thank you very much for your great work) - - Use of GetLastInputInfo when possible for detecting Windows' activity - - Made Windows' mouse hooks also aware of mouse clicking - - Made Miranda re-attended option react on windows restoring and ignoring mouse hovering an unfocused window - - New option for message events to avoid blinking if message window is focused - - Made the plugin handle metacontact's special issues - [!] Use of the new message API for windows detection when possible - [+] New message event option to check last message timestamp (requested by D46MD) - [+] Possibility of choosing more than one flash until option at the same time - [+] New flashing effect to make the leds blink accordingly to number of events - [+] Possibility of selecting/unselecting protocols (requested by tweety, usuful to avoid flashing on some protocols as rss) - 1.5.2.2: - [!] scriver's message window detection (thanks D46MD for your great help) - [!] corrected 'flash until' checking accordingly to pete's patch (thank you) - 1.5.2.1: - [!] nconvers++'s message window detection - [!] checked window detection for srmm, scriver, sramm and srmm_mod - 1.5.2.0: - [+] Custom theme support - [-] Custom order history - 1.5.1.0: - [+] Custom order effect - [+] Custom order history - 1.5.0.0: - [+] Drivers aren't needed anymore - [+] Status selection option - [+] Miranda/Windows activity detection (thank you Peter Boon) - [+] 'Opened events' stop method - [+] x seconds stop method - [+] Hooking database event for detecting incoming events - [+] Notifier option for pending events - [+] Checkbox for enabling disabling open messages notification - [+] In sequence and KIT flashing effects - [+] Preview button - [+] Tabbed options - [!] Several corrections/improvements in options page - [!] Not selected leds will preserve their original state - 1.4.1.0: (by me and Vampik) - [+] Notify on fullscreen, screensaver, worksation locked - [!] Try to improve Win98 keysimulation routines - [+] Added InTurn effect (thank you Vampik) - [!] Corrected speed of blinking (thank you Vampik) - 1.4.0.0: (by Std, unreleased) - [+] Added direct port handling using PortTalk.sys driver - 1.3.0.0: (by strickz) - This is strickz' final release. It still uses keypress simulation. It was nice (thanks *g*) - - -*/ - -#define WIN32_LEAN_AND_MEAN -#define _WIN32_WINNT 0x0500 - -#include "AggressiveOptimize.h" - -#include <stdio.h> -#include <stdlib.h>
-#include <windows.h>
-#include "flash.h"
-#include "ignore.h" -#include "keyboard.h"
-#include "trigger.h"
-#include "constants.h"
-#include "protolist.h"
-#include "EnumProc.h"
-#include "utils.h"
-#include "m_kbdnotify.h"
-#include <newpluginapi.h>
-#include <m_database.h>
-#include <m_options.h> -#include <m_clist.h> -#include <m_system.h> -#include <m_langpack.h> -#include <m_protocols.h> -#include <m_protosvc.h> -#include <m_contacts.h> -#include <m_message.h> -#include <m_utils.h> -#include <m_icq.h> -#include "m_metacontacts.h" -#include "m_updater.h" -#pragma comment(lib, "advapi32.lib") - -#define NCONVERS_BLINKID ((HANDLE)123456) //nconvers' random identifier used to flash an icon for "incoming message" on contact list - -#ifndef SPI_GETSCREENSAVERRUNNING -#define SPI_GETSCREENSAVERRUNNING 114 -#endif - -#ifndef WM_XBUTTONDBLCLK -#define WM_XBUTTONDBLCLK 0x020D -#endif -#ifndef WM_NCXBUTTONDBLCLK -#define WM_NCXBUTTONDBLCLK 0x00AD -#endif - - -HINSTANCE hInst; -PLUGINLINK *pluginLink; - - -DWORD IDThread = 0; -HANDLE hThread = NULL; -HANDLE hFlashEvent; -HANDLE hExitEvent; - -HANDLE hModulesLoaded = NULL; -HANDLE hMsgEventHook = NULL; -HANDLE hOptionsInitialize = NULL; -HANDLE hEnableService = NULL; -HANDLE hDisableService = NULL; -HANDLE hStartBlinkService = NULL; -HANDLE hEventsOpenedService = NULL; -HANDLE hFlashingEventService = NULL; -HANDLE hNormalizeSequenceService = NULL; - -HHOOK hMirandaMouseHook = NULL; -HHOOK hMirandaKeyBoardHook = NULL; -HHOOK hMirandaWndProcHook = NULL; -UINT hReminderTimer = 0; - -#pragma data_seg("Shared") -HHOOK hMouseHook = NULL; -HHOOK hKeyBoardHook = NULL; -BYTE bEmulateKeypresses = FALSE; -DWORD dwLastInput = 0; -POINT lastGlobalMousePos = {0, 0}; -#pragma data_seg() -#pragma comment(linker, "/section:Shared,rws") - -static BOOL (WINAPI * MyGetLastInputInfo)(PLASTINPUTINFO); - - -BYTE bFlashOnMsg; -BYTE bFlashOnURL; -BYTE bFlashOnFile; -BYTE bFlashOnOther; -BYTE bFullScreenMode; -BYTE bScreenSaverRunning; -BYTE bWorkstationLocked; -BYTE bProcessesAreRunning; -BYTE bWorkstationActive; -BYTE bFlashIfMsgOpen; -BYTE bFlashIfMsgWinNotTop; -BYTE bFlashIfMsgOlder; -WORD wSecondsOlder; -BYTE bFlashUntil; -WORD wBlinksNumber; -BYTE bMirandaOrWindows; -WORD wStatusMap; -WORD wReminderCheck; -BYTE bFlashLed[3]; -BYTE bFlashEffect; -BYTE bSequenceOrder; -WORD wCustomTheme; -WORD wStartDelay; -BYTE bFlashSpeed; -BYTE bOverride; -BYTE bTrillianLedsMsg; -BYTE bTrillianLedsURL; -BYTE bTrillianLedsFile; -BYTE bTrillianLedsOther; - -PROTOCOL_LIST ProtoList = {0, NULL}; -PROCESS_LIST ProcessList = {0, NULL}; - -double dWinVer; -BOOL bWindowsNT; - -int nWaitDelay; -unsigned int nExternCount = 0; -BOOL bFlashingEnabled = TRUE; -BOOL bReminderDisabled = FALSE; - -char *szMetaProto = NULL; -BYTE bMetaProtoEnabled = 0; - - -PLUGININFOEX pluginInfo={ - sizeof(PLUGININFO), - "Keyboard Notify Ext.", - PLUGIN_MAKE_VERSION(1,5,7,7), - "Flashes your keyboard LEDs when a message has arrived", - "TioDuke", - "tioduke@yahoo.ca", - "© 2002-2003 M.Öberg, 2004 Std, 2005-2008 TioDuke", - "http://addons.miranda-im.org/", - 0, //not transient - 0, //doesn't replace anything built-in - {0x119d7288, 0x2050, 0x448d, { 0x99, 0x00, 0xd8, 0x6a, 0xc7, 0x04, 0x26, 0xbf }} //{119D7288-2050-448d-9900-D86AC70426BF}
-};
-
- - -int InitializeOptions(WPARAM,LPARAM); -void LoadSettings(void); -int HookWindowsHooks(void); -int UnhookWindowsHooks(void); -static LRESULT CALLBACK MouseHookFunction(int, WPARAM, LPARAM); -static LRESULT CALLBACK KeyBoardHookFunction(int, WPARAM, LPARAM); -static LRESULT CALLBACK MirandaMouseHookFunction(int, WPARAM, LPARAM); -static LRESULT CALLBACK MirandaKeyBoardHookFunction(int, WPARAM, LPARAM);
-static LRESULT CALLBACK MirandaWndProcHookFunction(int, WPARAM, LPARAM);
-BOOL CheckMsgWnd(HANDLE, BOOL *);
-
-
-BOOL isMetaContactsSubContact(HANDLE hMetaContact, HANDLE hContact)
-{ - char *szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hMetaContact, 0); - if (szProto && !strcmp(szMetaProto, szProto)) { // Safety check - int i = DBGetContactSettingDword(hContact, szMetaProto, "ContactNumber", -1); - if (i >= 0 && hContact == (HANDLE)CallService(MS_MC_GETSUBCONTACT, (WPARAM)hMetaContact, i)) - return TRUE; - } - return FALSE; -} - - -BOOL checkOpenWindow(HANDLE hContact) -{ - BOOL found, focus; - - if (bFlashIfMsgOpen && !bFlashIfMsgWinNotTop) - return TRUE; - - found = CheckMsgWnd(hContact, &focus); - if (!found && szMetaProto && bMetaProtoEnabled) { - HANDLE hMetaContact = (HANDLE)DBGetContactSettingDword(hContact, szMetaProto, "Handle", 0); - if (hMetaContact && isMetaContactsSubContact(hMetaContact, hContact)) - found = CheckMsgWnd(hMetaContact, &focus); - } - if (!found) - return TRUE; - - if (bFlashIfMsgOpen && !focus) - return TRUE; - - return FALSE; -} - - -BOOL IsSaverOnNT4() -{ - HDESK hd = OpenDesktop("screen-saver", 0, FALSE, MAXIMUM_ALLOWED); - - if(hd == NULL) - return GetLastError()==ERROR_ACCESS_DENIED; - - CloseDesktop(hd); - return TRUE; -} - - -BOOL isScreenSaverRunning() -{ - BOOL screenSaverIsRunning=FALSE; - - if (bWindowsNT && dWinVer < 5) return IsSaverOnNT4(); - - SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, &screenSaverIsRunning, FALSE); - return screenSaverIsRunning; -} - - -/* this function is from the original idle module */ -BOOL isWorkstationLocked() -{ - HDESK hd; - char buf[MAX_PATH]; - - if (!bWindowsNT) return FALSE; - - hd = OpenInputDesktop(0, FALSE, MAXIMUM_ALLOWED); /* if it fails then the workstation is prolly locked anyway */ - if (hd == NULL) return TRUE; - GetUserObjectInformation(hd, UOI_NAME, buf, sizeof(buf), NULL); /* if we got it (hmm,) get a name */ - CloseDesktop(hd); - return strcmp(buf, "Winlogon")==0; -} - - -BOOL isFullScreen() -{ - int w = GetSystemMetrics(SM_CXSCREEN); - int h = GetSystemMetrics(SM_CYSCREEN); - - HWND hWnd = 0; - while (hWnd = FindWindowEx(NULL, hWnd, NULL, NULL)) { - RECT WindowRect; - - if (!(GetWindowLong(hWnd, GWL_EXSTYLE) & WS_EX_TOPMOST)) - continue; - - GetWindowRect(hWnd, &WindowRect); - if ((w != (WindowRect.right - WindowRect.left)) || (h != (WindowRect.bottom - WindowRect.top))) - continue; - - return TRUE; - } - - return FALSE; -} - - -BOOL checkNotifyOptions() -{ - BOOL fullScreenMode, screenSaverIsRunning, workstationIsLocked, processesRunning; - - screenSaverIsRunning = isScreenSaverRunning(); - if (screenSaverIsRunning && bScreenSaverRunning) - return TRUE; - - workstationIsLocked = isWorkstationLocked(); - if (workstationIsLocked && bWorkstationLocked) - return TRUE; - - fullScreenMode = isFullScreen() && !screenSaverIsRunning; - if (fullScreenMode && bFullScreenMode) - return TRUE; - - processesRunning = areThereProcessesRunning(); - if (processesRunning && bProcessesAreRunning) - return TRUE; - - return (!fullScreenMode && !screenSaverIsRunning && !workstationIsLocked && !processesRunning && bWorkstationActive); -} - - -BOOL isStatusEnabled(int status) -{ - switch (status) { - case ID_STATUS_OFFLINE: return wStatusMap & MAP_OFFLINE; - case ID_STATUS_ONLINE: return wStatusMap & MAP_ONLINE; - case ID_STATUS_AWAY: return wStatusMap & MAP_AWAY; - case ID_STATUS_NA: return wStatusMap & MAP_NA; - case ID_STATUS_OCCUPIED: return wStatusMap & MAP_OCCUPIED; - case ID_STATUS_DND: return wStatusMap & MAP_DND; - case ID_STATUS_FREECHAT: return wStatusMap & MAP_FREECHAT; - case ID_STATUS_INVISIBLE: return wStatusMap & MAP_INVISIBLE; - case ID_STATUS_ONTHEPHONE: return wStatusMap & MAP_ONTHEPHONE; - case ID_STATUS_OUTTOLUNCH: return wStatusMap & MAP_OUTTOLUNCH; - default: return FALSE; - } -} - - -BOOL checkGlobalStatus() -{ - return isStatusEnabled(CallService(MS_CLIST_GETSTATUSMODE, 0, 0)); -} - - -BOOL checkGlobalXstatus() -{ - ICQ_CUSTOM_STATUS xstatus={0}; - unsigned int i, protosSupporting; int status=0;
-
- for(i=0, protosSupporting=0; i < ProtoList.protoCount; i++) {
- if (!ProtoList.protoInfo[i].enabled || !ProtoList.protoInfo[i].xstatus.count) continue;
-
- protosSupporting++;
- // Retrieve xstatus for protocol
- xstatus.cbSize = sizeof(ICQ_CUSTOM_STATUS); - xstatus.flags = CSSF_MASK_STATUS; - xstatus.status = &status; - CallProtoService(ProtoList.protoInfo[i].szProto, PS_ICQ_GETCUSTOMSTATUSEX, 0, (LPARAM)&xstatus); - - if (ProtoList.protoInfo[i].xstatus.enabled[status]) return TRUE; - } - - if (!protosSupporting) - return TRUE; - else - return FALSE; -} - - -DBEVENTINFO createMsgEventInfo(HANDLE hContact) -{ - DBEVENTINFO einfo = {0}; - - einfo.cbSize = sizeof(einfo); - einfo.eventType = EVENTTYPE_MESSAGE; - einfo.szModule = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); - - return einfo; -} - - -DBEVENTINFO readEventInfo(HANDLE hDbEvent, HANDLE hContact) -{ - DBEVENTINFO einfo = {0}; - - if (hDbEvent == NCONVERS_BLINKID) // we need to handle nconvers' blink event - return createMsgEventInfo(hContact); - - einfo.cbSize = sizeof(einfo); - einfo.cbBlob = 0; - einfo.pBlob = NULL; - CallService(MS_DB_EVENT_GET, (WPARAM)hDbEvent, (LPARAM)&einfo); - - return einfo; -} - - -BOOL checkIgnore(HANDLE hContact, WORD eventType) -{ - return !IsIgnored(hContact, eventType); -} - - -BOOL checkProtocol(char *szProto) -{ - unsigned int i; - - if (!szProto) - return FALSE; - - for(i=0; i < ProtoList.protoCount; i++) - if (ProtoList.protoInfo[i].szProto && !strcmp(ProtoList.protoInfo[i].szProto, szProto)) - return ProtoList.protoInfo[i].enabled; - - return FALSE; -} - - -BOOL metaCheckProtocol(char *szProto, HANDLE hContact, WORD eventType) -{ - HANDLE hSubContact=NULL; - - if (szMetaProto && bMetaProtoEnabled && szProto && !strcmp(szMetaProto, szProto)) - if (hSubContact = (HANDLE)CallService(MS_MC_GETMOSTONLINECONTACT, (WPARAM)hContact, 0))
- szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hSubContact, 0);
-
- return checkProtocol(szProto) && checkIgnore(hSubContact?hSubContact:hContact, eventType);
-}
-
-
-BOOL checkUnopenEvents() -{ - int nIndex; - CLISTEVENT *pCLEvent; - - if (nExternCount && bFlashOnOther) - return TRUE; - - for (nIndex = 0; pCLEvent = (CLISTEVENT*)CallService(MS_CLIST_GETEVENT, -1, nIndex); nIndex++) { - DBEVENTINFO einfo = readEventInfo(pCLEvent->hDbEvent, pCLEvent->hContact); - - if ((einfo.eventType == EVENTTYPE_MESSAGE && bFlashOnMsg) || - (einfo.eventType == EVENTTYPE_URL && bFlashOnURL) || - (einfo.eventType == EVENTTYPE_FILE && bFlashOnFile) || - (einfo.eventType != EVENTTYPE_MESSAGE && einfo.eventType != EVENTTYPE_URL && einfo.eventType != EVENTTYPE_FILE && bFlashOnOther)) - - if (metaCheckProtocol(einfo.szModule, pCLEvent->hContact, einfo.eventType)) - return TRUE; - } - - return FALSE; -} - - -static void FlashThreadFunction() -{ - BOOL bEvent = FALSE; - DWORD dwEventStarted, dwFlashStarted; - BYTE data, unchangedLeds; - - while (TRUE) { - unchangedLeds = (BYTE)(LedState(VK_PAUSE) * !bFlashLed[2] + ((LedState(VK_NUMLOCK) * !bFlashLed[0])<<1) + ((LedState(VK_CAPITAL) * !bFlashLed[1])<<2)); - GetAsyncKeyState(VK_PAUSE); // empty Pause/Break's keystroke buffer - - // Start flashing - while(bEvent && bFlashingEnabled) - { - // Let's give the user the opportunity of finishing flashing manually :) - if (GetAsyncKeyState(VK_PAUSE) & 1) - break; - - if ((bFlashUntil & UNTIL_NBLINKS) && GetTickCount() > (dwFlashStarted + wBlinksNumber * 1000)) - break; - if (bFlashUntil & UNTIL_REATTENDED) { - if (bMirandaOrWindows == ACTIVE_WINDOWS && MyGetLastInputInfo && !bEmulateKeypresses) { - LASTINPUTINFO lii; - ZeroMemory(&lii, sizeof(lii)); - lii.cbSize = sizeof(lii); - MyGetLastInputInfo(&lii); - dwLastInput = lii.dwTime; - } - if (dwLastInput > dwEventStarted) - break; - } - if ((bFlashUntil & UNTIL_EVENTSOPEN) && !checkUnopenEvents()) - break; - if ((bFlashUntil & UNTIL_CONDITIONS) && (!checkNotifyOptions() || !checkGlobalStatus() || !checkGlobalXstatus())) - break; - - data = getBlinkingLeds(); - ToggleKeyboardLights((BYTE)(data|unchangedLeds)); - - // Wait for exit event - if (WaitForSingleObject(hExitEvent, nWaitDelay) == WAIT_OBJECT_0) - return; - } - RestoreLEDState(); - - setFlashingSequence(); - bReminderDisabled = FALSE; - - // Wait for new event - { - DWORD dwEvent; - HANDLE Objects[2]; - Objects[0] = hFlashEvent; - Objects[1] = hExitEvent; - dwEvent = WaitForMultipleObjects(2, Objects, FALSE, INFINITE); - if ((dwEvent - WAIT_OBJECT_0) == 1) - return; - } - - bEvent = TRUE; - bReminderDisabled = TRUE; - dwEventStarted = GetTickCount(); - // Wait StartDelay seconds - if (wStartDelay > 0) - Sleep(wStartDelay * 1000); - dwFlashStarted = GetTickCount(); - - } - -} - - -BOOL checkMsgTimestamp(HANDLE hEventCurrent, DWORD timestampCurrent) -{ - HANDLE hEvent; - - if (!bFlashIfMsgOlder) - return TRUE; - - for (hEvent=(HANDLE)CallService(MS_DB_EVENT_FINDPREV, (WPARAM)hEventCurrent, 0); hEvent; hEvent=(HANDLE)CallService(MS_DB_EVENT_FINDPREV, (WPARAM)hEvent, 0)) { - DBEVENTINFO einfo = {0}; - - einfo.cbSize = sizeof(einfo); - einfo.cbBlob = 0; - einfo.pBlob = NULL; - CallService(MS_DB_EVENT_GET, (WPARAM)hEvent, (LPARAM)&einfo); - if ((einfo.timestamp + wSecondsOlder) <= timestampCurrent) - return TRUE; - if (einfo.eventType == EVENTTYPE_MESSAGE) - return FALSE; - } - - return TRUE; -} - - -BOOL contactCheckProtocol(char *szProto, HANDLE hContact, WORD eventType) -{ - if (szMetaProto && bMetaProtoEnabled && hContact) { - HANDLE hMetaContact = (HANDLE)DBGetContactSettingDword(hContact, szMetaProto, "Handle", 0); - if (hMetaContact && isMetaContactsSubContact(hMetaContact, hContact)) - return FALSE; - } - - return (metaCheckProtocol(szProto, hContact, eventType)); -} - - -BOOL checkStatus(char *szProto) -{ - if(!szProto) - return checkGlobalStatus(); - - return isStatusEnabled(CallProtoService(szProto, PS_GETSTATUS, 0, 0)); -} - - -BOOL checkXstatus(char *szProto) -{ - unsigned int i; int status=0; - ICQ_CUSTOM_STATUS xstatus={0}; - - if(!szProto) - return checkGlobalXstatus(); - - for(i=0; i < ProtoList.protoCount; i++) - if (ProtoList.protoInfo[i].szProto && !strcmp(ProtoList.protoInfo[i].szProto, szProto)) { - if (!ProtoList.protoInfo[i].xstatus.count) return TRUE; - - // Retrieve xstatus for protocol - xstatus.cbSize = sizeof(ICQ_CUSTOM_STATUS); - xstatus.flags = CSSF_MASK_STATUS; - xstatus.status = &status; - CallProtoService(ProtoList.protoInfo[i].szProto, PS_ICQ_GETCUSTOMSTATUSEX, 0, (LPARAM)&xstatus); - - return ProtoList.protoInfo[i].xstatus.enabled[status]; - } - - return TRUE; -} - - -// 'Pings' the FlashThread to keep the LEDs flashing. -static int PluginMessageEventHook(WPARAM wParam, LPARAM lParam) -{ - DBEVENTINFO einfo = {0}; - HANDLE hContact = (HANDLE)wParam; - HANDLE hEvent = (HANDLE)lParam; - - //get DBEVENTINFO without pBlob - einfo.cbSize = sizeof(einfo); - einfo.cbBlob = 0; - einfo.pBlob = NULL; - CallService(MS_DB_EVENT_GET, (WPARAM)hEvent, (LPARAM)&einfo); - - if (!(einfo.flags & DBEF_SENT)) - if ((einfo.eventType == EVENTTYPE_MESSAGE && bFlashOnMsg && checkOpenWindow(hContact) && checkMsgTimestamp(hEvent, einfo.timestamp)) || - (einfo.eventType == EVENTTYPE_URL && bFlashOnURL) || - (einfo.eventType == EVENTTYPE_FILE && bFlashOnFile) || - (einfo.eventType != EVENTTYPE_MESSAGE && einfo.eventType != EVENTTYPE_URL && einfo.eventType != EVENTTYPE_FILE && bFlashOnOther)) { - - if (contactCheckProtocol(einfo.szModule, hContact, einfo.eventType) && checkNotifyOptions() && checkStatus(einfo.szModule) && checkXstatus(einfo.szModule)) - - SetEvent(hFlashEvent); - } - - return 0; -} - - -// ** -// ** Checks for pending events. If it finds any, it pings the FlashThread to keep the LEDs flashing. -// ** - -static VOID CALLBACK ReminderTimer(HWND hwnd, UINT message, UINT idEvent, DWORD dwTime) -{ - int nIndex; - CLISTEVENT *pCLEvent; - - if (!bReminderDisabled && nExternCount && bFlashOnOther) { - SetEvent(hFlashEvent); - return; - } - - for (nIndex = 0; !bReminderDisabled && (pCLEvent = (CLISTEVENT*)CallService(MS_CLIST_GETEVENT, -1, nIndex)); nIndex++) { - DBEVENTINFO einfo = readEventInfo(pCLEvent->hDbEvent, pCLEvent->hContact); - - if ((einfo.eventType == EVENTTYPE_MESSAGE && bFlashOnMsg) || - (einfo.eventType == EVENTTYPE_URL && bFlashOnURL) || - (einfo.eventType == EVENTTYPE_FILE && bFlashOnFile) || - (einfo.eventType != EVENTTYPE_MESSAGE && einfo.eventType != EVENTTYPE_URL && einfo.eventType != EVENTTYPE_FILE && bFlashOnOther)) - - if (metaCheckProtocol(einfo.szModule, pCLEvent->hContact, einfo.eventType) && checkNotifyOptions() && checkStatus(einfo.szModule) && checkXstatus(einfo.szModule)) { - - SetEvent(hFlashEvent); - return; - } - } - -} - - -// Support for third-party plugins and mBot's scripts -static int EnableService(WPARAM wParam, LPARAM lParam) -{ - bFlashingEnabled = TRUE; - - return 0; -} - - -static int DisableService(WPARAM wParam, LPARAM lParam) -{ - bFlashingEnabled = FALSE; - - return 0; -} - - -static int StartBlinkService(WPARAM wParam, LPARAM lParam) -{ - nExternCount += (unsigned int)wParam; - if (bFlashOnOther && checkNotifyOptions() && checkGlobalStatus() && checkGlobalXstatus()) { - if (lParam) - useExternSequence((char *)lParam); - SetEvent(hFlashEvent); - } - - return 0; -} - - -static int EventsWereOpenedService(WPARAM wParam, LPARAM lParam) -{ - if ((unsigned int)wParam > nExternCount) - nExternCount = 0; - else - nExternCount -= (unsigned int)wParam; - - return 0; -} - - -static int IsFlashingActiveService(WPARAM wParam, LPARAM lParam) -{ - if (!bReminderDisabled) - return 0; - - return (int)getCurrentSequenceString(); -} - - -static int NormalizeSequenceService(WPARAM wParam, LPARAM lParam) -{ - char strAux[MAX_PATH+1], *strIn = (char *)lParam; - - mir_snprintf(strAux, MAX_PATH, "%s", strIn); - mir_snprintf(strIn, MAX_PATH, "%s", normalizeCustomString(strAux)); - - return (int)strIn; -} -
-
-// Support for Trigger plugin
-static void ForceEventsWereOpenedThread(void *eventMaxSeconds)
-{
- Sleep(((WORD)eventMaxSeconds) * 1000);
- CallService(MS_KBDNOTIFY_EVENTSOPENED, 1, 0);
-}
-
- -void StartBlinkAction(char *flashSequence, WORD eventMaxSeconds) -{ - DWORD threadID = 0;
-
- if (eventMaxSeconds)
- CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ForceEventsWereOpenedThread, (void *)eventMaxSeconds, 0, &threadID);
-
- CallService(MS_KBDNOTIFY_STARTBLINK, 1, (LPARAM)flashSequence);
-}
- - -void createProcessList(void) -{ - DBVARIANT dbv; - unsigned int i, count; - - count = (unsigned int)DBGetContactSettingWord(NULL, KEYBDMODULE, "processcount", 0); - - ProcessList.count = 0; - ProcessList.szFileName = (char **)malloc(count * sizeof(char *));
- if (ProcessList.szFileName) {
- for(i=0; i < count; i++)
- if (DBGetContactSetting(NULL, KEYBDMODULE, fmtDBSettingName("process%d", i), &dbv))
- ProcessList.szFileName[i] = NULL;
- else {
- ProcessList.szFileName[i] = (char *)malloc(strlen(dbv.pszVal) + 1);
- if (ProcessList.szFileName[i]) - strcpy(ProcessList.szFileName[i], dbv.pszVal); - DBFreeVariant(&dbv); - } - ProcessList.count = count; - } - -} - - -void destroyProcessList(void) -{ - unsigned int i, count; - - count = ProcessList.count; - - ProcessList.count = 0; - for(i=0; i < count; i++) - if (ProcessList.szFileName[i]) - free(ProcessList.szFileName[i]); - - if (ProcessList.szFileName) - free(ProcessList.szFileName); - ProcessList.szFileName = NULL; -} - - -void LoadSettings(void) -{ - unsigned int i; - - bFlashOnMsg = DBGetContactSettingByte(NULL, KEYBDMODULE, "onmsg", DEF_SETTING_ONMSG); - bFlashOnURL = DBGetContactSettingByte(NULL, KEYBDMODULE, "onurl", DEF_SETTING_ONURL); - bFlashOnFile = DBGetContactSettingByte(NULL, KEYBDMODULE, "onfile", DEF_SETTING_ONFILE); - bFlashOnOther = DBGetContactSettingByte(NULL, KEYBDMODULE, "onother", DEF_SETTING_OTHER); - bFullScreenMode = DBGetContactSettingByte(NULL, KEYBDMODULE, "fscreenmode", DEF_SETTING_FSCREEN); - bScreenSaverRunning = DBGetContactSettingByte(NULL, KEYBDMODULE, "ssaverrunning", DEF_SETTING_SSAVER); - bWorkstationLocked = (bWindowsNT ? DBGetContactSettingByte(NULL, KEYBDMODULE, "wstationlocked", DEF_SETTING_LOCKED):0); - bProcessesAreRunning = DBGetContactSettingByte(NULL, KEYBDMODULE, "procsrunning", DEF_SETTING_PROCS); - bWorkstationActive = DBGetContactSettingByte(NULL, KEYBDMODULE, "wstationactive", DEF_SETTING_ACTIVE); - bFlashIfMsgOpen = DBGetContactSettingByte(NULL, KEYBDMODULE, "ifmsgopen", DEF_SETTING_IFMSGOPEN); - bFlashIfMsgWinNotTop = DBGetContactSettingByte(NULL, KEYBDMODULE, "ifmsgnottop", DEF_SETTING_IFMSGNOTTOP); - bFlashIfMsgOlder = DBGetContactSettingByte(NULL, KEYBDMODULE, "ifmsgolder", DEF_SETTING_IFMSGOLDER); - wSecondsOlder = DBGetContactSettingWord(NULL, KEYBDMODULE, "secsolder", DEF_SETTING_SECSOLDER); - bFlashUntil = DBGetContactSettingByte(NULL, KEYBDMODULE, "funtil", DEF_SETTING_FLASHUNTIL); - wBlinksNumber = DBGetContactSettingWord(NULL, KEYBDMODULE, "nblinks", DEF_SETTING_NBLINKS); - bMirandaOrWindows = DBGetContactSettingByte(NULL, KEYBDMODULE, "mirorwin", DEF_SETTING_MIRORWIN); - wStatusMap = DBGetContactSettingWord(NULL, KEYBDMODULE, "status", DEF_SETTING_STATUS); - wReminderCheck = DBGetContactSettingWord(NULL, KEYBDMODULE, "remcheck", DEF_SETTING_CHECKTIME); - bFlashLed[0] = !!DBGetContactSettingByte(NULL, KEYBDMODULE, "fnum", DEF_SETTING_FLASHNUM); - bFlashLed[1] = !!DBGetContactSettingByte(NULL, KEYBDMODULE, "fcaps", DEF_SETTING_FLASHCAPS); - bFlashLed[2] = !!DBGetContactSettingByte(NULL, KEYBDMODULE, "fscroll", DEF_SETTING_FLASHSCROLL); - bFlashEffect = DBGetContactSettingByte(NULL, KEYBDMODULE, "feffect", DEF_SETTING_FLASHEFFECT); - bSequenceOrder = DBGetContactSettingByte(NULL, KEYBDMODULE, "order", DEF_SETTING_SEQORDER); - wCustomTheme = DBGetContactSettingWord(NULL, KEYBDMODULE, "custom", DEF_SETTING_CUSTOMTHEME); - bTrillianLedsMsg = DBGetContactSettingByte(NULL, KEYBDMODULE, "ledsmsg", DEF_SETTING_LEDSMSG); - bTrillianLedsURL = DBGetContactSettingByte(NULL, KEYBDMODULE, "ledsurl", DEF_SETTING_LEDSURL); - bTrillianLedsFile = DBGetContactSettingByte(NULL, KEYBDMODULE, "ledsfile", DEF_SETTING_LEDSFILE); - bTrillianLedsOther = DBGetContactSettingByte(NULL, KEYBDMODULE, "ledsother", DEF_SETTING_LEDSOTHER); - wStartDelay = DBGetContactSettingWord(NULL, KEYBDMODULE, "sdelay", DEF_SETTING_STARTDELAY); - bFlashSpeed = DBGetContactSettingByte(NULL, KEYBDMODULE, "speed", DEF_SETTING_FLASHSPEED); - switch (bFlashSpeed) { - case 0: nWaitDelay = 1500; break; - case 1: nWaitDelay = 0750; break; - case 2: nWaitDelay = 0250; break; - case 3: nWaitDelay = 0150; break; - case 4: nWaitDelay = 0100; break; - default: nWaitDelay = 0050; break; - } - setFlashingSequence(); - bEmulateKeypresses = DBGetContactSettingByte(NULL, KEYBDMODULE, "keypresses", DEF_SETTING_KEYPRESSES); - bOverride = DBGetContactSettingByte(NULL, KEYBDMODULE, "override", DEF_SETTING_OVERRIDE); - // Create hidden settings (for test button) if needed - if (DBGetContactSettingByte(NULL, KEYBDMODULE, "testnum", -1) == -1) - DBWriteContactSettingByte(NULL, KEYBDMODULE, "testnum", DEF_SETTING_TESTNUM); - if (DBGetContactSettingByte(NULL, KEYBDMODULE, "testsecs", -1) == -1) - DBWriteContactSettingByte(NULL, KEYBDMODULE, "testsecs", DEF_SETTING_TESTSECS); - for(i=0; i < ProtoList.protoCount; i++)
- if (ProtoList.protoInfo[i].visible) {
- unsigned int j;
- ProtoList.protoInfo[i].enabled = DBGetContactSettingByte(NULL, KEYBDMODULE, ProtoList.protoInfo[i].szProto, DEF_SETTING_PROTOCOL);
- for(j=0; j < ProtoList.protoInfo[i].xstatus.count; j++)
- ProtoList.protoInfo[i].xstatus.enabled[j] = DBGetContactSettingByte(NULL, KEYBDMODULE, fmtDBSettingName("%sxstatus%d", ProtoList.protoInfo[i].szProto, j), DEF_SETTING_XSTATUS);
- }
-
- if (szMetaProto)
- bMetaProtoEnabled = DBGetContactSettingByte(NULL, szMetaProto, "Enabled", 1); - - destroyProcessList(); - createProcessList(); - UnhookWindowsHooks(); - HookWindowsHooks(); -} - - -void GetWindowsVersion(void) -{ - OSVERSIONINFOEX osvi; - BOOL bOsVersionInfoEx; - - ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); - if(!(bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO *) &osvi))) { - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - if(!GetVersionEx((OSVERSIONINFO *)&osvi)) - osvi.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS; - } - bWindowsNT = osvi.dwPlatformId==VER_PLATFORM_WIN32_NT; - dWinVer = osvi.dwMajorVersion + osvi.dwMinorVersion / 10.0; -} - - -void updateXstatusProto(PROTOCOL_INFO *protoInfo) -{ - unsigned int i; - char szServiceName[MAXMODULELABELLENGTH]; - ICQ_CUSTOM_STATUS xstatus={0}; - - mir_snprintf(szServiceName, sizeof(szServiceName), "%s%s", protoInfo->szProto, PS_ICQ_GETCUSTOMSTATUSEX); - if (!ServiceExists(szServiceName)) return; - - // Retrieve xstatus.count - xstatus.cbSize = sizeof(ICQ_CUSTOM_STATUS); - xstatus.flags = CSSF_STATUSES_COUNT; - xstatus.wParam = &(protoInfo->xstatus.count); - CallProtoService(protoInfo->szProto, PS_ICQ_GETCUSTOMSTATUSEX, 0, (LPARAM)&xstatus); - (protoInfo->xstatus.count)++; // Don't forget about xstatus=0 (None) - - // Alloc and initiailize xstatus.enabled array - protoInfo->xstatus.enabled = (BOOL *)malloc(protoInfo->xstatus.count * sizeof(BOOL)); - if (!protoInfo->xstatus.enabled) - protoInfo->xstatus.count = 0; - else - for(i=0; i < protoInfo->xstatus.count; i++) - protoInfo->xstatus.enabled[i] = FALSE; - -} - - -void createProtocolList(void) -{ - unsigned int i; - PROTOCOLDESCRIPTOR **proto; - - if (ServiceExists(MS_MC_GETPROTOCOLNAME)) - szMetaProto = (char *)CallService(MS_MC_GETPROTOCOLNAME, 0, 0); - - CallService(MS_PROTO_ENUMPROTOCOLS, (WPARAM)&ProtoList.protoCount, (LPARAM)&proto); - ProtoList.protoInfo = (PROTOCOL_INFO *)malloc(ProtoList.protoCount * sizeof(PROTOCOL_INFO)); - if (!ProtoList.protoInfo) - ProtoList.protoCount = 0; - else - for(i=0; i < ProtoList.protoCount; i++) { - ProtoList.protoInfo[i].xstatus.count = 0; - ProtoList.protoInfo[i].xstatus.enabled = NULL; - ProtoList.protoInfo[i].szProto = (char *)malloc(strlen(proto[i]->szName) + 1); - if (!ProtoList.protoInfo[i].szProto) { - ProtoList.protoInfo[i].enabled = FALSE; - ProtoList.protoInfo[i].visible = FALSE; - } else { - strcpy(ProtoList.protoInfo[i].szProto, proto[i]->szName); - ProtoList.protoInfo[i].enabled = FALSE; - if (proto[i]->type != PROTOTYPE_PROTOCOL) - ProtoList.protoInfo[i].visible = FALSE; - else - if (szMetaProto && !strcmp(proto[i]->szName, szMetaProto)) - ProtoList.protoInfo[i].visible = FALSE; - else { - ProtoList.protoInfo[i].visible = TRUE; - updateXstatusProto(&(ProtoList.protoInfo[i])); - } - } - } - -}
-
-
-// We use the profile name to create the first part of each event name
-// We do so to avoid problems between different instances of the plugin concurrently running
-void createEventPrefix(char *prefixName, size_t maxLen)
-{ - size_t len; - char profileName[MAX_PATH+1], *str; - - getAbsoluteProfileName(profileName, MAX_PATH); - - while (str = strchr(profileName, '\\')) - *str = '/'; - if ((len = strlen(profileName)) <= maxLen) - strcpy(prefixName, profileName); - else { - str = profileName + len - maxLen / 2; - mir_snprintf(prefixName, maxLen / 2, "%s", profileName); - strcat(prefixName, str); - } -} - - -// ** -// ** Everything below is just Miranda init/uninit stuff -// ** - - -static int ModulesLoaded(WPARAM wParam, LPARAM lParam) -{ - char eventPrefix[MAX_PATH+1], eventName[MAX_PATH+1]; - - LoadProcsLibrary(); - if (bWindowsNT && dWinVer >= 5) - MyGetLastInputInfo = (BOOL (WINAPI *)(PLASTINPUTINFO)) GetProcAddress(GetModuleHandle("user32"), "GetLastInputInfo"); - else - MyGetLastInputInfo = NULL; - - createProtocolList(); - LoadSettings(); - - // Create some synchronisation objects - createEventPrefix(eventPrefix, MAX_PATH - 11); - mir_snprintf(eventName, sizeof(eventName), "%s/FlashEvent", eventPrefix); - hFlashEvent = CreateEvent(NULL, FALSE, FALSE, eventName); - mir_snprintf(eventName, sizeof(eventName), "%s/ExitEvent", eventPrefix); - hExitEvent = CreateEvent(NULL, FALSE, FALSE, eventName); - - hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)FlashThreadFunction, NULL, 0, &IDThread); - - hMsgEventHook = HookEvent(ME_DB_EVENT_ADDED, PluginMessageEventHook); - hOptionsInitialize = HookEvent(ME_OPT_INITIALISE, InitializeOptions); - hEnableService = CreateServiceFunction(MS_KBDNOTIFY_ENABLE, EnableService); - hDisableService = CreateServiceFunction(MS_KBDNOTIFY_DISABLE, DisableService); - hStartBlinkService = CreateServiceFunction(MS_KBDNOTIFY_STARTBLINK, StartBlinkService); - hEventsOpenedService = CreateServiceFunction(MS_KBDNOTIFY_EVENTSOPENED, EventsWereOpenedService); - hFlashingEventService = CreateServiceFunction(MS_KBDNOTIFY_FLASHINGACTIVE, IsFlashingActiveService); - hNormalizeSequenceService = CreateServiceFunction(MS_KBDNOTIFY_NORMALSEQUENCE, NormalizeSequenceService); - - RegisterAction(); - if (ServiceExists("DBEditorpp/RegisterSingleModule")) - CallService("DBEditorpp/RegisterSingleModule", (WPARAM)KEYBDMODULE, 0); - if (ServiceExists(MS_UPDATE_REGISTERFL)) - CallService(MS_UPDATE_REGISTERFL, (WPARAM)2071, (LPARAM)&pluginInfo); - - return 0; -} - - - -BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) -{ - - hInst = hinstDLL; - - return TRUE; - -} - - - -__declspec(dllexport) PLUGININFO* MirandaPluginInfo(DWORD mirandaVersion)
-{
-
- pluginInfo.cbSize = sizeof(PLUGININFO);
- return (PLUGININFO*)&pluginInfo;
-
-}
-
-
-
-__declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
-{
-
- pluginInfo.cbSize = sizeof(PLUGININFOEX);
- return &pluginInfo;
-
-}
-
-
-
-#define MIID_KBDNOTIFY {0x119d7288, 0x2050, 0x448d, { 0x99, 0x00, 0xd8, 0x6a, 0xc7, 0x04, 0x26, 0xbf }}
-static const MUUID interfaces[] = {MIID_KBDNOTIFY, MIID_LAST};
-__declspec(dllexport) const MUUID* MirandaPluginInterfaces(void)
-{
-
- return interfaces;
-
-}
-
- - -int __declspec(dllexport) Load(PLUGINLINK *link) -{ - - pluginLink = link; - - GetWindowsVersion(); - OpenKeyboardDevice(); - hModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED, ModulesLoaded); - - return 0; -} - - - -void destroyProtocolList(void) -{ - unsigned int i; - - for(i=0; i < ProtoList.protoCount; i++) { - if (ProtoList.protoInfo[i].szProto) - free(ProtoList.protoInfo[i].szProto); - if (ProtoList.protoInfo[i].xstatus.enabled) - free(ProtoList.protoInfo[i].xstatus.enabled); - } - - ProtoList.protoCount = 0; - if (ProtoList.protoInfo) - free(ProtoList.protoInfo); -} - - -int __declspec(dllexport) Unload(void) -{ - - UnhookWindowsHooks(); - DeInitAction(); - if (hModulesLoaded) - UnhookEvent(hModulesLoaded); - if (hMsgEventHook) - UnhookEvent(hMsgEventHook); - if (hOptionsInitialize) - UnhookEvent(hOptionsInitialize); - if (hEnableService) - DestroyServiceFunction(hEnableService); - if (hDisableService) - DestroyServiceFunction(hDisableService); - if (hStartBlinkService) - DestroyServiceFunction(hStartBlinkService); - if (hEventsOpenedService) - DestroyServiceFunction(hEventsOpenedService); - if (hFlashingEventService) - DestroyServiceFunction(hFlashingEventService); - if (hNormalizeSequenceService) - DestroyServiceFunction(hNormalizeSequenceService); - - // Wait for thread to exit - SetEvent(hExitEvent); - WaitForSingleObject(hThread, INFINITE); - - RestoreLEDState(); - CloseKeyboardDevice(); - - UnloadProcsLibrary(); - destroyProcessList(); - destroyProtocolList(); - - return 0; -} - - -// ========================== Windows hooks ========================== -int HookWindowsHooks() -{ - if (wReminderCheck) - hReminderTimer = SetTimer(NULL,0, wReminderCheck * 60000, ReminderTimer); - - if (bFlashUntil & UNTIL_REATTENDED) - switch (bMirandaOrWindows) { - case ACTIVE_WINDOWS: - if (!MyGetLastInputInfo || bEmulateKeypresses) { - if (hMouseHook == NULL) - hMouseHook = SetWindowsHookEx(WH_MOUSE, MouseHookFunction, hInst, 0); - if (hKeyBoardHook == NULL) - hKeyBoardHook = SetWindowsHookEx(WH_KEYBOARD, KeyBoardHookFunction, hInst, 0); - } - break; - case ACTIVE_MIRANDA: - if (hMirandaMouseHook == NULL) - hMirandaMouseHook = SetWindowsHookEx(WH_MOUSE, MirandaMouseHookFunction, NULL, GetCurrentThreadId()); - if (hMirandaKeyBoardHook == NULL) - hMirandaKeyBoardHook = SetWindowsHookEx(WH_KEYBOARD, MirandaKeyBoardHookFunction, NULL, GetCurrentThreadId()); - if (hMirandaWndProcHook == NULL) - hMirandaWndProcHook = SetWindowsHookEx(WH_CALLWNDPROC, MirandaWndProcHookFunction, NULL, GetCurrentThreadId()); - } - - return 0; -} - -int UnhookWindowsHooks() -{ - if (hReminderTimer) - KillTimer(NULL, hReminderTimer); - if (hMouseHook) - UnhookWindowsHookEx(hMouseHook); - if (hKeyBoardHook) - UnhookWindowsHookEx(hKeyBoardHook); - if (hMirandaMouseHook) - UnhookWindowsHookEx(hMirandaMouseHook); - if (hMirandaKeyBoardHook) - UnhookWindowsHookEx(hMirandaKeyBoardHook); - if (hMirandaWndProcHook) - UnhookWindowsHookEx(hMirandaWndProcHook); - - hReminderTimer = 0; - hMouseHook = hKeyBoardHook = hMirandaMouseHook = hMirandaKeyBoardHook = hMirandaWndProcHook = NULL; - - return 0; -} - -static LRESULT CALLBACK MouseHookFunction(int code, WPARAM wParam, LPARAM lParam) -{ - if (code >= 0) { - /* This should handle all mouse buttons ... */ - if ((wParam >= WM_NCLBUTTONDOWN && wParam <= WM_NCXBUTTONDBLCLK && wParam != 0x00AA) || (wParam >= WM_LBUTTONDOWN && wParam <= WM_XBUTTONDBLCLK)) - dwLastInput = GetTickCount(); - /* ... and here it is either mouse move, hover, leave or something unexpected */ - else { - PMOUSEHOOKSTRUCT mouseInfo = (PMOUSEHOOKSTRUCT)lParam; - POINT pt = mouseInfo->pt; - if (pt.x!=lastGlobalMousePos.x || pt.y!=lastGlobalMousePos.y) { - lastGlobalMousePos = pt; - dwLastInput = GetTickCount(); - } - } - } - - return CallNextHookEx(hMouseHook, code, wParam, lParam); -} - -static LRESULT CALLBACK KeyBoardHookFunction(int code, WPARAM wParam, LPARAM lParam) -{ - if (code >= 0 && (!bEmulateKeypresses || (bEmulateKeypresses && wParam != VK_NUMLOCK && wParam != VK_CAPITAL && wParam != VK_SCROLL))) - dwLastInput = GetTickCount(); - - return CallNextHookEx(hKeyBoardHook, code, wParam, lParam); -} - -static LRESULT CALLBACK MirandaMouseHookFunction(int code, WPARAM wParam, LPARAM lParam) -{ - static POINT lastMousePos = {0, 0}; - - if (code >= 0) { - /* Movement mouse messages are for some reason incoming in inactive/background window too, that is not input */ - DWORD pid; - GetWindowThreadProcessId(GetForegroundWindow(), &pid); - if(pid == GetCurrentProcessId()) { - /* This should handle all mouse buttons ... */ - if ((wParam >= WM_NCLBUTTONDOWN && wParam <= WM_NCXBUTTONDBLCLK && wParam != 0x00AA) || (wParam >= WM_LBUTTONDOWN && wParam <= WM_XBUTTONDBLCLK)) - dwLastInput = GetTickCount(); - /* ... and here it is either mouse move, hover, leave or something unexpected */ - else { - PMOUSEHOOKSTRUCT mouseInfo = (PMOUSEHOOKSTRUCT)lParam; - POINT pt = mouseInfo->pt; - if (pt.x!=lastMousePos.x || pt.y!=lastMousePos.y) { - lastMousePos = pt; - dwLastInput = GetTickCount(); - } - } - } - } - - return CallNextHookEx(hMirandaMouseHook, code, wParam, lParam); -} - -static LRESULT CALLBACK MirandaKeyBoardHookFunction(int code, WPARAM wParam, LPARAM lParam) { - - if (code >= 0 && (!bEmulateKeypresses || (bEmulateKeypresses && wParam != VK_NUMLOCK && wParam != VK_CAPITAL && wParam != VK_SCROLL))) - dwLastInput = GetTickCount(); - - return CallNextHookEx(hMirandaKeyBoardHook, code, wParam, lParam); -} - -static LRESULT CALLBACK MirandaWndProcHookFunction(int code, WPARAM wParam, LPARAM lParam) { - - if (code >= 0) { - /* WM_ACTIVATEAPP with nonzero wParam means someone brought miranda to foreground, that equals to input */ - PCWPSTRUCT cwpInfo = (PCWPSTRUCT)lParam; - if(cwpInfo->message == WM_ACTIVATEAPP && cwpInfo->wParam) - dwLastInput = GetTickCount(); - } - - return CallNextHookEx(hMirandaWndProcHook, code, wParam, lParam); -} - - -//===================== Check Window Message function ===================== - -// Took this snippet of code from "EventNotify" by micron-x, thx *g* -// and updated with NGEventNotify and pete's patch -// checks if the message-dialog window is already opened and returns: -// TRUE - Windows found -// FALSE - No window found - -HWND findMessageWindow(HANDLE hContact) -{ - HWND hwnd; - char newtitle[256]; - char *szProto, *contactName, *szStatus; - CONTACTINFO ci = {0}; - - szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); - contactName = (char *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, 0); - szStatus = (char *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, szProto==NULL?ID_STATUS_OFFLINE:DBGetContactSettingWord(hContact, szProto, "Status", ID_STATUS_OFFLINE), 0); - - mir_snprintf(newtitle, sizeof(newtitle), "%s (%s): %s", contactName, szStatus, Translate("Message Received")); - if(hwnd = FindWindow(NULL, newtitle)) - return hwnd; - - mir_snprintf(newtitle, sizeof(newtitle), "%s %s", contactName, szStatus); - if(hwnd = FindWindow(NULL, newtitle)) - return hwnd; - mir_snprintf(newtitle, sizeof(newtitle), "%s (%s): %s", contactName, szStatus, Translate("Message Session")); - if(hwnd = FindWindow(NULL, newtitle)) - return hwnd; - mir_snprintf(newtitle, sizeof(newtitle), "%s (%s): %s", contactName, szStatus, Translate("Message Session is typing...")); - if(hwnd = FindWindow(NULL, newtitle)) - return hwnd; - // search for the nconvers++ message window that uses the UIN - ci.cbSize = sizeof(CONTACTINFO); - ci.dwFlag = CNF_UNIQUEID; - ci.hContact = hContact; - if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)&ci)) { - switch(ci.type) { - case CNFT_BYTE: - mir_snprintf(newtitle, sizeof(newtitle), "%s (%d) %s", contactName, ci.bVal, szStatus); - break; - case CNFT_WORD: - mir_snprintf(newtitle, sizeof(newtitle), "%s (%d) %s", contactName, ci.wVal, szStatus); - break; - case CNFT_DWORD: - mir_snprintf(newtitle, sizeof(newtitle), "%s (%d) %s", contactName, ci.dVal, szStatus); - break; - case CNFT_ASCIIZ: - mir_snprintf(newtitle, sizeof(newtitle), "%s (%s) %s", contactName, ci.pszVal, szStatus); - break; - } - if(hwnd = FindWindow(NULL, newtitle)) - return hwnd; - } - - return NULL; -} - -BOOL CheckMsgWnd(HANDLE hContact, BOOL *focus) -{ - if (ServiceExists(MS_MSG_GETWINDOWDATA)) { // use the new message API - MessageWindowData mwd; - MessageWindowInputData mwid; - mwid.cbSize = sizeof(MessageWindowInputData); - mwid.hContact = hContact; - mwid.uFlags = MSG_WINDOW_UFLAG_MSG_BOTH; - mwd.cbSize = sizeof(MessageWindowData); - mwd.hContact = hContact; - if (!CallService(MS_MSG_GETWINDOWDATA, (WPARAM)&mwid, (LPARAM)&mwd) && mwd.hwndWindow) { - *focus = mwd.uState & MSG_WINDOW_STATE_FOCUS; - return TRUE; - } - } else { // old way: find it by using the window class & title - HWND hwnd; - - if(hwnd = findMessageWindow(hContact)) { - *focus = hwnd==GetForegroundWindow(); - return TRUE; - } - } - - *focus = FALSE; - return FALSE; -} - - -void countUnopenEvents(int *msgCount, int *fileCount, int *urlCount, int *otherCount) -{ - int nIndex; - CLISTEVENT *pCLEvent; - - for (nIndex = 0; pCLEvent = (CLISTEVENT*)CallService(MS_CLIST_GETEVENT, -1, nIndex); nIndex++) { - DBEVENTINFO einfo = readEventInfo(pCLEvent->hDbEvent, pCLEvent->hContact); - - if (metaCheckProtocol(einfo.szModule, pCLEvent->hContact, einfo.eventType)) - switch (einfo.eventType) { - case EVENTTYPE_MESSAGE: - if (bFlashOnMsg) - (*msgCount)++; - break; - case EVENTTYPE_URL: - if (bFlashOnURL) - (*urlCount)++; - break; - case EVENTTYPE_FILE: - if (bFlashOnFile) - (*fileCount)++; - break; - default: - if (bFlashOnOther) - (*otherCount)++; - } - } - if (bFlashOnOther) - (*otherCount) += nExternCount; -} |