summaryrefslogtreecommitdiff
path: root/kbdnotify/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'kbdnotify/main.c')
-rw-r--r--kbdnotify/main.c1487
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;
-}