diff options
26 files changed, 6472 insertions, 0 deletions
diff --git a/plugins/KeyboardNotify/AggressiveOptimize.h b/plugins/KeyboardNotify/AggressiveOptimize.h new file mode 100644 index 0000000000..34c6074320 --- /dev/null +++ b/plugins/KeyboardNotify/AggressiveOptimize.h @@ -0,0 +1,165 @@ +//////////////////////////////
+// Version 1.40
+// October 22nd, 2002 - .NET (VC7, _MSC_VER=1300) support!
+// Version 1.30
+// Nov 24th, 2000
+// Version 1.20
+// Jun 9th, 2000
+// Version 1.10
+// Jan 23rd, 2000
+// Version 1.00
+// May 20th, 1999
+// Todd C. Wilson, Fresh Ground Software
+// (todd@nopcode.com)
+// This header file will kick in settings for Visual C++ 5 and 6 that will (usually)
+// result in smaller exe's.
+// The "trick" is to tell the compiler to not pad out the function calls; this is done
+// by not using the /O1 or /O2 option - if you do, you implicitly use /Gy, which pads
+// out each and every function call. In one single 500k dll, I managed to cut out 120k
+// by this alone!
+// The other two "tricks" are telling the Linker to merge all data-type segments together
+// in the exe file. The relocation, read-only (constants) data, and code section (.text)
+// sections can almost always be merged. Each section merged can save 4k in exe space,
+// since each section is padded out to 4k chunks. This is very noticeable with smaller
+// exes, since you could have only 700 bytes of data, 300 bytes of code, 94 bytes of
+// strings - padded out, this could be 12k of runtime, for 1094 bytes of stuff! For larger
+// programs, this is less overall, but can save at least 4k.
+// Note that if you're using MFC static or some other 3rd party libs, you may get poor
+// results with merging the readonly (.rdata) section - the exe may grow larger.
+// To use this feature, define _MERGE_RDATA_ in your project or before this header is used.
+// With Visual C++ 5, the program uses a file alignment of 512 bytes, which results
+// in a small exe. Under VC6, the program instead uses 4k, which is the same as the
+// section size. The reason (from what I understand) is that 4k is the chunk size of
+// the virtual memory manager, and that WinAlign (an end-user tuning tool for Win98)
+// will re-align the programs on this boundary. The problem with this is that all of
+// Microsoft's system exes and dlls are *NOT* tuned like this, and using 4k causes serious
+// exe bloat. This is very noticeable for smaller programs.
+// The "trick" for this is to use the undocumented FILEALIGN linker parm to change the
+// padding from 4k to 1/2k, which results in a much smaller exe - anywhere from 20%-75%
+// depending on the size. Note that this is the same as using /OPT:NOWIN98, which *is*
+// a previously documented switch, but was left out of the docs for some reason in VC6 and
+// all of the current MSDN's - see KB:Q235956 for more information.
+// Microsoft does say that using the 4k alignment will "speed up process loading",
+// but I've been unable to notice a difference, even on my P180, with a very large (4meg) exe.
+// Please note, however, that this will probably not change the size of the COMPRESSED
+// file (either in a .zip file or in an install archive), since this 4k is all zeroes and
+// gets compressed away.
+// Also, the /ALIGN:4096 switch will "magically" do the same thing, even though this is the
+// default setting for this switch. Apparently this sets the same values as the above two
+// switches do. We do not use this in this header, since it smacks of a bug and not a feature.
+// Thanks to Michael Geary <Mike@Geary.com> for some additional tips!
+//
+// Notes about using this header in .NET
+// First off, VC7 does not allow a lot of the linker command options in pragma's. There is no
+// honest or good reason why Microsoft decided to make this change, it just doesn't.
+// So that is why there are a lot of <1300 #if's in the header.
+// If you want to take full advantage of the VC7 linker options, you will need to do it on a
+// PER PROJECT BASIS; you can no longer use a global header file like this to make it better.
+// Items I strongly suggest putting in all your VC7 project linker options command line settings:
+// /ignore:4078 /RELEASE
+// Compiler options:
+// /GL (Whole Program Optimization)
+// If you're making an .EXE and not a .DLL, consider adding in:
+// /GA (Optimize for Windows Application)
+// Some items to consider using in your VC7 projects (not VC6):
+// Link-time Code Generation - whole code optimization. Put this in your exe/dll project link settings.
+// /LTCG:NOSTATUS
+// The classic no-padding and no-bloat compiler C/C++ switch:
+// /opt:nowin98
+//
+// (C++ command line options: /GL /opt:nowin98 and /GA for .exe files)
+// (Link command line options: /ignore:4078 /RELEASE /LTCG:NOSTATUS)
+//
+// Now, notes on using these options in VC7 vs VC6.
+// VC6 consistently, for me, produces smaller code from C++ the exact same sources,
+// with or without this header. On average, VC6 produces 5% smaller binaries compared
+// to VC7 compiling the exact same project, *without* this header. With this header, VC6
+// will make a 13k file, while VC7 will make a 64k one. VC7 is just bloaty, pure and
+// simple - all that managed/unmanaged C++ runtimes, and the CLR stuff must be getting
+// in the way of code generation. However, template support is better, so there.
+// Both VC6 and VC7 show the same end kind of end result savings - larger binary output
+// will shave about 2% off, where as smaller projects (support DLL's, cpl's,
+// activex controls, ATL libs, etc) get the best result, since the padding is usually
+// more than the actual usable code. But again, VC7 does not compile down as small as VC6.
+//
+// The argument can be made that doing this is a waste of time, since the "zero bytes"
+// will be compressed out in a zip file or install archive. Not really - it doesn't matter
+// if the data is a string of zeroes or ones or 85858585 - it will still take room (20 bytes
+// in a zip file, 29 bytes if only *4* of them 4k bytes are not the same) and time to
+// compress that data and decompress it. Also, 20k of zeros is NOT 20k on disk - it's the
+// size of the cluster slop- for Fat32 systems, 20k can be 32k, NTFS could make it 24k if you're
+// just 1 byte over (round up). Most end users do not have the dual P4 Xeon systems with
+// two gigs of RDram and a Raid 0+1 of Western Digital 120meg Special Editions that all
+// worthy developers have (all six of us), so they will need any space and LOADING TIME
+// savings they will need; taking an extra 32k or more out of your end user's 64megs of
+// ram on Windows 98 is Not a Good Thing.
+//
+// Now, as a ADDED BONUS at NO EXTRA COST TO YOU! Under VC6, using the /merge:.text=.data
+// pragma will cause the output file to be un-disassembleable! (is that a word?) At least,
+// with the normal tools - WinDisam, DumpBin, and the like will not work. Try it - use the
+// header, compile release, and then use DUMPBIN /DISASM filename.exe - no code!
+// Thanks to Gëzim Pani <gpani@siu.edu> for discovering this gem - for a full writeup on
+// this issue and the ramifactions of it, visit www.nopcode.com for the Aggressive Optimize
+// article.
+
+#ifndef _AGGRESSIVEOPTIMIZE_H_
+#define _AGGRESSIVEOPTIMIZE_H_
+
+#pragma warning(disable:4711)
+
+#ifdef NDEBUG
+// /Og (global optimizations), /Os (favor small code), /Oy (no frame pointers)
+#pragma optimize("gsy",on)
+
+#if (_MSC_VER<1300)
+ #pragma comment(linker,"/RELEASE")
+#endif
+
+// Note that merging the .rdata section will result in LARGER exe's if you using
+// MFC (esp. static link). If this is desirable, define _MERGE_RDATA_ in your project.
+//#ifdef _MERGE_RDATA_
+//#pragma comment(linker,"/merge:.rdata=.data")
+//#endif // _MERGE_RDATA_
+
+//#pragma comment(linker,"/merge:.text=.data")
+//#if (_MSC_VER<1300)
+ // In VC7, this causes problems with the relocation and data tables, so best to not merge them
+// #pragma comment(linker,"/merge:.reloc=.data")
+//#endif
+
+// Merging sections with different attributes causes a linker warning, so
+// turn off the warning. From Michael Geary. Undocumented, as usual!
+#if (_MSC_VER<1300)
+ // In VC7, you will need to put this in your project settings
+ #pragma comment(linker,"/ignore:4078")
+#endif
+
+// With Visual C++ 5, you already get the 512-byte alignment, so you will only need
+// it for VC6, and maybe later.
+#if _MSC_VER >= 1000
+
+// Option #1: use /filealign
+// Totally undocumented! And if you set it lower than 512 bytes, the program crashes.
+// Either leave at 0x200 or 0x1000
+//#pragma comment(linker,"/FILEALIGN:0x200")
+
+// Option #2: use /opt:nowin98
+// See KB:Q235956 or the READMEVC.htm in your VC directory for info on this one.
+// This is our currently preferred option, since it is fully documented and unlikely
+// to break in service packs and updates.
+#if (_MSC_VER<1300)
+ // In VC7, you will need to put this in your project settings
+ #pragma comment(linker,"/opt:nowin98")
+#else
+
+// Option #3: use /align:4096
+// A side effect of using the default align value is that it turns on the above switch.
+// Does nothing under Vc7 that /opt:nowin98 doesn't already give you
+// #pragma comment(linker,"/ALIGN:512")
+#endif
+
+#endif // _MSC_VER >= 1000
+
+#endif // NDEBUG
+
+#endif // _AGGRESSIVEOPTIMIZE_H_
diff --git a/plugins/KeyboardNotify/EnumProc.c b/plugins/KeyboardNotify/EnumProc.c new file mode 100644 index 0000000000..df085629eb --- /dev/null +++ b/plugins/KeyboardNotify/EnumProc.c @@ -0,0 +1,255 @@ +/*
+
+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.
+
+*/
+
+#define WIN32_LEAN_AND_MEAN
+
+#include <windows.h>
+#include <stdio.h>
+#include <tlhelp32.h>
+#include <vdmdbg.h>
+#include "EnumProc.h"
+
+
+BOOL findFilename(char *);
+char *filename(char *);
+BOOL WINAPI Enum16(DWORD, WORD, WORD, char *, char *, LPARAM);
+
+
+// Globals
+extern double dWinVer;
+extern BOOL bWindowsNT;
+extern PROCESS_LIST ProcessList;
+
+HINSTANCE hInstLib, hInstLib2;
+HANDLE (WINAPI *lpfCreateToolhelp32Snapshot)(DWORD, DWORD);
+BOOL (WINAPI *lpfProcess32First)(HANDLE, LPPROCESSENTRY32);
+BOOL (WINAPI *lpfProcess32Next)(HANDLE, LPPROCESSENTRY32);
+BOOL (WINAPI *lpfEnumProcesses)(DWORD *, DWORD, DWORD *);
+BOOL (WINAPI *lpfEnumProcessModules)(HANDLE, HMODULE *, DWORD, LPDWORD);
+DWORD (WINAPI *lpfGetModuleBaseName)(HANDLE, HMODULE, LPTSTR, DWORD);
+INT (WINAPI *lpfVDMEnumTaskWOWEx)(DWORD, TASKENUMPROCEX, LPARAM);
+
+
+void LoadProcsLibrary(void)
+{
+ if (bWindowsNT && dWinVer < 5) {
+
+ if (!(hInstLib = LoadLibraryA("PSAPI.DLL")))
+ return;
+
+ if (!(hInstLib2 = LoadLibraryA("VDMDBG.DLL")))
+ return;
+
+ lpfEnumProcesses = (BOOL (WINAPI *)(DWORD *, DWORD, DWORD*)) GetProcAddress(hInstLib, "EnumProcesses");
+ lpfEnumProcessModules = (BOOL (WINAPI *)(HANDLE, HMODULE *, DWORD, LPDWORD)) GetProcAddress(hInstLib, "EnumProcessModules");
+ lpfGetModuleBaseName = (DWORD (WINAPI *)(HANDLE, HMODULE, LPTSTR, DWORD)) GetProcAddress(hInstLib, "GetModuleBaseNameA");
+
+ lpfVDMEnumTaskWOWEx = (INT (WINAPI *)(DWORD, TASKENUMPROCEX, LPARAM)) GetProcAddress(hInstLib2, "VDMEnumTaskWOWEx");
+ } else {
+
+ if(!(hInstLib = LoadLibraryA("Kernel32.DLL")))
+ return;
+
+ if (bWindowsNT && !(hInstLib2 = LoadLibraryA("VDMDBG.DLL")))
+ return;
+
+ lpfCreateToolhelp32Snapshot = (HANDLE (WINAPI *)(DWORD,DWORD)) GetProcAddress(hInstLib, "CreateToolhelp32Snapshot");
+ lpfProcess32First = (BOOL (WINAPI *)(HANDLE,LPPROCESSENTRY32)) GetProcAddress(hInstLib, "Process32First");
+ lpfProcess32Next = (BOOL (WINAPI *)(HANDLE,LPPROCESSENTRY32)) GetProcAddress(hInstLib, "Process32Next");
+
+ if (bWindowsNT)
+ lpfVDMEnumTaskWOWEx = (INT (WINAPI *)(DWORD, TASKENUMPROCEX, LPARAM)) GetProcAddress(hInstLib2, "VDMEnumTaskWOWEx");
+ }
+}
+
+
+void UnloadProcsLibrary(void)
+{
+ if (hInstLib)
+ FreeLibrary(hInstLib);
+ if (hInstLib2)
+ FreeLibrary(hInstLib2);
+
+ hInstLib = hInstLib = NULL;
+ lpfCreateToolhelp32Snapshot = NULL;
+ lpfProcess32First = (void *)lpfProcess32Next = (void *)lpfEnumProcesses = (void *)lpfEnumProcessModules = (void *)lpfGetModuleBaseName = (void *)lpfVDMEnumTaskWOWEx = NULL;
+}
+
+
+BOOL areThereProcessesRunning(void)
+{
+ HANDLE hSnapShot = NULL;
+ LPDWORD lpdwPIDs = NULL;
+ PROCESSENTRY32 procentry;
+ BOOL bFlag;
+ DWORD dwSize;
+ DWORD dwSize2;
+ DWORD dwIndex;
+ HMODULE hMod;
+ HANDLE hProcess;
+ char szFileName[MAX_PATH+1];
+
+
+ if (!ProcessList.count) // Process list is empty
+ return FALSE;
+
+ // If Windows NT 4.0
+ if (bWindowsNT && dWinVer < 5) {
+
+ if (!lpfEnumProcesses || !lpfEnumProcessModules || !lpfGetModuleBaseName || !lpfVDMEnumTaskWOWEx)
+ return FALSE;
+
+ //
+ // Call the PSAPI function EnumProcesses to get all of the ProcID's currently in the system.
+ //
+ // NOTE: In the documentation, the third parameter of EnumProcesses is named cbNeeded, which implies that you
+ // can call the function once to find out how much space to allocate for a buffer and again to fill the buffer.
+ // This is not the case. The cbNeeded parameter returns the number of PIDs returned, so if your buffer size is
+ // zero cbNeeded returns zero.
+ //
+ // NOTE: The "HeapAlloc" loop here ensures that we actually allocate a buffer large enough for all the
+ // PIDs in the system.
+ //
+ dwSize2 = 256 * sizeof(DWORD);
+ do {
+ if (lpdwPIDs) {
+ HeapFree(GetProcessHeap(), 0, lpdwPIDs);
+ dwSize2 *= 2;
+ }
+ if (!(lpdwPIDs = (LPDWORD)HeapAlloc(GetProcessHeap(), 0, dwSize2)))
+ return FALSE;
+ if (!lpfEnumProcesses(lpdwPIDs, dwSize2, &dwSize)) {
+ HeapFree(GetProcessHeap(), 0, lpdwPIDs);
+ return FALSE;
+ }
+ } while (dwSize == dwSize2);
+
+ // How many ProcID's did we get?
+ dwSize /= sizeof(DWORD);
+
+ // Loop through each ProcID.
+ for (dwIndex = 0; dwIndex < dwSize; dwIndex++) {
+ char *szFileNameAux;
+ szFileName[0] = '\0';
+
+ // Open the process (if we can... security does not permit every process in the system to be opened).
+ hProcess = OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, FALSE, lpdwPIDs[dwIndex]);
+ if (hProcess) {
+ // Here we call EnumProcessModules to get only the first module in the process. This will be the
+ // EXE module for which we will retrieve the name.
+ if (lpfEnumProcessModules(hProcess, &hMod, sizeof(hMod), &dwSize2)) {
+ // Get the module name
+ if (!lpfGetModuleBaseName(hProcess, hMod, szFileName, sizeof(szFileName)))
+ szFileName[0] = '\0';
+ }
+ CloseHandle(hProcess);
+ }
+ szFileNameAux = filename(szFileName);
+
+ // Search szFileName in user-defined list
+ if (findFilename(szFileNameAux)) {
+ HeapFree(GetProcessHeap(), 0, lpdwPIDs);
+ return TRUE;
+ }
+
+ // Did we just bump into an NTVDM?
+ if (!_stricmp(szFileNameAux, "NTVDM.EXE")) {
+ BOOL bFound = FALSE;
+
+ // Enum the 16-bit stuff.
+ lpfVDMEnumTaskWOWEx(lpdwPIDs[dwIndex], (TASKENUMPROCEX) Enum16, (LPARAM)&bFound);
+
+ // Did we find any user-defined process?
+ if (bFound) {
+ HeapFree(GetProcessHeap(), 0, lpdwPIDs);
+ return TRUE;
+ }
+ }
+ }
+ HeapFree(GetProcessHeap(), 0, lpdwPIDs);
+
+ // If any OS other than Windows NT 4.0.
+ } else {
+
+ if (!lpfProcess32Next || !lpfProcess32First || !lpfCreateToolhelp32Snapshot)
+ return FALSE;
+
+ // Get a handle to a Toolhelp snapshot of all processes.
+ if ((hSnapShot = lpfCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)) == INVALID_HANDLE_VALUE)
+ return FALSE;
+
+ // While there are processes, keep looping.
+ for (procentry.dwSize=sizeof(PROCESSENTRY32), bFlag=lpfProcess32First(hSnapShot, &procentry); bFlag; procentry.dwSize=sizeof(PROCESSENTRY32), bFlag=lpfProcess32Next(hSnapShot, &procentry)) {
+ char *szFileNameAux = filename(procentry.szExeFile);
+
+ // Search szFileName in user-defined list
+ if (findFilename(szFileNameAux))
+ return TRUE;
+
+ // Did we just bump into an NTVDM?
+ if (lpfVDMEnumTaskWOWEx && !_stricmp(szFileNameAux, "NTVDM.EXE")) {
+ BOOL bFound = FALSE;
+
+ // Enum the 16-bit stuff.
+ lpfVDMEnumTaskWOWEx(procentry.th32ProcessID, (TASKENUMPROCEX)Enum16, (LPARAM)&bFound);
+
+ // Did we find any user-defined process?
+ if (bFound)
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+
+BOOL WINAPI Enum16(DWORD dwThreadId, WORD hMod16, WORD hTask16, char *szModName, char *szFileName, LPARAM lpUserDefined)
+{
+ BOOL bRet;
+ BOOL *pbFound = (BOOL *)lpUserDefined;
+
+ if ((bRet = findFilename(filename(szFileName))))
+ *pbFound = TRUE;
+
+ return bRet;
+}
+
+
+BOOL findFilename(char *fileName)
+{
+ unsigned int i;
+
+ for (i=0; i < ProcessList.count; i++)
+ if (ProcessList.szFileName[i] && !_stricmp(ProcessList.szFileName[i], fileName))
+ return TRUE;
+
+ return FALSE;
+}
+
+
+char *filename(char *fullFileName)
+{
+ char *str;
+
+ str = strrchr(fullFileName, '\\');
+ if (!str)
+ return fullFileName;
+
+ return ++str;
+}
\ No newline at end of file diff --git a/plugins/KeyboardNotify/EnumProc.h b/plugins/KeyboardNotify/EnumProc.h new file mode 100644 index 0000000000..f7e6a4283b --- /dev/null +++ b/plugins/KeyboardNotify/EnumProc.h @@ -0,0 +1,27 @@ +/*
+
+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.
+
+*/
+
+typedef struct {
+ unsigned int count;
+ char **szFileName;
+} PROCESS_LIST;
+
+
+void LoadProcsLibrary(void);
+void UnloadProcsLibrary(void);
+BOOL areThereProcessesRunning(void);
diff --git a/plugins/KeyboardNotify/KeyboardNotify_10.sln b/plugins/KeyboardNotify/KeyboardNotify_10.sln new file mode 100644 index 0000000000..b816c2f081 --- /dev/null +++ b/plugins/KeyboardNotify/KeyboardNotify_10.sln @@ -0,0 +1,29 @@ +
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KeyboardNotify", "KeyboardNotify_10.vcxproj", "{21F6C0E4-DD1A-49E6-82FD-64574BB902BD}"
+EndProject
+Global
+ GlobalSection(DPCodeReviewSolutionGUID) = preSolution
+ DPCodeReviewSolutionGUID = {00000000-0000-0000-0000-000000000000}
+ EndGlobalSection
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {21F6C0E4-DD1A-49E6-82FD-64574BB902BD}.Debug|Win32.ActiveCfg = Debug|Win32
+ {21F6C0E4-DD1A-49E6-82FD-64574BB902BD}.Debug|Win32.Build.0 = Debug|Win32
+ {21F6C0E4-DD1A-49E6-82FD-64574BB902BD}.Debug|x64.ActiveCfg = Debug|x64
+ {21F6C0E4-DD1A-49E6-82FD-64574BB902BD}.Debug|x64.Build.0 = Debug|x64
+ {21F6C0E4-DD1A-49E6-82FD-64574BB902BD}.Release|Win32.ActiveCfg = Release|Win32
+ {21F6C0E4-DD1A-49E6-82FD-64574BB902BD}.Release|Win32.Build.0 = Release|Win32
+ {21F6C0E4-DD1A-49E6-82FD-64574BB902BD}.Release|x64.ActiveCfg = Release|x64
+ {21F6C0E4-DD1A-49E6-82FD-64574BB902BD}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/plugins/KeyboardNotify/KeyboardNotify_10.vcxproj b/plugins/KeyboardNotify/KeyboardNotify_10.vcxproj new file mode 100644 index 0000000000..6f9460f811 --- /dev/null +++ b/plugins/KeyboardNotify/KeyboardNotify_10.vcxproj @@ -0,0 +1,223 @@ +<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="AggressiveOptimize.h" />
+ <ClInclude Include="constants.h" />
+ <ClInclude Include="EnumProc.h" />
+ <ClInclude Include="flash.h" />
+ <ClInclude Include="ignore.h" />
+ <ClInclude Include="keyboard.h" />
+ <ClInclude Include="keypresses.h" />
+ <ClInclude Include="protolist.h" />
+ <ClInclude Include="resource.h" />
+ <ClInclude Include="trigger.h" />
+ <ClInclude Include="utils.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="EnumProc.c" />
+ <ClCompile Include="flash.c" />
+ <ClCompile Include="ignore.c" />
+ <ClCompile Include="keyboard.c" />
+ <ClCompile Include="keypresses.c" />
+ <ClCompile Include="main.c" />
+ <ClCompile Include="options.c" />
+ <ClCompile Include="trigger.c" />
+ <ClCompile Include="utils.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="resources.rc" />
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectName>KeyboardNotify</ProjectName>
+ <ProjectGuid>{21F6C0E4-DD1A-49E6-82FD-64574BB902BD}</ProjectGuid>
+ <RootNamespace>KeyboardNotify</RootNamespace>
+ <Keyword>Win32Proj</Keyword>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64/Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64/Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\</IntDir>
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;KEYBORDNOTIFY_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ <DisableSpecificWarnings>4996</DisableSpecificWarnings>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ <AdditionalManifestDependencies>
+ </AdditionalManifestDependencies>
+ <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ <PostBuildEvent>
+ <Command>
+ </Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;KEYBORDNOTIFY_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ <DisableSpecificWarnings>4996</DisableSpecificWarnings>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>Common.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>Wininet.lib;urlmon.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ </Link>
+ <PostBuildEvent>
+ <Command>
+ </Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;KEYBORDNOTIFY_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4996</DisableSpecificWarnings>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Windows</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ <AdditionalManifestDependencies>
+ </AdditionalManifestDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ <Manifest>
+ <AdditionalManifestFiles>
+ </AdditionalManifestFiles>
+ </Manifest>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;KEYBORDNOTIFY_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4996</DisableSpecificWarnings>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>Common.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>Wininet.lib;urlmon.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Windows</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
\ No newline at end of file diff --git a/plugins/KeyboardNotify/KeyboardNotify_10.vcxproj.filters b/plugins/KeyboardNotify/KeyboardNotify_10.vcxproj.filters new file mode 100644 index 0000000000..885c295393 --- /dev/null +++ b/plugins/KeyboardNotify/KeyboardNotify_10.vcxproj.filters @@ -0,0 +1,83 @@ +<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{cb4f36de-a3ec-4ac1-af20-7d5e2e377159}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{5985f873-7bf0-485a-bcdc-82402f88b768}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{f11828c5-0ed8-4c09-b2b5-ed38536f7f2c}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="AggressiveOptimize.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="constants.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="EnumProc.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="flash.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="ignore.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="keyboard.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="keypresses.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="protolist.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="trigger.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="utils.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="EnumProc.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="flash.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="ignore.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="keyboard.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="keypresses.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="main.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="options.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="trigger.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="utils.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="resources.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project>
\ No newline at end of file diff --git a/plugins/KeyboardNotify/constants.h b/plugins/KeyboardNotify/constants.h new file mode 100644 index 0000000000..2f339d07a6 --- /dev/null +++ b/plugins/KeyboardNotify/constants.h @@ -0,0 +1,85 @@ +/* + +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. + +*/ + +// Settings values +#define KEYBDMODULE "keybdnotify" +#define FLASH_SAMETIME 0 +#define FLASH_INTURN 1 +#define FLASH_INSEQUENCE 2 +#define FLASH_CUSTOM 3 +#define FLASH_TRILLIAN 4 +#define SEQ_LEFT2RIGHT 0 +#define SEQ_RIGHT2LEFT 1 +#define SEQ_LIKEKIT 2 +#define ACTIVE_MIRANDA 0 +#define ACTIVE_WINDOWS 1 +// Until settings map +#define UNTIL_NBLINKS 1 +#define UNTIL_REATTENDED 2 +#define UNTIL_EVENTSOPEN 4 +#define UNTIL_CONDITIONS 8 + +// Status map +#define MAP_ONLINE 1 +#define MAP_AWAY 2 +#define MAP_NA 4 +#define MAP_OCCUPIED 8 +#define MAP_DND 16 +#define MAP_FREECHAT 32 +#define MAP_INVISIBLE 64 +#define MAP_ONTHEPHONE 128 +#define MAP_OUTTOLUNCH 256 +#define MAP_OFFLINE 512 + +// Default settings +#define DEF_SETTING_ONMSG 1 // 1: Yes, 0: No +#define DEF_SETTING_ONURL 1 // 1: Yes, 0: No +#define DEF_SETTING_ONFILE 1 // 1: Yes, 0: No +#define DEF_SETTING_OTHER 1 // 1: Yes, 0: No +#define DEF_SETTING_FSCREEN 1 // 1: Yes, 0: No +#define DEF_SETTING_SSAVER 1 // 1: Yes, 0: No +#define DEF_SETTING_LOCKED 1 // 1: Yes, 0: No +#define DEF_SETTING_PROCS 0 // 1: Yes, 0: No +#define DEF_SETTING_ACTIVE 1 // 1: Yes, 0: No +#define DEF_SETTING_IFMSGOPEN 1 // 1: Yes, 0: No +#define DEF_SETTING_IFMSGNOTTOP 0 // 1: Yes, 0: No +#define DEF_SETTING_IFMSGOLDER 0 // 1: Yes, 0: No +#define DEF_SETTING_SECSOLDER 10 // Seconds +#define DEF_SETTING_FLASHUNTIL 2 // 1 = After x blinks, 2 = Until Miranda/Windows become active, 4 = Events are opened, 8 = Until end of 'notify when' conditions +#define DEF_SETTING_NBLINKS 4 // Seconds +#define DEF_SETTING_MIRORWIN 0 // 0-1, 0 = Miranda becomes active, 1 = Windows becomes active +#define DEF_SETTING_STATUS 1023 // 1023 = All +#define DEF_SETTING_CHECKTIME 0 // Minutes, 0 = don't check +#define DEF_SETTING_FLASHCAPS 1 // 1: Yes, 0: No +#define DEF_SETTING_FLASHNUM 1 // 1: Yes, 0: No +#define DEF_SETTING_FLASHSCROLL 1 // 1: Yes, 0: No +#define DEF_SETTING_FLASHEFFECT 0 // 0-3, 0 = All together, 1 = In turn, 2 = In sequence, 3 = Custom Theme, 4 = Trillian-like sequences +#define DEF_SETTING_SEQORDER 0 // 0-2, 0 = left to right, 1 = right to left, 2 = left <-> right +#define DEF_SETTING_CUSTOMTHEME 0 // Theme number +#define DEF_SETTING_LEDSMSG 2 // 2: Num Lock +#define DEF_SETTING_LEDSFILE 4 // 2: Caps Lock +#define DEF_SETTING_LEDSURL 1 // 2: Scroll Lock +#define DEF_SETTING_LEDSOTHER 7 // 2: Num Lock + Caps Lock + Scroll Lock +#define DEF_SETTING_STARTDELAY 2 // Seconds +#define DEF_SETTING_FLASHSPEED 3 // 0-5, 0 = really slow, 5 = really fast +#define DEF_SETTING_KEYPRESSES 0 // 1: Yes, 0: No +#define DEF_SETTING_OVERRIDE 0 // 1: Yes, 0: No +#define DEF_SETTING_TESTNUM 2 // Number of sequences to test before stopping
+#define DEF_SETTING_TESTSECS 2 // Seconds to test before stopping
+#define DEF_SETTING_PROTOCOL 1 // 1: Yes, 0: No
+#define DEF_SETTING_XSTATUS 1 // 1: Yes, 0: No
diff --git a/plugins/KeyboardNotify/docs/keyboardnotify_readme.txt b/plugins/KeyboardNotify/docs/keyboardnotify_readme.txt new file mode 100644 index 0000000000..c7dfaa5c77 --- /dev/null +++ b/plugins/KeyboardNotify/docs/keyboardnotify_readme.txt @@ -0,0 +1,292 @@ + -=====================================-
+ Keyboard Notify plugin for Miranda-IM
+ -=====================================-
+
+
+Copyright (C) 2002,2003 Martin Öberg
+Copyright (C) 2004 Std
+Copyright (C) 2005-2006 TioDuke (tioduke@yahoo.ca)
+
+
+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 (unopened 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 - left to right, right to left and left to right and to left again - and custom, preview button
+
+It was designed to be flexible and performing 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 services to allow third party plugins use its notifier capabilities and supports Trigger plugin.
+
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------
+IMPORTANT NOTE FOR USB KEYBOARD'S USERS: The plugin will only work if you choose to emulate keypresses (which is not the nicest solution but is the only way I found)
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+
+Installation
+------------
+Just the typical Miranda way: drop keyboardnotify.dll into your plugins folder, restart Miranda and configure the options as you like... voilà! done! NO OTHER FILES ARE REQUIRED.
+
+
+Options
+-------
+Options page Options->Plugins->Keyboard Flash. Tabbed: Protocols, Rules (when), Flashing (how), Themes and Ignore.
+
+Here there are some explanations on features on the Options' Page.
+
+Protocols tab:
+Protocols to check: check/uncheck the protocols you want this plugin to work with.
+
+Rules tab:
+Events to react on:
+ - Incoming messages: check this if you want to be notified on incoming message events
+ - Incoming files: check this if you want to be notified on incoming file events
+ - Incoming URLs: check this if you want to be notified on incoming URL events
+ - Everything else: check this if you want to be notified on incoming events that are not messages, files or URLs (like authorization requests or you-were-added events).
+Message event only:
+ - Blink if message window is open: check it if you want to be notified of incoming messages even if that contact's message window is open, if you uncheck it you will only be notified of incoming messages if the window is closed
+ - ... and not in foreground: check this option if you want to be notified if the message window is open and that window is not focused
+ - Only if last is xx seconds old: if you check this option the plugin will not notify you of new messages until xx seconds have passed after the last message for that contact was sent/received
+Notify when:
+ - Full screen mode: check this if you want to be notified when you are on full screen mode (screen saver excluded form the full screen classification, although it is a special type of full screen application)
+ - Screen saver is running: check this if you want to be notified while screen saver is running
+ - Workstation is locked (2000/XP): check this if you want to be notified when your workstation is locked (only for Windows NT systems)
+ - Defined programs are running: check this one if you want to be notified when certain programs are running. To define those programs you have to click over the [...] button and enter the .exe filenames (including the .exe suffix).
+ - All other situations: check this if you want to be notified when neither you are in full screen mode, nor the screen saver is running and nor the workstation is locked.
+ Note on 'notify when': to be notified on ANY condition (always) you will have to check them all.
+Notify if status is:
+ - Online, Away, NA, etc: check each status for which you want notification to be turn on. Checking all means on all statuses.
+ Note on 'notify if status is ...': The plugin will check these options against the event's protocol status, this means that if you choose to be notified only when you are online and at a certain moment you are online in one protocol but away in another, then you will be notified on events for the first one only.
+Flash until:
+ - nn seconds: if this option is selected leds will flash for the amount of seconds you have specified
+ - Miranda/Windows is re-attended: if this option is selected flashing will stop when either the mouse or a key is pressed on any of Miranda/Windows's windows
+ - Events are opened: if this option is selected flashing will stop when there will be no more pending events (for the selected protocols, of course)
+ - End of 'notify when' conditions: if this option is selected the flashing will stop when all situations checked under 'notify when' (and also the status conditions) ceased to be true.
+ Note on 'End of notify when conditions': this means that if you select ALL the 'notify when' situations and all the statuses (e.g. always) flashing will not stop (you may still stop it manually by pressing the Pause/Break key).
+ This option is particluarly usuful if you want to be notified only when you are in full screen mode (for example) and you want the flashing to stop when you change to non full screen mode. The same applies to all the other situations.
+Pending Events:
+ - Remind me every xx minutes: this option will make the plugin check for unopen events every xx minutes and start notifying if any is found and the 'notify when' and the status conditions are met. If you don't want this option, just specify 0 minutes and it will be disabled.
+ This option is usuful if you, for example, select to be notified on workstation locked and then to stop the flashing using 'end of notify conditions'. If you do not open the event that generated the flashing (e.g. leaving the event pending) then when you lock your computer back the flashing will begin again.
+ Note that if on your messaging plugin you have enabled the option to pop up the message window, then the reminder won't alert you of messages (as they will be promptly opened) but it will still work for files/URLs/others.
+
+Flashing tab:
+Keys to flash:
+ - Num Lock: check this if you want the Num Lock led to blink
+ - Caps Lock: check this if you want the Caps Lock led to blink
+ - Scroll Lock: check this if you want the Scroll Lock led to blink.
+ Note on 'keys to flash': if you don't choose any you will see nothing happen.
+Flashing effects:
+ - All at the same time: if you select this one the leds will blink at the same time
+ - In turn: if you select this one the leds will blink this way: Num+Scroll first and then Caps if the three of them are selected in 'keys to flash', if not they will blink alternately
+ - In sequence: if you select this one leds will blink one at the time in sequence; the order of the sequence depends on:
+ - left->right: from left to right
+ - right->left: from right to left
+ - left<->right: from left to right and then right to left (producing the infamous KITT effect)
+ - Custom theme: if you select this one you will have to select from the combo box one of the themes you have created in the "Themes" tab. For more information refer to the 'Themes tabs' explanation
+ - Accordingly to events' count: if you select this option the plugin will flash the num lock led as many times as pending message events there will be, the same for caps lock and file events, scroll lock and urls events and the three at the same time and other events.
+ Since v.1.5.3.2 you can use the [...] button to open the dialog that allows you to change the default leds assign to each event.
+ Note on 'flashing effects': effects will take into consideration the 'keys to flash' options, which means that only the checked leds will blink. In the case of custom flashing sequences (themes), the plugin will show no led turned on if you specify one led (or a combination of leds) that is not selected in 'keys to flash'.
+Wait before starting flashing:
+ - nn seconds: specify the amount of time for the plugin to wait before starting flashing (0 means do not wait).
+Speed: You may select between 5 different speeds that go from really slow to really fast.
+Preview button: This button will allow you to test your flashing settings. Since v.1.5.3.3 it is an on/off button (thank you tweety for the definition), which means that it will flash when it is on and stop when it is off.
+Note on preview button: the preview button will show nothing at all when you select the "Accordingly to events' count' flashing effect: as most probably there will be no pending event it will just turn off your leds (it has really nothing to show).
+Emulate keypresses: if you check this option the plugin will act as if keystrokes were sent from the keyboard, which means that some nasty things may happen, as toggling on and off capital letters or being kicked from Windows' screensaver. It is meant only for people having trouble with the other method (ie people using USB keyboards).
+
+Themes tab:
+Create/Edit theme:
+ - In the 'Theme' combo box you type the name of the new theme you want to add or you select from the dropdown list the one you want to modify or delete.
+ - In the text box you specify a flashing sequence in the form of an expression in a special 'flashing language' created by me (to take a look at the specification of this 'language' please refer to next section: 'Custom order language').
+ - Test button: use this one to see how the sequence in the text box will actualy look in action.
+ Note on the test button: this button and the preview button act differently (and don't expect the 'Preview' to act like this one, as its function is completely different). First, this one will show you how the sequence will look without taking into consideration options in the 'flashing tab' (like 'keys to flash', 'wait delay', but it will use the 'speed' setting). This test button will finish playing the sequence after showing it twice and at least for 2 seconds (both conditions). This behaviour, I think, will work fine for almost any user but if you think you need to change that (say, making it flash for 3 seconds or 4 times) there is a way if you change two settings stored in the DB using DBEditor++: you have to change the values of "testnum" and/or "testsecs", both of the 'byte' type (the first one rules the x times condition and the second the x seconds one). I did not put these options in the Option page just because I don't like the idea of a control to control another control (superstition?); I find it confusing.
+ - Add/Update/Delete: these buttons will either add a new theme, update and delete an existing one. 'Add' will be enabled only if you type a new theme name in the theme combo box. 'Update' will be enabled if you have modified the flashing sequence for an existing theme. 'Delete' will be enabled if the theme currently selected is an existing one (e.g., not a new one that has not been added yet). After pressing any of these buttons the 'Apply' button will be automatically enabled. This means that changes will be saved in the database only after activating the 'Apply' button.
+Import/Export:
+ - Export: it will export the themes stored in the DB to a text file with the .knt extension (keyboard Notify Theme).
+ - Import: it will load into the option page the themes specified in a text file with the .knt extension (the file, obviously, has the same format that the export one). Themes will be stored only after clicking on the 'Aply' button (just like the add/update/delete buttons).
+ - Override existing: check this option if you want existing themes (it checks by theme name) to be overwritten when you import them. If you don't check this option existing themes will not be overwritten.
+Note on Import/Export: I packed my own themes file to show you the file format (mythemes.knt). Most of the themes are the creation of Sir_Qwerty (thank you very much *g*), the boring ones are mine.
+
+
+Custom order 'language'
+-----------------------
+I designed a special 'flashing language' in order to allow users to provide the plugin with the flashing sequence. Here is an explanation of which symbols it uses and what they mean:
+1: turn on Num Lock led
+2: turn on Caps Lock led
+3: turn on Scroll Lock led
+0: turn all leds off
+[...]: turn on at the same time the leds specified inside the brackets (1, 2, 3)
+This is the complete list of symbols. Any other will be ignored by the plugin parser (and cleaned from the text box).
+And here you have some examples of how the predefined effects should look in this 'language':
+All at the same time: [123]0
+In turn: [13]2
+In sequence (left->right): 123
+In sequence (right->left): 321
+In sequence (left<->right) 1232
+Turn on all leds without blinking: [123]
+Sliding lights: [12]30[23]10
+Heartbeat (created by sir_qwerty): 00000000000000000000000000000000303
+Note: remember that when the sequence is finished the plugin will go back to the beginning until it has to stop due to 'until when' settings.
+
+
+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.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 keyboards 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:
+ [!] fixed nconvers++'s message window detection and checked window detection for srmm, scriver, sramm and srmm_mod
+ [!] checking of 'notify when' and statuses added for API events
+
+1.5.2.0:
+ [+] Themes support (another of Slaktarn's ideas: thank you *g*)
+ [-] History dropdown list for the custom order string
+
+1.5.1.0:
+ [+] Custom effects using 'flashing language' (thank you very much Slaktarn for this very nice idea!)
+ [+] History dropdown list for the custom order string
+
+1.5.0.0: (unreleased)
+ [+] Drivers aren't needed anymore
+ [+] Status selection option
+ [+] Miranda/Windows activity detection (thank you Peter Boon)
+ [+] 'Opened events' stop method
+ [+] 'End of notify when conditions' stop method
+ [+] 'Miranda/Windows are re-attended' 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 Martin Öberg)
+ This is strickz' final release. It still uses keypress simulation. It was nice (thanks *g*)
+
+
+TODO:
+-----
+ - I consider the plugin feature finished. :-D
+
+License
+-------
+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.
+
+=====================================================================
diff --git a/plugins/KeyboardNotify/docs/keyboardnotify_translation.txt b/plugins/KeyboardNotify/docs/keyboardnotify_translation.txt new file mode 100644 index 0000000000..a6edc8f6a0 --- /dev/null +++ b/plugins/KeyboardNotify/docs/keyboardnotify_translation.txt @@ -0,0 +1,296 @@ +
+; This file contains the list of translatable strings in the
+; Miranda KeyboardNotify Ext plugin.
+; Author TioDuke
+
+; Last updated: may, 2005
+; KeyboardNotify Ext 1.5.3.0
+
+
+[Plugins]
+trans!
+
+[Keyboard Flash]
+trans!
+
+[Protocols]
+trans!
+
+[Protocols to check]
+trans!
+
+[Rules]
+trans!
+
+[Events to react on]
+trans!
+
+[Incoming messages]
+trans!
+
+[Incoming files]
+trans!
+
+[Incoming URLs]
+trans!
+
+[Everything else]
+trans!
+
+[Message-Event only]
+trans!
+
+[Blink if message window is open]
+trans!
+
+[ ... and not in foreground]
+trans!
+
+[Only if last is]
+trans!
+
+[sec. old]
+trans!
+
+[Flash until]
+trans!
+
+[seconds]
+trans!
+
+[is re-attended]
+trans!
+
+[Events are opened]
+trans!
+
+[End of 'notify when' conditions]
+trans!
+
+[Notify when]
+trans!
+
+[Full Screen mode]
+trans!
+
+[Screen Saver is running]
+trans!
+
+[Workstation is Locked (2000/XP)]
+trans!
+
+[Defined programs are running]
+trans!
+
+[All other situations]
+trans!
+
+[Only notify if status is]
+trans!
+
+[Online]
+trans!
+
+[Away]
+trans!
+
+[NA]
+trans!
+
+[Occupied]
+trans!
+
+[DND]
+trans!
+
+[Free for chat]
+trans!
+
+[Invisible]
+trans!
+
+[On the phone]
+trans!
+
+[Out to lunch]
+trans!
+
+[Offline]
+trans!
+
+[Pending Events]
+trans!
+
+[Remind me every]
+trans!
+
+[minutes]
+trans!
+
+[Flashing]
+trans!
+
+[Keys to flash]
+trans!
+
+[Num Lock]
+trans!
+
+[Caps Lock]
+trans!
+
+[Scroll Lock]
+trans!
+
+[Flashing effects]
+trans!
+
+[All at the same time]
+trans!
+
+[In turn]
+trans!
+
+[In sequence]
+trans!
+
+[left->right]
+trans!
+
+[right->left]
+trans!
+
+[left<->right]
+trans!
+
+[Custom theme]
+trans!
+
+[Accordingly to events' count]
+trans!
+
+[Wait before starting flashing]
+trans!
+
+[seconds]
+trans!
+
+[Flash speed]
+trans!
+
+[Fast]
+trans!
+
+[Slow]
+trans!
+
+[&Preview]
+trans!
+
+[Emulate keypresses (Use this option if you are using an USB keyboard)]
+trans!
+
+[Themes]
+trans!
+
+[Create/Edit theme]
+trans!
+
+[Theme]
+trans!
+
+[Test]
+trans!
+
+[Add]
+trans!
+
+[Update]
+trans!
+
+[Import/Export]
+trans!
+
+[Export...]
+trans!
+
+[Import...]
+trans!
+
+[Override existing]
+trans!
+
+[Keyboard Notify Theme]
+trans!
+
+[Set LEDs for events]
+trans!
+
+[Num]
+trans!
+
+[Caps]
+trans!
+
+[Scroll]
+trans!
+
+[Message events]
+trans!
+
+[File events]
+trans!
+
+[URL events]
+trans!
+
+[Other events]
+trans!
+
+[Cancel]
+trans!
+
+[OK]
+trans!
+
+[Set program list]
+trans!
+
+[Program]
+trans!
+
+[Ignore]
+trans!
+
+[The following events are being ignored:]
+trans!
+
+[** Unknown contacts **]
+trans!
+
+[** All contacts **]
+trans!
+
+[Ignore messages]
+trans!
+
+[Ignore URLs]
+trans!
+
+[Ignore files]
+trans!
+
+[Ignore others]
+trans!
+
+[Ignore all]
+trans!
+
+[Ignore none]
+trans!
+
+[xStatuses]
+trans!
+
+[Set xStatus list]
+trans!
diff --git a/plugins/KeyboardNotify/flash.c b/plugins/KeyboardNotify/flash.c new file mode 100644 index 0000000000..f2bb647a89 --- /dev/null +++ b/plugins/KeyboardNotify/flash.c @@ -0,0 +1,438 @@ +/*
+
+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.
+
+*/
+
+#define WIN32_LEAN_AND_MEAN
+
+#include <windows.h>
+#include "flash.h"
+#include "keyboard.h"
+#include "keypresses.h"
+#include "utils.h"
+#include "constants.h"
+#include <newpluginapi.h>
+#include <m_database.h>
+
+typedef struct {
+ unsigned int size;
+ unsigned int index;
+ BYTE frame[MAX_PATH];
+} FLASHING_SEQUENCE;
+
+
+// Prototypes
+FLASHING_SEQUENCE *getCustomSeq(void);
+FLASHING_SEQUENCE *getPredefinedSeq(void);
+FLASHING_SEQUENCE *getTrillianSeq(void);
+void updateTrillianSeq(void);
+static void TestThread(FLASHING_SEQUENCE *);
+static void PreviewThread(void *);
+FLASHING_SEQUENCE str2FS(char *);
+BYTE KbdChar2Byte(char);
+void countUnopenEvents(int *, int *, int *, int *);
+
+#define Leds2Flash ((BYTE)(bFlashLed[2] + (bFlashLed[0]<<1) + (bFlashLed[1]<<2)))
+
+// Flashing settings
+FLASHING_SEQUENCE *pFS;
+BOOL bTemporarilyUseExtern;
+extern BYTE bFlashLed[3];
+extern BYTE bFlashEffect; extern BYTE bSequenceOrder;
+extern WORD wCustomTheme;
+extern BYTE bTrillianLedsMsg; extern BYTE bTrillianLedsURL; extern BYTE bTrillianLedsFile; extern BYTE bTrillianLedsOther;
+extern BYTE bEmulateKeypresses;
+
+
+// TestThread/PreviewThread globals
+extern int nWaitDelay; extern WORD wStartDelay;
+BOOL bTestSemaphore, bPreviewSemaphore, bPreview;
+
+
+void RestoreLEDState(void)
+{
+ if (bEmulateKeypresses)
+ keypresses_RestoreLEDState();
+ else
+ ToggleKeyboardLights((BYTE)(LedState(VK_SCROLL) + (LedState(VK_NUMLOCK)<<1) + (LedState(VK_CAPITAL)<<2)));
+}
+
+
+BYTE getBlinkingLeds(void)
+{
+ if (!pFS->size)
+ return (BYTE)(LedState(VK_SCROLL) + (LedState(VK_NUMLOCK)<<1) + (LedState(VK_CAPITAL)<<2));
+
+ pFS->index %= pFS->size;
+ if (bFlashEffect == FLASH_TRILLIAN && !bTemporarilyUseExtern && !pFS->index)
+ updateTrillianSeq();
+ return pFS->frame[pFS->index++];
+}
+
+
+void setFlashingSequence(void)
+{
+ switch (bFlashEffect) {
+ case FLASH_CUSTOM:
+ pFS = getCustomSeq();
+ break;
+ case FLASH_TRILLIAN:
+ pFS = getTrillianSeq();
+ break;
+ default:
+ pFS = getPredefinedSeq();
+ }
+ bTemporarilyUseExtern = FALSE;
+}
+
+
+FLASHING_SEQUENCE *getCustomSeq(void)
+{
+ static FLASHING_SEQUENCE Custom = {0};
+
+ DBVARIANT dbv;
+ char customStr[MAX_PATH+1];
+
+
+ customStr[0] = '\0';
+ if(!DBGetContactSetting(NULL, KEYBDMODULE, fmtDBSettingName("custom%d", wCustomTheme), &dbv)) {
+ strcpy(customStr, dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+
+ Custom = str2FS(customStr);
+
+ return &Custom;
+}
+
+
+FLASHING_SEQUENCE *getPredefinedSeq(void)
+{
+ static FLASHING_SEQUENCE Predefined = {0};
+
+ FLASHING_SEQUENCE *pAux;
+ FLASHING_SEQUENCE SameTime = {2, 0, {7, 0}};
+ FLASHING_SEQUENCE InTurn = {2, 0, {3, 4}};
+ FLASHING_SEQUENCE InSeq = {3, 0, {2, 4, 1}};
+ FLASHING_SEQUENCE InSeqRev = {3, 0, {1, 4, 2}};
+ FLASHING_SEQUENCE InSeqKIT = {4, 0, {2, 4, 1, 4}};
+
+
+ if (Leds2Flash < 3 || Leds2Flash == 4)
+ pAux = &SameTime;
+ else
+ switch (bFlashEffect) {
+ default:
+ case FLASH_SAMETIME:
+ pAux = &SameTime;
+ break;
+ case FLASH_INTURN:
+ if (Leds2Flash == 3) // 3 = Num+Scroll
+ pAux = &InSeq;
+ else
+ pAux = &InTurn;
+ break;
+ case FLASH_INSEQUENCE:
+ switch (bSequenceOrder) {
+ default:
+ case SEQ_LEFT2RIGHT:
+ pAux = &InSeq;
+ break;
+ case SEQ_RIGHT2LEFT:
+ pAux = &InSeqRev;
+ break;
+ case SEQ_LIKEKIT:
+ if (Leds2Flash != 7) // 7 = Num+Caps+Scroll
+ pAux = &InSeq;
+ else
+ pAux = &InSeqKIT;
+ break;
+ }
+ break;
+ }
+
+ Predefined.size = Predefined.index = 0;
+ for (pAux->index=0; pAux->index < pAux->size; pAux->index++)
+ if (!pAux->frame[pAux->index] || (pAux->frame[pAux->index] & Leds2Flash)) {
+ Predefined.size++;
+ Predefined.frame[Predefined.size - 1] = pAux->frame[pAux->index] & Leds2Flash;
+ }
+
+ return &Predefined;
+}
+
+
+FLASHING_SEQUENCE *getTrillianSeq(void)
+{
+ static FLASHING_SEQUENCE Trillian = {2, 0, {0, 0}};
+
+ Trillian.size = 2;
+ Trillian.index = 0;
+
+ return &Trillian;
+}
+
+
+void updateTrillianSeq(void)
+{
+ unsigned int i, msgCount=0, fileCount=0, urlCount=0, otherCount=0;
+
+ pFS->size = 2;
+ countUnopenEvents(&msgCount, &fileCount, &urlCount, &otherCount);
+
+ if ((bTrillianLedsMsg & Leds2Flash) && (pFS->size + 2 * msgCount) <= MAX_PATH)
+ for (i=0; i < msgCount; i++) {
+ pFS->frame[pFS->size++] = bTrillianLedsMsg & Leds2Flash;
+ pFS->frame[pFS->size++] = 0;
+ }
+
+ if ((bTrillianLedsFile & Leds2Flash) && (pFS->size + 2 * fileCount) <= MAX_PATH)
+ for (i=0; i < fileCount; i++) {
+ pFS->frame[pFS->size++] = bTrillianLedsFile & Leds2Flash;
+ pFS->frame[pFS->size++] = 0;
+ }
+
+ if ((bTrillianLedsURL & Leds2Flash) && (pFS->size + 2 * urlCount) <= MAX_PATH)
+ for (i=0; i < urlCount; i++) {
+ pFS->frame[pFS->size++] = bTrillianLedsURL & Leds2Flash;
+ pFS->frame[pFS->size++] = 0;
+ }
+
+ if ((bTrillianLedsOther & Leds2Flash) && (pFS->size + 2 * otherCount) <= MAX_PATH)
+ for (i=0; i < otherCount; i++) {
+ pFS->frame[pFS->size++] = bTrillianLedsOther & Leds2Flash;
+ pFS->frame[pFS->size++] = 0;
+ }
+
+}
+
+
+void useExternSequence(char *extStr)
+{
+ static FLASHING_SEQUENCE Extern = {0};
+
+ char externStr[MAX_PATH+1];
+
+
+ strcpy(externStr, extStr);
+
+ Extern = str2FS(normalizeCustomString(externStr));
+
+ pFS = &Extern;
+ bTemporarilyUseExtern = TRUE;
+}
+
+
+char *normalizeCustomString(char *customStr)
+{
+ int len=0, status=0;
+ BOOL used[4];
+ char strAux[MAX_PATH+1], *str;
+
+ for (strcpy(str=strAux, customStr); *str; str++)
+ switch (*str) {
+ case '[':
+ if (status == 0) {
+ status = 1;
+ customStr[len++] = *str;
+ used[0] = used [1] = used[2] = used[3] = FALSE;
+ }
+ break;
+ case ']':
+ if (status == 1) {
+ status = 0;
+ customStr[len++] = *str;
+ }
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ if (status == 0)
+ customStr[len++] = *str;
+ else
+ if (!used[*str - '0']) {
+ customStr[len++] = *str;
+ used[*str - '0'] = TRUE;
+ }
+ break;
+ }
+ if (status == 1)
+ customStr[len++] = ']';
+ customStr[len] = '\0';
+
+ return customStr;
+}
+
+
+char *getCurrentSequenceString(void)
+{
+ static char CurrentSeqString[MAX_PATH+1];
+
+ unsigned int i;
+ char *str;
+
+
+ for (i=0, str=CurrentSeqString; i < pFS->size; i++)
+ switch (pFS->frame[i]) {
+ case 0:
+ *(str++) = '0';
+ break;
+ case 1:
+ *(str++) = '3';
+ break;
+ case 2:
+ *(str++) = '1';
+ break;
+ case 3:
+ *(str++) = '[';
+ *(str++) = '1';
+ *(str++) = '3';
+ *(str++) = ']';
+ break;
+ case 4:
+ *(str++) = '2';
+ break;
+ case 5:
+ *(str++) = '[';
+ *(str++) = '2';
+ *(str++) = '3';
+ *(str++) = ']';
+ break;
+ case 6:
+ *(str++) = '[';
+ *(str++) = '1';
+ *(str++) = '2';
+ *(str++) = ']';
+ break;
+ case 7:
+ *(str++) = '[';
+ *(str++) = '1';
+ *(str++) = '2';
+ *(str++) = '3';
+ *(str++) = ']';
+ }
+ *str = '\0';
+
+
+ return CurrentSeqString;
+}
+
+
+void testSequence(char *testStr)
+{
+ static FLASHING_SEQUENCE Test = {0};
+
+ DWORD threadID = 0;
+
+
+ if (bTestSemaphore) // we try to avoid concurrent test threads
+ return;
+ bTestSemaphore = TRUE;
+
+ Test = str2FS(testStr);
+
+ CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)TestThread, &Test, 0, &threadID);
+}
+
+
+static void TestThread(FLASHING_SEQUENCE *pTest)
+{
+ unsigned int i;
+ DWORD dwEndTest;
+
+ unsigned int testNum = (unsigned int)DBGetContactSettingByte(NULL, KEYBDMODULE, "testnum", DEF_SETTING_TESTNUM);
+ unsigned int testSecs = (unsigned int)DBGetContactSettingByte(NULL, KEYBDMODULE, "testsecs", DEF_SETTING_TESTSECS);
+
+ for (i=0, dwEndTest=GetTickCount()+testSecs*1000; i < testNum || GetTickCount() < dwEndTest; i++)
+ for (pTest->index=0; pTest->index < pTest->size; pTest->index++) {
+ ToggleKeyboardLights(pTest->frame[pTest->index]);
+ Sleep(nWaitDelay);
+ }
+
+ RestoreLEDState();
+
+ bTestSemaphore = FALSE;
+}
+
+
+void previewFlashing(BOOL buttonState)
+{
+ DWORD threadID = 0;
+
+ bPreview = buttonState;
+
+ if (!bPreview || bPreviewSemaphore) // turn off flashing or already running
+ return;
+
+ bPreviewSemaphore = TRUE;
+ CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PreviewThread, NULL, 0, &threadID);
+}
+
+
+static void PreviewThread(void *dummy)
+{
+ unsigned int i;
+ BYTE unchangedLeds;
+
+ if (wStartDelay > 0)
+ Sleep(wStartDelay * 1000);
+
+ unchangedLeds = (BYTE)(LedState(VK_SCROLL) * !bFlashLed[2] + ((LedState(VK_NUMLOCK) * !bFlashLed[0])<<1) + ((LedState(VK_CAPITAL) * !bFlashLed[1])<<2));
+
+ while (bPreview)
+ for (i=0; bPreview && i < pFS->size; i++) {
+ ToggleKeyboardLights((BYTE)(pFS->frame[i%pFS->size]|unchangedLeds));
+ Sleep(nWaitDelay);
+ }
+
+ RestoreLEDState();
+
+ bPreviewSemaphore = FALSE;
+}
+
+
+FLASHING_SEQUENCE str2FS(char *str)
+{
+ FLASHING_SEQUENCE Temp = {0};
+
+ for (Temp.size=Temp.index=0; *str; str++) {
+ Temp.size++;
+ if (*str == '[') {
+ Temp.frame[Temp.size - 1] = 0;
+ for (str++; *str && *str != ']'; str++)
+ Temp.frame[Temp.size - 1] += KbdChar2Byte(*str) & Leds2Flash;
+ if (!*str) break;
+ } else
+ Temp.frame[Temp.size - 1] = KbdChar2Byte(*str) & Leds2Flash;
+ }
+
+ return Temp;
+}
+
+
+BYTE KbdChar2Byte(char kbdChar)
+{
+ switch (kbdChar) {
+ case '1': //NumLock
+ return 2;
+ case '2': //CapsLock
+ return 4;
+ case '3': //ScrollLock
+ return 1;
+ }
+ return 0;
+}
diff --git a/plugins/KeyboardNotify/flash.h b/plugins/KeyboardNotify/flash.h new file mode 100644 index 0000000000..594cb16fd1 --- /dev/null +++ b/plugins/KeyboardNotify/flash.h @@ -0,0 +1,28 @@ +/*
+
+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.
+
+*/
+
+void RestoreLEDState(void);
+BYTE getBlinkingLeds(void);
+void setFlashingSequence(void);
+void useExternSequence(char *);
+char *normalizeCustomString(char *);
+char *getCurrentSequenceString(void);
+void testSequence(char *);
+void previewFlashing(BOOL);
+
+#define LedState(a) (((BYTE)(GetKeyState(a) & 0xffff))!=0)
diff --git a/plugins/KeyboardNotify/ignore.c b/plugins/KeyboardNotify/ignore.c new file mode 100644 index 0000000000..b9d897b358 --- /dev/null +++ b/plugins/KeyboardNotify/ignore.c @@ -0,0 +1,389 @@ +/*
+
+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.
+
+*/
+
+#define WIN32_LEAN_AND_MEAN
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <windows.h>
+#include <commctrl.h>
+#include <commdlg.h>
+#include "ignore.h"
+#include "resource.h"
+#include "constants.h"
+#include <newpluginapi.h>
+#include <m_clc.h>
+#include <m_clist.h>
+#include <m_database.h>
+#include <m_langpack.h>
+#include <m_options.h>
+#include <m_protosvc.h>
+#include <m_protocols.h>
+#include <m_skin.h>
+
+
+#define IGNOREEVENT_MAX 4
+#define IDI_SMALLDOT 211
+#define IDI_FILLEDBLOB 212
+#define IDI_EMPTYBLOB 213
+
+#define SIZEOF(a) (sizeof(a) / sizeof(a[0]))
+
+static const DWORD ignoreIdToPf1[IGNOREEVENT_MAX] = {PF1_IMRECV, PF1_URLRECV, PF1_FILERECV, 0xFFFFFFFF};
+
+extern double dWinVer;
+extern BOOL bWindowsNT;
+
+
+static DWORD GetMask(HANDLE hContact)
+{
+ DWORD mask = DBGetContactSettingDword(hContact, KEYBDMODULE, "Mask1", (DWORD)(-1));
+ if(mask == (DWORD)(-1)) {
+ if(hContact == NULL)
+ mask=0;
+ else {
+ if(DBGetContactSettingByte(hContact, "CList", "Hidden", 0) || DBGetContactSettingByte(hContact, "CList", "NotOnList", 0))
+ mask = DBGetContactSettingDword(NULL, KEYBDMODULE, "Mask1", 0);
+ else
+ mask = DBGetContactSettingDword(NULL, KEYBDMODULE, "Default1", 0);
+ }
+ }
+ return mask;
+}
+
+static void SetListGroupIcons(HWND hwndList, HANDLE hFirstItem, HANDLE hParentItem, int *groupChildCount)
+{
+ int typeOfFirst;
+ int iconOn[IGNOREEVENT_MAX]={1,1,1,1};
+ int childCount[IGNOREEVENT_MAX]={0,0,0,0}, i;
+ int iImage;
+ HANDLE hItem, hChildItem;
+
+ typeOfFirst = SendMessage(hwndList, CLM_GETITEMTYPE, (WPARAM)hFirstItem, 0);
+ //check groups
+ if(typeOfFirst == CLCIT_GROUP)
+ hItem = hFirstItem;
+ else
+ hItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXTGROUP, (LPARAM)hFirstItem);
+ while(hItem) {
+ hChildItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_CHILD, (LPARAM)hItem);
+ if(hChildItem)
+ SetListGroupIcons(hwndList, hChildItem, hItem, childCount);
+ for(i=0; i < SIZEOF(iconOn); i++)
+ if(iconOn[i] && SendMessage(hwndList, CLM_GETEXTRAIMAGE, (WPARAM)hItem, i) == 0)
+ iconOn[i] = 0;
+ hItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXTGROUP, (LPARAM)hItem);
+ }
+ //check contacts
+ if(typeOfFirst == CLCIT_CONTACT)
+ hItem = hFirstItem;
+ else
+ hItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXTCONTACT, (LPARAM)hFirstItem);
+ while(hItem) {
+ for(i=0; i < SIZEOF(iconOn); i++) {
+ iImage = SendMessage(hwndList, CLM_GETEXTRAIMAGE, (WPARAM)hItem, i);
+ if(iconOn[i] && iImage == 0)
+ iconOn[i] = 0;
+ if(iImage != 0xFF)
+ childCount[i]++;
+ }
+ hItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXTCONTACT, (LPARAM)hItem);
+ }
+ //set icons
+ for(i=0; i < SIZEOF(iconOn); i++) {
+ SendMessage(hwndList, CLM_SETEXTRAIMAGE, (WPARAM)hParentItem, MAKELPARAM(i, childCount[i]?(iconOn[i]?i+3:0):0xFF));
+ if(groupChildCount)
+ groupChildCount[i] += childCount[i];
+ }
+ SendMessage(hwndList, CLM_SETEXTRAIMAGE, (WPARAM)hParentItem, MAKELPARAM(IGNOREEVENT_MAX, 1));
+ SendMessage(hwndList, CLM_SETEXTRAIMAGE, (WPARAM)hParentItem, MAKELPARAM(IGNOREEVENT_MAX+1, 2));
+}
+
+static void SetAllChildIcons(HWND hwndList, HANDLE hFirstItem, int iColumn, int iImage)
+{
+ int typeOfFirst, iOldIcon;
+ HANDLE hItem, hChildItem;
+
+ typeOfFirst = SendMessage(hwndList,CLM_GETITEMTYPE,(WPARAM)hFirstItem, 0);
+ //check groups
+ if(typeOfFirst == CLCIT_GROUP)
+ hItem = hFirstItem;
+ else
+ hItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXTGROUP, (LPARAM)hFirstItem);
+ while(hItem) {
+ hChildItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_CHILD, (LPARAM)hItem);
+ if(hChildItem)
+ SetAllChildIcons(hwndList, hChildItem, iColumn, iImage);
+ hItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXTGROUP, (LPARAM)hItem);
+ }
+ //check contacts
+ if(typeOfFirst == CLCIT_CONTACT)
+ hItem = hFirstItem;
+ else
+ hItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXTCONTACT, (LPARAM)hFirstItem);
+ while(hItem) {
+ iOldIcon = SendMessage(hwndList, CLM_GETEXTRAIMAGE, (WPARAM)hItem, iColumn);
+ if(iOldIcon != 0xFF && iOldIcon != iImage)
+ SendMessage(hwndList, CLM_SETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(iColumn, iImage));
+ hItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXTCONTACT, (LPARAM)hItem);
+ }
+}
+
+static void ResetListOptions(HWND hwndList)
+{
+ int i;
+
+ SendMessage(hwndList, CLM_SETBKBITMAP, 0, (LPARAM)NULL);
+ SendMessage(hwndList, CLM_SETBKCOLOR, GetSysColor(COLOR_WINDOW), 0);
+ SendMessage(hwndList, CLM_SETGREYOUTFLAGS, 0, 0);
+ SendMessage(hwndList, CLM_SETLEFTMARGIN, 4, 0);
+ SendMessage(hwndList, CLM_SETINDENT, 10, 0);
+ SendMessage(hwndList, CLM_SETHIDEEMPTYGROUPS, 1, 0);
+ for(i=0; i <= FONTID_MAX; i++)
+ SendMessage(hwndList, CLM_SETTEXTCOLOR, i, GetSysColor(COLOR_WINDOWTEXT));
+}
+
+static void SetIconsForColumn(HWND hwndList, HANDLE hItem, HANDLE hItemAll, int iColumn, int iImage)
+{
+ int itemType;
+
+ itemType = SendMessage(hwndList, CLM_GETITEMTYPE, (WPARAM)hItem, 0);
+ if(itemType == CLCIT_CONTACT) {
+ int oldiImage = SendMessage(hwndList, CLM_GETEXTRAIMAGE, (WPARAM)hItem, iColumn);
+ if (oldiImage != 0xFF && oldiImage != iImage)
+ SendMessage(hwndList, CLM_SETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(iColumn, iImage));
+ }
+ else if(itemType == CLCIT_INFO) {
+ if(hItem == hItemAll)
+ SetAllChildIcons(hwndList, hItem, iColumn, iImage);
+ else
+ SendMessage(hwndList, CLM_SETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(iColumn, iImage)); //hItemUnknown
+ }
+ else if(itemType == CLCIT_GROUP) {
+ hItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_CHILD, (LPARAM)hItem);
+ if(hItem)
+ SetAllChildIcons(hwndList, hItem, iColumn, iImage);
+ }
+}
+
+static void InitialiseItem(HWND hwndList, HANDLE hContact, HANDLE hItem, DWORD protoCaps)
+{
+ DWORD mask;
+ int i;
+
+ mask = GetMask(hContact);
+ for(i=0; i < IGNOREEVENT_MAX; i++)
+ if(ignoreIdToPf1[i] == 0xFFFFFFFF || protoCaps & ignoreIdToPf1[i])
+ SendMessage(hwndList, CLM_SETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(i, mask&(1<<i)?i+3:0));
+ SendMessage(hwndList, CLM_SETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(IGNOREEVENT_MAX, 1));
+ SendMessage(hwndList, CLM_SETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(IGNOREEVENT_MAX+1, 2));
+}
+
+static void SaveItemMask(HWND hwndList, HANDLE hContact, HANDLE hItem, const char *pszSetting)
+{
+ DWORD mask;
+ int i, iImage;
+
+ for(i=0, mask=0; i < IGNOREEVENT_MAX; i++) {
+ iImage = SendMessage(hwndList, CLM_GETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(i, 0));
+ if(iImage && iImage != 0xFF)
+ mask |= 1<<i;
+ }
+ DBWriteContactSettingDword(hContact, KEYBDMODULE, pszSetting, mask);
+}
+
+static void SetAllContactIcons(HWND hwndList)
+{
+ HANDLE hContact,hItem;
+ DWORD protoCaps;
+ char *szProto;
+
+ hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ do {
+ hItem = (HANDLE)SendMessage(hwndList, CLM_FINDCONTACT, (WPARAM)hContact, 0);
+ if(hItem && SendMessage(hwndList, CLM_GETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(IGNOREEVENT_MAX, 0)) == 0xFF) {
+ szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ if(szProto == NULL)
+ protoCaps = 0;
+ else
+ protoCaps = CallProtoService(szProto, PS_GETCAPS,PFLAGNUM_1, 0);
+ InitialiseItem(hwndList, hContact, hItem, protoCaps);
+ }
+ } while(hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0));
+}
+
+INT_PTR CALLBACK DlgProcIgnoreOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ static HICON hIcons[IGNOREEVENT_MAX+2];
+ static HANDLE hItemAll, hItemUnknown;
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ { int i;
+ HIMAGELIST hIml;
+ hIml=ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ((bWindowsNT && dWinVer >= 5.01)?ILC_COLOR32:ILC_COLOR16)|ILC_MASK, 3+IGNOREEVENT_MAX, 3+IGNOREEVENT_MAX);
+ ImageList_AddIcon(hIml, LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_SMALLDOT)));
+ ImageList_AddIcon(hIml, LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_FILLEDBLOB)));
+ ImageList_AddIcon(hIml, LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_EMPTYBLOB)));
+ ImageList_AddIcon(hIml, LoadSkinnedIcon(SKINICON_EVENT_MESSAGE));
+ ImageList_AddIcon(hIml, LoadSkinnedIcon(SKINICON_EVENT_URL));
+ ImageList_AddIcon(hIml, LoadSkinnedIcon(SKINICON_EVENT_FILE));
+ ImageList_AddIcon(hIml, LoadSkinnedIcon(SKINICON_OTHER_MIRANDA));
+ SendDlgItemMessage(hwndDlg, IDC_LIST, CLM_SETEXTRAIMAGELIST, 0, (LPARAM)hIml);
+ for(i=0; i < SIZEOF(hIcons); i++)
+ hIcons[i] = ImageList_GetIcon(hIml, 1+i, ILD_NORMAL);
+ }
+ SendDlgItemMessage(hwndDlg, IDC_ALLICON, STM_SETICON, (WPARAM)hIcons[0], 0);
+ SendDlgItemMessage(hwndDlg, IDC_NONEICON, STM_SETICON, (WPARAM)hIcons[1], 0);
+ SendDlgItemMessage(hwndDlg, IDC_MSGICON, STM_SETICON, (WPARAM)hIcons[2], 0);
+ SendDlgItemMessage(hwndDlg, IDC_URLICON, STM_SETICON, (WPARAM)hIcons[3], 0);
+ SendDlgItemMessage(hwndDlg, IDC_FILEICON, STM_SETICON, (WPARAM)hIcons[4], 0);
+ SendDlgItemMessage(hwndDlg, IDC_OTHERICON, STM_SETICON, (WPARAM)hIcons[5], 0);
+
+ SetWindowLong(GetDlgItem(hwndDlg, IDC_LIST), GWL_STYLE, GetWindowLong(GetDlgItem(hwndDlg, IDC_LIST), GWL_STYLE) &~ (CLS_CHECKBOXES|CLS_GROUPCHECKBOXES));
+ SendDlgItemMessage(hwndDlg, IDC_LIST, CLM_AUTOREBUILD, 0, 0);
+
+ ResetListOptions(GetDlgItem(hwndDlg, IDC_LIST));
+ SendDlgItemMessage(hwndDlg, IDC_LIST, CLM_SETEXTRACOLUMNS, IGNOREEVENT_MAX+2, 0);
+
+ { CLCINFOITEM cii = {0};
+ cii.cbSize = sizeof(cii);
+ cii.flags = CLCIIF_GROUPFONT;
+ cii.pszText = Translate("** All contacts **");
+ hItemAll=(HANDLE)SendDlgItemMessage(hwndDlg, IDC_LIST, CLM_ADDINFOITEM, 0, (LPARAM)&cii);
+
+ cii.pszText = Translate("** Unknown contacts **");
+ hItemUnknown=(HANDLE)SendDlgItemMessage(hwndDlg, IDC_LIST,CLM_ADDINFOITEM, 0, (LPARAM)&cii);
+ InitialiseItem(GetDlgItem(hwndDlg, IDC_LIST), NULL, hItemUnknown, 0xFFFFFFFF);
+ }
+
+ SetAllContactIcons(GetDlgItem(hwndDlg, IDC_LIST));
+ SetListGroupIcons(GetDlgItem(hwndDlg, IDC_LIST),(HANDLE)SendDlgItemMessage(hwndDlg, IDC_LIST, CLM_GETNEXTITEM, CLGN_ROOT, 0), hItemAll, NULL);
+ return TRUE;
+ case WM_SETFOCUS:
+ SetFocus(GetDlgItem(hwndDlg, IDC_LIST));
+ break;
+ case WM_NOTIFY:
+ switch(((LPNMHDR)lParam)->idFrom) {
+ case IDC_LIST:
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case CLN_NEWCONTACT:
+ case CLN_LISTREBUILT:
+ SetAllContactIcons(GetDlgItem(hwndDlg, IDC_LIST));
+ //fall through
+ case CLN_CONTACTMOVED:
+ SetListGroupIcons(GetDlgItem(hwndDlg, IDC_LIST), (HANDLE)SendDlgItemMessage(hwndDlg, IDC_LIST, CLM_GETNEXTITEM, CLGN_ROOT, 0), hItemAll, NULL);
+ break;
+ case CLN_OPTIONSCHANGED:
+ ResetListOptions(GetDlgItem(hwndDlg, IDC_LIST));
+ break;
+ case CLN_CHECKCHANGED:
+ SendMessage(GetParent(GetParent(hwndDlg)), PSM_CHANGED, 0, 0);
+ break;
+ case NM_CLICK:
+ { int iImage;
+ HANDLE hItem;
+ DWORD hitFlags;
+ NMCLISTCONTROL *nm = (NMCLISTCONTROL*)lParam;
+
+ if(nm->iColumn == -1)
+ break;
+ hItem = (HANDLE)SendDlgItemMessage(hwndDlg, IDC_LIST, CLM_HITTEST, (WPARAM)&hitFlags, MAKELPARAM(nm->pt.x, nm->pt.y));
+ if(hItem == NULL)
+ break;
+ if(!(hitFlags & CLCHT_ONITEMEXTRA))
+ break;
+ if(nm->iColumn == IGNOREEVENT_MAX) { //ignore all
+ for(iImage=0; iImage < IGNOREEVENT_MAX; iImage++)
+ SetIconsForColumn(GetDlgItem(hwndDlg, IDC_LIST), hItem, hItemAll, iImage, iImage+3);
+ }
+ else if(nm->iColumn == IGNOREEVENT_MAX+1) { //ignore none
+ for(iImage=0; iImage < IGNOREEVENT_MAX; iImage++)
+ SetIconsForColumn(GetDlgItem(hwndDlg, IDC_LIST), hItem, hItemAll, iImage, 0);
+ }
+ else {
+ iImage = SendDlgItemMessage(hwndDlg, IDC_LIST, CLM_GETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(nm->iColumn, 0));
+ if(iImage == 0)
+ iImage = nm->iColumn + 3;
+ else if(iImage != 0xFF)
+ iImage = 0;
+ SetIconsForColumn(GetDlgItem(hwndDlg, IDC_LIST), hItem, hItemAll, nm->iColumn, iImage);
+ }
+ SetListGroupIcons(GetDlgItem(hwndDlg, IDC_LIST),(HANDLE)SendDlgItemMessage(hwndDlg, IDC_LIST, CLM_GETNEXTITEM, CLGN_ROOT, 0), hItemAll, NULL);
+ SendMessage(GetParent(GetParent(hwndDlg)), PSM_CHANGED, 0, 0);
+ break;
+ }
+ }
+ break;
+ case 0:
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ { HANDLE hContact, hItem;
+
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ do {
+ hItem = (HANDLE)SendDlgItemMessage(hwndDlg, IDC_LIST, CLM_FINDCONTACT, (WPARAM)hContact, 0);
+ if(hItem)
+ SaveItemMask(GetDlgItem(hwndDlg, IDC_LIST), hContact, hItem, "Mask1");
+ } while(hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0));
+ SaveItemMask(GetDlgItem(hwndDlg, IDC_LIST), NULL, hItemAll, "Default1");
+ SaveItemMask(GetDlgItem(hwndDlg, IDC_LIST), NULL, hItemUnknown, "Mask1");
+ return TRUE;
+ }
+ }
+ break;
+ }
+ break;
+ case WM_DESTROY:
+ { int i;
+ HIMAGELIST hIml;
+ for(i=0; i < SIZEOF(hIcons); i++)
+ DestroyIcon(hIcons[i]);
+ hIml = (HIMAGELIST)SendDlgItemMessage(hwndDlg, IDC_LIST, CLM_GETEXTRAIMAGELIST, 0, 0);
+ ImageList_Destroy(hIml);
+ break;
+ }
+ }
+ return FALSE;
+}
+
+BOOL IsIgnored(HANDLE hContact, WORD eventType)
+{
+ WORD ignoreID = 0;
+ DWORD mask = GetMask(hContact);
+
+ switch(eventType) {
+ case EVENTTYPE_MESSAGE:
+ ignoreID = 0;
+ break;
+ case EVENTTYPE_URL:
+ ignoreID = 1;
+ break;
+ case EVENTTYPE_FILE:
+ ignoreID = 2;
+ break;
+ default:
+ ignoreID = 3;
+ }
+
+ return (mask>>ignoreID)&1;
+}
diff --git a/plugins/KeyboardNotify/ignore.h b/plugins/KeyboardNotify/ignore.h new file mode 100644 index 0000000000..a72df7b6f6 --- /dev/null +++ b/plugins/KeyboardNotify/ignore.h @@ -0,0 +1,20 @@ +/*
+
+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.
+
+*/
+
+BOOL IsIgnored(HANDLE, WORD);
+INT_PTR CALLBACK DlgProcIgnoreOptions(HWND, UINT, WPARAM, LPARAM);
diff --git a/plugins/KeyboardNotify/keyboard.c b/plugins/KeyboardNotify/keyboard.c new file mode 100644 index 0000000000..5e7c261c26 --- /dev/null +++ b/plugins/KeyboardNotify/keyboard.c @@ -0,0 +1,118 @@ +/*
+
+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.
+
+*/
+
+#define WIN32_LEAN_AND_MEAN
+
+#include <stdio.h>
+#include <windows.h>
+#include <winioctl.h>
+#include "keypresses.h"
+#include <newpluginapi.h>
+#include <m_utils.h>
+
+
+// Globals
+extern BOOL bWindowsNT;
+extern BOOL bEmulateKeypresses;
+HANDLE hKbdDev[10] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE};
+
+// Defines
+#define MAX_KBDHANDLES 10
+#define IOCTL_KEYBOARD_SET_INDICATORS CTL_CODE(FILE_DEVICE_KEYBOARD, 0x0002, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_KEYBOARD_QUERY_TYPEMATIC CTL_CODE(FILE_DEVICE_KEYBOARD, 0x0008, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_KEYBOARD_QUERY_INDICATORS CTL_CODE(FILE_DEVICE_KEYBOARD, 0x0010, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+typedef struct _KEYBOARD_INDICATOR_PARAMETERS {
+ USHORT UnitId; // Unit identifier.
+ USHORT LedFlags; // LED indicator state.
+
+} KEYBOARD_INDICATOR_PARAMETERS, *PKEYBOARD_INDICATOR_PARAMETERS;
+
+
+void outportb(UINT portid, BYTE value)
+{
+ __asm mov edx,portid
+ __asm mov al,value
+ __asm out dx,al
+}
+
+
+BOOL OpenKeyboardDevice()
+{
+ int i = 0;
+ char aux1[MAX_PATH+1], aux2[MAX_PATH+1];
+
+ if (!bWindowsNT)
+ return TRUE;
+
+ do {
+ mir_snprintf(aux1, sizeof(aux1), "Kbd%d", i);
+ mir_snprintf(aux2, sizeof(aux2), "\\Device\\KeyboardClass%d", i);
+ DefineDosDevice(DDD_RAW_TARGET_PATH, aux1, aux2);
+
+ mir_snprintf(aux1, sizeof(aux1), "\\\\.\\Kbd%d", i);
+ hKbdDev[i] = CreateFile(aux1, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
+
+ } while (hKbdDev[i] != INVALID_HANDLE_VALUE && ++i < MAX_KBDHANDLES);
+
+ return hKbdDev[0] != INVALID_HANDLE_VALUE;
+}
+
+BOOL ToggleKeyboardLights(BYTE byte)
+{
+ int i; BOOL result = FALSE;
+ KEYBOARD_INDICATOR_PARAMETERS InputBuffer; // Input buffer for DeviceIoControl
+ ULONG DataLength = sizeof(KEYBOARD_INDICATOR_PARAMETERS);
+ ULONG ReturnedLength; // Number of bytes returned in output buffer
+
+ if (bEmulateKeypresses)
+ return keypresses_ToggleKeyboardLights(byte);
+
+ if (!bWindowsNT) {
+ outportb(0x60, 0xED);
+ Sleep(10);
+ outportb(0x60, byte);
+ return TRUE;
+ }
+
+ InputBuffer.UnitId = 0;
+ InputBuffer.LedFlags = byte;
+
+ for (i=0; i < MAX_KBDHANDLES && hKbdDev[i] != INVALID_HANDLE_VALUE; i++)
+ result |= DeviceIoControl(hKbdDev[i], IOCTL_KEYBOARD_SET_INDICATORS, &InputBuffer, DataLength, NULL, 0, &ReturnedLength, NULL);
+
+ return result;
+}
+
+void CloseKeyboardDevice()
+{
+ int i = 0;
+ char aux[MAX_PATH+1];
+
+ if (!bWindowsNT)
+ return;
+
+ do {
+ if (hKbdDev[i] != INVALID_HANDLE_VALUE)
+ CloseHandle(hKbdDev[i]);
+
+ mir_snprintf(aux, sizeof(aux), "Kbd%d", i);
+ DefineDosDevice(DDD_REMOVE_DEFINITION, aux, NULL);
+
+ } while (hKbdDev[i] != INVALID_HANDLE_VALUE && ++i < MAX_KBDHANDLES);
+}
diff --git a/plugins/KeyboardNotify/keyboard.h b/plugins/KeyboardNotify/keyboard.h new file mode 100644 index 0000000000..8fe6b52fe9 --- /dev/null +++ b/plugins/KeyboardNotify/keyboard.h @@ -0,0 +1,21 @@ +/*
+
+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.
+
+*/
+
+BOOL OpenKeyboardDevice(void);
+BOOL ToggleKeyboardLights(BYTE);
+void CloseKeyboardDevice(void);
diff --git a/plugins/KeyboardNotify/keypresses.c b/plugins/KeyboardNotify/keypresses.c new file mode 100644 index 0000000000..6d1cef58e6 --- /dev/null +++ b/plugins/KeyboardNotify/keypresses.c @@ -0,0 +1,77 @@ +/*
+
+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.
+
+*/
+
+#define WIN32_LEAN_AND_MEAN
+#define _WIN32_WINNT 0x0500
+
+#include <windows.h>
+#include "flash.h"
+#include "keypresses.h"
+
+
+// Prototypes
+void SetLock(WORD, BYTE, unsigned int *, INPUT *);
+
+// Globals
+BOOL LEDstateSaved = FALSE;
+BYTE LEDstate;
+
+
+void keypresses_RestoreLEDState(void)
+{
+ if (LEDstateSaved)
+ keypresses_ToggleKeyboardLights(LEDstate);
+ LEDstateSaved = FALSE;
+}
+
+BOOL keypresses_ToggleKeyboardLights(BYTE byte)
+{
+ unsigned int n = 0;
+ INPUT keystrokes[6] = {0};
+
+ if (!LEDstateSaved) {
+ LEDstate = (BYTE)(LedState(VK_SCROLL) + (LedState(VK_NUMLOCK)<<1) + (LedState(VK_CAPITAL)<<2));
+ LEDstateSaved = TRUE;
+ }
+
+ SetLock(VK_NUMLOCK, (BYTE)(byte&2), &n, keystrokes);
+ SetLock(VK_CAPITAL, (BYTE)(byte&4), &n, keystrokes);
+ SetLock(VK_SCROLL, (BYTE)(byte&1), &n, keystrokes);
+ SendInput(n, keystrokes, sizeof(INPUT));
+
+ return TRUE;
+}
+
+void SetLock(WORD keyCode, BYTE value, unsigned int *n, INPUT *keystrokes)
+{
+ BYTE status;
+
+ GetAsyncKeyState(keyCode);
+ status = GetKeyState(keyCode) & 1;
+
+ if ((!value && status) || (value && !status)) {
+ keystrokes[*n].type = INPUT_KEYBOARD;
+ keystrokes[*n].ki.wVk = keyCode;
+ keystrokes[*n].ki.wScan = 0x45;
+ keystrokes[(*n)++].ki.dwFlags = KEYEVENTF_EXTENDEDKEY | 0;
+ keystrokes[*n].type = INPUT_KEYBOARD;
+ keystrokes[*n].ki.wVk = keyCode;
+ keystrokes[*n].ki.wScan = 0x45;
+ keystrokes[(*n)++].ki.dwFlags = KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP;
+ }
+}
diff --git a/plugins/KeyboardNotify/keypresses.h b/plugins/KeyboardNotify/keypresses.h new file mode 100644 index 0000000000..57e99aa25c --- /dev/null +++ b/plugins/KeyboardNotify/keypresses.h @@ -0,0 +1,20 @@ +/*
+
+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.
+
+*/
+
+void keypresses_RestoreLEDState(void);
+BOOL keypresses_ToggleKeyboardLights(BYTE);
diff --git a/plugins/KeyboardNotify/main.c b/plugins/KeyboardNotify/main.c new file mode 100644 index 0000000000..5de2805280 --- /dev/null +++ b/plugins/KeyboardNotify/main.c @@ -0,0 +1,1489 @@ +/*
+ 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;
+int hLangpack;
+struct MM_INTERFACE mmi;
+
+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;
+ mir_getLP(&pluginInfo);
+ mir_getMMI(&mmi);
+
+ 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;
+}
diff --git a/plugins/KeyboardNotify/options.c b/plugins/KeyboardNotify/options.c new file mode 100644 index 0000000000..57ea559a99 --- /dev/null +++ b/plugins/KeyboardNotify/options.c @@ -0,0 +1,1569 @@ +/* + +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. + +*/ + +#define WIN32_LEAN_AND_MEAN
+ +#include <stdio.h> +#include <stdlib.h> +#include <windows.h> +#include <commctrl.h> +#include <commdlg.h> +#include "flash.h" +#include "ignore.h" +#include "resource.h" +#include "constants.h" +#include "protolist.h" +#include "EnumProc.h" +#include "utils.h"
+#include <newpluginapi.h> +#include <m_clc.h> +#include <m_clist.h> +#include <m_database.h> +#include <m_langpack.h> +#include <m_options.h> +#include <m_protosvc.h> +#include <m_protocols.h> +#include <m_icq.h>
+ +#define IDI_BLANK 200
+
+#ifndef ETDT_ENABLE +#define ETDT_ENABLE 0x00000002 +#endif +#ifndef ETDT_USETABTEXTURE +#define ETDT_USETABTEXTURE 0x00000004 +#endif +#ifndef ETDT_ENABLETAB +#define ETDT_ENABLETAB (ETDT_ENABLE|ETDT_USETABTEXTURE) +#endif + +#ifndef ListView_SetCheckState +#define ListView_SetCheckState(hLv, iItem, bCheck) \
+ ListView_SetItemState(hLv, iItem, bCheck ? INDEXTOSTATEIMAGEMASK(2) : INDEXTOSTATEIMAGEMASK(1), LVIS_STATEIMAGEMASK) +#endif
+
+#ifndef TVS_NOHSCROLL
+#define TVS_NOHSCROLL 0x8000
+#endif
+
+#ifndef TVM_GETITEMSTATE
+#define TVM_GETITEMSTATE (TV_FIRST+39)
+#endif
+
+#ifndef TreeView_SetItemState
+#define TreeView_SetItemState(hwndTv, hti, data, _mask) \
+ { TVITEM _TVI; \
+ _TVI.mask = TVIF_STATE; \
+ _TVI.hItem = hti; \
+ _TVI.stateMask = _mask; \
+ _TVI.state = data; \
+ SendMessageA((hwndTv), TVM_SETITEM, 0, (LPARAM)&_TVI); }
+#endif
+
+#ifndef TreeView_GetItemState
+#define TreeView_GetItemState(hwndTv, hti, mask) \
+ (UINT)SendMessageA((hwndTv), TVM_GETITEMSTATE, (WPARAM)(hti), (LPARAM)(mask))
+#endif + +void LoadSettings(void); +int InitializeOptions(WPARAM,LPARAM); +INT_PTR CALLBACK DlgProcOptions(HWND, UINT, WPARAM, LPARAM); +INT_PTR CALLBACK DlgProcProtoOptions(HWND, UINT, WPARAM, LPARAM); +INT_PTR CALLBACK DlgProcBasicOptions(HWND, UINT, WPARAM, LPARAM); +INT_PTR CALLBACK DlgProcEffectOptions(HWND, UINT, WPARAM, LPARAM); +INT_PTR CALLBACK DlgProcThemeOptions(HWND, UINT, WPARAM, LPARAM); +INT_PTR CALLBACK DlgProcProcesses(HWND, UINT, WPARAM, LPARAM); +INT_PTR CALLBACK DlgProcEventLeds(HWND, UINT, WPARAM, LPARAM);
+INT_PTR CALLBACK DlgProcXstatusList(HWND, UINT, WPARAM, LPARAM); +void exportThemes(const char *); +void importThemes(const char *, BOOL); +void writeThemeToCombo(const char *, const char *, BOOL); +void createProcessListAux(void); +void destroyProcessListAux(void); +void createXstatusListAux(void);
+void destroyXstatusListAux(void);
+ + +extern HINSTANCE hInst; +extern double dWinVer; +extern BOOL bWindowsNT; + +extern BYTE bFlashOnMsg; +extern BYTE bFlashOnURL; +extern BYTE bFlashOnFile; +extern BYTE bFlashOnOther; +extern BYTE bFullScreenMode; +extern BYTE bScreenSaverRunning; +extern BYTE bWorkstationLocked; +extern BYTE bProcessesAreRunning; +extern BYTE bWorkstationActive; +extern BYTE bFlashIfMsgOpen; +extern BYTE bFlashIfMsgOlder; +extern WORD wSecondsOlder; +extern BYTE bFlashUntil; +extern WORD wBlinksNumber; +extern BYTE bMirandaOrWindows; +extern WORD wStatusMap; +extern WORD wReminderCheck; +extern BYTE bFlashLed[3]; +extern BYTE bFlashEffect; +extern BYTE bSequenceOrder; +extern WORD wCustomTheme; +extern WORD wStartDelay; +extern BYTE bFlashSpeed; +extern BYTE bEmulateKeypresses; +extern BYTE bOverride; +extern BYTE bFlashIfMsgWinNotTop; +extern BYTE bTrillianLedsMsg; +extern BYTE bTrillianLedsURL; +extern BYTE bTrillianLedsFile; +extern BYTE bTrillianLedsOther; + +extern PROTOCOL_LIST ProtoList; +extern PROCESS_LIST ProcessList; + +HWND hwndProto, hwndBasic, hwndEffect, hwndTheme, hwndIgnore, hwndCurrentTab; + +char *AttendedName[]={"Miranda", "Windows"}; +char *OrderName[]={"left->right", "right->left", "left<->right"}; + +PROCESS_LIST ProcessListAux; +XSTATUS_INFO *XstatusListAux;
+BYTE trillianLedsMsg, trillianLedsURL, trillianLedsFile, trillianLedsOther; + +static BOOL (WINAPI *pfnEnableThemeDialogTexture)(HANDLE, DWORD) = 0; + + +// ** +// ** Initialize the Miranda options page +// ** +int InitializeOptions(WPARAM wParam,LPARAM lParam) +{ + + OPTIONSDIALOGPAGE odp; + HMODULE hUxTheme = NULL; + + if(bWindowsNT && dWinVer >= 5.01) { + hUxTheme = GetModuleHandle("uxtheme.dll"); + + if(hUxTheme) + pfnEnableThemeDialogTexture = (BOOL (WINAPI *)(HANDLE, DWORD))GetProcAddress(hUxTheme, "EnableThemeDialogTexture"); + } + + ZeroMemory(&odp,sizeof(odp)); + odp.cbSize = sizeof(odp); + odp.position = 0; + odp.hInstance = hInst; + odp.pszTemplate = MAKEINTRESOURCE(IDD_OPTIONS); + odp.pszTitle = Translate("Keyboard Flash"); + odp.pszGroup = Translate("Plugins"); + odp.groupPosition = 910000000; + odp.flags=ODPF_BOLDGROUPS; + odp.pfnDlgProc = DlgProcOptions; + odp.nIDBottomSimpleControl = 0; + CallService(MS_OPT_ADDPAGE,wParam, (LPARAM)&odp); + + return 0; +} + +INT_PTR CALLBACK DlgProcOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_INITDIALOG: + { + HWND tc; + TCITEM tci; + tc = GetDlgItem(hwndDlg, IDC_TABS); + tci.mask = TCIF_TEXT; + tci.pszText = Translate("Protocols"); + TabCtrl_InsertItem(tc, 0, &tci); + tci.pszText = Translate("Rules"); + TabCtrl_InsertItem(tc, 1, &tci); + tci.pszText = Translate("Flashing"); + TabCtrl_InsertItem(tc, 2, &tci); + tci.pszText = Translate("Themes"); + TabCtrl_InsertItem(tc, 3, &tci); + tci.pszText = Translate("Ignore"); + TabCtrl_InsertItem(tc, 4, &tci); + + hwndProto = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_PROTO_OPTIONS), hwndDlg, DlgProcProtoOptions, (LPARAM) NULL); + if(hwndProto && pfnEnableThemeDialogTexture) + pfnEnableThemeDialogTexture(hwndProto, ETDT_ENABLETAB); + SetWindowPos(hwndProto, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + ShowWindow(hwndProto, SW_SHOW); + hwndBasic = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_BASIC_OPTIONS), hwndDlg, DlgProcBasicOptions, (LPARAM) NULL); + if(hwndBasic && pfnEnableThemeDialogTexture) + pfnEnableThemeDialogTexture(hwndBasic, ETDT_ENABLETAB); + SetWindowPos(hwndBasic, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + hwndEffect = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_EFFECT_OPTIONS), hwndDlg, DlgProcEffectOptions, (LPARAM) NULL); + if(hwndEffect && pfnEnableThemeDialogTexture) + pfnEnableThemeDialogTexture(hwndEffect, ETDT_ENABLETAB); + SetWindowPos(hwndEffect, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + hwndTheme = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_THEME_OPTIONS), hwndDlg, DlgProcThemeOptions, (LPARAM) NULL); + if(hwndTheme && pfnEnableThemeDialogTexture) + pfnEnableThemeDialogTexture(hwndTheme, ETDT_ENABLETAB); + SetWindowPos(hwndTheme, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + hwndIgnore = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_IGNORE_OPTIONS), hwndDlg, DlgProcIgnoreOptions, (LPARAM) NULL); + if(hwndIgnore && pfnEnableThemeDialogTexture) + pfnEnableThemeDialogTexture(hwndIgnore, ETDT_ENABLETAB); + SetWindowPos(hwndIgnore, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + hwndCurrentTab = hwndProto; + return TRUE; + + } + case WM_COMMAND: + break; + case WM_NOTIFY: + { + switch (((LPNMHDR) lParam)->code) { + case TCN_SELCHANGE: + switch (wParam) { + case IDC_TABS: + { + HWND hwnd; + switch (TabCtrl_GetCurSel(GetDlgItem(hwndDlg, IDC_TABS))) { + default: + case 0: + hwnd = hwndProto; + break; + case 1: + hwnd = hwndBasic; + break; + case 2: + hwnd = hwndEffect; + break; + case 3: + hwnd = hwndTheme; + break; + case 4: + hwnd = hwndIgnore; + break; + } + if (hwnd!=hwndCurrentTab) { + ShowWindow(hwnd, SW_SHOW); + ShowWindow(hwndCurrentTab, SW_HIDE); + hwndCurrentTab = hwnd; + } + } + break; + } + break; + case PSN_APPLY: + SendMessage(hwndProto, WM_NOTIFY, wParam, lParam); + SendMessage(hwndBasic, WM_NOTIFY, wParam, lParam); + SendMessage(hwndEffect, WM_NOTIFY, wParam, lParam); + SendMessage(hwndTheme, WM_NOTIFY, wParam, lParam); + SendMessage(hwndIgnore, WM_NOTIFY, wParam, lParam); + return TRUE; + } + } + break; + case WM_DESTROY: + break; + } + return FALSE; +} + + +INT_PTR CALLBACK DlgProcProtoOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static BOOL initDlg=FALSE; + + switch (msg) { + + case WM_INITDIALOG: + initDlg=TRUE; + TranslateDialogDefault(hwndDlg); + + // proto list + { + unsigned int i; + LVCOLUMN lvCol; + LVITEM lvItem; + HWND hList = GetDlgItem(hwndDlg, IDC_PROTOCOLLIST); + + // create columns + ListView_SetExtendedListViewStyleEx(hList, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES); + memset(&lvCol, 0, sizeof(lvCol)); + lvCol.mask = LVCF_WIDTH|LVCF_TEXT; + lvCol.pszText = Translate("Protocol"); + lvCol.cx = 118; + ListView_InsertColumn(hList, 0, &lvCol); + // fill + memset(&lvItem, 0, sizeof(lvItem)); + lvItem.mask = LVIF_TEXT|LVIF_PARAM; + lvItem.cchTextMax = 256; + lvItem.iItem = 0; + lvItem.iSubItem = 0; + for(i=0; i < ProtoList.protoCount; i++) { + char protoName[MAX_PATH+1]; + + if(ProtoList.protoInfo[i].visible) { + lvItem.lParam = (LPARAM)ProtoList.protoInfo[i].szProto; + CallProtoService(ProtoList.protoInfo[i].szProto, PS_GETNAME, sizeof(protoName), (LPARAM)protoName); + lvItem.pszText = protoName; + ListView_InsertItem(hList, &lvItem); + ListView_SetCheckState(hList, lvItem.iItem, ProtoList.protoInfo[i].enabled); + lvItem.iItem++; + } + } + } + + initDlg=FALSE; + return TRUE; + + case WM_NOTIFY: + { + //Here we have pressed either the OK or the APPLY button. + switch(((LPNMHDR)lParam)->idFrom) { + case 0: + switch (((LPNMHDR)lParam)->code) { + 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++) { + lvItem.iItem = i; + ListView_GetItem(hList, &lvItem); + DBWriteContactSettingByte(NULL, KEYBDMODULE, (char *)lvItem.lParam, (BYTE)!!ListView_GetCheckState(hList, lvItem.iItem)); + } + } + + LoadSettings(); + + return TRUE; + } // switch code - 0 + break; + case IDC_PROTOCOLLIST: + switch(((NMHDR*)lParam)->code) { + case LVN_ITEMCHANGED: + { + NMLISTVIEW *nmlv = (NMLISTVIEW *)lParam; + + if (!initDlg && ((nmlv->uNewState ^ nmlv->uOldState) & LVIS_STATEIMAGEMASK)) + SendMessage(GetParent(GetParent(hwndDlg)), PSM_CHANGED, 0, 0); + } + break; + } // switch code - IDC_PROTOCOLLIST + break; + } //switch idFrom + } + break; //End WM_NOTIFY + + default: + break; + } + + return FALSE; +} + +INT_PTR CALLBACK DlgProcBasicOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + unsigned int i; + static BOOL initDlg=FALSE; + + switch (msg) { + + case WM_INITDIALOG: + initDlg=TRUE; + TranslateDialogDefault(hwndDlg); + + createProcessListAux(); + createXstatusListAux();
+ + CheckDlgButton(hwndDlg, IDC_ONMESSAGE, bFlashOnMsg ? BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_ONURL, bFlashOnURL ? BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_ONFILE, bFlashOnFile ? BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_ONOTHER, bFlashOnOther ? BST_CHECKED:BST_UNCHECKED); + + CheckDlgButton(hwndDlg, IDC_FSCREEN, bFullScreenMode ? BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SSAVER, bScreenSaverRunning ? BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_LOCKED, bWorkstationLocked ? BST_CHECKED:BST_UNCHECKED); + if (!bWindowsNT) + EnableWindow(GetDlgItem(hwndDlg, IDC_LOCKED), FALSE); + CheckDlgButton(hwndDlg, IDC_PGMS, bProcessesAreRunning ? BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_ACTIVE, bWorkstationActive ? BST_CHECKED:BST_UNCHECKED); + + CheckDlgButton(hwndDlg, IDC_IFOPEN, bFlashIfMsgOpen ? BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_IFNOTTOP, bFlashIfMsgWinNotTop ? BST_CHECKED:BST_UNCHECKED); + if (!bFlashIfMsgOpen) + EnableWindow(GetDlgItem(hwndDlg, IDC_IFNOTTOP), FALSE); + CheckDlgButton(hwndDlg, IDC_IFOLDER, bFlashIfMsgOlder ? BST_CHECKED:BST_UNCHECKED); + SendDlgItemMessage(hwndDlg, IDC_OLDERSPIN, UDM_SETBUDDY, (WPARAM)GetDlgItem(hwndDlg, IDC_SOLDER), 0); + SendDlgItemMessage(hwndDlg, IDC_OLDERSPIN, UDM_SETRANGE32, 1, MAKELONG(UD_MAXVAL, 0)); + SendDlgItemMessage(hwndDlg, IDC_OLDERSPIN, UDM_SETPOS, 0, MAKELONG(wSecondsOlder, 0)); + if (!bFlashIfMsgOlder) { + EnableWindow(GetDlgItem(hwndDlg, IDC_SOLDER), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_OLDERSPIN), FALSE); + } + + CheckDlgButton(hwndDlg, IDC_UNTILBLK, bFlashUntil&UNTIL_NBLINKS ? BST_CHECKED:BST_UNCHECKED); + SendDlgItemMessage(hwndDlg, IDC_BLINKSPIN, UDM_SETBUDDY, (WPARAM)GetDlgItem(hwndDlg, IDC_SBLINK), 0); + SendDlgItemMessage(hwndDlg, IDC_BLINKSPIN, UDM_SETRANGE32, 1, MAKELONG(UD_MAXVAL, 0)); + SendDlgItemMessage(hwndDlg, IDC_BLINKSPIN, UDM_SETPOS, 0, MAKELONG(wBlinksNumber, 0)); + if (!(bFlashUntil & UNTIL_NBLINKS)) { + EnableWindow(GetDlgItem(hwndDlg, IDC_SBLINK), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_BLINKSPIN), FALSE); + } + CheckDlgButton(hwndDlg, IDC_UNTILATTENDED, bFlashUntil&UNTIL_REATTENDED ? BST_CHECKED:BST_UNCHECKED); + for (i=0; i < 2; i++) { + int index = SendDlgItemMessage(hwndDlg, IDC_MIRORWIN, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)AttendedName[i]); + if (index != CB_ERR && index != CB_ERRSPACE) + SendDlgItemMessage(hwndDlg, IDC_MIRORWIN, CB_SETITEMDATA, (WPARAM)index, (LPARAM)i); + } + SendDlgItemMessage(hwndDlg, IDC_MIRORWIN, CB_SETCURSEL, (WPARAM)bMirandaOrWindows, 0); + if (!(bFlashUntil & UNTIL_REATTENDED)) + EnableWindow(GetDlgItem(hwndDlg, IDC_MIRORWIN), FALSE); + CheckDlgButton(hwndDlg, IDC_UNTILOPEN, bFlashUntil&UNTIL_EVENTSOPEN ? BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_UNTILCOND, bFlashUntil&UNTIL_CONDITIONS ? BST_CHECKED:BST_UNCHECKED); + + CheckDlgButton(hwndDlg, IDC_ONLINE, wStatusMap&MAP_ONLINE ? BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_AWAY, wStatusMap&MAP_AWAY ? BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_NA, wStatusMap&MAP_NA ? BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_OCCUPIED, wStatusMap&MAP_OCCUPIED ? BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_DND, wStatusMap&MAP_DND ? BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_FREECHAT, wStatusMap&MAP_FREECHAT ? BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_INVISIBLE, wStatusMap&MAP_INVISIBLE ? BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_ONTHEPHONE, wStatusMap&MAP_ONTHEPHONE ? BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_OUTTOLUNCH, wStatusMap&MAP_OUTTOLUNCH ? BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_OFFLINE, wStatusMap&MAP_OFFLINE ? BST_CHECKED:BST_UNCHECKED); + + SendDlgItemMessage(hwndDlg, IDC_REMCHECK, UDM_SETBUDDY, (WPARAM)GetDlgItem(hwndDlg, IDC_SREMCHECK), 0); + SendDlgItemMessage(hwndDlg, IDC_REMCHECK, UDM_SETRANGE32, 0, MAKELONG(UD_MAXVAL, 0)); + SendDlgItemMessage(hwndDlg, IDC_REMCHECK, UDM_SETPOS, 0, MAKELONG(wReminderCheck, 0)); + + initDlg=FALSE; + return TRUE; + + case WM_VSCROLL: + case WM_HSCROLL: + SendMessage(GetParent(GetParent(hwndDlg)), PSM_CHANGED, 0, 0); + break; + + case WM_DESTROY: + destroyProcessListAux(); + destroyXstatusListAux();
+ break; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_ONMESSAGE: + case IDC_ONURL: + case IDC_ONFILE: + case IDC_ONOTHER: + case IDC_IFOPEN: + case IDC_IFNOTTOP: + case IDC_IFOLDER: + case IDC_UNTILBLK: + case IDC_UNTILATTENDED: + case IDC_MIRORWIN: + case IDC_UNTILOPEN: + case IDC_UNTILCOND: + case IDC_FSCREEN: + case IDC_SSAVER: + case IDC_LOCKED: + case IDC_PGMS: + case IDC_ACTIVE: + case IDC_ONLINE: + case IDC_AWAY: + case IDC_NA: + case IDC_OCCUPIED: + case IDC_DND: + case IDC_FREECHAT: + case IDC_INVISIBLE: + case IDC_ONTHEPHONE: + case IDC_OUTTOLUNCH: + case IDC_OFFLINE: + EnableWindow(GetDlgItem(hwndDlg, IDC_IFNOTTOP), IsDlgButtonChecked(hwndDlg, IDC_IFOPEN) == BST_CHECKED); + EnableWindow(GetDlgItem(hwndDlg, IDC_SOLDER), IsDlgButtonChecked(hwndDlg, IDC_IFOLDER) == BST_CHECKED); + EnableWindow(GetDlgItem(hwndDlg, IDC_OLDERSPIN), IsDlgButtonChecked(hwndDlg, IDC_IFOLDER) == BST_CHECKED); + EnableWindow(GetDlgItem(hwndDlg, IDC_SBLINK), IsDlgButtonChecked(hwndDlg, IDC_UNTILBLK) == BST_CHECKED); + EnableWindow(GetDlgItem(hwndDlg, IDC_BLINKSPIN), IsDlgButtonChecked(hwndDlg, IDC_UNTILBLK) == BST_CHECKED); + EnableWindow(GetDlgItem(hwndDlg, IDC_MIRORWIN), IsDlgButtonChecked(hwndDlg, IDC_UNTILATTENDED) == BST_CHECKED); + SendMessage(GetParent(GetParent(hwndDlg)), PSM_CHANGED, 0, 0); + return TRUE; + case IDC_SOLDER: + if(HIWORD(wParam) == EN_CHANGE && !initDlg) { + BOOL translated; + int val = GetDlgItemInt(hwndDlg, IDC_SOLDER, &translated, FALSE); + if (translated && val < 1) + SendDlgItemMessage(hwndDlg, IDC_OLDERSPIN, UDM_SETPOS, 0, MAKELONG(val, 0)); + SendMessage(GetParent(GetParent(hwndDlg)), PSM_CHANGED, 0, 0); + } + return TRUE; + case IDC_SBLINK: + if(HIWORD(wParam) == EN_CHANGE && !initDlg) { + BOOL translated; + int val = GetDlgItemInt(hwndDlg, IDC_SBLINK, &translated, FALSE); + if (translated && val < 1) + SendDlgItemMessage(hwndDlg, IDC_BLINKSPIN, UDM_SETPOS, 0, MAKELONG(val, 0)); + SendMessage(GetParent(GetParent(hwndDlg)), PSM_CHANGED, 0, 0); + } + return TRUE; + case IDC_ASSIGNPGMS: + if (DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_PROCESSES), hwndDlg, DlgProcProcesses, 0) == IDC_OKPGM) + SendMessage(GetParent(GetParent(hwndDlg)), PSM_CHANGED, 0, 0); + return TRUE; + case IDC_SELECTXSTATUS:
+ if (DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_XSTATUSES), hwndDlg, DlgProcXstatusList, 0) == IDC_OKXST)
+ SendMessage(GetParent(GetParent(hwndDlg)), PSM_CHANGED, 0, 0);
+ return TRUE;
+ case IDC_SREMCHECK: + if(HIWORD(wParam) == EN_CHANGE && !initDlg) + SendMessage(GetParent(GetParent(hwndDlg)), PSM_CHANGED, 0, 0); + return TRUE; + } + break; + + case WM_NOTIFY: + { + unsigned int j; + BYTE untilMap = 0; + WORD statusMap = 0; + //Here we have pressed either the OK or the APPLY button. + switch(((LPNMHDR)lParam)->idFrom) { + case 0: + switch (((LPNMHDR)lParam)->code) { + case PSN_APPLY: + DBWriteContactSettingByte(NULL, KEYBDMODULE, "onmsg", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_ONMESSAGE) == BST_CHECKED ? 1:0)); + DBWriteContactSettingByte(NULL, KEYBDMODULE, "onurl", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_ONURL) == BST_CHECKED ? 1:0)); + DBWriteContactSettingByte(NULL, KEYBDMODULE, "onfile", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_ONFILE) == BST_CHECKED ? 1:0)); + DBWriteContactSettingByte(NULL, KEYBDMODULE, "onother", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_ONOTHER) == BST_CHECKED ? 1:0)); + + DBWriteContactSettingByte(NULL, KEYBDMODULE, "fscreenmode", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_FSCREEN) == BST_CHECKED ? 1:0)); + DBWriteContactSettingByte(NULL, KEYBDMODULE, "ssaverrunning", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_SSAVER) == BST_CHECKED ? 1:0)); + DBWriteContactSettingByte(NULL, KEYBDMODULE, "wstationlocked", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_LOCKED) == BST_CHECKED ? 1:0)); + DBWriteContactSettingByte(NULL, KEYBDMODULE, "procsrunning", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_PGMS) == BST_CHECKED ? 1:0)); + DBWriteContactSettingByte(NULL, KEYBDMODULE, "wstationactive", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_ACTIVE) == BST_CHECKED ? 1:0)); + + DBWriteContactSettingByte(NULL, KEYBDMODULE, "ifmsgopen", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_IFOPEN) == BST_CHECKED ? 1:0)); + DBWriteContactSettingByte(NULL, KEYBDMODULE, "ifmsgnottop", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_IFNOTTOP) == BST_CHECKED ? 1:0)); + DBWriteContactSettingByte(NULL, KEYBDMODULE, "ifmsgolder", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_IFOLDER) == BST_CHECKED ? 1:0)); + DBWriteContactSettingWord(NULL, KEYBDMODULE, "secsolder", (WORD)SendDlgItemMessage(hwndDlg, IDC_OLDERSPIN, UDM_GETPOS, 0, 0)); + + if(IsDlgButtonChecked(hwndDlg, IDC_UNTILBLK) == BST_CHECKED) + untilMap |= UNTIL_NBLINKS; + if (IsDlgButtonChecked(hwndDlg, IDC_UNTILATTENDED) == BST_CHECKED) + untilMap |= UNTIL_REATTENDED; + if (IsDlgButtonChecked(hwndDlg, IDC_UNTILOPEN) == BST_CHECKED) + untilMap |= UNTIL_EVENTSOPEN; + if (IsDlgButtonChecked(hwndDlg, IDC_UNTILCOND) == BST_CHECKED) + untilMap |= UNTIL_CONDITIONS; + DBWriteContactSettingByte(NULL, KEYBDMODULE, "funtil", untilMap); + DBWriteContactSettingWord(NULL, KEYBDMODULE, "nblinks", (WORD)SendDlgItemMessage(hwndDlg, IDC_BLINKSPIN, UDM_GETPOS, 0, 0)); + DBWriteContactSettingByte(NULL, KEYBDMODULE, "mirorwin", (BYTE)SendDlgItemMessage(hwndDlg, IDC_MIRORWIN, CB_GETITEMDATA, (WPARAM)SendDlgItemMessage(hwndDlg, IDC_MIRORWIN, CB_GETCURSEL, 0, 0), 0)); + + if(IsDlgButtonChecked(hwndDlg, IDC_ONLINE) == BST_CHECKED) + statusMap |= MAP_ONLINE; + if(IsDlgButtonChecked(hwndDlg, IDC_AWAY) == BST_CHECKED) + statusMap |= MAP_AWAY; + if(IsDlgButtonChecked(hwndDlg, IDC_NA) == BST_CHECKED) + statusMap |= MAP_NA; + if(IsDlgButtonChecked(hwndDlg, IDC_OCCUPIED) == BST_CHECKED) + statusMap |= MAP_OCCUPIED; + if(IsDlgButtonChecked(hwndDlg, IDC_DND) == BST_CHECKED) + statusMap |= MAP_DND; + if(IsDlgButtonChecked(hwndDlg, IDC_FREECHAT) == BST_CHECKED) + statusMap |= MAP_FREECHAT; + if(IsDlgButtonChecked(hwndDlg, IDC_INVISIBLE) == BST_CHECKED) + statusMap |= MAP_INVISIBLE; + if(IsDlgButtonChecked(hwndDlg, IDC_ONTHEPHONE) == BST_CHECKED) + statusMap |= MAP_ONTHEPHONE; + if(IsDlgButtonChecked(hwndDlg, IDC_OUTTOLUNCH) == BST_CHECKED) + statusMap |= MAP_OUTTOLUNCH; + if(IsDlgButtonChecked(hwndDlg, IDC_OFFLINE) == BST_CHECKED) + statusMap |= MAP_OFFLINE; + DBWriteContactSettingWord(NULL, KEYBDMODULE, "status", statusMap); + + DBWriteContactSettingWord(NULL, KEYBDMODULE, "remcheck", (WORD)SendDlgItemMessage(hwndDlg, IDC_REMCHECK, UDM_GETPOS, 0, 0)); + + for (i=0, j=0; j < ProcessListAux.count; j++) + if (ProcessListAux.szFileName[j]) + DBWriteContactSettingString(NULL, KEYBDMODULE, fmtDBSettingName("process%d", i++), ProcessListAux.szFileName[j]); + DBWriteContactSettingWord(NULL, KEYBDMODULE, "processcount", (WORD)i); + while (!DBDeleteContactSetting(NULL, KEYBDMODULE, fmtDBSettingName("process%d", i++))); + + if (XstatusListAux)
+ for (i=0; i < ProtoList.protoCount; i++)
+ for(j=0; j < XstatusListAux[i].count; j++)
+ DBWriteContactSettingByte(NULL, KEYBDMODULE, fmtDBSettingName("%sxstatus%d", ProtoList.protoInfo[i].szProto, j), (BYTE)XstatusListAux[i].enabled[j]);
+
+ LoadSettings(); + + return TRUE; + } // switch code + break; + } //switch idFrom + } + break; //End WM_NOTIFY + + default: + break; + } + + return FALSE; +} + +INT_PTR CALLBACK DlgProcEffectOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + int i; + DBVARIANT dbv; + static BOOL initDlg=FALSE; + + switch (msg) { + + case WM_INITDIALOG: + initDlg=TRUE; + TranslateDialogDefault(hwndDlg); + + trillianLedsMsg = bTrillianLedsMsg; + trillianLedsURL = bTrillianLedsURL; + trillianLedsFile = bTrillianLedsFile; + trillianLedsOther = bTrillianLedsOther; + + CheckDlgButton(hwndDlg, IDC_NUM, bFlashLed[0] ? BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_CAPS, bFlashLed[1] ? BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SCROLL, bFlashLed[2] ? BST_CHECKED:BST_UNCHECKED); + + CheckDlgButton(hwndDlg, IDC_SAMETIME, bFlashEffect == FLASH_SAMETIME ? BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_INTURN, bFlashEffect == FLASH_INTURN ? BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_INSEQUENCE, bFlashEffect == FLASH_INSEQUENCE ? BST_CHECKED:BST_UNCHECKED); + for (i=0; i < 3; i++) { + int index = SendDlgItemMessage(hwndDlg, IDC_SEQORDER, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)Translate(OrderName[i])); + if (index != CB_ERR && index != CB_ERRSPACE) + SendDlgItemMessage(hwndDlg, IDC_SEQORDER, CB_SETITEMDATA, (WPARAM)index, (LPARAM)i); + } + SendDlgItemMessage(hwndDlg, IDC_SEQORDER, CB_SETCURSEL, (WPARAM)bSequenceOrder, 0); + if (bFlashEffect != FLASH_INSEQUENCE) + EnableWindow(GetDlgItem(hwndDlg, IDC_SEQORDER), FALSE); + CheckDlgButton(hwndDlg, IDC_CUSTOM, bFlashEffect == FLASH_CUSTOM ? BST_CHECKED:BST_UNCHECKED); + for (i=0; !DBGetContactSetting(NULL, KEYBDMODULE, fmtDBSettingName("theme%d", i), &dbv); i++) { + int index = SendDlgItemMessage(hwndDlg, IDC_SCUSTOM, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)dbv.pszVal); + DBFreeVariant(&dbv); + if (index != CB_ERR && index != CB_ERRSPACE) + SendDlgItemMessage(hwndDlg, IDC_SCUSTOM, CB_SETITEMDATA, (WPARAM)index, (LPARAM)i); + } + SendDlgItemMessage(hwndDlg, IDC_SCUSTOM, CB_SETCURSEL, (WPARAM)wCustomTheme, 0); + if (bFlashEffect != FLASH_CUSTOM) + EnableWindow(GetDlgItem(hwndDlg, IDC_SCUSTOM), FALSE); + CheckDlgButton(hwndDlg, IDC_TRILLIAN, bFlashEffect == FLASH_TRILLIAN ? BST_CHECKED:BST_UNCHECKED); + if (bFlashEffect != FLASH_TRILLIAN) + EnableWindow(GetDlgItem(hwndDlg, IDC_ASSIGNLEDS), FALSE); + + SendDlgItemMessage(hwndDlg, IDC_DELAYSPIN, UDM_SETBUDDY, (WPARAM)GetDlgItem(hwndDlg, IDC_SDELAY), 0); + SendDlgItemMessage(hwndDlg, IDC_DELAYSPIN, UDM_SETRANGE32, 0, MAKELONG(UD_MAXVAL, 0)); + SendDlgItemMessage(hwndDlg, IDC_DELAYSPIN, UDM_SETPOS, 0, MAKELONG(wStartDelay, 0)); + + SendDlgItemMessage(hwndDlg, IDC_SPEED, TBM_SETRANGE, FALSE, MAKELONG(0, 5)); + SendDlgItemMessage(hwndDlg, IDC_SPEED, TBM_SETPOS, TRUE, bFlashSpeed); + + CheckDlgButton(hwndDlg, IDC_KEYPRESSES, bEmulateKeypresses ? BST_CHECKED:BST_UNCHECKED); + + initDlg=FALSE; + return TRUE; + + case WM_VSCROLL: + case WM_HSCROLL: + SendMessage(GetParent(GetParent(hwndDlg)), PSM_CHANGED, 0, 0); + break; + + case WM_DESTROY: + previewFlashing(FALSE); + break; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_NUM: + case IDC_CAPS: + case IDC_SCROLL: + case IDC_SAMETIME: + case IDC_INTURN: + case IDC_INSEQUENCE: + case IDC_SEQORDER: + case IDC_CUSTOM: + case IDC_TRILLIAN: + case IDC_SCUSTOM: + case IDC_SPEED: + case IDC_KEYPRESSES: + EnableWindow(GetDlgItem(hwndDlg, IDC_SEQORDER), IsDlgButtonChecked(hwndDlg, IDC_INSEQUENCE) == BST_CHECKED); + EnableWindow(GetDlgItem(hwndDlg, IDC_SCUSTOM), IsDlgButtonChecked(hwndDlg, IDC_CUSTOM) == BST_CHECKED); + EnableWindow(GetDlgItem(hwndDlg, IDC_ASSIGNLEDS), IsDlgButtonChecked(hwndDlg, IDC_TRILLIAN) == BST_CHECKED); + SendMessage(GetParent(GetParent(hwndDlg)), PSM_CHANGED, 0, 0); + return TRUE; + case IDC_ASSIGNLEDS: + if (DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_EVENTLEDS), hwndDlg, DlgProcEventLeds, 0) == IDC_OK) + SendMessage(GetParent(GetParent(hwndDlg)), PSM_CHANGED, 0, 0); + return TRUE; + case IDC_SDELAY: + if(HIWORD(wParam) == EN_CHANGE && !initDlg) + SendMessage(GetParent(GetParent(hwndDlg)), PSM_CHANGED, 0, 0); + return TRUE; + case IDC_PREVIEW: + previewFlashing(IsDlgButtonChecked(hwndDlg, IDC_PREVIEW) == BST_CHECKED); + return TRUE; + } + break; + + case WM_NOTIFY: + { + //Here we have pressed either the OK or the APPLY button. + switch(((LPNMHDR)lParam)->idFrom) { + case 0: + switch (((LPNMHDR)lParam)->code) { + case PSN_APPLY: + DBWriteContactSettingByte(NULL, KEYBDMODULE, "fnum", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_NUM) == BST_CHECKED ? 1:0)); + DBWriteContactSettingByte(NULL, KEYBDMODULE, "fcaps", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CAPS) == BST_CHECKED ? 1:0)); + DBWriteContactSettingByte(NULL, KEYBDMODULE, "fscroll", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_SCROLL) == BST_CHECKED ? 1:0)); + + if(IsDlgButtonChecked(hwndDlg, IDC_INTURN) == BST_CHECKED) + DBWriteContactSettingByte(NULL, KEYBDMODULE, "feffect", FLASH_INTURN); + else + if (IsDlgButtonChecked(hwndDlg, IDC_INSEQUENCE) == BST_CHECKED) + DBWriteContactSettingByte(NULL, KEYBDMODULE, "feffect", FLASH_INSEQUENCE); + else + if (IsDlgButtonChecked(hwndDlg, IDC_CUSTOM) == BST_CHECKED) + DBWriteContactSettingByte(NULL, KEYBDMODULE, "feffect", FLASH_CUSTOM); + else + if (IsDlgButtonChecked(hwndDlg, IDC_TRILLIAN) == BST_CHECKED) + DBWriteContactSettingByte(NULL, KEYBDMODULE, "feffect", FLASH_TRILLIAN); + else + DBWriteContactSettingByte(NULL, KEYBDMODULE, "feffect", FLASH_SAMETIME); + DBWriteContactSettingByte(NULL, KEYBDMODULE, "order", (BYTE)SendDlgItemMessage(hwndDlg, IDC_SEQORDER, CB_GETITEMDATA, (WPARAM)SendDlgItemMessage(hwndDlg, IDC_SEQORDER, CB_GETCURSEL, 0, 0), 0)); + DBWriteContactSettingWord(NULL, KEYBDMODULE, "custom", (WORD)SendDlgItemMessage(hwndDlg, IDC_SCUSTOM, CB_GETITEMDATA, (WPARAM)SendDlgItemMessage(hwndDlg, IDC_SCUSTOM, CB_GETCURSEL, 0, 0), 0)); + + DBWriteContactSettingByte(NULL, KEYBDMODULE, "ledsmsg", trillianLedsMsg); + DBWriteContactSettingByte(NULL, KEYBDMODULE, "ledsfile", trillianLedsFile); + DBWriteContactSettingByte(NULL, KEYBDMODULE, "ledsurl", trillianLedsURL); + DBWriteContactSettingByte(NULL, KEYBDMODULE, "ledsother", trillianLedsOther); + + DBWriteContactSettingWord(NULL, KEYBDMODULE, "sdelay", (WORD)SendDlgItemMessage(hwndDlg, IDC_DELAYSPIN, UDM_GETPOS, 0, 0)); + + DBWriteContactSettingByte(NULL, KEYBDMODULE, "speed", (BYTE)SendDlgItemMessage(hwndDlg, IDC_SPEED, TBM_GETPOS, 0, 0)); + + DBWriteContactSettingByte(NULL, KEYBDMODULE, "keypresses", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_KEYPRESSES) == BST_CHECKED ? 1:0)); + + LoadSettings(); + + return TRUE; + } // switch code + break; + } //switch idFrom + } + break; //End WM_NOTIFY + + default: + break; + } + + return FALSE; +} + +INT_PTR CALLBACK DlgProcThemeOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + int i; + char *str; + DBVARIANT dbv; + static BOOL initDlg=FALSE; + + switch (msg) { + + case WM_INITDIALOG: + initDlg=TRUE; + TranslateDialogDefault(hwndDlg); + + SendDlgItemMessage(hwndDlg, IDC_THEME, EM_LIMITTEXT, MAX_PATH, 0); + SendDlgItemMessage(hwndDlg, IDC_CUSTOMSTRING, EM_LIMITTEXT, MAX_PATH, 0); + + for (i=0; !DBGetContactSetting(NULL, KEYBDMODULE, fmtDBSettingName("theme%d", i), &dbv); i++) { + int index = SendDlgItemMessage(hwndDlg, IDC_THEME, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)dbv.pszVal); + DBFreeVariant(&dbv); + if (index != CB_ERR && index != CB_ERRSPACE) { + str = (char *)malloc(MAX_PATH+1); + if (str) + if (DBGetContactSetting(NULL, KEYBDMODULE, fmtDBSettingName("custom%d", i), &dbv)) + str[0] = '\0'; + else { + strcpy(str, dbv.pszVal); + DBFreeVariant(&dbv); + } + SendDlgItemMessage(hwndDlg, IDC_THEME, CB_SETITEMDATA, (WPARAM)index, (LPARAM)str); + } + } + + EnableWindow(GetDlgItem(hwndDlg, IDC_ADD), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_UPDATE), FALSE); + if (SendDlgItemMessage(hwndDlg, IDC_THEME, CB_GETCOUNT, 0, 0) == 0) + EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), FALSE); + else { + SendDlgItemMessage(hwndDlg, IDC_THEME, CB_SETCURSEL, (WPARAM)wCustomTheme, 0); + str = (char *)SendDlgItemMessage(hwndDlg, IDC_THEME, CB_GETITEMDATA, (WPARAM)wCustomTheme, 0); + if (str) + SetDlgItemText(hwndDlg, IDC_CUSTOMSTRING, str); + } + + CheckDlgButton(hwndDlg, IDC_OVERRIDE, bOverride ? BST_CHECKED:BST_UNCHECKED); + + initDlg=FALSE; + return TRUE; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_THEME: + switch (HIWORD(wParam)) { + int item; + char theme[MAX_PATH+1]; + + case CBN_SELENDOK: + case CBN_SELCHANGE: + str = (char *)SendMessage((HWND)lParam, CB_GETITEMDATA, (WPARAM)SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0), 0); + if (str) + SetDlgItemText(hwndDlg, IDC_CUSTOMSTRING, str); + else + SetDlgItemText(hwndDlg, IDC_CUSTOMSTRING, ""); + EnableWindow(GetDlgItem(hwndDlg, IDC_ADD), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_UPDATE), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), TRUE); + break; + case CBN_EDITCHANGE: + GetDlgItemText(hwndDlg, IDC_THEME, theme, sizeof(theme)); + if ((item = SendMessage((HWND)lParam, CB_FINDSTRINGEXACT, -1, (LPARAM)theme)) == CB_ERR) { //new theme + SetDlgItemText(hwndDlg, IDC_CUSTOMSTRING, ""); + EnableWindow(GetDlgItem(hwndDlg, IDC_ADD), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), FALSE); + } else { + str = (char *)SendMessage((HWND)lParam, CB_GETITEMDATA, (WPARAM)item, 0); + if (str) + SetDlgItemText(hwndDlg, IDC_CUSTOMSTRING, str); + else + SetDlgItemText(hwndDlg, IDC_CUSTOMSTRING, ""); + EnableWindow(GetDlgItem(hwndDlg, IDC_ADD), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), TRUE); + } + EnableWindow(GetDlgItem(hwndDlg, IDC_UPDATE), FALSE); + break; + } + return TRUE; + case IDC_CUSTOMSTRING: + if(HIWORD(wParam) == EN_CHANGE) { + int item; + char theme[MAX_PATH+1], customAux[MAX_PATH+1]; + + GetDlgItemText(hwndDlg, IDC_THEME, theme, sizeof(theme)); + if ((item = SendDlgItemMessage(hwndDlg, IDC_THEME, CB_FINDSTRINGEXACT, -1, (LPARAM)theme)) == CB_ERR) + return TRUE; + str = (char *)SendDlgItemMessage(hwndDlg, IDC_THEME, CB_GETITEMDATA, (WPARAM)item, 0); + if (str) { + GetDlgItemText(hwndDlg, IDC_CUSTOMSTRING, customAux, MAX_PATH); + if (strcmp(str, customAux)) + EnableWindow(GetDlgItem(hwndDlg, IDC_UPDATE), TRUE); + else + EnableWindow(GetDlgItem(hwndDlg, IDC_UPDATE), FALSE); + } + } + return TRUE; + case IDC_TEST: + { + char custom[MAX_PATH+1]; + + GetDlgItemText(hwndDlg, IDC_CUSTOMSTRING, custom, MAX_PATH); + SetDlgItemText(hwndDlg, IDC_CUSTOMSTRING, normalizeCustomString(custom)); + testSequence(custom); + } + return TRUE; + case IDC_ADD: + { + int item; + char theme[MAX_PATH+1]; + + GetDlgItemText(hwndDlg, IDC_THEME, theme, sizeof(theme)); + if (!theme[0]) + return TRUE; + item = SendDlgItemMessage(hwndDlg, IDC_THEME, CB_ADDSTRING, 0, (LPARAM)theme); + str = (char *)malloc(MAX_PATH+1); + if (str) { + GetDlgItemText(hwndDlg, IDC_CUSTOMSTRING, str, MAX_PATH); + SetDlgItemText(hwndDlg, IDC_CUSTOMSTRING, normalizeCustomString(str)); + } + SendDlgItemMessage(hwndDlg, IDC_THEME, CB_SETITEMDATA, (WPARAM)item, (LPARAM)str); + EnableWindow(GetDlgItem(hwndDlg, IDC_ADD), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_UPDATE), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), TRUE); + } + SendMessage(GetParent(GetParent(hwndDlg)), PSM_CHANGED, 0, 0); + return TRUE; + case IDC_UPDATE: + { + int item; + char theme[MAX_PATH+1]; + + GetDlgItemText(hwndDlg, IDC_THEME, theme, sizeof(theme)); + item = SendDlgItemMessage(hwndDlg, IDC_THEME, CB_FINDSTRINGEXACT, -1, (LPARAM)theme); + str = (char *)SendDlgItemMessage(hwndDlg, IDC_THEME, CB_GETITEMDATA, (WPARAM)item, 0); + if (str) { + GetDlgItemText(hwndDlg, IDC_CUSTOMSTRING, str, MAX_PATH); + SetDlgItemText(hwndDlg, IDC_CUSTOMSTRING, normalizeCustomString(str)); + } + EnableWindow(GetDlgItem(hwndDlg, IDC_UPDATE), FALSE); + } + SendMessage(GetParent(GetParent(hwndDlg)), PSM_CHANGED, 0, 0); + return TRUE; + case IDC_DELETE: + { + int item; + char theme[MAX_PATH+1]; + + GetDlgItemText(hwndDlg, IDC_THEME, theme, sizeof(theme)); + item = SendDlgItemMessage(hwndDlg, IDC_THEME, CB_FINDSTRINGEXACT, -1, (LPARAM)theme); + str = (char *)SendDlgItemMessage(hwndDlg, IDC_THEME, CB_GETITEMDATA, (WPARAM)item, 0); + if (str) + 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, ""); + SetDlgItemText(hwndDlg, IDC_CUSTOMSTRING, ""); + EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), FALSE); + } else { + SendDlgItemMessage(hwndDlg, IDC_THEME, CB_SETCURSEL, 0, 0); + str = (char *)SendDlgItemMessage(hwndDlg, IDC_THEME, CB_GETITEMDATA, 0, 0); + if (str) + SetDlgItemText(hwndDlg, IDC_CUSTOMSTRING, str); + } + EnableWindow(GetDlgItem(hwndDlg, IDC_UPDATE), FALSE); + } + SendMessage(GetParent(GetParent(hwndDlg)), PSM_CHANGED, 0, 0); + return TRUE; + case IDC_EXPORT: + { + char path[MAX_PATH+1], filter[MAX_PATH+1], *pfilter; + OPENFILENAME ofn={0}; + + path[0] = '\0'; + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = hwndDlg; + ofn.hInstance = NULL; + strcpy(filter, Translate("Keyboard Notify Theme")); + strcat(filter, " (*.knt)"); + pfilter = filter + strlen(filter) + 1; + strcpy(pfilter, "*.knt"); + pfilter = pfilter + strlen(pfilter) + 1; + strcpy(pfilter, Translate("All Files")); + pfilter = pfilter + strlen(pfilter) + 1; + strcpy(pfilter, "*.*"); + pfilter = pfilter + strlen(pfilter) + 1; + *pfilter = '\0'; + ofn.lpstrFilter = filter; + ofn.lpstrFile = path; + ofn.Flags = OFN_HIDEREADONLY|OFN_NOCHANGEDIR|OFN_NOREADONLYRETURN|OFN_PATHMUSTEXIST; + ofn.nMaxFile = sizeof(path); + ofn.lpstrDefExt = "knt"; + if(GetSaveFileName(&ofn)) + exportThemes(path); + } + return TRUE; + case IDC_IMPORT: + { + char path[MAX_PATH+1], filter[MAX_PATH+1], *pfilter; + OPENFILENAME ofn={0}; + + path[0] = '\0'; + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = hwndDlg; + ofn.hInstance = NULL; + strcpy(filter, Translate("Keyboard Notify Theme")); + strcat(filter, " (*.knt)"); + pfilter = filter + strlen(filter) + 1; + strcpy(pfilter, "*.knt"); + pfilter = pfilter + strlen(pfilter) + 1; + strcpy(pfilter, Translate("All Files")); + pfilter = pfilter + strlen(pfilter) + 1; + strcpy(pfilter, "*.*"); + pfilter = pfilter + strlen(pfilter) + 1; + *pfilter = '\0'; + ofn.lpstrFilter = filter; + ofn.lpstrFile = path; + ofn.Flags = OFN_FILEMUSTEXIST|OFN_HIDEREADONLY|OFN_NOCHANGEDIR; + ofn.nMaxFile = sizeof(path); + ofn.lpstrDefExt = "knt"; + if(GetOpenFileName(&ofn)) { + importThemes(path, IsDlgButtonChecked(hwndDlg, IDC_OVERRIDE) == BST_CHECKED); + SendMessage(GetParent(GetParent(hwndDlg)), PSM_CHANGED, 0, 0); + } + } + return TRUE; + case IDC_OVERRIDE: + SendMessage(GetParent(GetParent(hwndDlg)), PSM_CHANGED, 0, 0); + return TRUE; + } + break; + + case WM_NOTIFY: + { + int count; + char theme[MAX_PATH+1], themeAux[MAX_PATH+1], *str; + //Here we have pressed either the OK or the APPLY button. + switch(((LPNMHDR)lParam)->idFrom) { + case 0: + switch (((LPNMHDR)lParam)->code) { + case PSN_APPLY: + if (!DBGetContactSetting(NULL, KEYBDMODULE, fmtDBSettingName("theme%d", wCustomTheme), &dbv)) + strcpy(theme, dbv.pszVal); + else + theme[0] = '\0'; + + // Here we will delete all the items in the theme combo on the Flashing tab: we will load them again later + for (i=0; SendDlgItemMessage(hwndEffect, IDC_SCUSTOM, CB_DELETESTRING, 0, (LPARAM)i) != CB_ERR; i++); + + count = SendDlgItemMessage(hwndDlg, IDC_THEME, CB_GETCOUNT, 0, 0); + for (i=0, wCustomTheme=0; i < count; i++) { + SendDlgItemMessage(hwndDlg, IDC_THEME, CB_GETLBTEXT, (WPARAM)i, (LPARAM)themeAux); + DBWriteContactSettingString(NULL, KEYBDMODULE, fmtDBSettingName("theme%d", i), themeAux); + str = (char *)SendDlgItemMessage(hwndDlg, IDC_THEME, CB_GETITEMDATA, (WPARAM)i, 0); + if (str) + DBWriteContactSettingString(NULL, KEYBDMODULE, fmtDBSettingName("custom%d", i), str); + else + DBWriteContactSettingString(NULL, KEYBDMODULE, fmtDBSettingName("custom%d", i), ""); + + if (!strcmp(theme, themeAux)) + wCustomTheme = i; + + // Here we will update the theme combo on the Flashing tab: horrible but can't imagine a better way right now + SendDlgItemMessage(hwndEffect, IDC_SCUSTOM, CB_INSERTSTRING, (WPARAM)i, (LPARAM)themeAux); + SendDlgItemMessage(hwndEffect, IDC_SCUSTOM, CB_SETITEMDATA, (WPARAM)i, (LPARAM)i); + } + for (i=count; !DBDeleteContactSetting(NULL, KEYBDMODULE, fmtDBSettingName("theme%d", i)); i++) + DBDeleteContactSetting(NULL, KEYBDMODULE, fmtDBSettingName("custom%d", i)); + + DBWriteContactSettingWord(NULL, KEYBDMODULE, "custom", wCustomTheme); + // Still updating here the the Flashing tab's controls + SendDlgItemMessage(hwndEffect, IDC_SCUSTOM, CB_SETCURSEL, (WPARAM)wCustomTheme, 0); + + DBWriteContactSettingByte(NULL, KEYBDMODULE, "override", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_OVERRIDE) == BST_CHECKED ? 1:0)); + + return TRUE; + } // switch code + break; + } //switch idFrom + } + break; //End WM_NOTIFY + + case WM_DESTROY: + { + int item, count = SendDlgItemMessage(hwndDlg, IDC_THEME, CB_GETCOUNT, 0, 0); + + for (item=0; item < count; item++) { + str = (char *)SendDlgItemMessage(hwndDlg, IDC_THEME, CB_GETITEMDATA, (WPARAM)item, 0); + if (str) + free(str); + } + break; + } + + default: + break; + } + + return FALSE; +} + + +void exportThemes(const char *filename) +{ + int i; + FILE *fExport; + DBVARIANT dbv; + + if (!(fExport = fopen(filename, "wt"))) + return; + + fprintf(fExport, "\n; Automatically generated Keyboard Notify Theme file\n\n\n"); + + for (i=0; !DBGetContactSetting(NULL, KEYBDMODULE, fmtDBSettingName("theme%d", i), &dbv); i++) { + fprintf(fExport, "[%s]\n", dbv.pszVal); + DBFreeVariant(&dbv); + if (DBGetContactSetting(NULL, KEYBDMODULE, fmtDBSettingName("custom%d", i), &dbv)) + fprintf(fExport, "0\n\n"); + else { + fprintf(fExport, "%s\n\n", dbv.pszVal); + DBFreeVariant(&dbv); + } + } + + fprintf(fExport, "\n; End of automatically generated Keyboard Notify Theme file\n"); + + fclose(fExport); +} + + +void importThemes(const char *filename, BOOL overrideExisting) +{ + int i, status=0; + FILE *fImport; + char buffer[MAX_PATH+1], theme[MAX_PATH+1], *str; + + if (!(fImport = fopen(filename, "rt"))) + return; + + while (fgets(buffer, MAX_PATH, fImport) != NULL) { + for (str=buffer; *str && isspace(*str); str++); //ltrim + if (!*str || *str == ';') //empty line or comment + continue; + for (i=strlen(str)-1; isspace(str[i]); str[i--]='\0'); //rtrim + switch (status) { + case 0: + if (i > 1 && str[0] == '[' && str[i] == ']') { + status = 1; + strcpy(theme, str+1); + theme[i-1] = '\0'; + } + break; + case 1: + status = 0; + writeThemeToCombo(theme, normalizeCustomString(str), overrideExisting); + break; + } + } + + fclose(fImport); +} + + +void writeThemeToCombo(const char *theme, const char *custom, BOOL overrideExisting) +{ + int item; + char *str; + + item = SendDlgItemMessage(hwndTheme, IDC_THEME, CB_FINDSTRINGEXACT, -1, (LPARAM)theme); + if (item == CB_ERR) { + item = SendDlgItemMessage(hwndTheme, IDC_THEME, CB_ADDSTRING, 0, (LPARAM)theme); + str = (char *)malloc(MAX_PATH+1); + if (str) + strcpy(str, custom); + SendDlgItemMessage(hwndTheme, IDC_THEME, CB_SETITEMDATA, (WPARAM)item, (LPARAM)str); + } else + if (overrideExisting) { + str = (char *)SendDlgItemMessage(hwndTheme, IDC_THEME, CB_GETITEMDATA, (WPARAM)item, 0); + if (str) + strcpy(str, custom); + } +} + + +INT_PTR CALLBACK DlgProcProcesses(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + unsigned int i; + + switch (msg) { + + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + + SendDlgItemMessage(hwndDlg, IDC_PROGRAMS, EM_LIMITTEXT, MAX_PATH, 0); + + for (i=0; i < ProcessListAux.count; i++) + if (ProcessListAux.szFileName[i]) { + int index = SendDlgItemMessage(hwndDlg, IDC_PROGRAMS, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)ProcessListAux.szFileName[i]); + if (index != CB_ERR && index != CB_ERRSPACE) + SendDlgItemMessage(hwndDlg, IDC_PROGRAMS, CB_SETITEMDATA, (WPARAM)index, (LPARAM)i); + } + + EnableWindow(GetDlgItem(hwndDlg, IDC_ADDPGM), FALSE); + if (SendDlgItemMessage(hwndDlg, IDC_PROGRAMS, CB_GETCOUNT, 0, 0) == 0) + EnableWindow(GetDlgItem(hwndDlg, IDC_DELETEPGM), FALSE); + else + SendDlgItemMessage(hwndDlg, IDC_PROGRAMS, CB_SETCURSEL, 0, 0); + + return TRUE; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_PROGRAMS: + switch (HIWORD(wParam)) { + int item; + char szFileName[MAX_PATH+1]; + + case CBN_SELENDOK: + case CBN_SELCHANGE: + EnableWindow(GetDlgItem(hwndDlg, IDC_ADDPGM), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_DELETEPGM), TRUE); + break; + case CBN_EDITCHANGE: + GetDlgItemText(hwndDlg, IDC_PROGRAMS, szFileName, sizeof(szFileName)); + if ((item = SendMessage((HWND)lParam, CB_FINDSTRINGEXACT, -1, (LPARAM)szFileName)) == CB_ERR) { //new program + EnableWindow(GetDlgItem(hwndDlg, IDC_ADDPGM), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_DELETEPGM), FALSE); + } else { + EnableWindow(GetDlgItem(hwndDlg, IDC_ADDPGM), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_DELETEPGM), TRUE); + } + break; + } + break; + case IDC_ADDPGM: + { + int item; + char szFileName[MAX_PATH+1]; + + GetDlgItemText(hwndDlg, IDC_PROGRAMS, szFileName, sizeof(szFileName)); + if (!szFileName[0]) + break; + item = SendDlgItemMessage(hwndDlg, IDC_PROGRAMS, CB_ADDSTRING, 0, (LPARAM)szFileName); + EnableWindow(GetDlgItem(hwndDlg, IDC_ADDPGM), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_DELETEPGM), TRUE); + } + break; + case IDC_DELETEPGM: + { + int item; + char szFileName[MAX_PATH+1]; + + GetDlgItemText(hwndDlg, IDC_PROGRAMS, szFileName, sizeof(szFileName)); + item = SendDlgItemMessage(hwndDlg, IDC_PROGRAMS, CB_FINDSTRINGEXACT, -1, (LPARAM)szFileName); + SendDlgItemMessage(hwndDlg, IDC_PROGRAMS, CB_DELETESTRING, (WPARAM)item, 0); + if (SendDlgItemMessage(hwndDlg, IDC_PROGRAMS, CB_GETCOUNT, 0, 0) == 0) { + SetDlgItemText(hwndDlg, IDC_PROGRAMS, ""); + EnableWindow(GetDlgItem(hwndDlg, IDC_DELETEPGM), FALSE); + } else + SendDlgItemMessage(hwndDlg, IDC_PROGRAMS, CB_SETCURSEL, 0, 0); + } + break; + case IDC_OKPGM: + destroyProcessListAux(); + + ProcessListAux.count = SendDlgItemMessage(hwndDlg, IDC_PROGRAMS, CB_GETCOUNT, 0, 0); + ProcessListAux.szFileName = (char **)malloc(ProcessListAux.count * sizeof(char *)); + if (!ProcessListAux.szFileName) + ProcessListAux.count = 0; + else + for (i=0; i < ProcessListAux.count; i++) { + char szFileNameAux[MAX_PATH+1]; + + SendDlgItemMessage(hwndDlg, IDC_PROGRAMS, CB_GETLBTEXT, (WPARAM)i, (LPARAM)szFileNameAux); + ProcessListAux.szFileName[i] = (char *)malloc(strlen(szFileNameAux) + 1); + if (ProcessListAux.szFileName[i]) + strcpy(ProcessListAux.szFileName[i], szFileNameAux); + } + + case IDC_CANCELPGM: + EndDialog(hwndDlg, LOWORD(wParam)); + break; + } + break; + } + + return FALSE; +} + + +void createProcessListAux(void) +{ + unsigned int i; + + ProcessListAux.count = ProcessList.count; + ProcessListAux.szFileName = (char **)malloc(ProcessListAux.count * sizeof(char *)); + if (!ProcessListAux.szFileName) + ProcessListAux.count = 0; + else + for (i=0; i < ProcessListAux.count; i++) + if (!ProcessList.szFileName[i]) + ProcessListAux.szFileName[i] = NULL; + else { + ProcessListAux.szFileName[i] = (char *)malloc(strlen(ProcessList.szFileName[i]) + 1); + if (ProcessListAux.szFileName[i]) + strcpy(ProcessListAux.szFileName[i], ProcessList.szFileName[i]); + } + +} + + +void destroyProcessListAux(void)
+{
+ unsigned int i;
+
+ for(i=0; i < ProcessListAux.count; i++)
+ if (ProcessListAux.szFileName[i])
+ free(ProcessListAux.szFileName[i]);
+
+ if (ProcessListAux.szFileName)
+ free(ProcessListAux.szFileName);
+
+ ProcessListAux.count = 0;
+ ProcessListAux.szFileName = NULL;
+}
+
+
+INT_PTR CALLBACK DlgProcEventLeds(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + + CheckDlgButton(hwndDlg, IDC_MSGLEDNUM, trillianLedsMsg&2 ? BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_MSGLEDCAPS, trillianLedsMsg&4 ? BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_MSGLEDSCROLL, trillianLedsMsg&1 ? BST_CHECKED:BST_UNCHECKED); + + CheckDlgButton(hwndDlg, IDC_FILELEDNUM, trillianLedsFile&2 ? BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_FILELEDCAPS, trillianLedsFile&4 ? BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_FILELEDSCROLL, trillianLedsFile&1 ? BST_CHECKED:BST_UNCHECKED); + + CheckDlgButton(hwndDlg, IDC_URLLEDNUM, trillianLedsURL&2 ? BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_URLLEDCAPS, trillianLedsURL&4 ? BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_URLLEDSCROLL, trillianLedsURL&1 ? BST_CHECKED:BST_UNCHECKED); + + CheckDlgButton(hwndDlg, IDC_OTHERLEDNUM, trillianLedsOther&2 ? BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_OTHERLEDCAPS, trillianLedsOther&4 ? BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_OTHERLEDSCROLL, trillianLedsOther&1 ? BST_CHECKED:BST_UNCHECKED); + + return TRUE; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_OK: + trillianLedsMsg = 0; + if(IsDlgButtonChecked(hwndDlg, IDC_MSGLEDNUM) == BST_CHECKED) + trillianLedsMsg |= 2; + if(IsDlgButtonChecked(hwndDlg, IDC_MSGLEDCAPS) == BST_CHECKED) + trillianLedsMsg |= 4; + if(IsDlgButtonChecked(hwndDlg, IDC_MSGLEDSCROLL) == BST_CHECKED) + trillianLedsMsg |= 1; + + trillianLedsFile = 0; + if(IsDlgButtonChecked(hwndDlg, IDC_FILELEDNUM) == BST_CHECKED) + trillianLedsFile |= 2; + if(IsDlgButtonChecked(hwndDlg, IDC_FILELEDCAPS) == BST_CHECKED) + trillianLedsFile |= 4; + if(IsDlgButtonChecked(hwndDlg, IDC_FILELEDSCROLL) == BST_CHECKED) + trillianLedsFile |= 1; + + trillianLedsURL = 0; + if(IsDlgButtonChecked(hwndDlg, IDC_URLLEDNUM) == BST_CHECKED) + trillianLedsURL |= 2; + if(IsDlgButtonChecked(hwndDlg, IDC_URLLEDCAPS) == BST_CHECKED) + trillianLedsURL |= 4; + if(IsDlgButtonChecked(hwndDlg, IDC_URLLEDSCROLL) == BST_CHECKED) + trillianLedsURL |= 1; + + trillianLedsOther = 0; + if(IsDlgButtonChecked(hwndDlg, IDC_OTHERLEDNUM) == BST_CHECKED) + trillianLedsOther |= 2; + if(IsDlgButtonChecked(hwndDlg, IDC_OTHERLEDCAPS) == BST_CHECKED) + trillianLedsOther |= 4; + if(IsDlgButtonChecked(hwndDlg, IDC_OTHERLEDSCROLL) == BST_CHECKED) + trillianLedsOther |= 1; + + case IDC_CANCEL: + EndDialog(hwndDlg, LOWORD(wParam)); + break; + } + break; + } + + return FALSE; +} +
+
+void createXstatusListAux(void)
+{
+ unsigned int i, j;
+
+ XstatusListAux = (XSTATUS_INFO *)malloc(ProtoList.protoCount * sizeof(XSTATUS_INFO));
+ if (XstatusListAux)
+ for (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));
+ if (!XstatusListAux[i].enabled)
+ XstatusListAux[i].count = 0;
+ else
+ for(j=0; j < XstatusListAux[i].count; j++)
+ XstatusListAux[i].enabled[j] = ProtoList.protoInfo[i].xstatus.enabled[j];
+ }
+ }
+
+}
+
+
+void destroyXstatusListAux(void)
+{
+ unsigned int i;
+
+ if (XstatusListAux) {
+ for(i=0; i < ProtoList.protoCount; i++)
+ if (XstatusListAux[i].enabled)
+ free(XstatusListAux[i].enabled);
+
+ free(XstatusListAux);
+ XstatusListAux = NULL;
+ }
+
+}
+
+
+INT_PTR CALLBACK DlgProcXstatusList(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+
+ case WM_INITDIALOG:
+
+ {
+ unsigned int i, j;
+ int imageCount;
+ HICON hIconAux;
+ HIMAGELIST hImageList;
+ TVINSERTSTRUCT tvis={0};
+ TVITEM tvi={0};
+ HTREEITEM hSectionItem, hItem;
+ HWND hwndTree = GetDlgItem(hwndDlg, IDC_TREE_XSTATUS);
+
+ TranslateDialogDefault(hwndDlg);
+ SetWindowLong(hwndTree, GWL_STYLE, GetWindowLong(hwndTree, GWL_STYLE)|TVS_NOHSCROLL|TVS_CHECKBOXES);
+
+ if (!XstatusListAux) return TRUE;
+
+ // Calculate hImageList size
+ for (i=0, imageCount=1; i < ProtoList.protoCount; i++)
+ if (ProtoList.protoInfo[i].enabled && XstatusListAux[i].count)
+ imageCount += XstatusListAux[i].count;
+
+ hImageList = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), (bWindowsNT && dWinVer >= 5.01?ILC_COLOR32:ILC_COLOR16)|ILC_MASK, imageCount, imageCount);
+ TreeView_SetImageList(hwndTree, hImageList, TVSIL_NORMAL);
+
+ ImageList_AddIcon(hImageList, hIconAux=LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_BLANK), IMAGE_ICON, 0, 0, 0));
+ if (hIconAux) DestroyIcon(hIconAux);
+
+ TreeView_SelectItem(hwndTree, NULL);
+ ShowWindow(hwndTree, SW_HIDE);
+ TreeView_DeleteAllItems(hwndTree);
+
+ for (i=0; i < ProtoList.protoCount; i++)
+ if (ProtoList.protoInfo[i].enabled && XstatusListAux[i].count) {
+ HTREEITEM hParent;
+ char szProtoName[MAXMODULELABELLENGTH];
+
+ CallProtoService(ProtoList.protoInfo[i].szProto, PS_GETNAME, sizeof(szProtoName), (LPARAM)szProtoName);
+
+ tvis.hParent = NULL;
+ tvis.hInsertAfter = TVI_LAST;
+ tvis.item.mask = TVIF_TEXT|TVIF_PARAM|TVIF_STATE|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
+ tvis.item.pszText = szProtoName;
+ tvis.item.lParam = (LPARAM)i;
+ tvis.item.stateMask = TVIS_BOLD|TVIS_EXPANDED;
+ tvis.item.state = TVIS_BOLD|TVIS_EXPANDED;
+ tvis.item.iImage = tvis.item.iSelectedImage = ImageList_AddIcon(hImageList, hIconAux=(HICON)CallProtoService(ProtoList.protoInfo[i].szProto, PS_LOADICON, PLI_PROTOCOL, 0));
+ if (hIconAux) DestroyIcon(hIconAux);
+ hParent = TreeView_InsertItem(hwndTree, &tvis);
+ for(j=0; j < XstatusListAux[i].count; j++) {
+ char szDefaultName[1024];
+ ICQ_CUSTOM_STATUS xstatus={0};
+
+ tvis.hParent = hParent;
+ tvis.item.mask = TVIF_TEXT|TVIF_PARAM|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
+ if (!j)
+ tvis.item.pszText = Translate("None");
+ else {
+ xstatus.cbSize = sizeof(ICQ_CUSTOM_STATUS);
+ xstatus.flags = CSSF_MASK_NAME|CSSF_DEFAULT_NAME;
+ xstatus.pszName = szDefaultName;
+ xstatus.wParam = &j;
+ CallProtoService(ProtoList.protoInfo[i].szProto, PS_ICQ_GETCUSTOMSTATUSEX, 0, (LPARAM)&xstatus);
+ tvis.item.pszText = szDefaultName;
+ }
+ tvis.item.lParam = (LPARAM)j;
+ tvis.item.iImage = tvis.item.iSelectedImage = j?ImageList_AddIcon(hImageList, hIconAux=(HICON)CallProtoService(ProtoList.protoInfo[i].szProto, PS_ICQ_GETCUSTOMSTATUSICON, (WPARAM)j, 0)):0;
+ if (hIconAux) DestroyIcon(hIconAux);
+ TreeView_InsertItem(hwndTree, &tvis);
+ }
+ }
+
+ tvi.mask = TVIF_HANDLE|TVIF_PARAM;
+ for (hSectionItem=TreeView_GetRoot(hwndTree); hSectionItem; hSectionItem=TreeView_GetNextSibling(hwndTree, hSectionItem)) {
+ tvi.hItem = hSectionItem;
+ TreeView_GetItem(hwndTree, &tvi);
+ i = (unsigned int)tvi.lParam;
+ TreeView_SetItemState(hwndTree, hSectionItem, INDEXTOSTATEIMAGEMASK(0), TVIS_STATEIMAGEMASK);
+ for (hItem=TreeView_GetChild(hwndTree, hSectionItem); hItem; hItem=TreeView_GetNextSibling(hwndTree, hItem)) {
+ tvi.hItem = hItem;
+ TreeView_GetItem(hwndTree, &tvi);
+ j = (unsigned int)tvi.lParam;
+ TreeView_SetItemState(hwndTree, hItem, INDEXTOSTATEIMAGEMASK(XstatusListAux[i].enabled[j]?2:1), TVIS_STATEIMAGEMASK);
+ }
+ }
+
+ ShowWindow(hwndTree, SW_SHOW);
+ TreeView_SetItemState(hwndTree, 0, TVIS_SELECTED, TVIS_SELECTED);
+ return TRUE;
+ }
+
+ case WM_DESTROY:
+ {
+ HIMAGELIST hImageList;
+
+ // Destroy tree view imagelist since it does not get destroyed automatically (see msdn docs)
+ hImageList = TreeView_GetImageList(GetDlgItem(hwndDlg, IDC_TREE_XSTATUS), TVSIL_STATE);
+ if (hImageList) {
+ TreeView_SetImageList(GetDlgItem(hwndDlg, IDC_TREE_XSTATUS), NULL, TVSIL_STATE);
+ ImageList_Destroy(hImageList);
+ }
+ hImageList = TreeView_GetImageList(GetDlgItem(hwndDlg, IDC_TREE_XSTATUS), TVSIL_NORMAL);
+ if (hImageList) {
+ TreeView_SetImageList(GetDlgItem(hwndDlg, IDC_TREE_XSTATUS), NULL, TVSIL_NORMAL);
+ ImageList_Destroy(hImageList);
+ }
+ return TRUE;
+ }
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDC_OKXST:
+ {
+ unsigned int i, j;
+ HTREEITEM hSectionItem, hItem;
+ TVITEM tvi={0};
+ HWND hwndTree = GetDlgItem(hwndDlg, IDC_TREE_XSTATUS);
+
+ tvi.mask = TVIF_HANDLE|TVIF_PARAM;
+ for (hSectionItem=TreeView_GetRoot(hwndTree); hSectionItem; hSectionItem=TreeView_GetNextSibling(hwndTree, hSectionItem)) {
+ tvi.hItem = hSectionItem;
+ TreeView_GetItem(hwndTree, &tvi);
+ i = (unsigned int)tvi.lParam;
+ for (hItem=TreeView_GetChild(hwndTree, hSectionItem); hItem; hItem=TreeView_GetNextSibling(hwndTree, hItem)) {
+ tvi.hItem = hItem;
+ TreeView_GetItem(hwndTree, &tvi);
+ j = (unsigned int)tvi.lParam;
+ XstatusListAux[i].enabled[j] = !!(TreeView_GetItemState(hwndTree, hItem, TVIS_STATEIMAGEMASK)&INDEXTOSTATEIMAGEMASK(2));
+ }
+ }
+ }
+
+ case IDC_CANCELXST:
+ EndDialog(hwndDlg, LOWORD(wParam));
+ return TRUE;
+ }
+ break;
+ }
+
+ return FALSE;
+}
diff --git a/plugins/KeyboardNotify/protolist.h b/plugins/KeyboardNotify/protolist.h new file mode 100644 index 0000000000..9c71ae65ce --- /dev/null +++ b/plugins/KeyboardNotify/protolist.h @@ -0,0 +1,34 @@ +/* + +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. + +*/
+
+typedef struct {
+ unsigned int count;
+ BOOL *enabled;
+} XSTATUS_INFO;
+
+typedef struct {
+ char *szProto;
+ BOOL enabled;
+ BOOL visible;
+ XSTATUS_INFO xstatus;
+} PROTOCOL_INFO;
+
+typedef struct {
+ unsigned int protoCount; + PROTOCOL_INFO *protoInfo; +} PROTOCOL_LIST; diff --git a/plugins/KeyboardNotify/resource.h b/plugins/KeyboardNotify/resource.h new file mode 100644 index 0000000000..4ebfb19cd0 --- /dev/null +++ b/plugins/KeyboardNotify/resource.h @@ -0,0 +1,120 @@ +//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by resources.rc
+//
+#define IDC_OTHERICON 1
+#define IDD_OPT_KN_ACTION 120
+#define IDD_OPTIONS 150
+#define IDD_PROTO_OPTIONS 151
+#define IDD_BASIC_OPTIONS 152
+#define IDD_EFFECT_OPTIONS 153
+#define IDD_THEME_OPTIONS 154
+#define IDD_EVENTLEDS 155
+#define IDD_PROCESSES 156
+#define IDD_IGNORE_OPTIONS 157
+#define IDD_XSTATUSES 158
+#define IDC_ONMESSAGE 1000
+#define IDC_ONFILE 1001
+#define IDC_ONURL 1002
+#define IDC_ONOTHER 1003
+#define IDC_IFOPEN 1004
+#define IDC_IFNOTTOP 1005
+#define IDC_IFOLDER 1006
+#define IDC_SOLDER 1007
+#define IDC_OLDERSPIN 1008
+#define IDC_UNTILBLK 1009
+#define IDC_SBLINK 1010
+#define IDC_BLINKSPIN 1011
+#define IDC_UNTILATTENDED 1012
+#define IDC_MIRORWIN 1013
+#define IDC_UNTILOPEN 1014
+#define IDC_UNTILCOND 1015
+#define IDC_FSCREEN 1016
+#define IDC_SSAVER 1017
+#define IDC_LOCKED 1018
+#define IDC_PGMS 1019
+#define IDC_ASSIGNPGMS 1020
+#define IDC_ACTIVE 1021
+#define IDC_ONLINE 1022
+#define IDC_AWAY 1023
+#define IDC_NA 1024
+#define IDC_OCCUPIED 1025
+#define IDC_DND 1026
+#define IDC_FREECHAT 1027
+#define IDC_INVISIBLE 1028
+#define IDC_ONTHEPHONE 1029
+#define IDC_OUTTOLUNCH 1030
+#define IDC_OFFLINE 1031
+#define IDC_REMCHECK 1032
+#define IDC_SREMCHECK 1033
+#define IDC_NUM 1034
+#define IDC_CAPS 1035
+#define IDC_SCROLL 1036
+#define IDC_SAMETIME 1037
+#define IDC_INTURN 1038
+#define IDC_INSEQUENCE 1039
+#define IDC_SEQORDER 1040
+#define IDC_CUSTOM 1041
+#define IDC_SCUSTOM 1042
+#define IDC_TRILLIAN 1043
+#define IDC_ASSIGNLEDS 1044
+#define IDC_SDELAY 1045
+#define IDC_DELAYSPIN 1046
+#define IDC_PREVIEW 1047
+#define IDC_SPEED 1048
+#define IDC_THEME 1049
+#define IDC_CUSTOMSTRING 1050
+#define IDC_TEST 1051
+#define IDC_ADD 1052
+#define IDC_UPDATE 1053
+#define IDC_DELETE 1054
+#define IDC_EXPORT 1055
+#define IDC_IMPORT 1056
+#define IDC_OVERRIDE 1057
+#define IDC_PROTOCOLLIST 1058
+#define IDC_MSGLEDNUM 1059
+#define IDC_MSGLEDCAPS 1060
+#define IDC_MSGLEDSCROLL 1061
+#define IDC_FILELEDNUM 1062
+#define IDC_FILELEDCAPS 1063
+#define IDC_FILELEDSCROLL 1064
+#define IDC_URLLEDNUM 1065
+#define IDC_URLLEDCAPS 1066
+#define IDC_URLLEDSCROLL 1067
+#define IDC_OTHERLEDNUM 1068
+#define IDC_OTHERLEDCAPS 1069
+#define IDC_OTHERLEDSCROLL 1070
+#define IDC_OK 1071
+#define IDC_CANCEL 1072
+#define IDC_PROGRAMS 1073
+#define IDC_ADDPGM 1074
+#define IDC_DELETEPGM 1075
+#define IDC_OKPGM 1076
+#define IDC_CANCELPGM 1077
+#define IDC_KEYPRESSES 1078
+#define IDC_CUSTOMTHEME 1079
+#define IDC_USECUSTOM 1080
+#define IDC_LIST 1081
+#define IDC_FORCEOPEN 1082
+#define IDC_SFORCEOPEN 1083
+#define IDC_SELECTXSTATUS 1084
+#define IDC_TREE_XSTATUS 1085
+#define IDC_OKXST 1086
+#define IDC_CANCELXST 1087
+#define IDC_FILEICON 1206
+#define IDC_ALLICON 1208
+#define IDC_NONEICON 1209
+#define IDC_MSGICON 1375
+#define IDC_URLICON 1376
+#define IDC_TABS 2000
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 103
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1088
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/plugins/KeyboardNotify/resources.rc b/plugins/KeyboardNotify/resources.rc new file mode 100644 index 0000000000..7bbf535460 --- /dev/null +++ b/plugins/KeyboardNotify/resources.rc @@ -0,0 +1,424 @@ +//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_OPTIONS DIALOGEX 0, 0, 323, 245
+STYLE DS_FIXEDSYS | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ CONTROL "Tab1",IDC_TABS,"SysTabControl32",TCS_FIXEDWIDTH | 0x8,0,
+ 0,317,245
+END
+
+IDD_PROTO_OPTIONS DIALOGEX 1, 15, 314, 229
+STYLE DS_FIXEDSYS | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "Protocols to check",IDC_STATIC,81,6,149,143
+ CONTROL "",IDC_PROTOCOLLIST,"SysListView32",LVS_REPORT |
+ LVS_ALIGNLEFT | LVS_NOCOLUMNHEADER | WS_BORDER |
+ WS_TABSTOP,105,25,100,108
+END
+
+IDD_BASIC_OPTIONS DIALOGEX 1, 15, 314, 229
+STYLE DS_FIXEDSYS | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg"
+BEGIN
+ GROUPBOX "Events to react on",IDC_STATIC,8,6,147,68
+ CONTROL "Incoming messages",IDC_ONMESSAGE,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,24,18,127,10
+ CONTROL "Incoming files",IDC_ONFILE,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,24,31,127,10
+ CONTROL "Incoming URLs",IDC_ONURL,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,24,44,127,10
+ CONTROL "Everything else",IDC_ONOTHER,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,24,57,128,10
+ GROUPBOX "Message-Event only",IDC_STATIC,8,79,147,57
+ CONTROL "Blink if message window is open",IDC_IFOPEN,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,24,91,126,10
+ CONTROL " ... and not in foreground",IDC_IFNOTTOP,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,24,104,125,10
+ CONTROL "Only if last is",IDC_IFOLDER,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,24,117,54,10
+ EDITTEXT IDC_SOLDER,81,116,36,13,ES_NUMBER
+ CONTROL "Spin1",IDC_OLDERSPIN,"msctls_updown32",UDS_SETBUDDYINT |
+ UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_NOTHOUSANDS,107,116,
+ 9,13
+ LTEXT "sec. old",IDC_STATIC,119,118,29,10
+ GROUPBOX "Flash until",IDC_STATIC,8,141,147,78
+ CONTROL "",IDC_UNTILBLK,"Button",BS_AUTOCHECKBOX | WS_GROUP,24,
+ 156,11,10
+ EDITTEXT IDC_SBLINK,36,154,44,13,ES_NUMBER
+ CONTROL "Spin1",IDC_BLINKSPIN,"msctls_updown32",UDS_SETBUDDYINT |
+ UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_NOTHOUSANDS,68,154,
+ 9,13
+ LTEXT "seconds",IDC_STATIC,83,156,67,10
+ CONTROL "",IDC_UNTILATTENDED,"Button",BS_AUTOCHECKBOX,24,171,11,
+ 10
+ COMBOBOX IDC_MIRORWIN,36,169,44,96,CBS_DROPDOWNLIST | WS_TABSTOP
+ LTEXT "is re-attended",IDC_STATIC,83,171,67,10
+ CONTROL "Events are opened",IDC_UNTILOPEN,"Button",
+ BS_AUTOCHECKBOX,24,186,125,10
+ CONTROL "End of 'notify when' conditions",IDC_UNTILCOND,"Button",
+ BS_AUTOCHECKBOX,24,200,126,10
+ GROUPBOX "Notify when",IDC_STATIC,160,6,147,68
+ CONTROL "Full Screen mode",IDC_FSCREEN,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,173,16,117,10
+ CONTROL "Screen Saver is running",IDC_SSAVER,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,173,27,117,10
+ CONTROL "Workstation is Locked (2000/XP)",IDC_LOCKED,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,173,38,117,10
+ CONTROL "Defined programs are running",IDC_PGMS,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,173,49,111,10
+ PUSHBUTTON "...",IDC_ASSIGNPGMS,287,51,15,9
+ CONTROL "All other situations",IDC_ACTIVE,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,173,60,117,10
+ GROUPBOX "Only notify if status is",IDC_STATIC,160,79,147,107
+ CONTROL "Online",IDC_ONLINE,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,173,90,65,9
+ CONTROL "Away",IDC_AWAY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 173,100,128,9
+ CONTROL "Occupied",IDC_OCCUPIED,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,173,120,128,9
+ CONTROL "NA",IDC_NA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,173,
+ 110,128,9
+ CONTROL "DND",IDC_DND,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,173,
+ 130,85,9
+ CONTROL "Free for chat",IDC_FREECHAT,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,173,140,127,9
+ CONTROL "Invisible",IDC_INVISIBLE,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,173,150,128,9
+ CONTROL "On the phone",IDC_ONTHEPHONE,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,173,160,128,9
+ CONTROL "Out to lunch",IDC_OUTTOLUNCH,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,173,170,127,9
+ GROUPBOX "Pending Events",IDC_STATIC,160,191,147,28
+ LTEXT "Remind me every",IDC_STATIC,173,202,58,9
+ EDITTEXT IDC_SREMCHECK,231,200,37,13,ES_NUMBER
+ CONTROL "Spin1",IDC_REMCHECK,"msctls_updown32",UDS_SETBUDDYINT |
+ UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_NOTHOUSANDS,257,200,
+ 9,13
+ LTEXT "minutes",IDC_STATIC,271,202,30,9
+ CONTROL "Offline",IDC_OFFLINE,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,242,90,61,9
+ PUSHBUTTON "xStatuses",IDC_SELECTXSTATUS,263,130,40,9
+END
+
+IDD_EFFECT_OPTIONS DIALOGEX 1, 15, 314, 229
+STYLE DS_FIXEDSYS | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "Keys to flash",IDC_STATIC,8,6,147,91
+ CONTROL "Num Lock",IDC_NUM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 24,22,124,10
+ CONTROL "Caps Lock",IDC_CAPS,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,24,36,123,10
+ CONTROL "Scroll Lock",IDC_SCROLL,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,24,50,124,10
+ GROUPBOX "Flashing effects",IDC_STATIC,160,6,147,91
+ CONTROL "All at the same time",IDC_SAMETIME,"Button",
+ BS_AUTORADIOBUTTON | WS_GROUP,172,22,127,10
+ CONTROL "In turn",IDC_INTURN,"Button",BS_AUTORADIOBUTTON,172,36,
+ 126,10
+ CONTROL "In sequence",IDC_INSEQUENCE,"Button",BS_AUTORADIOBUTTON,
+ 172,50,62,10
+ COMBOBOX IDC_SEQORDER,235,48,53,95,CBS_DROPDOWNLIST | WS_TABSTOP
+ CONTROL "Custom theme",IDC_CUSTOM,"Button",BS_AUTORADIOBUTTON,
+ 172,64,62,10
+ COMBOBOX IDC_SCUSTOM,235,63,67,95,CBS_DROPDOWNLIST |
+ CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP
+ CONTROL "Accordingly to events' count",IDC_TRILLIAN,"Button",
+ BS_AUTORADIOBUTTON,172,78,113,10
+ PUSHBUTTON "...",IDC_ASSIGNLEDS,287,79,15,9
+ GROUPBOX "Wait before starting flashing",IDC_STATIC,8,102,147,54
+ EDITTEXT IDC_SDELAY,29,122,39,14,ES_NUMBER
+ LTEXT "seconds",IDC_STATIC,72,124,80,9
+ GROUPBOX "Flash speed",IDC_STATIC,160,102,147,54
+ CONTROL "Slider1",IDC_SPEED,"msctls_trackbar32",TBS_AUTOTICKS |
+ WS_TABSTOP,170,128,127,19
+ RTEXT "Fast",IDC_STATIC,238,113,50,9
+ LTEXT "Slow",IDC_STATIC,178,113,55,8
+ CONTROL "Spin1",IDC_DELAYSPIN,"msctls_updown32",UDS_SETBUDDYINT |
+ UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_NOTHOUSANDS,59,122,
+ 9,14
+ CONTROL "&Preview",IDC_PREVIEW,"Button",BS_AUTOCHECKBOX |
+ BS_PUSHLIKE,125,173,63,14
+ CONTROL "Emulate keypresses (Use this option if you are using an USB keyboard)",
+ IDC_KEYPRESSES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,
+ 209,293,10
+END
+
+IDD_THEME_OPTIONS DIALOGEX 1, 15, 314, 229
+STYLE DS_FIXEDSYS | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "Create/Edit Themes",IDC_STATIC,8,6,183,92
+ LTEXT "Theme",IDC_STATIC,26,25,34,9
+ COMBOBOX IDC_THEME,65,23,107,96,CBS_DROPDOWN | CBS_AUTOHSCROLL |
+ CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ EDITTEXT IDC_CUSTOMSTRING,26,47,118,14,ES_AUTOHSCROLL
+ PUSHBUTTON "Test",IDC_TEST,144,47,27,14,BS_FLAT
+ PUSHBUTTON "Add",IDC_ADD,26,71,44,14
+ PUSHBUTTON "Update",IDC_UPDATE,77,71,44,14
+ PUSHBUTTON "Delete",IDC_DELETE,128,71,44,14
+ GROUPBOX "Import/Export",IDC_STATIC,196,6,111,92
+ PUSHBUTTON "Export...",IDC_EXPORT,209,29,83,14
+ PUSHBUTTON "Import...",IDC_IMPORT,209,57,83,14
+ CONTROL "Override existing",IDC_OVERRIDE,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,209,76,84,10
+END
+
+IDD_PROCESSES DIALOG DISCARDABLE 175, 60, 176, 98
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Set program list"
+FONT 8, "MS Sans Serif"
+BEGIN
+ LTEXT "Program",IDC_STATIC,13,20,34,9
+ COMBOBOX IDC_PROGRAMS,53,18,107,96,CBS_DROPDOWN | CBS_AUTOHSCROLL |
+ CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "Add",IDC_ADDPGM,36,41,44,14
+ PUSHBUTTON "Delete",IDC_DELETEPGM,99,41,44,14
+ DEFPUSHBUTTON "OK",IDC_OKPGM,119,77,50,14
+ PUSHBUTTON "Cancel",IDC_CANCELPGM,63,77,50,14
+END
+
+IDD_EVENTLEDS DIALOG DISCARDABLE 175, 60, 176, 111
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Set LEDs for events"
+FONT 8, "MS Sans Serif"
+BEGIN
+ CTEXT "Num",IDC_STATIC,83,7,16,8
+ CTEXT "Caps",IDC_STATIC,108,7,17,8
+ CTEXT "Scroll",IDC_STATIC,130,7,18,8
+ LTEXT "Message events",IDC_STATIC,7,19,74,9
+ CONTROL "",IDC_MSGLEDNUM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 87,19,10,10
+ CONTROL "",IDC_MSGLEDCAPS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 111,19,10,10
+ CONTROL "",IDC_MSGLEDSCROLL,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,135,19,10,10
+ LTEXT "File events",IDC_STATIC,7,32,74,10
+ CONTROL "",IDC_FILELEDNUM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 87,32,10,10
+ CONTROL "",IDC_FILELEDCAPS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 111,32,10,10
+ CONTROL "",IDC_FILELEDSCROLL,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,135,32,10,10
+ LTEXT "URL events",IDC_STATIC,7,45,74,9
+ CONTROL "",IDC_URLLEDNUM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 87,45,10,10
+ CONTROL "",IDC_URLLEDCAPS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 111,45,10,10
+ CONTROL "",IDC_URLLEDSCROLL,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,135,45,10,10
+ LTEXT "Other events",IDC_STATIC,7,58,74,10
+ CONTROL "",IDC_OTHERLEDNUM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 87,58,10,10
+ CONTROL "",IDC_OTHERLEDCAPS,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,111,58,10,10
+ CONTROL "",IDC_OTHERLEDSCROLL,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,135,58,10,10
+ DEFPUSHBUTTON "OK",IDC_OK,119,90,50,14
+ PUSHBUTTON "Cancel",IDC_CANCEL,63,90,50,14
+END
+
+IDD_OPT_KN_ACTION DIALOGEX 0, 0, 194, 65
+STYLE DS_3DLOOK | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Sans Serif"
+BEGIN
+ COMBOBOX IDC_CUSTOMTHEME,95,13,84,96,CBS_DROPDOWN |
+ CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Consider event opened after",IDC_STATIC,13,36,98,9
+ EDITTEXT IDC_SFORCEOPEN,111,34,37,13,ES_NUMBER
+ LTEXT "seconds",IDC_STATIC,151,36,32,9
+ CONTROL "Use custom theme",IDC_USECUSTOM,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,13,14,82,10
+ CONTROL "Spin1",IDC_FORCEOPEN,"msctls_updown32",UDS_SETBUDDYINT |
+ UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_NOTHOUSANDS,132,34,
+ 11,13
+END
+
+IDD_IGNORE_OPTIONS DIALOGEX 1, 15, 314, 229
+STYLE DS_FIXEDSYS | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LTEXT "The following events are being ignored:",IDC_STATIC,13,
+ 17,288,8
+ ICON "IDI_RECVMSG",IDC_MSGICON,17,177,20,20,SS_CENTERIMAGE
+ LTEXT "Ignore messages",IDC_STATIC,35,183,70,8,SS_NOPREFIX |
+ SS_CENTERIMAGE
+ ICON "IDI_URL",IDC_URLICON,17,192,20,20,SS_CENTERIMAGE
+ LTEXT "Ignore URLs",IDC_STATIC,35,201,70,8,SS_NOPREFIX |
+ SS_CENTERIMAGE
+ ICON "IDI_FILE",IDC_FILEICON,121,177,20,20,SS_CENTERIMAGE
+ LTEXT "Ignore files",IDC_STATIC,139,183,70,8,SS_NOPREFIX |
+ SS_CENTERIMAGE
+ ICON "IDI_MIRANDA",IDC_OTHERICON,121,193,20,20,SS_CENTERIMAGE
+ LTEXT "Ignore others",IDC_STATIC,139,201,69,8,SS_NOPREFIX |
+ SS_CENTERIMAGE
+ ICON "IDI_FILLEDBLOB",IDC_ALLICON,217,178,20,20,
+ SS_CENTERIMAGE
+ LTEXT "Ignore all",IDC_STATIC,234,185,64,8,SS_NOPREFIX |
+ SS_CENTERIMAGE
+ ICON "IDI_EMPTYBLOB",IDC_NONEICON,217,191,20,20,
+ SS_CENTERIMAGE
+ LTEXT "Ignore none",IDC_STATIC,234,201,63,8,SS_NOPREFIX |
+ SS_CENTERIMAGE
+ CONTROL "",IDC_LIST,"CListControl",WS_TABSTOP | 0x3da,13,30,286,
+ 142,WS_EX_CLIENTEDGE
+ GROUPBOX "Ignore",IDC_STATIC,7,4,300,217
+END
+
+IDD_XSTATUSES DIALOG DISCARDABLE 175, 60, 175, 204
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Set xStatus list"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "OK",IDC_OKXST,118,183,50,14
+ PUSHBUTTON "Cancel",IDC_CANCELXST,63,183,50,14
+ CONTROL "Tree1",IDC_TREE_XSTATUS,"SysTreeView32",TVS_DISABLEDRAGDROP |
+ WS_BORDER | WS_TABSTOP | 0x8000,7,7,161,166
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ IDD_OPTIONS, DIALOG
+ BEGIN
+ RIGHTMARGIN, 317
+ END
+
+ IDD_BASIC_OPTIONS, DIALOG
+ BEGIN
+ BOTTOMMARGIN, 220
+ END
+
+ IDD_THEME_OPTIONS, DIALOG
+ BEGIN
+ BOTTOMMARGIN, 220
+ END
+
+ IDD_PROCESSES, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 169
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 91
+ END
+
+ IDD_EVENTLEDS, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 169
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 104
+ END
+
+ IDD_OPT_KN_ACTION, DIALOG
+ BEGIN
+ RIGHTMARGIN, 186
+ VERTGUIDE, 7
+ BOTTOMMARGIN, 55
+ HORZGUIDE, 7
+ END
+
+ IDD_XSTATUSES, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 168
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 197
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// French (Canada) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_FRC)
+#ifdef _WIN32
+LANGUAGE LANG_FRENCH, SUBLANG_FRENCH_CANADIAN
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // French (Canada) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/plugins/KeyboardNotify/trigger.c b/plugins/KeyboardNotify/trigger.c new file mode 100644 index 0000000000..e8b155e4e8 --- /dev/null +++ b/plugins/KeyboardNotify/trigger.c @@ -0,0 +1,178 @@ +/*
+
+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.
+
+*/
+
+#define WIN32_LEAN_AND_MEAN
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <windows.h>
+#include <commctrl.h>
+#include <commdlg.h>
+#include "constants.h"
+#include "utils.h"
+#include "resource.h"
+#include <newpluginapi.h>
+#include <m_database.h>
+#include <m_langpack.h>
+#include "m_trigger.h"
+
+extern HINSTANCE hInst;
+
+void StartBlinkAction(char *, WORD);
+
+
+int getCustomNro(DWORD actionID, HWND hwndDlg, int nItems)
+{
+ int i;
+ DBVARIANT dbv;
+ char theme[MAX_PATH+1];
+
+ if (DBGetTriggerSetting(actionID, NULL, KEYBDMODULE, "custom", &dbv))
+ return DEF_SETTING_CUSTOMTHEME;
+
+ for (i=0; i < nItems; i++) {
+ SendDlgItemMessage(hwndDlg, IDC_CUSTOMTHEME, CB_GETLBTEXT, (WPARAM)i, (LPARAM)theme);
+ if (!strcmp(dbv.pszVal, theme)) {
+ DBFreeVariant(&dbv);
+ return i;
+ }
+ }
+
+ DBFreeVariant(&dbv);
+ return DEF_SETTING_CUSTOMTHEME;
+}
+
+static BOOL CALLBACK DlgProcOptsActionKbdNotify(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ DBVARIANT dbv;
+ DWORD actionID;
+ int i, nItems;
+ char theme[MAX_PATH+1];
+
+ switch (msg) {
+ case WM_INITDIALOG:
+ actionID = (DWORD)lParam;
+ TranslateDialogDefault(hwndDlg);
+
+ for (i=0; !DBGetContactSetting(NULL, KEYBDMODULE, fmtDBSettingName("theme%d", i), &dbv); i++) {
+ int index = SendDlgItemMessage(hwndDlg, IDC_CUSTOMTHEME, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)dbv.pszVal);
+ DBFreeVariant(&dbv);
+ if (index != CB_ERR && index != CB_ERRSPACE)
+ SendDlgItemMessage(hwndDlg, IDC_CUSTOMTHEME, CB_SETITEMDATA, (WPARAM)index, (LPARAM)i);
+ }
+
+ nItems = SendDlgItemMessage(hwndDlg, IDC_CUSTOMTHEME, CB_GETCOUNT, 0, 0);
+
+ CheckDlgButton(hwndDlg, IDC_USECUSTOM, nItems && DBGetTriggerSettingByte(actionID, NULL, KEYBDMODULE, "usecustom", 0) ? BST_CHECKED:BST_UNCHECKED);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_USECUSTOM), nItems);
+
+ SendDlgItemMessage(hwndDlg, IDC_CUSTOMTHEME, CB_SETCURSEL, (WPARAM)getCustomNro(actionID, hwndDlg, nItems), 0);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CUSTOMTHEME), IsDlgButtonChecked(hwndDlg, IDC_USECUSTOM) == BST_CHECKED);
+
+ SendDlgItemMessage(hwndDlg, IDC_FORCEOPEN, UDM_SETBUDDY, (WPARAM)GetDlgItem(hwndDlg, IDC_SFORCEOPEN), 0);
+ SendDlgItemMessage(hwndDlg, IDC_FORCEOPEN, UDM_SETRANGE32, 1, MAKELONG(UD_MAXVAL, 0));
+ SendDlgItemMessage(hwndDlg, IDC_FORCEOPEN, UDM_SETPOS, 0, MAKELONG(DBGetTriggerSettingWord(actionID, NULL, KEYBDMODULE, "forceopen", DEF_SETTING_NBLINKS), 0));
+
+ break;
+
+ case TM_ADDACTION: // save the settings
+ actionID = (DWORD)wParam;
+ DBWriteTriggerSettingByte(actionID, NULL, KEYBDMODULE, "usecustom", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_USECUSTOM) == BST_CHECKED ? 1:0));
+ SendDlgItemMessage(hwndDlg, IDC_CUSTOMTHEME, CB_GETLBTEXT, (WPARAM)SendDlgItemMessage(hwndDlg, IDC_CUSTOMTHEME, CB_GETCURSEL, 0, 0), (LPARAM)theme);
+ DBWriteTriggerSettingString(actionID, NULL, KEYBDMODULE, "custom", theme);
+ DBWriteTriggerSettingWord(actionID, NULL, KEYBDMODULE, "forceopen", (WORD)SendDlgItemMessage(hwndDlg, IDC_FORCEOPEN, UDM_GETPOS, 0, 0));
+ break;
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDC_USECUSTOM)
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CUSTOMTHEME), IsDlgButtonChecked(hwndDlg, IDC_USECUSTOM) == BST_CHECKED);
+ break;
+
+ case WM_DESTROY:
+ break;
+ }
+
+ return FALSE;
+}
+
+char *getCustomString(DWORD actionID)
+{
+ int i;
+ DBVARIANT dbv, dbv2;
+ static char customString[MAX_PATH+1];
+
+ if (DBGetTriggerSetting(actionID, NULL, KEYBDMODULE, "custom", &dbv))
+ return NULL;
+
+ for (i=0; !DBGetContactSetting(NULL, KEYBDMODULE, fmtDBSettingName("theme%d", i), &dbv2); i++) {
+ if (!strcmp(dbv.pszVal, dbv2.pszVal)) {
+ DBFreeVariant(&dbv);
+ DBFreeVariant(&dbv2);
+ if(DBGetContactSetting(NULL, KEYBDMODULE, fmtDBSettingName("custom%d", i), &dbv2))
+ return NULL;
+ strcpy(customString, dbv2.pszVal);
+ DBFreeVariant(&dbv2);
+ return customString;
+ }
+ DBFreeVariant(&dbv2);
+ }
+
+ DBFreeVariant(&dbv);
+ return NULL;
+}
+
+static int TriggerStartBlinkFunction(DWORD actionID, REPORTINFO *ri)
+{
+ if (ri->flags&ACT_PERFORM) {
+ char *customStr;
+
+ if (!DBGetTriggerSettingByte(actionID, NULL, KEYBDMODULE, "usecustom", 0))
+ customStr = NULL;
+ else
+ customStr = getCustomString(actionID);
+ StartBlinkAction(customStr, DBGetTriggerSettingWord(actionID, NULL, KEYBDMODULE, "forceopen", DEF_SETTING_NBLINKS));
+ }
+ if (ri->flags&ACT_CLEANUP) { // request to delete all associated settings
+ RemoveAllActionSettings(actionID, KEYBDMODULE);
+ }
+
+ return 0; // all ok
+}
+
+int RegisterAction()
+{
+ ACTIONREGISTER ar;
+
+ if (!ServiceExists(MS_TRIGGER_REGISTERACTION))
+ return -1;
+
+ ZeroMemory(&ar, sizeof(ar));
+ ar.cbSize = sizeof(ar);
+ ar.pszName = "Keyboard Flash: Start Blinking";
+ ar.actionFunction = TriggerStartBlinkFunction;
+ ar.hInstance = hInst;
+ ar.pfnDlgProc = DlgProcOptsActionKbdNotify;
+ ar.pszTemplate = MAKEINTRESOURCE(IDD_OPT_KN_ACTION);
+ ar.flags = ARF_FUNCTION;
+ return CallService(MS_TRIGGER_REGISTERACTION, 0, (LPARAM)&ar);
+}
+
+int DeInitAction()
+{
+ return 0;
+}
diff --git a/plugins/KeyboardNotify/trigger.h b/plugins/KeyboardNotify/trigger.h new file mode 100644 index 0000000000..41d830938c --- /dev/null +++ b/plugins/KeyboardNotify/trigger.h @@ -0,0 +1,20 @@ +/*
+
+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.
+
+*/
+
+int RegisterAction();
+int DeInitAction();
diff --git a/plugins/KeyboardNotify/utils.c b/plugins/KeyboardNotify/utils.c new file mode 100644 index 0000000000..1307fbe570 --- /dev/null +++ b/plugins/KeyboardNotify/utils.c @@ -0,0 +1,52 @@ +/*
+
+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.
+
+*/
+
+#define WIN32_LEAN_AND_MEAN
+
+#include <stdio.h>
+#include <windows.h>
+#include "utils.h"
+#include <newpluginapi.h>
+#include <m_database.h>
+#include <m_utils.h>
+
+
+char *fmtDBSettingName(const char *fmt, ...)
+{
+ va_list va;
+ static char returnString[1024];
+
+ va_start(va, fmt);
+ mir_vsnprintf(returnString, sizeof(returnString), fmt, va);
+ va_end(va);
+
+ return returnString;
+}
+
+
+char *getAbsoluteProfileName(char *absoluteProfileName, size_t maxLen)
+{
+ char profilePath[MAX_PATH+1], profileName[MAX_PATH+1];
+
+ profilePath[0] = profileName[0] = '\0';
+ CallService(MS_DB_GETPROFILEPATH, MAX_PATH, (LPARAM)profilePath);
+ CallService(MS_DB_GETPROFILENAME, MAX_PATH, (LPARAM)profileName);
+ mir_snprintf(absoluteProfileName, maxLen, "%s\\%s", profilePath, profileName);
+
+ return absoluteProfileName;
+}
diff --git a/plugins/KeyboardNotify/utils.h b/plugins/KeyboardNotify/utils.h new file mode 100644 index 0000000000..fe3a2664bb --- /dev/null +++ b/plugins/KeyboardNotify/utils.h @@ -0,0 +1,20 @@ +/*
+
+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.
+
+*/
+
+char *fmtDBSettingName(const char *, ...);
+char *getAbsoluteProfileName(char *, size_t);
|