summaryrefslogtreecommitdiff
path: root/plugins/KeyboardNotify/src
diff options
context:
space:
mode:
authorTobias Weimer <wishmaster51@googlemail.com>2016-04-02 22:37:42 +0000
committerTobias Weimer <wishmaster51@googlemail.com>2016-04-02 22:37:42 +0000
commit2c03b22f2db0f8e68c944af232e28094e8ebf811 (patch)
treee3a030edfa1fa2d35e93f6b8755aacad0e84ea9e /plugins/KeyboardNotify/src
parentccbec1ea1c080d76b85fef65c6fb18d861e063bf (diff)
KeyboardNotify: -Use mir_alloc instead of malloc
git-svn-id: http://svn.miranda-ng.org/main/trunk@16579 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/KeyboardNotify/src')
-rw-r--r--plugins/KeyboardNotify/src/main.cpp1928
-rw-r--r--plugins/KeyboardNotify/src/options.cpp65
2 files changed, 988 insertions, 1005 deletions
diff --git a/plugins/KeyboardNotify/src/main.cpp b/plugins/KeyboardNotify/src/main.cpp
index d54a584af7..af392241d3 100644
--- a/plugins/KeyboardNotify/src/main.cpp
+++ b/plugins/KeyboardNotify/src/main.cpp
@@ -1,968 +1,964 @@
-/*
- 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.
-*/
-
-#include "stdafx.h"
-
-#define NCONVERS_BLINKID ((MEVENT)123456) //nconvers' random identifier used to flash an icon for "incoming message" on contact list
-
-HINSTANCE g_hInst;
-
+/*
+ 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.
+*/
+
+#include "stdafx.h"
+
+#define NCONVERS_BLINKID ((MEVENT)123456) //nconvers' random identifier used to flash an icon for "incoming message" on contact list
+
+HINSTANCE g_hInst;
+
CLIST_INTERFACE *pcli;
-int hLangpack;
-
-DWORD IDThread = 0;
-HANDLE hThread = NULL;
-HANDLE hFlashEvent;
-HANDLE hExitEvent;
-
-HHOOK hMirandaMouseHook = NULL;
-HHOOK hMirandaKeyBoardHook = NULL;
-HHOOK hMirandaWndProcHook = NULL;
-UINT hReminderTimer = 0;
-
-HHOOK hMouseHook = NULL;
-HHOOK hKeyBoardHook = NULL;
-BYTE bEmulateKeypresses = 0;
-DWORD dwLastInput = 0;
-POINT lastGlobalMousePos = { 0, 0 };
-
-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 };
-
-int nWaitDelay;
-unsigned int nExternCount = 0;
-BOOL bFlashingEnabled = TRUE;
-BOOL bReminderDisabled = FALSE;
-
-BYTE bMetaProtoEnabled = 0;
-
-PLUGININFOEX pluginInfo = {
- sizeof(PLUGININFOEX),
- __PLUGIN_NAME,
- PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
- __DESCRIPTION,
- __AUTHOR,
- __AUTHOREMAIL,
- __COPYRIGHT,
- __AUTHORWEB,
- UNICODE_AWARE,
- //{119D7288-2050-448D-9900-D86AC70426BF}
- {0x119d7288, 0x2050, 0x448d, {0x99, 0x00, 0xd8, 0x6a, 0xc7, 0x04, 0x26, 0xbf}}
-};
-
-extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD)
-{
- return &pluginInfo;
-}
-
-BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD, LPVOID)
-{
- g_hInst = hinstDLL;
- return TRUE;
-}
-
-int InitializeOptions(WPARAM, LPARAM);
-void LoadSettings(void);
-int HookWindowsHooks(void);
-int UnhookWindowsHooks(void);
-void destroyProcessList(void);
-
-BOOL CheckMsgWnd(MCONTACT, BOOL *);
-
-BOOL checkOpenWindow(MCONTACT hContact)
-{
- if (bFlashIfMsgOpen && !bFlashIfMsgWinNotTop)
- return TRUE;
-
- BOOL focus, found = CheckMsgWnd(hContact, &focus);
- if (!found && bMetaProtoEnabled)
- found = CheckMsgWnd(db_mc_getMeta(hContact), &focus);
-
- if (!found)
- return TRUE;
-
- if (bFlashIfMsgOpen && !focus)
- return TRUE;
-
- return FALSE;
-}
-
-BOOL checkNotifyOptions()
-{
- BOOL screenSaverIsRunning = IsScreenSaverRunning();
- if (screenSaverIsRunning && bScreenSaverRunning)
- return TRUE;
-
- BOOL workstationIsLocked = IsWorkstationLocked();
- if (workstationIsLocked && bWorkstationLocked)
- return TRUE;
-
- BOOL fullScreenMode = IsFullScreen() && !screenSaverIsRunning;
- if (fullScreenMode && bFullScreenMode)
- return TRUE;
-
- BOOL 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;
- }
- return FALSE;
-}
-
-BOOL checkGlobalStatus()
-{
- return isStatusEnabled(CallService(MS_CLIST_GETSTATUSMODE, 0, 0));
-}
-
-BOOL checkGlobalXstatus()
-{
- int protosSupporting = 0, status = 0;
-
- for (int i = 0; i < ProtoList.protoCount; i++) {
- if (!ProtoList.protoInfo[i].enabled || !ProtoList.protoInfo[i].xstatus.count)
- continue;
-
- protosSupporting++;
- // Retrieve xstatus for protocol
- CUSTOM_STATUS xstatus = { sizeof(CUSTOM_STATUS) };
- xstatus.flags = CSSF_MASK_STATUS;
- xstatus.status = &status;
- CallProtoService(ProtoList.protoInfo[i].szProto, PS_GETCUSTOMSTATUSEX, 0, (LPARAM)&xstatus);
-
- if (ProtoList.protoInfo[i].xstatus.enabled[status])
- return TRUE;
- }
-
- return protosSupporting == 0;
-}
-
-DBEVENTINFO createMsgEventInfo(MCONTACT hContact)
-{
- DBEVENTINFO einfo = { sizeof(einfo) };
- einfo.eventType = EVENTTYPE_MESSAGE;
- einfo.szModule = GetContactProto(hContact);
- return einfo;
-}
-
-DBEVENTINFO readEventInfo(MEVENT hDbEvent, MCONTACT hContact)
-{
- if (hDbEvent == NCONVERS_BLINKID) // we need to handle nconvers' blink event
- return createMsgEventInfo(hContact);
-
- DBEVENTINFO einfo = { sizeof(einfo) };
- db_event_get(hDbEvent, &einfo);
- return einfo;
-}
-
-BOOL checkIgnore(MCONTACT hContact, WORD eventType)
-{
- return !IsIgnored(hContact, eventType);
-}
-
-BOOL checkProtocol(char *szProto)
-{
- if (!szProto)
- return FALSE;
-
- for (int i = 0; i < ProtoList.protoCount; i++)
- if (ProtoList.protoInfo[i].szProto && !mir_strcmp(ProtoList.protoInfo[i].szProto, szProto))
- return ProtoList.protoInfo[i].enabled;
-
- return FALSE;
-}
-
-BOOL metaCheckProtocol(char *szProto, MCONTACT hContact, WORD eventType)
-{
- MCONTACT hSubContact = NULL;
-
- if (bMetaProtoEnabled && szProto && !mir_strcmp(META_PROTO, szProto))
- if (hSubContact = db_mc_getMostOnline(hContact))
- szProto = GetContactProto(hSubContact);
-
- return checkProtocol(szProto) && checkIgnore(hSubContact ? hSubContact : hContact, eventType);
-}
-
-
-BOOL checkUnopenEvents()
-{
- int nIndex;
- CLISTEVENT *pCLEvent;
-
- if (nExternCount && bFlashOnOther)
- return TRUE;
-
- for (nIndex = 0; pCLEvent = pcli->pfnGetEvent(-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 __cdecl FlashThreadFunction(void*)
-{
- BOOL bEvent = FALSE;
- DWORD dwEventStarted = 0, dwFlashStarted = 0;
- 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 && !bEmulateKeypresses) {
- LASTINPUTINFO ii = { sizeof(ii) };
- GetLastInputInfo(&ii);
- dwLastInput = ii.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
- HANDLE Objects[2];
- Objects[0] = hFlashEvent;
- Objects[1] = hExitEvent;
- if (WaitForMultipleObjects(2, Objects, FALSE, INFINITE) == WAIT_OBJECT_0 + 1)
- return;
-
- bEvent = TRUE;
- bReminderDisabled = TRUE;
- dwEventStarted = GetTickCount();
- // Wait StartDelay seconds
- if (wStartDelay > 0)
- Sleep(wStartDelay * 1000);
- dwFlashStarted = GetTickCount();
- }
-}
-
-BOOL checkMsgTimestamp(MCONTACT hContact, MEVENT hEventCurrent, DWORD timestampCurrent)
-{
- if (!bFlashIfMsgOlder)
- return TRUE;
-
- for (MEVENT hEvent = db_event_prev(hContact, hEventCurrent); hEvent; hEvent = db_event_prev(hContact, hEvent)) {
- DBEVENTINFO einfo = { sizeof(einfo) };
- if (!db_event_get(hEvent, &einfo)) {
- if ((einfo.timestamp + wSecondsOlder) <= timestampCurrent)
- return TRUE;
- if (einfo.eventType == EVENTTYPE_MESSAGE)
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
-
-BOOL contactCheckProtocol(char *szProto, MCONTACT hContact, WORD eventType)
-{
- if (bMetaProtoEnabled && hContact) {
- MCONTACT hMetaContact = (MCONTACT)db_get_dw(hContact, META_PROTO, "Handle", 0);
- if (hMetaContact && db_mc_getMeta(hContact) == hMetaContact)
- 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)
-{
- int status = 0;
-
- if (!szProto)
- return checkGlobalXstatus();
-
- for (int i = 0; i < ProtoList.protoCount; i++)
- if (ProtoList.protoInfo[i].szProto && !mir_strcmp(ProtoList.protoInfo[i].szProto, szProto)) {
- if (!ProtoList.protoInfo[i].xstatus.count) return TRUE;
-
- // Retrieve xstatus for protocol
- CUSTOM_STATUS xstatus = { sizeof(CUSTOM_STATUS) };
- xstatus.flags = CSSF_MASK_STATUS;
- xstatus.status = &status;
- CallProtoService(ProtoList.protoInfo[i].szProto, PS_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 hContact, LPARAM hEvent)
-{
- //get DBEVENTINFO without pBlob
- DBEVENTINFO einfo = { sizeof(einfo) };
- if (!db_event_get(hEvent, &einfo) && !(einfo.flags & DBEF_SENT))
- if ((einfo.eventType == EVENTTYPE_MESSAGE && bFlashOnMsg && checkOpenWindow(hContact) && checkMsgTimestamp(hContact, 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, UINT, UINT_PTR, DWORD)
-{
- int nIndex;
- CLISTEVENT *pCLEvent;
-
- if (!bReminderDisabled && nExternCount && bFlashOnOther) {
- SetEvent(hFlashEvent);
- return;
- }
-
- for (nIndex = 0; !bReminderDisabled && (pCLEvent = pcli->pfnGetEvent(-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_PTR EnableService(WPARAM, LPARAM)
-{
- bFlashingEnabled = TRUE;
- return 0;
-}
-
-static INT_PTR DisableService(WPARAM, LPARAM)
-{
- bFlashingEnabled = FALSE;
- return 0;
-}
-
-static INT_PTR StartBlinkService(WPARAM wParam, LPARAM lParam)
-{
- nExternCount += (unsigned int)wParam;
- if (bFlashOnOther && checkNotifyOptions() && checkGlobalStatus() && checkGlobalXstatus()) {
- if (lParam)
- useExternSequence((TCHAR *)lParam);
- SetEvent(hFlashEvent);
- }
-
- return 0;
-}
-
-static INT_PTR EventsWereOpenedService(WPARAM wParam, LPARAM)
-{
- if ((unsigned int)wParam > nExternCount)
- nExternCount = 0;
- else
- nExternCount -= (unsigned int)wParam;
-
- return 0;
-}
-
-static INT_PTR IsFlashingActiveService(WPARAM, LPARAM)
-{
- if (!bReminderDisabled)
- return 0;
-
- return (INT_PTR)getCurrentSequenceString();
-}
-
-INT_PTR NormalizeSequenceService(WPARAM, LPARAM lParam)
-{
- TCHAR strAux[MAX_PATH + 1], *strIn = (TCHAR*)lParam;
-
- _tcsncpy_s(strAux, strIn, _TRUNCATE);
- _tcsncpy_s(strIn, MAX_PATH, normalizeCustomString(strAux), _TRUNCATE);
-
- return (INT_PTR)strIn;
-}
-
-// Support for Trigger plugin
-static void __cdecl ForceEventsWereOpenedThread(void *eventMaxSeconds)
-{
- Sleep(((UINT_PTR)eventMaxSeconds) * 1000);
- CallService(MS_KBDNOTIFY_EVENTSOPENED, 1, 0);
-}
-
-void StartBlinkAction(char *flashSequence, WORD eventMaxSeconds)
-{
- if (eventMaxSeconds)
- mir_forkthread(ForceEventsWereOpenedThread, (void *)eventMaxSeconds);
-
- CallService(MS_KBDNOTIFY_STARTBLINK, 1, (LPARAM)flashSequence);
-}
-
-void createProcessList(void)
-{
- int count = db_get_w(NULL, KEYBDMODULE, "processcount", 0);
-
- ProcessList.count = 0;
- ProcessList.szFileName = (TCHAR **)malloc(count * sizeof(TCHAR *));
- if (ProcessList.szFileName) {
- for (int i = 0; i < count; i++)
- ProcessList.szFileName[i] = db_get_tsa(NULL, KEYBDMODULE, fmtDBSettingName("process%d", i));
-
- ProcessList.count = count;
- }
-}
-
-void LoadSettings(void)
-{
- bFlashOnMsg = db_get_b(NULL, KEYBDMODULE, "onmsg", DEF_SETTING_ONMSG);
- bFlashOnURL = db_get_b(NULL, KEYBDMODULE, "onurl", DEF_SETTING_ONURL);
- bFlashOnFile = db_get_b(NULL, KEYBDMODULE, "onfile", DEF_SETTING_ONFILE);
- bFlashOnOther = db_get_b(NULL, KEYBDMODULE, "onother", DEF_SETTING_OTHER);
- bFullScreenMode = db_get_b(NULL, KEYBDMODULE, "fscreenmode", DEF_SETTING_FSCREEN);
- bScreenSaverRunning = db_get_b(NULL, KEYBDMODULE, "ssaverrunning", DEF_SETTING_SSAVER);
- bWorkstationLocked = db_get_b(NULL, KEYBDMODULE, "wstationlocked", DEF_SETTING_LOCKED);
- bProcessesAreRunning = db_get_b(NULL, KEYBDMODULE, "procsrunning", DEF_SETTING_PROCS);
- bWorkstationActive = db_get_b(NULL, KEYBDMODULE, "wstationactive", DEF_SETTING_ACTIVE);
- bFlashIfMsgOpen = db_get_b(NULL, KEYBDMODULE, "ifmsgopen", DEF_SETTING_IFMSGOPEN);
- bFlashIfMsgWinNotTop = db_get_b(NULL, KEYBDMODULE, "ifmsgnottop", DEF_SETTING_IFMSGNOTTOP);
- bFlashIfMsgOlder = db_get_b(NULL, KEYBDMODULE, "ifmsgolder", DEF_SETTING_IFMSGOLDER);
- wSecondsOlder = db_get_w(NULL, KEYBDMODULE, "secsolder", DEF_SETTING_SECSOLDER);
- bFlashUntil = db_get_b(NULL, KEYBDMODULE, "funtil", DEF_SETTING_FLASHUNTIL);
- wBlinksNumber = db_get_w(NULL, KEYBDMODULE, "nblinks", DEF_SETTING_NBLINKS);
- bMirandaOrWindows = db_get_b(NULL, KEYBDMODULE, "mirorwin", DEF_SETTING_MIRORWIN);
- wStatusMap = db_get_w(NULL, KEYBDMODULE, "status", DEF_SETTING_STATUS);
- wReminderCheck = db_get_w(NULL, KEYBDMODULE, "remcheck", DEF_SETTING_CHECKTIME);
- bFlashLed[0] = db_get_b(NULL, KEYBDMODULE, "fnum", DEF_SETTING_FLASHNUM);
- bFlashLed[1] = db_get_b(NULL, KEYBDMODULE, "fcaps", DEF_SETTING_FLASHCAPS);
- bFlashLed[2] = db_get_b(NULL, KEYBDMODULE, "fscroll", DEF_SETTING_FLASHSCROLL);
- bFlashEffect = db_get_b(NULL, KEYBDMODULE, "feffect", DEF_SETTING_FLASHEFFECT);
- bSequenceOrder = db_get_b(NULL, KEYBDMODULE, "order", DEF_SETTING_SEQORDER);
- wCustomTheme = db_get_w(NULL, KEYBDMODULE, "custom", DEF_SETTING_CUSTOMTHEME);
- bTrillianLedsMsg = db_get_b(NULL, KEYBDMODULE, "ledsmsg", DEF_SETTING_LEDSMSG);
- bTrillianLedsURL = db_get_b(NULL, KEYBDMODULE, "ledsurl", DEF_SETTING_LEDSURL);
- bTrillianLedsFile = db_get_b(NULL, KEYBDMODULE, "ledsfile", DEF_SETTING_LEDSFILE);
- bTrillianLedsOther = db_get_b(NULL, KEYBDMODULE, "ledsother", DEF_SETTING_LEDSOTHER);
- wStartDelay = db_get_w(NULL, KEYBDMODULE, "sdelay", DEF_SETTING_STARTDELAY);
- bFlashSpeed = db_get_b(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 = db_get_b(NULL, KEYBDMODULE, "keypresses", DEF_SETTING_KEYPRESSES);
- bOverride = db_get_b(NULL, KEYBDMODULE, "override", DEF_SETTING_OVERRIDE);
- // Create hidden settings (for test button) if needed
- if (db_get_b(NULL, KEYBDMODULE, "testnum", -1) == -1)
- db_set_b(NULL, KEYBDMODULE, "testnum", DEF_SETTING_TESTNUM);
- if (db_get_b(NULL, KEYBDMODULE, "testsecs", -1) == -1)
- db_set_b(NULL, KEYBDMODULE, "testsecs", DEF_SETTING_TESTSECS);
- for (int i = 0; i < ProtoList.protoCount; i++)
- if (ProtoList.protoInfo[i].visible) {
- unsigned int j;
- ProtoList.protoInfo[i].enabled = db_get_b(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] = db_get_b(NULL, KEYBDMODULE, fmtDBSettingName("%sxstatus%d", ProtoList.protoInfo[i].szProto, j), DEF_SETTING_XSTATUS);
- }
-
- bMetaProtoEnabled = db_mc_isEnabled();
-
- destroyProcessList();
- createProcessList();
- UnhookWindowsHooks();
- HookWindowsHooks();
-}
-
-
-void GetWindowsVersion(void)
-{
- OSVERSIONINFOEX osvi = { sizeof(OSVERSIONINFOEX) };
- BOOL bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO *)&osvi);
-
- if (!bOsVersionInfoEx) {
- osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- if (!GetVersionEx((OSVERSIONINFO *)&osvi))
- osvi.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS;
- }
-}
-
-
-void updateXstatusProto(PROTOCOL_INFO *protoInfo)
-{
- if (!ProtoServiceExists(protoInfo->szProto, PS_GETCUSTOMSTATUSEX))
- return;
-
- // Retrieve xstatus.count
- CUSTOM_STATUS xstatus = { sizeof(xstatus) };
- xstatus.flags = CSSF_STATUSES_COUNT;
- xstatus.wParam = &(protoInfo->xstatus.count);
- CallProtoService(protoInfo->szProto, PS_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 (unsigned i = 0; i < protoInfo->xstatus.count; i++)
- protoInfo->xstatus.enabled[i] = FALSE;
-}
-
-
-void createProtocolList(void)
-{
- PROTOACCOUNT **proto;
- Proto_EnumAccounts(&ProtoList.protoCount, &proto);
- ProtoList.protoInfo = (PROTOCOL_INFO *)malloc(ProtoList.protoCount * sizeof(PROTOCOL_INFO));
- if (!ProtoList.protoInfo) {
- ProtoList.protoCount = 0;
- return;
- }
-
- for (int i = 0; i < ProtoList.protoCount; i++) {
- ProtoList.protoInfo[i].xstatus.count = 0;
- ProtoList.protoInfo[i].xstatus.enabled = NULL;
- ProtoList.protoInfo[i].szProto = (char *)malloc(mir_strlen(proto[i]->szModuleName) + 1);
- if (!ProtoList.protoInfo[i].szProto) {
- ProtoList.protoInfo[i].enabled = FALSE;
- ProtoList.protoInfo[i].visible = FALSE;
- }
- else {
- mir_strcpy(ProtoList.protoInfo[i].szProto, proto[i]->szModuleName);
- ProtoList.protoInfo[i].enabled = FALSE;
- if (!mir_strcmp(proto[i]->szModuleName, META_PROTO))
- 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(TCHAR *prefixName, size_t maxLen)
-{
- size_t len;
- TCHAR profileName[MAX_PATH + 1], *str;
-
- getAbsoluteProfileName(profileName, MAX_PATH);
-
- while (str = _tcschr(profileName, _T('\\')))
- *str = _T('/');
- if ((len = mir_tstrlen(profileName)) <= maxLen)
- _tcsncpy_s(prefixName, maxLen, profileName, _TRUNCATE);
- else {
- str = profileName + len - maxLen / 2;
- _tcsncpy_s(prefixName, (maxLen / 2), profileName, _TRUNCATE);
- mir_tstrcat(prefixName, str);
- }
-}
-
-//========================== Windows hooks ==========================
-
-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);
-}
-
-int HookWindowsHooks()
-{
- if (wReminderCheck)
- hReminderTimer = SetTimer(NULL, 0, wReminderCheck * 60000, ReminderTimer);
-
- if (bFlashUntil & UNTIL_REATTENDED) {
- switch (bMirandaOrWindows) {
- case ACTIVE_WINDOWS:
- if (bEmulateKeypresses) {
- if (hMouseHook == NULL)
- hMouseHook = SetWindowsHookEx(WH_MOUSE, MouseHookFunction, 0, GetCurrentThreadId());
- if (hKeyBoardHook == NULL)
- hKeyBoardHook = SetWindowsHookEx(WH_KEYBOARD, KeyBoardHookFunction, 0, GetCurrentThreadId());
- }
- 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;
-}
-
-BOOL CheckMsgWnd(MCONTACT hContact, BOOL *focus)
-{
- if (hContact) {
- MessageWindowData mwd = { sizeof(MessageWindowData) };
- MessageWindowInputData mwid = { sizeof(MessageWindowInputData) };
- mwid.hContact = hContact;
- mwid.uFlags = MSG_WINDOW_UFLAG_MSG_BOTH;
- mwd.hContact = hContact;
- if (!CallService(MS_MSG_GETWINDOWDATA, (WPARAM)&mwid, (LPARAM)&mwd) && mwd.hwndWindow) {
- *focus = mwd.uState & MSG_WINDOW_STATE_FOCUS;
- return TRUE;
- }
- }
-
- *focus = FALSE;
- return FALSE;
-}
-
-
-void countUnopenEvents(int *msgCount, int *fileCount, int *urlCount, int *otherCount)
-{
- int nIndex;
- CLISTEVENT *pCLEvent;
-
- for (nIndex = 0; pCLEvent = pcli->pfnGetEvent(-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;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Load
-
-static int OnMetaChanged(WPARAM wParam, LPARAM)
-{
- bMetaProtoEnabled = wParam;
- return 0;
-}
-
-static int OnPreshutdown(WPARAM, LPARAM)
-{
- SetEvent(hExitEvent);
- return 0;
-}
-
-static int ModulesLoaded(WPARAM, LPARAM)
-{
- TCHAR eventPrefix[MAX_PATH + 1], eventName[MAX_PATH + 1];
-
- createProtocolList();
- LoadSettings();
-
- // Create some synchronisation objects
- createEventPrefix(eventPrefix, MAX_PATH - 11);
- mir_sntprintf(eventName, _T("%s/FlashEvent"), eventPrefix);
- hFlashEvent = CreateEvent(NULL, FALSE, FALSE, eventName);
- mir_sntprintf(eventName, _T("%s/ExitEvent"), eventPrefix);
- hExitEvent = CreateEvent(NULL, FALSE, FALSE, eventName);
-
- hThread = mir_forkthread(FlashThreadFunction, 0);
-
- HookEvent(ME_MC_ENABLED, OnMetaChanged);
- HookEvent(ME_DB_EVENT_ADDED, PluginMessageEventHook);
- HookEvent(ME_OPT_INITIALISE, InitializeOptions);
-
- CreateServiceFunction(MS_KBDNOTIFY_ENABLE, EnableService);
- CreateServiceFunction(MS_KBDNOTIFY_DISABLE, DisableService);
- CreateServiceFunction(MS_KBDNOTIFY_STARTBLINK, StartBlinkService);
- CreateServiceFunction(MS_KBDNOTIFY_EVENTSOPENED, EventsWereOpenedService);
- CreateServiceFunction(MS_KBDNOTIFY_FLASHINGACTIVE, IsFlashingActiveService);
- CreateServiceFunction(MS_KBDNOTIFY_NORMALSEQUENCE, NormalizeSequenceService);
- return 0;
-}
-
-extern "C" __declspec(dllexport) int Load(void)
-{
- mir_getLP(&pluginInfo);
+int hLangpack;
+
+DWORD IDThread = 0;
+HANDLE hThread = NULL;
+HANDLE hFlashEvent;
+HANDLE hExitEvent;
+
+HHOOK hMirandaMouseHook = NULL;
+HHOOK hMirandaKeyBoardHook = NULL;
+HHOOK hMirandaWndProcHook = NULL;
+UINT hReminderTimer = 0;
+
+HHOOK hMouseHook = NULL;
+HHOOK hKeyBoardHook = NULL;
+BYTE bEmulateKeypresses = 0;
+DWORD dwLastInput = 0;
+POINT lastGlobalMousePos = { 0, 0 };
+
+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 };
+
+int nWaitDelay;
+unsigned int nExternCount = 0;
+BOOL bFlashingEnabled = TRUE;
+BOOL bReminderDisabled = FALSE;
+
+BYTE bMetaProtoEnabled = 0;
+
+PLUGININFOEX pluginInfo = {
+ sizeof(PLUGININFOEX),
+ __PLUGIN_NAME,
+ PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
+ __DESCRIPTION,
+ __AUTHOR,
+ __AUTHOREMAIL,
+ __COPYRIGHT,
+ __AUTHORWEB,
+ UNICODE_AWARE,
+ //{119D7288-2050-448D-9900-D86AC70426BF}
+ {0x119d7288, 0x2050, 0x448d, {0x99, 0x00, 0xd8, 0x6a, 0xc7, 0x04, 0x26, 0xbf}}
+};
+
+extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD)
+{
+ return &pluginInfo;
+}
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD, LPVOID)
+{
+ g_hInst = hinstDLL;
+ return TRUE;
+}
+
+int InitializeOptions(WPARAM, LPARAM);
+BOOL CheckMsgWnd(MCONTACT, BOOL *);
+
+BOOL checkOpenWindow(MCONTACT hContact)
+{
+ if (bFlashIfMsgOpen && !bFlashIfMsgWinNotTop)
+ return TRUE;
+
+ BOOL focus, found = CheckMsgWnd(hContact, &focus);
+ if (!found && bMetaProtoEnabled)
+ found = CheckMsgWnd(db_mc_getMeta(hContact), &focus);
+
+ if (!found)
+ return TRUE;
+
+ if (bFlashIfMsgOpen && !focus)
+ return TRUE;
+
+ return FALSE;
+}
+
+BOOL checkNotifyOptions()
+{
+ BOOL screenSaverIsRunning = IsScreenSaverRunning();
+ if (screenSaverIsRunning && bScreenSaverRunning)
+ return TRUE;
+
+ BOOL workstationIsLocked = IsWorkstationLocked();
+ if (workstationIsLocked && bWorkstationLocked)
+ return TRUE;
+
+ BOOL fullScreenMode = IsFullScreen() && !screenSaverIsRunning;
+ if (fullScreenMode && bFullScreenMode)
+ return TRUE;
+
+ BOOL 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;
+ }
+ return FALSE;
+}
+
+BOOL checkGlobalStatus()
+{
+ return isStatusEnabled(CallService(MS_CLIST_GETSTATUSMODE, 0, 0));
+}
+
+BOOL checkGlobalXstatus()
+{
+ int protosSupporting = 0, status = 0;
+
+ for (int i = 0; i < ProtoList.protoCount; i++) {
+ if (!ProtoList.protoInfo[i].enabled || !ProtoList.protoInfo[i].xstatus.count)
+ continue;
+
+ protosSupporting++;
+ // Retrieve xstatus for protocol
+ CUSTOM_STATUS xstatus = { sizeof(CUSTOM_STATUS) };
+ xstatus.flags = CSSF_MASK_STATUS;
+ xstatus.status = &status;
+ CallProtoService(ProtoList.protoInfo[i].szProto, PS_GETCUSTOMSTATUSEX, 0, (LPARAM)&xstatus);
+
+ if (ProtoList.protoInfo[i].xstatus.enabled[status])
+ return TRUE;
+ }
+
+ return protosSupporting == 0;
+}
+
+DBEVENTINFO createMsgEventInfo(MCONTACT hContact)
+{
+ DBEVENTINFO einfo = { sizeof(einfo) };
+ einfo.eventType = EVENTTYPE_MESSAGE;
+ einfo.szModule = GetContactProto(hContact);
+ return einfo;
+}
+
+DBEVENTINFO readEventInfo(MEVENT hDbEvent, MCONTACT hContact)
+{
+ if (hDbEvent == NCONVERS_BLINKID) // we need to handle nconvers' blink event
+ return createMsgEventInfo(hContact);
+
+ DBEVENTINFO einfo = { sizeof(einfo) };
+ db_event_get(hDbEvent, &einfo);
+ return einfo;
+}
+
+BOOL checkIgnore(MCONTACT hContact, WORD eventType)
+{
+ return !IsIgnored(hContact, eventType);
+}
+
+BOOL checkProtocol(char *szProto)
+{
+ if (!szProto)
+ return FALSE;
+
+ for (int i = 0; i < ProtoList.protoCount; i++)
+ if (ProtoList.protoInfo[i].szProto && !mir_strcmp(ProtoList.protoInfo[i].szProto, szProto))
+ return ProtoList.protoInfo[i].enabled;
+
+ return FALSE;
+}
+
+BOOL metaCheckProtocol(char *szProto, MCONTACT hContact, WORD eventType)
+{
+ MCONTACT hSubContact = NULL;
+
+ if (bMetaProtoEnabled && szProto && !mir_strcmp(META_PROTO, szProto))
+ if (hSubContact = db_mc_getMostOnline(hContact))
+ szProto = GetContactProto(hSubContact);
+
+ return checkProtocol(szProto) && checkIgnore(hSubContact ? hSubContact : hContact, eventType);
+}
+
+
+BOOL checkUnopenEvents()
+{
+ int nIndex;
+ CLISTEVENT *pCLEvent;
+
+ if (nExternCount && bFlashOnOther)
+ return TRUE;
+
+ for (nIndex = 0; pCLEvent = pcli->pfnGetEvent(-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 __cdecl FlashThreadFunction(void*)
+{
+ BOOL bEvent = FALSE;
+ DWORD dwEventStarted = 0, dwFlashStarted = 0;
+ 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 && !bEmulateKeypresses) {
+ LASTINPUTINFO ii = { sizeof(ii) };
+ GetLastInputInfo(&ii);
+ dwLastInput = ii.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
+ HANDLE Objects[2];
+ Objects[0] = hFlashEvent;
+ Objects[1] = hExitEvent;
+ if (WaitForMultipleObjects(2, Objects, FALSE, INFINITE) == WAIT_OBJECT_0 + 1)
+ return;
+
+ bEvent = TRUE;
+ bReminderDisabled = TRUE;
+ dwEventStarted = GetTickCount();
+ // Wait StartDelay seconds
+ if (wStartDelay > 0)
+ Sleep(wStartDelay * 1000);
+ dwFlashStarted = GetTickCount();
+ }
+}
+
+BOOL checkMsgTimestamp(MCONTACT hContact, MEVENT hEventCurrent, DWORD timestampCurrent)
+{
+ if (!bFlashIfMsgOlder)
+ return TRUE;
+
+ for (MEVENT hEvent = db_event_prev(hContact, hEventCurrent); hEvent; hEvent = db_event_prev(hContact, hEvent)) {
+ DBEVENTINFO einfo = { sizeof(einfo) };
+ if (!db_event_get(hEvent, &einfo)) {
+ if ((einfo.timestamp + wSecondsOlder) <= timestampCurrent)
+ return TRUE;
+ if (einfo.eventType == EVENTTYPE_MESSAGE)
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+BOOL contactCheckProtocol(char *szProto, MCONTACT hContact, WORD eventType)
+{
+ if (bMetaProtoEnabled && hContact) {
+ MCONTACT hMetaContact = (MCONTACT)db_get_dw(hContact, META_PROTO, "Handle", 0);
+ if (hMetaContact && db_mc_getMeta(hContact) == hMetaContact)
+ 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)
+{
+ int status = 0;
+
+ if (!szProto)
+ return checkGlobalXstatus();
+
+ for (int i = 0; i < ProtoList.protoCount; i++)
+ if (ProtoList.protoInfo[i].szProto && !mir_strcmp(ProtoList.protoInfo[i].szProto, szProto)) {
+ if (!ProtoList.protoInfo[i].xstatus.count) return TRUE;
+
+ // Retrieve xstatus for protocol
+ CUSTOM_STATUS xstatus = { sizeof(CUSTOM_STATUS) };
+ xstatus.flags = CSSF_MASK_STATUS;
+ xstatus.status = &status;
+ CallProtoService(ProtoList.protoInfo[i].szProto, PS_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 hContact, LPARAM hEvent)
+{
+ //get DBEVENTINFO without pBlob
+ DBEVENTINFO einfo = { sizeof(einfo) };
+ if (!db_event_get(hEvent, &einfo) && !(einfo.flags & DBEF_SENT))
+ if ((einfo.eventType == EVENTTYPE_MESSAGE && bFlashOnMsg && checkOpenWindow(hContact) && checkMsgTimestamp(hContact, 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, UINT, UINT_PTR, DWORD)
+{
+ int nIndex;
+ CLISTEVENT *pCLEvent;
+
+ if (!bReminderDisabled && nExternCount && bFlashOnOther) {
+ SetEvent(hFlashEvent);
+ return;
+ }
+
+ for (nIndex = 0; !bReminderDisabled && (pCLEvent = pcli->pfnGetEvent(-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_PTR EnableService(WPARAM, LPARAM)
+{
+ bFlashingEnabled = TRUE;
+ return 0;
+}
+
+static INT_PTR DisableService(WPARAM, LPARAM)
+{
+ bFlashingEnabled = FALSE;
+ return 0;
+}
+
+static INT_PTR StartBlinkService(WPARAM wParam, LPARAM lParam)
+{
+ nExternCount += (unsigned int)wParam;
+ if (bFlashOnOther && checkNotifyOptions() && checkGlobalStatus() && checkGlobalXstatus()) {
+ if (lParam)
+ useExternSequence((TCHAR *)lParam);
+ SetEvent(hFlashEvent);
+ }
+
+ return 0;
+}
+
+static INT_PTR EventsWereOpenedService(WPARAM wParam, LPARAM)
+{
+ if ((unsigned int)wParam > nExternCount)
+ nExternCount = 0;
+ else
+ nExternCount -= (unsigned int)wParam;
+
+ return 0;
+}
+
+static INT_PTR IsFlashingActiveService(WPARAM, LPARAM)
+{
+ if (!bReminderDisabled)
+ return 0;
+
+ return (INT_PTR)getCurrentSequenceString();
+}
+
+INT_PTR NormalizeSequenceService(WPARAM, LPARAM lParam)
+{
+ TCHAR strAux[MAX_PATH + 1], *strIn = (TCHAR*)lParam;
+
+ _tcsncpy_s(strAux, strIn, _TRUNCATE);
+ _tcsncpy_s(strIn, MAX_PATH, normalizeCustomString(strAux), _TRUNCATE);
+
+ return (INT_PTR)strIn;
+}
+
+// Support for Trigger plugin
+static void __cdecl ForceEventsWereOpenedThread(void *eventMaxSeconds)
+{
+ Sleep(((UINT_PTR)eventMaxSeconds) * 1000);
+ CallService(MS_KBDNOTIFY_EVENTSOPENED, 1, 0);
+}
+
+void StartBlinkAction(char *flashSequence, WORD eventMaxSeconds)
+{
+ if (eventMaxSeconds)
+ mir_forkthread(ForceEventsWereOpenedThread, (void *)eventMaxSeconds);
+
+ CallService(MS_KBDNOTIFY_STARTBLINK, 1, (LPARAM)flashSequence);
+}
+
+void createProcessList(void)
+{
+ int count = db_get_w(NULL, KEYBDMODULE, "processcount", 0);
+
+ ProcessList.count = 0;
+ ProcessList.szFileName = (TCHAR **)mir_alloc(count * sizeof(TCHAR *));
+ if (ProcessList.szFileName) {
+ for (int i = 0; i < count; i++)
+ ProcessList.szFileName[i] = db_get_tsa(NULL, KEYBDMODULE, fmtDBSettingName("process%d", i));
+
+ ProcessList.count = count;
+ }
+}
+
+void destroyProcessList(void)
+{
+ if (ProcessList.szFileName == NULL)
+ return;
+
+ for (int i = 0; i < ProcessList.count; i++)
+ if (ProcessList.szFileName[i])
+ mir_free(ProcessList.szFileName[i]);
+
+ mir_free(ProcessList.szFileName);
+ ProcessList.count = 0;
+ ProcessList.szFileName = NULL;
+}
+
+//========================== Windows hooks ==========================
+
+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);
+}
+
+int HookWindowsHooks()
+{
+ if (wReminderCheck)
+ hReminderTimer = SetTimer(NULL, 0, wReminderCheck * 60000, ReminderTimer);
+
+ if (bFlashUntil & UNTIL_REATTENDED) {
+ switch (bMirandaOrWindows) {
+ case ACTIVE_WINDOWS:
+ if (bEmulateKeypresses) {
+ if (hMouseHook == NULL)
+ hMouseHook = SetWindowsHookEx(WH_MOUSE, MouseHookFunction, 0, GetCurrentThreadId());
+ if (hKeyBoardHook == NULL)
+ hKeyBoardHook = SetWindowsHookEx(WH_KEYBOARD, KeyBoardHookFunction, 0, GetCurrentThreadId());
+ }
+ 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;
+}
+
+void LoadSettings(void)
+{
+ bFlashOnMsg = db_get_b(NULL, KEYBDMODULE, "onmsg", DEF_SETTING_ONMSG);
+ bFlashOnURL = db_get_b(NULL, KEYBDMODULE, "onurl", DEF_SETTING_ONURL);
+ bFlashOnFile = db_get_b(NULL, KEYBDMODULE, "onfile", DEF_SETTING_ONFILE);
+ bFlashOnOther = db_get_b(NULL, KEYBDMODULE, "onother", DEF_SETTING_OTHER);
+ bFullScreenMode = db_get_b(NULL, KEYBDMODULE, "fscreenmode", DEF_SETTING_FSCREEN);
+ bScreenSaverRunning = db_get_b(NULL, KEYBDMODULE, "ssaverrunning", DEF_SETTING_SSAVER);
+ bWorkstationLocked = db_get_b(NULL, KEYBDMODULE, "wstationlocked", DEF_SETTING_LOCKED);
+ bProcessesAreRunning = db_get_b(NULL, KEYBDMODULE, "procsrunning", DEF_SETTING_PROCS);
+ bWorkstationActive = db_get_b(NULL, KEYBDMODULE, "wstationactive", DEF_SETTING_ACTIVE);
+ bFlashIfMsgOpen = db_get_b(NULL, KEYBDMODULE, "ifmsgopen", DEF_SETTING_IFMSGOPEN);
+ bFlashIfMsgWinNotTop = db_get_b(NULL, KEYBDMODULE, "ifmsgnottop", DEF_SETTING_IFMSGNOTTOP);
+ bFlashIfMsgOlder = db_get_b(NULL, KEYBDMODULE, "ifmsgolder", DEF_SETTING_IFMSGOLDER);
+ wSecondsOlder = db_get_w(NULL, KEYBDMODULE, "secsolder", DEF_SETTING_SECSOLDER);
+ bFlashUntil = db_get_b(NULL, KEYBDMODULE, "funtil", DEF_SETTING_FLASHUNTIL);
+ wBlinksNumber = db_get_w(NULL, KEYBDMODULE, "nblinks", DEF_SETTING_NBLINKS);
+ bMirandaOrWindows = db_get_b(NULL, KEYBDMODULE, "mirorwin", DEF_SETTING_MIRORWIN);
+ wStatusMap = db_get_w(NULL, KEYBDMODULE, "status", DEF_SETTING_STATUS);
+ wReminderCheck = db_get_w(NULL, KEYBDMODULE, "remcheck", DEF_SETTING_CHECKTIME);
+ bFlashLed[0] = db_get_b(NULL, KEYBDMODULE, "fnum", DEF_SETTING_FLASHNUM);
+ bFlashLed[1] = db_get_b(NULL, KEYBDMODULE, "fcaps", DEF_SETTING_FLASHCAPS);
+ bFlashLed[2] = db_get_b(NULL, KEYBDMODULE, "fscroll", DEF_SETTING_FLASHSCROLL);
+ bFlashEffect = db_get_b(NULL, KEYBDMODULE, "feffect", DEF_SETTING_FLASHEFFECT);
+ bSequenceOrder = db_get_b(NULL, KEYBDMODULE, "order", DEF_SETTING_SEQORDER);
+ wCustomTheme = db_get_w(NULL, KEYBDMODULE, "custom", DEF_SETTING_CUSTOMTHEME);
+ bTrillianLedsMsg = db_get_b(NULL, KEYBDMODULE, "ledsmsg", DEF_SETTING_LEDSMSG);
+ bTrillianLedsURL = db_get_b(NULL, KEYBDMODULE, "ledsurl", DEF_SETTING_LEDSURL);
+ bTrillianLedsFile = db_get_b(NULL, KEYBDMODULE, "ledsfile", DEF_SETTING_LEDSFILE);
+ bTrillianLedsOther = db_get_b(NULL, KEYBDMODULE, "ledsother", DEF_SETTING_LEDSOTHER);
+ wStartDelay = db_get_w(NULL, KEYBDMODULE, "sdelay", DEF_SETTING_STARTDELAY);
+ bFlashSpeed = db_get_b(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 = db_get_b(NULL, KEYBDMODULE, "keypresses", DEF_SETTING_KEYPRESSES);
+ bOverride = db_get_b(NULL, KEYBDMODULE, "override", DEF_SETTING_OVERRIDE);
+ // Create hidden settings (for test button) if needed
+ if (db_get_b(NULL, KEYBDMODULE, "testnum", -1) == -1)
+ db_set_b(NULL, KEYBDMODULE, "testnum", DEF_SETTING_TESTNUM);
+ if (db_get_b(NULL, KEYBDMODULE, "testsecs", -1) == -1)
+ db_set_b(NULL, KEYBDMODULE, "testsecs", DEF_SETTING_TESTSECS);
+ for (int i = 0; i < ProtoList.protoCount; i++)
+ if (ProtoList.protoInfo[i].visible) {
+ unsigned int j;
+ ProtoList.protoInfo[i].enabled = db_get_b(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] = db_get_b(NULL, KEYBDMODULE, fmtDBSettingName("%sxstatus%d", ProtoList.protoInfo[i].szProto, j), DEF_SETTING_XSTATUS);
+ }
+
+ bMetaProtoEnabled = db_mc_isEnabled();
+
+ destroyProcessList();
+ createProcessList();
+ UnhookWindowsHooks();
+ HookWindowsHooks();
+}
+
+
+void GetWindowsVersion(void)
+{
+ OSVERSIONINFOEX osvi = { sizeof(OSVERSIONINFOEX) };
+ BOOL bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO *)&osvi);
+
+ if (!bOsVersionInfoEx) {
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ if (!GetVersionEx((OSVERSIONINFO *)&osvi))
+ osvi.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS;
+ }
+}
+
+
+void updateXstatusProto(PROTOCOL_INFO *protoInfo)
+{
+ if (!ProtoServiceExists(protoInfo->szProto, PS_GETCUSTOMSTATUSEX))
+ return;
+
+ // Retrieve xstatus.count
+ CUSTOM_STATUS xstatus = { sizeof(xstatus) };
+ xstatus.flags = CSSF_STATUSES_COUNT;
+ xstatus.wParam = &(protoInfo->xstatus.count);
+ CallProtoService(protoInfo->szProto, PS_GETCUSTOMSTATUSEX, 0, (LPARAM)&xstatus);
+ (protoInfo->xstatus.count)++; // Don't forget about xstatus=0 (None)
+
+ // Alloc and initiailize xstatus.enabled array
+ protoInfo->xstatus.enabled = (BOOL *)mir_alloc(protoInfo->xstatus.count * sizeof(BOOL));
+ if (!protoInfo->xstatus.enabled)
+ protoInfo->xstatus.count = 0;
+ else
+ for (unsigned i = 0; i < protoInfo->xstatus.count; i++)
+ protoInfo->xstatus.enabled[i] = FALSE;
+}
+
+
+void createProtocolList(void)
+{
+ PROTOACCOUNT **proto;
+ Proto_EnumAccounts(&ProtoList.protoCount, &proto);
+ ProtoList.protoInfo = (PROTOCOL_INFO *)mir_alloc(ProtoList.protoCount * sizeof(PROTOCOL_INFO));
+ if (!ProtoList.protoInfo) {
+ ProtoList.protoCount = 0;
+ return;
+ }
+
+ for (int i = 0; i < ProtoList.protoCount; i++) {
+ ProtoList.protoInfo[i].xstatus.count = 0;
+ ProtoList.protoInfo[i].xstatus.enabled = NULL;
+ ProtoList.protoInfo[i].szProto = mir_strdup(proto[i]->szModuleName);
+ if (!ProtoList.protoInfo[i].szProto) {
+ ProtoList.protoInfo[i].enabled = FALSE;
+ ProtoList.protoInfo[i].visible = FALSE;
+ }
+ else {
+ ProtoList.protoInfo[i].enabled = FALSE;
+ if (!mir_strcmp(proto[i]->szModuleName, META_PROTO))
+ ProtoList.protoInfo[i].visible = FALSE;
+ else {
+ ProtoList.protoInfo[i].visible = TRUE;
+ updateXstatusProto(&(ProtoList.protoInfo[i]));
+ }
+ }
+ }
+}
+
+static void destroyProtocolList(void)
+{
+ if (ProtoList.protoInfo == NULL)
+ return;
+
+ for (int i = 0; i < ProtoList.protoCount; i++) {
+ if (ProtoList.protoInfo[i].szProto)
+ mir_free(ProtoList.protoInfo[i].szProto);
+ if (ProtoList.protoInfo[i].xstatus.enabled)
+ mir_free(ProtoList.protoInfo[i].xstatus.enabled);
+ }
+
+ mir_free(ProtoList.protoInfo);
+ ProtoList.protoCount = 0;
+ ProtoList.protoInfo = NULL;
+}
+
+
+
+// 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(TCHAR *prefixName, size_t maxLen)
+{
+ size_t len;
+ TCHAR profileName[MAX_PATH + 1], *str;
+
+ getAbsoluteProfileName(profileName, MAX_PATH);
+
+ while (str = _tcschr(profileName, _T('\\')))
+ *str = _T('/');
+ if ((len = mir_tstrlen(profileName)) <= maxLen)
+ _tcsncpy_s(prefixName, maxLen, profileName, _TRUNCATE);
+ else {
+ str = profileName + len - maxLen / 2;
+ _tcsncpy_s(prefixName, (maxLen / 2), profileName, _TRUNCATE);
+ mir_tstrcat(prefixName, str);
+ }
+}
+
+
+BOOL CheckMsgWnd(MCONTACT hContact, BOOL *focus)
+{
+ if (hContact) {
+ MessageWindowData mwd = { sizeof(MessageWindowData) };
+ MessageWindowInputData mwid = { sizeof(MessageWindowInputData) };
+ mwid.hContact = hContact;
+ mwid.uFlags = MSG_WINDOW_UFLAG_MSG_BOTH;
+ mwd.hContact = hContact;
+ if (!CallService(MS_MSG_GETWINDOWDATA, (WPARAM)&mwid, (LPARAM)&mwd) && mwd.hwndWindow) {
+ *focus = mwd.uState & MSG_WINDOW_STATE_FOCUS;
+ return TRUE;
+ }
+ }
+
+ *focus = FALSE;
+ return FALSE;
+}
+
+
+void countUnopenEvents(int *msgCount, int *fileCount, int *urlCount, int *otherCount)
+{
+ int nIndex;
+ CLISTEVENT *pCLEvent;
+
+ for (nIndex = 0; pCLEvent = pcli->pfnGetEvent(-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;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Load
+
+static int OnMetaChanged(WPARAM wParam, LPARAM)
+{
+ bMetaProtoEnabled = wParam;
+ return 0;
+}
+
+static int OnPreshutdown(WPARAM, LPARAM)
+{
+ SetEvent(hExitEvent);
+ return 0;
+}
+
+static int ModulesLoaded(WPARAM, LPARAM)
+{
+ TCHAR eventPrefix[MAX_PATH + 1], eventName[MAX_PATH + 1];
+
+ createProtocolList();
+ LoadSettings();
+
+ // Create some synchronisation objects
+ createEventPrefix(eventPrefix, MAX_PATH - 11);
+ mir_sntprintf(eventName, _T("%s/FlashEvent"), eventPrefix);
+ hFlashEvent = CreateEvent(NULL, FALSE, FALSE, eventName);
+ mir_sntprintf(eventName, _T("%s/ExitEvent"), eventPrefix);
+ hExitEvent = CreateEvent(NULL, FALSE, FALSE, eventName);
+
+ hThread = mir_forkthread(FlashThreadFunction, 0);
+
+ HookEvent(ME_MC_ENABLED, OnMetaChanged);
+ HookEvent(ME_DB_EVENT_ADDED, PluginMessageEventHook);
+ HookEvent(ME_OPT_INITIALISE, InitializeOptions);
+
+ CreateServiceFunction(MS_KBDNOTIFY_ENABLE, EnableService);
+ CreateServiceFunction(MS_KBDNOTIFY_DISABLE, DisableService);
+ CreateServiceFunction(MS_KBDNOTIFY_STARTBLINK, StartBlinkService);
+ CreateServiceFunction(MS_KBDNOTIFY_EVENTSOPENED, EventsWereOpenedService);
+ CreateServiceFunction(MS_KBDNOTIFY_FLASHINGACTIVE, IsFlashingActiveService);
+ CreateServiceFunction(MS_KBDNOTIFY_NORMALSEQUENCE, NormalizeSequenceService);
+ return 0;
+}
+
+extern "C" __declspec(dllexport) int Load(void)
+{
+ mir_getLP(&pluginInfo);
mir_getCLI();
-
- GetWindowsVersion();
- OpenKeyboardDevice();
-
- HookEvent(ME_SYSTEM_MODULESLOADED, ModulesLoaded);
- HookEvent(ME_SYSTEM_PRESHUTDOWN, OnPreshutdown);
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Unload
-
-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;
-}
-
-void destroyProcessList(void)
-{
- if (ProcessList.szFileName == NULL)
- return;
-
- for (int i = 0; i < ProcessList.count; i++)
- if (ProcessList.szFileName[i])
- mir_free(ProcessList.szFileName[i]);
-
- free(ProcessList.szFileName);
- ProcessList.count = 0;
- ProcessList.szFileName = NULL;
-}
-
-static void destroyProtocolList(void)
-{
- if (ProtoList.protoInfo == NULL)
- return;
-
- for (int 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);
- }
-
- free(ProtoList.protoInfo);
- ProtoList.protoCount = 0;
- ProtoList.protoInfo = NULL;
-}
-
-extern "C" __declspec(dllexport) int Unload(void)
-{
- UnhookWindowsHooks();
-
- // Wait for thread to exit
- WaitForSingleObject(hThread, INFINITE);
-
- RestoreLEDState();
- CloseKeyboardDevice();
-
- destroyProcessList();
- destroyProtocolList();
- return 0;
-}
+
+ GetWindowsVersion();
+ OpenKeyboardDevice();
+
+ HookEvent(ME_SYSTEM_MODULESLOADED, ModulesLoaded);
+ HookEvent(ME_SYSTEM_PRESHUTDOWN, OnPreshutdown);
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Unload
+
+extern "C" __declspec(dllexport) int Unload(void)
+{
+ UnhookWindowsHooks();
+
+ // Wait for thread to exit
+ WaitForSingleObject(hThread, INFINITE);
+
+ RestoreLEDState();
+ CloseKeyboardDevice();
+
+ destroyProcessList();
+ destroyProtocolList();
+ return 0;
+}
diff --git a/plugins/KeyboardNotify/src/options.cpp b/plugins/KeyboardNotify/src/options.cpp
index 977348ccf5..5b20e8f4b7 100644
--- a/plugins/KeyboardNotify/src/options.cpp
+++ b/plugins/KeyboardNotify/src/options.cpp
@@ -46,9 +46,7 @@ static void writeThemeToCombo(const TCHAR *theme, const TCHAR *custom, BOOL over
int item = SendDlgItemMessage(hwndTheme, IDC_THEME, CB_FINDSTRINGEXACT, -1, (LPARAM)theme);
if (item == CB_ERR) {
item = SendDlgItemMessage(hwndTheme, IDC_THEME, CB_ADDSTRING, 0, (LPARAM)theme);
- TCHAR *str = (TCHAR *)malloc((MAX_PATH + 1)*sizeof(TCHAR));
- if (str)
- mir_tstrcpy(str, custom);
+ TCHAR *str = mir_tstrdup(custom);
SendDlgItemMessage(hwndTheme, IDC_THEME, CB_SETITEMDATA, (WPARAM)item, (LPARAM)str);
}
else
@@ -121,7 +119,7 @@ void importThemes(const TCHAR *filename, BOOL overrideExisting)
static void createProcessListAux(void)
{
ProcessListAux.count = ProcessList.count;
- ProcessListAux.szFileName = (TCHAR **)malloc(ProcessListAux.count * sizeof(TCHAR *));
+ ProcessListAux.szFileName = (TCHAR **)mir_alloc(ProcessListAux.count * sizeof(TCHAR *));
if (!ProcessListAux.szFileName)
ProcessListAux.count = 0;
else
@@ -129,9 +127,7 @@ static void createProcessListAux(void)
if (!ProcessList.szFileName[i])
ProcessListAux.szFileName[i] = NULL;
else {
- ProcessListAux.szFileName[i] = (TCHAR *)malloc((mir_tstrlen(ProcessList.szFileName[i]) + 1)*sizeof(TCHAR));
- if (ProcessListAux.szFileName[i])
- mir_tstrcpy(ProcessListAux.szFileName[i], ProcessList.szFileName[i]);
+ ProcessListAux.szFileName[i] = mir_tstrdup(ProcessList.szFileName[i]);
}
}
@@ -142,24 +138,24 @@ static void destroyProcessListAux(void)
return;
for (int i = 0; i < ProcessListAux.count; i++) {
if (ProcessListAux.szFileName[i]) {
- free(ProcessListAux.szFileName[i]);
+ mir_free(ProcessListAux.szFileName[i]);
}
}
- free(ProcessListAux.szFileName);
+ mir_free(ProcessListAux.szFileName);
ProcessListAux.count = 0;
ProcessListAux.szFileName = NULL;
}
static void createXstatusListAux(void)
{
- XstatusListAux = (XSTATUS_INFO *)malloc(ProtoList.protoCount * sizeof(XSTATUS_INFO));
+ XstatusListAux = (XSTATUS_INFO *)mir_alloc(ProtoList.protoCount * sizeof(XSTATUS_INFO));
if (XstatusListAux)
for (int i = 0; i < ProtoList.protoCount; i++) {
XstatusListAux[i].count = ProtoList.protoInfo[i].xstatus.count;
if (!XstatusListAux[i].count)
XstatusListAux[i].enabled = NULL;
else {
- XstatusListAux[i].enabled = (BOOL *)malloc(XstatusListAux[i].count * sizeof(BOOL));
+ XstatusListAux[i].enabled = (BOOL *)mir_alloc(XstatusListAux[i].count * sizeof(BOOL));
if (!XstatusListAux[i].enabled)
XstatusListAux[i].count = 0;
else
@@ -175,8 +171,8 @@ static void destroyXstatusListAux(void)
if (XstatusListAux) {
for (int i = 0; i < ProtoList.protoCount; i++)
if (XstatusListAux[i].enabled)
- free(XstatusListAux[i].enabled);
- free(XstatusListAux);
+ mir_free(XstatusListAux[i].enabled);
+ mir_free(XstatusListAux);
XstatusListAux = NULL;
}
@@ -210,8 +206,6 @@ static INT_PTR CALLBACK DlgProcProcesses(HWND hwndDlg, UINT msg, WPARAM wParam,
switch (LOWORD(wParam)) {
case IDC_PROGRAMS:
switch (HIWORD(wParam)) {
- int item;
- TCHAR szFileName[MAX_PATH + 1];
case CBN_SELENDOK:
case CBN_SELCHANGE:
@@ -219,8 +213,10 @@ static INT_PTR CALLBACK DlgProcProcesses(HWND hwndDlg, UINT msg, WPARAM wParam,
EnableWindow(GetDlgItem(hwndDlg, IDC_DELETEPGM), TRUE);
break;
case CBN_EDITCHANGE:
+ TCHAR szFileName[MAX_PATH + 1];
GetDlgItemText(hwndDlg, IDC_PROGRAMS, szFileName, _countof(szFileName));
- if ((item = SendMessage((HWND)lParam, CB_FINDSTRINGEXACT, -1, (LPARAM)szFileName)) == CB_ERR) { //new program
+ int item = SendMessage((HWND)lParam, CB_FINDSTRINGEXACT, -1, (LPARAM)szFileName);
+ if (item == CB_ERR) { //new program
EnableWindow(GetDlgItem(hwndDlg, IDC_ADDPGM), TRUE);
EnableWindow(GetDlgItem(hwndDlg, IDC_DELETEPGM), FALSE);
}
@@ -260,7 +256,7 @@ static INT_PTR CALLBACK DlgProcProcesses(HWND hwndDlg, UINT msg, WPARAM wParam,
destroyProcessListAux();
ProcessListAux.count = SendDlgItemMessage(hwndDlg, IDC_PROGRAMS, CB_GETCOUNT, 0, 0);
- ProcessListAux.szFileName = (TCHAR **)malloc(ProcessListAux.count * sizeof(TCHAR *));
+ ProcessListAux.szFileName = (TCHAR **)mir_alloc(ProcessListAux.count * sizeof(TCHAR *));
if (!ProcessListAux.szFileName)
ProcessListAux.count = 0;
else
@@ -268,9 +264,7 @@ static INT_PTR CALLBACK DlgProcProcesses(HWND hwndDlg, UINT msg, WPARAM wParam,
TCHAR szFileNameAux[MAX_PATH + 1];
SendDlgItemMessage(hwndDlg, IDC_PROGRAMS, CB_GETLBTEXT, (WPARAM)i, (LPARAM)szFileNameAux);
- ProcessListAux.szFileName[i] = (TCHAR *)malloc((mir_tstrlen(szFileNameAux) + 1)*sizeof(TCHAR));
- if (ProcessListAux.szFileName[i])
- mir_tstrcpy(ProcessListAux.szFileName[i], szFileNameAux);
+ ProcessListAux.szFileName[i] = mir_tstrdup(szFileNameAux);
}
// fallthrough
@@ -412,7 +406,7 @@ static INT_PTR CALLBACK DlgProcXstatusList(HWND hwndDlg, UINT msg, WPARAM wParam
tvi.hItem = hItem;
TreeView_GetItem(hwndTree, &tvi);
j = (unsigned int)tvi.lParam;
- XstatusListAux[i].enabled[j] = !!(TreeView_GetItemState(hwndTree, hItem, TVIS_STATEIMAGEMASK)&INDEXTOSTATEIMAGEMASK(2));
+ XstatusListAux[i].enabled[j] = (TreeView_GetItemState(hwndTree, hItem, TVIS_STATEIMAGEMASK)&INDEXTOSTATEIMAGEMASK(2));
}
}
} // fallthrough
@@ -486,7 +480,7 @@ static INT_PTR CALLBACK DlgProcEventLeds(HWND hwndDlg, UINT msg, WPARAM wParam,
trillianLedsOther |= 4;
if (IsDlgButtonChecked(hwndDlg, IDC_OTHERLEDSCROLL) == BST_CHECKED)
trillianLedsOther |= 1;
-
+ // fall through
case IDC_CANCEL:
EndDialog(hwndDlg, LOWORD(wParam));
break;
@@ -550,17 +544,16 @@ static INT_PTR CALLBACK DlgProcProtoOptions(HWND hwndDlg, UINT msg, WPARAM, LPAR
case PSN_APPLY:
// enabled protos
{
- int i;
LVITEM lvItem;
HWND hList = GetDlgItem(hwndDlg, IDC_PROTOCOLLIST);
memset(&lvItem, 0, sizeof(lvItem));
lvItem.mask = LVIF_PARAM;
lvItem.iSubItem = 0;
- for (i = 0; i < ListView_GetItemCount(hList); i++) {
+ for (int i = 0; i < ListView_GetItemCount(hList); i++) {
lvItem.iItem = i;
ListView_GetItem(hList, &lvItem);
- db_set_b(NULL, KEYBDMODULE, (char *)lvItem.lParam, (BYTE)!!ListView_GetCheckState(hList, lvItem.iItem));
+ db_set_b(NULL, KEYBDMODULE, (char *)lvItem.lParam, (BYTE)ListView_GetCheckState(hList, lvItem.iItem));
}
}
@@ -1012,14 +1005,8 @@ static INT_PTR CALLBACK DlgProcThemeOptions(HWND hwndDlg, UINT msg, WPARAM wPara
int index = SendDlgItemMessage(hwndDlg, IDC_THEME, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)szTheme);
mir_free(szTheme);
if (index != CB_ERR && index != CB_ERRSPACE) {
- TCHAR *str = (TCHAR *)malloc((MAX_PATH + 1)*sizeof(TCHAR));
+ TCHAR *str = db_get_tsa(NULL, KEYBDMODULE, fmtDBSettingName("custom%d", i));
if (str)
- if (szTheme = db_get_tsa(NULL, KEYBDMODULE, fmtDBSettingName("custom%d", i))) {
- mir_tstrcpy(str, szTheme);
- mir_free(szTheme);
- }
- else
- str[0] = _T('\0');
SendDlgItemMessage(hwndDlg, IDC_THEME, CB_SETITEMDATA, (WPARAM)index, (LPARAM)str);
}
}
@@ -1044,9 +1031,6 @@ static INT_PTR CALLBACK DlgProcThemeOptions(HWND hwndDlg, UINT msg, WPARAM wPara
switch (LOWORD(wParam)) {
case IDC_THEME:
switch (HIWORD(wParam)) {
- int item;
- TCHAR theme[MAX_PATH + 1];
-
case CBN_SELENDOK:
case CBN_SELCHANGE: {
TCHAR *str = (TCHAR *)SendMessage((HWND)lParam, CB_GETITEMDATA, (WPARAM)SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0), 0);
@@ -1060,8 +1044,11 @@ static INT_PTR CALLBACK DlgProcThemeOptions(HWND hwndDlg, UINT msg, WPARAM wPara
}
break;
case CBN_EDITCHANGE:
+ TCHAR theme[MAX_PATH + 1];
GetDlgItemText(hwndDlg, IDC_THEME, theme, _countof(theme));
- if ((item = SendMessage((HWND)lParam, CB_FINDSTRINGEXACT, -1, (LPARAM)theme)) == CB_ERR) { //new theme
+ int item = SendMessage((HWND)lParam, CB_FINDSTRINGEXACT, -1, (LPARAM)theme);
+ if (item == CB_ERR) {
+ //new theme
SetDlgItemText(hwndDlg, IDC_CUSTOMSTRING, _T(""));
EnableWindow(GetDlgItem(hwndDlg, IDC_ADD), TRUE);
EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), FALSE);
@@ -1114,7 +1101,7 @@ static INT_PTR CALLBACK DlgProcThemeOptions(HWND hwndDlg, UINT msg, WPARAM wPara
if (!theme[0])
return TRUE;
int item = SendDlgItemMessage(hwndDlg, IDC_THEME, CB_ADDSTRING, 0, (LPARAM)theme);
- TCHAR *str = (TCHAR *)malloc((MAX_PATH + 1)*sizeof(TCHAR));
+ TCHAR *str = (TCHAR *)mir_alloc((MAX_PATH + 1)*sizeof(TCHAR));
if (str) {
GetDlgItemText(hwndDlg, IDC_CUSTOMSTRING, str, MAX_PATH);
SetDlgItemText(hwndDlg, IDC_CUSTOMSTRING, normalizeCustomString(str));
@@ -1149,7 +1136,7 @@ static INT_PTR CALLBACK DlgProcThemeOptions(HWND hwndDlg, UINT msg, WPARAM wPara
int item = SendDlgItemMessage(hwndDlg, IDC_THEME, CB_FINDSTRINGEXACT, -1, (LPARAM)theme);
TCHAR *str = (TCHAR *)SendDlgItemMessage(hwndDlg, IDC_THEME, CB_GETITEMDATA, (WPARAM)item, 0);
if (str)
- free(str);
+ mir_free(str);
SendDlgItemMessage(hwndDlg, IDC_THEME, CB_DELETESTRING, (WPARAM)item, 0);
if (SendDlgItemMessage(hwndDlg, IDC_THEME, CB_GETCOUNT, 0, 0) == 0) {
SetDlgItemText(hwndDlg, IDC_THEME, _T(""));
@@ -1289,7 +1276,7 @@ static INT_PTR CALLBACK DlgProcThemeOptions(HWND hwndDlg, UINT msg, WPARAM wPara
for (int item = 0; item < count; item++) {
TCHAR *str = (TCHAR *)SendDlgItemMessage(hwndDlg, IDC_THEME, CB_GETITEMDATA, (WPARAM)item, 0);
if (str)
- free(str);
+ mir_free(str);
}
break;
}