summaryrefslogtreecommitdiff
path: root/windows/keybuddy2/src
diff options
context:
space:
mode:
Diffstat (limited to 'windows/keybuddy2/src')
-rw-r--r--windows/keybuddy2/src/KeyBuddy2.h83
-rw-r--r--windows/keybuddy2/src/KeyBuddy2.lay66
-rw-r--r--windows/keybuddy2/src/KeyBuddy2.upp29
-rw-r--r--windows/keybuddy2/src/KeyBuddy2_debug.lay67
-rw-r--r--windows/keybuddy2/src/hookfuncs.cpp60
-rw-r--r--windows/keybuddy2/src/hookfuncs.h10
-rw-r--r--windows/keybuddy2/src/hotstrings.cpp268
-rw-r--r--windows/keybuddy2/src/hotstrings.h53
-rw-r--r--windows/keybuddy2/src/icon.icobin0 -> 894 bytes
-rw-r--r--windows/keybuddy2/src/icon.rc1
-rw-r--r--windows/keybuddy2/src/includes.h45
-rw-r--r--windows/keybuddy2/src/init4
-rw-r--r--windows/keybuddy2/src/kb2images.iml136
-rw-r--r--windows/keybuddy2/src/keyButton.h25
-rw-r--r--windows/keybuddy2/src/keybuttons.inc121
-rw-r--r--windows/keybuddy2/src/keydefines.inc58
-rw-r--r--windows/keybuddy2/src/logger.cpp57
-rw-r--r--windows/keybuddy2/src/logger.h30
-rw-r--r--windows/keybuddy2/src/main.cpp819
-rw-r--r--windows/keybuddy2/src/mousecontrol.cpp107
-rw-r--r--windows/keybuddy2/src/mousecontrol.h24
-rw-r--r--windows/keybuddy2/src/mousedefines.inc9
22 files changed, 2072 insertions, 0 deletions
diff --git a/windows/keybuddy2/src/KeyBuddy2.h b/windows/keybuddy2/src/KeyBuddy2.h
new file mode 100644
index 0000000..0acec8f
--- /dev/null
+++ b/windows/keybuddy2/src/KeyBuddy2.h
@@ -0,0 +1,83 @@
+#ifndef _KeyBuddy2_KeyBuddy2_h
+#define _KeyBuddy2_KeyBuddy2_h
+
+#include "includes.h"
+
+// main class of the program
+class KeyBuddy2 : public WithKeyBuddy2Layout<TopWindow> {
+public:
+
+ typedef KeyBuddy2 CLASSNAME;
+ KeyBuddy2(); // init stuff
+ ~KeyBuddy2(); // clean up stuff
+
+ Button::Style buttonStyle[7]; // standard/pushed/index finger/middle finger/ring finger/small finger
+ Font buttonFont;
+ Font smallButtonFont;
+ Font buttonFontU;
+
+ TrayIcon trayicon;
+ void trayclick(){Show(!IsShown());}
+ void traymenu(Bar& bar){bar.Add(t_("Exit"), THISBACK(closeProgram));}
+ void closeProgram(){Break();}
+
+ static KeyBuddy2* pKB2; // pointer to the main class instance
+ static LineEdit* pdisplay; // pointer to the display
+ static keyButton* pKeyButton[256]; // pointers to gui key buttons
+ static BYTE keyFinger[256]; // which finger is associated to this key (=style index)
+
+ static bool neoLevelsActive; // whether the additional layers of neo are active
+ static bool neoRemapActive; // false=qwertz layout, true=neo layout
+ static bool cyrillicActive; // if roman letters are translated into cyrillic
+ static bool capslockActive; // if capital letters shall be sent
+ static bool lockLayer4Active; // if neo layer 4 is locked
+ static bool mouseControlActive; // if mouse control via keyboard is active
+ static bool dummySwitch; // that is switched by badly assigned switch pointers to prevent memory access violation
+ static bool keyPressed[256]; // key state
+ static wchar lastDeadKey; // buffer that stores which dead key was pressed
+ static wchar ruDeadChar[2]; // the dead characters for the russian keyboard (small and capital)
+ static wchar map[256][7]; // character to send = map[vkCode][mod]
+ static wchar symbolMap[256][7]; // character to draw on keyboard = map[vkCode][mod]
+ static BYTE neoRemap[256]; // vkNeoKey = neoRemap[vkQWERTZKey]
+ static wchar rumap[256][2]; // cyrillic character = rumap[ansi of latin character][ruDeadKey toggled]
+ static bool* pSwitch[256]; // pointer to the switches
+ static WString keyNames[256]; // names of unmodified keys
+ static wchar upperCaseMap[1023][2]; // mapping lowercase unicode characters to uppercase
+
+ // this function gets called by the hook callback procedure:
+ static bool ProcessKbdEvent( // return true: pass event, return false: block event
+ WPARAM upDownInfo, //WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN or WM_SYSKEYUP
+ DWORD vkCode, // virtual keycode
+ DWORD scanCode, // scancode
+ bool isExtended, // no clue
+ bool isInjected, // if it is a simulated keystroke
+ bool isAltDown, // if alt is down
+ bool isReleased, // if key was not pushed down but released
+ ULONG_PTR dwExtraInfo);
+
+ static WString buttonLabel(DWORD vkCode); // which char appears on the button with this keycode?
+
+ static int getNeoMod(); // which mod key combination is pressed?
+
+ static void SendUNIKey(wchar key, bool release, ULONG_PTR extraInfo=0); // send one virtual unicode key
+ // if the first byte of 'key' is 0xF8, then the other byte
+ // is interpreted as virtual keycode, not unicode character
+ // F8 was chosen because it lies at the end of the "Private Use Area" of unicode
+
+ static void releaseAllKeys(); // release all keys
+
+ static void loadMaps(); // loads the maps
+ // QWERTZ keycode -> neo keycode (neomap.txt, ANSI)
+ // keycode -> character (charmap.txt, UCS-2 little endian)
+ // latin character -> russian character (rumap.txt, UCS-2 little endian)
+ // keycode -> keyname on unmodified keyboard
+
+ void initKeyButtons();
+ void drawKeyButtons();
+
+ static wchar upperCase(wchar letter); // uppercase of unicode letter (for capslock)
+};
+
+#endif
+
+
diff --git a/windows/keybuddy2/src/KeyBuddy2.lay b/windows/keybuddy2/src/KeyBuddy2.lay
new file mode 100644
index 0000000..958a283
--- /dev/null
+++ b/windows/keybuddy2/src/KeyBuddy2.lay
@@ -0,0 +1,66 @@
+LAYOUT(KeyBuddy2Layout, 664, 224)
+ ITEM(keyButton, but_invis, SetFont(StdFontZ(24)).LeftPosZ(668, 48).TopPosZ(180, 40))
+ ITEM(keyButton, but_rctrl, SetFont(StdFontZ(24)).LeftPosZ(612, 48).TopPosZ(180, 40))
+ ITEM(keyButton, but_contmenu, SetFont(StdFontZ(24)).LeftPosZ(560, 48).TopPosZ(180, 40))
+ ITEM(keyButton, but_rwin, SetFont(StdFontZ(24)).LeftPosZ(504, 52).TopPosZ(180, 40))
+ ITEM(keyButton, but_altgr, SetFont(StdFontZ(24)).LeftPosZ(448, 52).TopPosZ(180, 40))
+ ITEM(keyButton, but_space, SetFont(StdFontZ(24)).LeftPosZ(176, 268).TopPosZ(180, 40))
+ ITEM(keyButton, but_lalt, SetFont(StdFontZ(24)).LeftPosZ(120, 52).TopPosZ(180, 40))
+ ITEM(keyButton, but_lwin, SetFont(StdFontZ(24)).LeftPosZ(64, 52).TopPosZ(180, 40))
+ ITEM(keyButton, but_lctrl, SetFont(StdFontZ(24)).LeftPosZ(4, 56).TopPosZ(180, 40))
+ ITEM(keyButton, but_rshift, SetFont(StdFontZ(24)).LeftPosZ(548, 112).TopPosZ(136, 40))
+ ITEM(keyButton, but_dash, SetFont(StdFontZ(24)).LeftPosZ(504, 40).TopPosZ(136, 40))
+ ITEM(keyButton, but_dot, SetFont(StdFontZ(24)).LeftPosZ(460, 40).TopPosZ(136, 40))
+ ITEM(keyButton, but_comma, SetFont(StdFontZ(24)).LeftPosZ(416, 40).TopPosZ(136, 40))
+ ITEM(keyButton, but_M, SetFont(StdFontZ(24)).LeftPosZ(372, 40).TopPosZ(136, 40))
+ ITEM(keyButton, but_N, SetFont(StdFontZ(24)).LeftPosZ(328, 40).TopPosZ(136, 40))
+ ITEM(keyButton, but_B, SetFont(StdFontZ(24)).LeftPosZ(284, 40).TopPosZ(136, 40))
+ ITEM(keyButton, but_V, SetFont(StdFontZ(24)).LeftPosZ(240, 40).TopPosZ(136, 40))
+ ITEM(keyButton, but_C, SetFont(StdFontZ(24)).LeftPosZ(196, 40).TopPosZ(136, 40))
+ ITEM(keyButton, but_X, SetFont(StdFontZ(24)).LeftPosZ(152, 40).TopPosZ(136, 40))
+ ITEM(keyButton, but_Y, SetFont(StdFontZ(24)).LeftPosZ(108, 40).TopPosZ(136, 40))
+ ITEM(keyButton, but_smaller, SetFont(StdFontZ(24)).LeftPosZ(64, 40).TopPosZ(136, 40))
+ ITEM(keyButton, but_lshift, SetFont(StdFontZ(24)).LeftPosZ(4, 56).TopPosZ(136, 40))
+ ITEM(keyButton, but_hash, SetFont(StdFontZ(24)).LeftPosZ(572, 40).TopPosZ(92, 40))
+ ITEM(keyButton, but_AE, SetFont(StdFontZ(24)).LeftPosZ(528, 40).TopPosZ(92, 40))
+ ITEM(keyButton, but_OE, SetFont(StdFontZ(24)).LeftPosZ(484, 40).TopPosZ(92, 40))
+ ITEM(keyButton, but_L, SetFont(StdFontZ(24)).LeftPosZ(440, 40).TopPosZ(92, 40))
+ ITEM(keyButton, but_K, SetFont(StdFontZ(24)).LeftPosZ(396, 40).TopPosZ(92, 40))
+ ITEM(keyButton, but_J, SetFont(StdFontZ(24)).LeftPosZ(352, 40).TopPosZ(92, 40))
+ ITEM(keyButton, but_H, SetFont(StdFontZ(24)).LeftPosZ(308, 40).TopPosZ(92, 40))
+ ITEM(keyButton, but_G, SetFont(StdFontZ(24)).LeftPosZ(264, 40).TopPosZ(92, 40))
+ ITEM(keyButton, but_F, SetFont(StdFontZ(24)).LeftPosZ(220, 40).TopPosZ(92, 40))
+ ITEM(keyButton, but_D, SetFont(StdFontZ(24)).LeftPosZ(176, 40).TopPosZ(92, 40))
+ ITEM(keyButton, but_S, SetFont(StdFontZ(24)).LeftPosZ(132, 40).TopPosZ(92, 40))
+ ITEM(keyButton, but_A, SetFont(StdFontZ(24)).LeftPosZ(88, 40).TopPosZ(92, 40))
+ ITEM(keyButton, but_capslock, SetFont(StdFontZ(24)).LeftPosZ(4, 80).TopPosZ(92, 40))
+ ITEM(keyButton, but_enter, SetFont(StdFontZ(24)).LeftPosZ(616, 44).TopPosZ(48, 84))
+ ITEM(keyButton, but_plus, SetFont(StdFontZ(24)).LeftPosZ(556, 40).TopPosZ(48, 40))
+ ITEM(keyButton, but_UE, SetFont(StdFontZ(24)).LeftPosZ(512, 40).TopPosZ(48, 40))
+ ITEM(keyButton, but_P, SetFont(StdFontZ(24)).LeftPosZ(468, 40).TopPosZ(48, 40))
+ ITEM(keyButton, but_O, SetFont(StdFontZ(24)).LeftPosZ(424, 40).TopPosZ(48, 40))
+ ITEM(keyButton, but_I, SetFont(StdFontZ(24)).LeftPosZ(380, 40).TopPosZ(48, 40))
+ ITEM(keyButton, but_U, SetFont(StdFontZ(24)).LeftPosZ(336, 40).TopPosZ(48, 40))
+ ITEM(keyButton, but_Z, SetFont(StdFontZ(24)).LeftPosZ(292, 40).TopPosZ(48, 40))
+ ITEM(keyButton, but_T, SetFont(StdFontZ(24)).LeftPosZ(248, 40).TopPosZ(48, 40))
+ ITEM(keyButton, but_R, SetFont(StdFontZ(24)).LeftPosZ(204, 40).TopPosZ(48, 40))
+ ITEM(keyButton, but_E, SetFont(StdFontZ(24)).LeftPosZ(160, 40).TopPosZ(48, 40))
+ ITEM(keyButton, but_W, SetFont(StdFontZ(24)).LeftPosZ(116, 40).TopPosZ(48, 40))
+ ITEM(keyButton, but_Q, SetFont(StdFontZ(24)).LeftPosZ(72, 40).TopPosZ(48, 40))
+ ITEM(keyButton, but_tab, SetFont(StdFontZ(24)).LeftPosZ(4, 64).TopPosZ(48, 40))
+ ITEM(keyButton, but_backspace, SetFont(StdFontZ(24)).LeftPosZ(576, 84).TopPosZ(4, 40))
+ ITEM(keyButton, but_acut, SetFont(StdFontZ(24)).LeftPosZ(532, 40).TopPosZ(4, 40))
+ ITEM(keyButton, but_sz, SetFont(StdFontZ(24)).LeftPosZ(488, 40).TopPosZ(4, 40))
+ ITEM(keyButton, but_0, SetFont(StdFontZ(24)).LeftPosZ(444, 40).TopPosZ(4, 40))
+ ITEM(keyButton, but_9, SetFont(StdFontZ(24)).LeftPosZ(400, 40).TopPosZ(4, 40))
+ ITEM(keyButton, but_8, SetFont(StdFontZ(24)).LeftPosZ(356, 40).TopPosZ(4, 40))
+ ITEM(keyButton, but_7, SetFont(StdFontZ(24)).LeftPosZ(312, 40).TopPosZ(4, 40))
+ ITEM(keyButton, but_6, SetFont(StdFontZ(24)).LeftPosZ(268, 40).TopPosZ(4, 40))
+ ITEM(keyButton, but_5, SetFont(StdFontZ(24)).LeftPosZ(224, 40).TopPosZ(4, 40))
+ ITEM(keyButton, but_4, SetFont(StdFontZ(24)).LeftPosZ(180, 40).TopPosZ(4, 40))
+ ITEM(keyButton, but_3, SetFont(StdFontZ(24)).LeftPosZ(136, 40).TopPosZ(4, 40))
+ ITEM(keyButton, but_2, SetFont(StdFontZ(24)).LeftPosZ(92, 40).TopPosZ(4, 40))
+ ITEM(keyButton, but_1, SetFont(StdFontZ(24)).LeftPosZ(48, 40).TopPosZ(4, 40))
+ ITEM(keyButton, but_circ, SetFont(StdFontZ(24)).LeftPosZ(4, 40).TopPosZ(4, 40))
+END_LAYOUT
+
diff --git a/windows/keybuddy2/src/KeyBuddy2.upp b/windows/keybuddy2/src/KeyBuddy2.upp
new file mode 100644
index 0000000..bc3a8ca
--- /dev/null
+++ b/windows/keybuddy2/src/KeyBuddy2.upp
@@ -0,0 +1,29 @@
+uses
+ CtrlLib;
+
+file
+ hookfuncs.cpp,
+ hookfuncs.h,
+ logger.cpp,
+ logger.h,
+ keyButton.h,
+ KeyBuddy2.h,
+ kb2images.iml,
+ hotstrings.h,
+ hotstrings.cpp,
+ icon.ico,
+ icon.rc,
+ includes.h,
+ info.txt,
+ keydefines.inc,
+ keybuttons.inc,
+ mousecontrol.cpp,
+ mousedefines.inc,
+ mousecontrol.h,
+ main.cpp,
+ KeyBuddy2_debug.lay,
+ KeyBuddy2.lay;
+
+mainconfig
+ "" = "GUI";
+
diff --git a/windows/keybuddy2/src/KeyBuddy2_debug.lay b/windows/keybuddy2/src/KeyBuddy2_debug.lay
new file mode 100644
index 0000000..0c0bf3c
--- /dev/null
+++ b/windows/keybuddy2/src/KeyBuddy2_debug.lay
@@ -0,0 +1,67 @@
+LAYOUT(KeyBuddy2Layout, 972, 520)
+ ITEM(LineEdit, display, SetFont(MonospaceZ(12)).SetEditable(false).LeftPosZ(0, 968).TopPosZ(264, 252))
+ ITEM(keyButton, but_invis, SetFont(StdFontZ(24)).LeftPosZ(828, 48).TopPosZ(200, 40))
+ ITEM(keyButton, but_rctrl, SetFont(StdFontZ(24)).LeftPosZ(772, 48).TopPosZ(200, 40))
+ ITEM(keyButton, but_contmenu, SetFont(StdFontZ(24)).LeftPosZ(720, 48).TopPosZ(200, 40))
+ ITEM(keyButton, but_rwin, SetFont(StdFontZ(24)).LeftPosZ(664, 52).TopPosZ(200, 40))
+ ITEM(keyButton, but_altgr, SetFont(StdFontZ(24)).LeftPosZ(608, 52).TopPosZ(200, 40))
+ ITEM(keyButton, but_space, SetFont(StdFontZ(24)).LeftPosZ(336, 268).TopPosZ(200, 40))
+ ITEM(keyButton, but_lalt, SetFont(StdFontZ(24)).LeftPosZ(280, 52).TopPosZ(200, 40))
+ ITEM(keyButton, but_lwin, SetFont(StdFontZ(24)).LeftPosZ(224, 52).TopPosZ(200, 40))
+ ITEM(keyButton, but_lctrl, SetFont(StdFontZ(24)).LeftPosZ(164, 56).TopPosZ(200, 40))
+ ITEM(keyButton, but_rshift, SetFont(StdFontZ(24)).LeftPosZ(708, 112).TopPosZ(156, 40))
+ ITEM(keyButton, but_dash, SetFont(StdFontZ(24)).LeftPosZ(664, 40).TopPosZ(156, 40))
+ ITEM(keyButton, but_dot, SetFont(StdFontZ(24)).LeftPosZ(620, 40).TopPosZ(156, 40))
+ ITEM(keyButton, but_comma, SetFont(StdFontZ(24)).LeftPosZ(576, 40).TopPosZ(156, 40))
+ ITEM(keyButton, but_M, SetFont(StdFontZ(24)).LeftPosZ(532, 40).TopPosZ(156, 40))
+ ITEM(keyButton, but_N, SetFont(StdFontZ(24)).LeftPosZ(488, 40).TopPosZ(156, 40))
+ ITEM(keyButton, but_B, SetFont(StdFontZ(24)).LeftPosZ(444, 40).TopPosZ(156, 40))
+ ITEM(keyButton, but_V, SetFont(StdFontZ(24)).LeftPosZ(400, 40).TopPosZ(156, 40))
+ ITEM(keyButton, but_C, SetFont(StdFontZ(24)).LeftPosZ(356, 40).TopPosZ(156, 40))
+ ITEM(keyButton, but_X, SetFont(StdFontZ(24)).LeftPosZ(312, 40).TopPosZ(156, 40))
+ ITEM(keyButton, but_Y, SetFont(StdFontZ(24)).LeftPosZ(268, 40).TopPosZ(156, 40))
+ ITEM(keyButton, but_smaller, SetFont(StdFontZ(24)).LeftPosZ(224, 40).TopPosZ(156, 40))
+ ITEM(keyButton, but_lshift, SetFont(StdFontZ(24)).LeftPosZ(164, 56).TopPosZ(156, 40))
+ ITEM(keyButton, but_hash, SetFont(StdFontZ(24)).LeftPosZ(732, 40).TopPosZ(112, 40))
+ ITEM(keyButton, but_AE, SetFont(StdFontZ(24)).LeftPosZ(688, 40).TopPosZ(112, 40))
+ ITEM(keyButton, but_OE, SetFont(StdFontZ(24)).LeftPosZ(644, 40).TopPosZ(112, 40))
+ ITEM(keyButton, but_L, SetFont(StdFontZ(24)).LeftPosZ(600, 40).TopPosZ(112, 40))
+ ITEM(keyButton, but_K, SetFont(StdFontZ(24)).LeftPosZ(556, 40).TopPosZ(112, 40))
+ ITEM(keyButton, but_J, SetFont(StdFontZ(24)).LeftPosZ(512, 40).TopPosZ(112, 40))
+ ITEM(keyButton, but_H, SetFont(StdFontZ(24)).LeftPosZ(468, 40).TopPosZ(112, 40))
+ ITEM(keyButton, but_G, SetFont(StdFontZ(24)).LeftPosZ(424, 40).TopPosZ(112, 40))
+ ITEM(keyButton, but_F, SetFont(StdFontZ(24)).LeftPosZ(380, 40).TopPosZ(112, 40))
+ ITEM(keyButton, but_D, SetFont(StdFontZ(24)).LeftPosZ(336, 40).TopPosZ(112, 40))
+ ITEM(keyButton, but_S, SetFont(StdFontZ(24)).LeftPosZ(292, 40).TopPosZ(112, 40))
+ ITEM(keyButton, but_A, SetFont(StdFontZ(24)).LeftPosZ(248, 40).TopPosZ(112, 40))
+ ITEM(keyButton, but_capslock, SetFont(StdFontZ(24)).LeftPosZ(164, 80).TopPosZ(112, 40))
+ ITEM(keyButton, but_enter, SetFont(StdFontZ(24)).LeftPosZ(776, 44).TopPosZ(68, 84))
+ ITEM(keyButton, but_plus, SetFont(StdFontZ(24)).LeftPosZ(716, 40).TopPosZ(68, 40))
+ ITEM(keyButton, but_UE, SetFont(StdFontZ(24)).LeftPosZ(672, 40).TopPosZ(68, 40))
+ ITEM(keyButton, but_P, SetFont(StdFontZ(24)).LeftPosZ(628, 40).TopPosZ(68, 40))
+ ITEM(keyButton, but_O, SetFont(StdFontZ(24)).LeftPosZ(584, 40).TopPosZ(68, 40))
+ ITEM(keyButton, but_I, SetFont(StdFontZ(24)).LeftPosZ(540, 40).TopPosZ(68, 40))
+ ITEM(keyButton, but_U, SetFont(StdFontZ(24)).LeftPosZ(496, 40).TopPosZ(68, 40))
+ ITEM(keyButton, but_Z, SetFont(StdFontZ(24)).LeftPosZ(452, 40).TopPosZ(68, 40))
+ ITEM(keyButton, but_T, SetFont(StdFontZ(24)).LeftPosZ(408, 40).TopPosZ(68, 40))
+ ITEM(keyButton, but_R, SetFont(StdFontZ(24)).LeftPosZ(364, 40).TopPosZ(68, 40))
+ ITEM(keyButton, but_E, SetFont(StdFontZ(24)).LeftPosZ(320, 40).TopPosZ(68, 40))
+ ITEM(keyButton, but_W, SetFont(StdFontZ(24)).LeftPosZ(276, 40).TopPosZ(68, 40))
+ ITEM(keyButton, but_Q, SetFont(StdFontZ(24)).LeftPosZ(232, 40).TopPosZ(68, 40))
+ ITEM(keyButton, but_tab, SetFont(StdFontZ(24)).LeftPosZ(164, 64).TopPosZ(68, 40))
+ ITEM(keyButton, but_backspace, SetFont(StdFontZ(24)).LeftPosZ(736, 84).TopPosZ(24, 40))
+ ITEM(keyButton, but_acut, SetFont(StdFontZ(24)).LeftPosZ(692, 40).TopPosZ(24, 40))
+ ITEM(keyButton, but_sz, SetFont(StdFontZ(24)).LeftPosZ(648, 40).TopPosZ(24, 40))
+ ITEM(keyButton, but_0, SetFont(StdFontZ(24)).LeftPosZ(604, 40).TopPosZ(24, 40))
+ ITEM(keyButton, but_9, SetFont(StdFontZ(24)).LeftPosZ(560, 40).TopPosZ(24, 40))
+ ITEM(keyButton, but_8, SetFont(StdFontZ(24)).LeftPosZ(516, 40).TopPosZ(24, 40))
+ ITEM(keyButton, but_7, SetFont(StdFontZ(24)).LeftPosZ(472, 40).TopPosZ(24, 40))
+ ITEM(keyButton, but_6, SetFont(StdFontZ(24)).LeftPosZ(428, 40).TopPosZ(24, 40))
+ ITEM(keyButton, but_5, SetFont(StdFontZ(24)).LeftPosZ(384, 40).TopPosZ(24, 40))
+ ITEM(keyButton, but_4, SetFont(StdFontZ(24)).LeftPosZ(340, 40).TopPosZ(24, 40))
+ ITEM(keyButton, but_3, SetFont(StdFontZ(24)).LeftPosZ(296, 40).TopPosZ(24, 40))
+ ITEM(keyButton, but_2, SetFont(StdFontZ(24)).LeftPosZ(252, 40).TopPosZ(24, 40))
+ ITEM(keyButton, but_1, SetFont(StdFontZ(24)).LeftPosZ(208, 40).TopPosZ(24, 40))
+ ITEM(keyButton, but_circ, SetFont(StdFontZ(24)).LeftPosZ(164, 40).TopPosZ(24, 40))
+END_LAYOUT
+
diff --git a/windows/keybuddy2/src/hookfuncs.cpp b/windows/keybuddy2/src/hookfuncs.cpp
new file mode 100644
index 0000000..26686a4
--- /dev/null
+++ b/windows/keybuddy2/src/hookfuncs.cpp
@@ -0,0 +1,60 @@
+
+#include "includes.h"
+
+HHOOK hHookKB2=NULL;
+
+// install low level keyboard hook
+int SetHook()
+{
+ int err = 0;
+ hHookKB2 = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)LowLevelKeyboardProc, GetModuleHandle( NULL ),0);
+ if(hHookKB2==NULL)
+ {
+ err = (int)GetLastError();
+ return err;
+ }
+ return 0;
+}
+
+// remove low level keyboard hook
+int RemoveHook()
+{
+ BOOL Hbool = 0;
+ int err = 0;
+ Hbool = UnhookWindowsHookEx(hHookKB2);
+ if(Hbool == 0)
+ {
+ err = (int)GetLastError();
+ return err;
+ }
+ return 0;
+}
+
+// this function is called by windows if a key is pressed
+LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
+{
+ KBDLLHOOKSTRUCT *kbdl_struct;
+
+ if(nCode != HC_ACTION){
+ return ( CallNextHookEx(hHookKB2, nCode, wParam, lParam) );
+ }
+
+ kbdl_struct = (KBDLLHOOKSTRUCT*) lParam;
+
+ if(KeyBuddy2::ProcessKbdEvent(
+ wParam,
+ kbdl_struct->vkCode,
+ kbdl_struct->scanCode,
+ (kbdl_struct->flags & LLKHF_EXTENDED) !=0,
+ (kbdl_struct->flags & LLKHF_INJECTED) !=0,
+ (kbdl_struct->flags & LLKHF_ALTDOWN) !=0,
+ (kbdl_struct->flags & LLKHF_UP) !=0,
+ kbdl_struct->dwExtraInfo))
+ {
+ return ( CallNextHookEx(hHookKB2, nCode, wParam, lParam) );
+ }
+ else
+ {
+ return 1;
+ }
+}
diff --git a/windows/keybuddy2/src/hookfuncs.h b/windows/keybuddy2/src/hookfuncs.h
new file mode 100644
index 0000000..8405af0
--- /dev/null
+++ b/windows/keybuddy2/src/hookfuncs.h
@@ -0,0 +1,10 @@
+#ifndef _KeyBuddy2_hookfuncs_h_
+#define _KeyBuddy2_hookfuncs_h_
+
+#include "includes.h"
+
+int SetHook();
+int RemoveHook();
+LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);
+
+#endif
diff --git a/windows/keybuddy2/src/hotstrings.cpp b/windows/keybuddy2/src/hotstrings.cpp
new file mode 100644
index 0000000..2c5a397
--- /dev/null
+++ b/windows/keybuddy2/src/hotstrings.cpp
@@ -0,0 +1,268 @@
+#include "includes.h"
+
+hotString* hotString::pHotStrings=NULL;
+int hotString::numHotStrings=0;
+WString hotString::hsBuffer;
+int hotString::bufferLen=0;
+long hotString::lastFocusPtr=0;
+
+// load all hotstrings from file
+void hotString::loadHotStrings(){
+
+ // in a first pass, just rush through the file and count the number of hotstrings
+
+ FILE* pFile;
+ int i;
+ char buffer;
+ wchar unibuffer;
+
+ #define FGETUC(pbuf,pfile) fread(pbuf,sizeof(wchar),1,pfile)
+
+ numHotStrings=0;
+ bool valueEnd;
+
+ pFile = fopen(SRCPATH "hotstrings.txt", "rb");
+ if (pFile==NULL) {PromptOK("Can't read hotstrings.txt"); exit(1);}
+
+ fgetc(pFile); // skip BOM
+ fgetc(pFile);
+
+ while(!feof(pFile)){
+ FGETUC(&unibuffer,pFile); // read identifier
+ if( unibuffer>=97 && unibuffer<=122 ){
+
+ FGETUC(&unibuffer,pFile); // read =
+ FGETUC(&unibuffer,pFile); // read "
+
+ valueEnd=false;
+ while(!valueEnd){
+ FGETUC(&unibuffer,pFile);
+ if(unibuffer==34){valueEnd=true;} // read " -> end of value
+ if(unibuffer==92){FGETUC(&unibuffer,pFile);} // read \ -> skip next character
+ }
+ FGETUC(&unibuffer,pFile); // read separator
+ if(unibuffer==13){ // line break -> entry complete
+ numHotStrings++;
+ FGETUC(&unibuffer,pFile); // read chr10
+ }
+ }
+ }
+
+ // now allocate as much memory as needed
+ pHotStrings = new hotString[numHotStrings];
+
+ // now go through in a second pass and store hotstrings
+ int iEntry=0;
+
+ rewind(pFile);
+
+ fgetc(pFile); // skip BOM
+ fgetc(pFile);
+
+ WString* pTarget=NULL;
+ fpos_t valueStart;
+ int valueLength;
+ bool isH;
+
+ while(!feof(pFile)){
+ FGETUC(&unibuffer,pFile); // read identifier
+ if(feof(pFile)){break;} // sometimes the first feof didnt indicate the end, so check again after read operatio
+
+ isH=false;
+
+ switch(unibuffer){
+ case 'h':
+ case 'H':
+ pTarget=&(hotString::pHotStrings[iEntry].hs);
+ isH=true;
+ break;
+ case 'c':
+ case 'C':
+ pTarget=&(hotString::pHotStrings[iEntry].winClass);
+ break;
+ case 't':
+ case 'T':
+ pTarget=&(hotString::pHotStrings[iEntry].winTitle);
+ break;
+ case 's':
+ case 'S':
+ pTarget=&(hotString::pHotStrings[iEntry].value);
+ hotString::pHotStrings[iEntry].launch=false;
+ break;
+ case 'l':
+ case 'L':
+ pTarget=&(hotString::pHotStrings[iEntry].value);
+ hotString::pHotStrings[iEntry].launch=true;
+ break;
+ default:
+ PromptOK("Error parsing hotstrings.txt: unknown element"); exit(1);
+ }
+
+ FGETUC(&unibuffer,pFile); // read =
+ FGETUC(&unibuffer,pFile); // read "
+
+ fgetpos(pFile, &valueStart);
+
+ // read value first to determine its length, then again and store
+
+ valueEnd=false;
+ valueLength=0;
+ while(!valueEnd){
+ FGETUC(&unibuffer,pFile);
+ if(unibuffer==34){ // read " -> end of value
+ valueEnd=true;
+ }
+ else{
+ if(unibuffer==92){ // read \ -> dont check next character
+ FGETUC(&unibuffer,pFile);
+ valueLength++;
+ }
+ else{ // increase number of chars
+ valueLength++;
+ }
+ }
+ }
+
+ if(isH && valueLength>bufferLen){
+ bufferLen=valueLength;
+ }
+
+ *pTarget = WString(0,valueLength);
+ fsetpos(pFile, &valueStart);
+ for(i=0;i<valueLength;i++){
+ FGETUC(&unibuffer,pFile);
+ if(unibuffer==92){FGETUC(&unibuffer,pFile);} // read \ -> skip to next character
+ pTarget->Set(i,unibuffer);
+ }
+
+ FGETUC(&unibuffer,pFile); // read "
+ FGETUC(&unibuffer,pFile); // read separator
+ if(unibuffer==13){ // line break -> entry complete
+ LOGG("Read hotstring: hs=");LOGG(pHotStrings[iEntry].hs);
+ LOGG(" winTitle=");LOGG(pHotStrings[iEntry].winTitle);
+ LOGG(" winClass=");LOGG(pHotStrings[iEntry].winClass);
+ LOGG(" value=");LOGG(pHotStrings[iEntry].value);LOGGNL;
+ iEntry++;
+ FGETUC(&unibuffer,pFile); // read chr10
+ }
+ }
+ fclose(pFile);
+
+ // create log buffer as long as the longest hotstring
+ hsBuffer = WString(0,bufferLen);
+
+ // sort list
+ qsort(pHotStrings,numHotStrings,sizeof(hotString),compareHotStrings);
+
+}
+
+// compare the hotstringbuffer to all hotstrings and fire if there is a match
+// to be more efficient, this could be done using a trie
+// however, c++ takes very few time to compare thousands of strings, so this was
+// not considered necessary
+void hotString::checkHotStrings(){
+ int i,k;
+ bool hit;
+
+ for(i=0;i<numHotStrings;i++){
+
+ if(pHotStrings[i].hs.IsEqual(hsBuffer.Right(pHotStrings[i].hs.GetLength()))){ // current hotstring matches typed letters
+
+ hit=false;
+
+ if(pHotStrings[i].winClass.IsEmpty() && pHotStrings[i].winTitle.IsEmpty()){ // no further conditions, send
+ hit=true;
+ }
+ else{ // check if focus object class and foreground window title match
+ WString wt,oc;
+ getFocusInfo(oc,wt);
+
+ if( (pHotStrings[i].winClass.IsEmpty() || pHotStrings[i].winClass.IsEqual(oc))
+ && (pHotStrings[i].winTitle.IsEmpty() || wt.Find(pHotStrings[i].winTitle)>-1) ){ // ok, everything matches, fire!
+
+ hit=true;
+ }
+ }
+
+ if(hit){
+
+ for(k=0;k<pHotStrings[i].hs.GetLength();k++){ // backspaces to delete the typement
+ KeyBuddy2::SendUNIKey(0xF008,false,HOTSTRING);
+ KeyBuddy2::SendUNIKey(0xF008,true,HOTSTRING);
+ }
+
+ if(!pHotStrings[i].launch){ // send string
+ for(k=0;k<pHotStrings[i].value.GetLength();k++){
+ KeyBuddy2::SendUNIKey(pHotStrings[i].value[k],false,HOTSTRING);
+ KeyBuddy2::SendUNIKey(pHotStrings[i].value[k],true,HOTSTRING);
+ }
+ break;
+ clearBuffer();
+ }
+ else{ // launch program
+ WString cmd=pHotStrings[i].value;
+
+ WString path,exe,params;
+ int delim1=-2,delim2=-2;
+
+ delim1=cmd.Find("|");
+ if(delim1==-1){
+ path="";
+ exe=cmd;
+ params="";
+ }
+ else{
+ delim2=cmd.Find("|",delim1+1);
+
+ if(delim2==-1){
+ path=cmd.Left(delim1);
+ exe=cmd.Mid(delim1+1);;
+ params="";
+ }
+ else{
+ path=cmd.Left(delim1);
+ exe=cmd.Mid(delim1+1,delim2-delim1-1);
+ params=cmd.Mid(delim2+1);
+ }
+ }
+
+ ShellExecuteW( NULL, NULL, exe, params, path, SW_SHOWNORMAL );
+
+ LOGG("working directory: ");LOGG(path);LOGGNL;
+ LOGG("exe: ");LOGG(exe);LOGGNL;
+ LOGG("params: ");LOGG(params);LOGGNL;
+ }
+ }
+ }
+ }
+}
+
+long hotString::getFocusWindowPtr(){
+
+ DWORD unused;
+
+ long myThread=GetWindowThreadProcessId(KeyBuddy2::pKB2->GetHWND(),&unused);
+ long otherThread=GetWindowThreadProcessId(GetForegroundWindow(),&unused);
+
+ if(myThread!=otherThread){
+ AttachThreadInput(otherThread,myThread,true);
+ }
+
+ long result=(long)GetFocus();
+
+ if(myThread!=otherThread){
+ AttachThreadInput(otherThread,myThread,false);
+ }
+
+ return result;
+}
+
+void hotString::getFocusInfo(WString& objectClass, WString& parentTitle){
+
+ char buffer[256];
+ GetClassName((HWND)getFocusWindowPtr(),buffer,255);
+ objectClass=WString(buffer);
+
+ GetWindowText(GetForegroundWindow(),buffer,255);
+ parentTitle=WString(buffer);
+}
diff --git a/windows/keybuddy2/src/hotstrings.h b/windows/keybuddy2/src/hotstrings.h
new file mode 100644
index 0000000..0ec6bf8
--- /dev/null
+++ b/windows/keybuddy2/src/hotstrings.h
@@ -0,0 +1,53 @@
+#ifndef _KeyBuddy2_hotstrings_h_
+#define _KeyBuddy2_hotstrings_h_
+
+#include "includes.h"
+
+// when certain strings are typed ("hotstrings"), they get replaced or they launch programs
+
+class hotString{
+ public:
+ WString hs; // string that activates this hotstring when typed
+ WString winTitle; // only if the window that has the focus contains this string
+ WString winClass; // only if the window that has the focus is of this class
+ WString value; // string that is to be sent / program that is to be launched
+ bool launch; // false = send the string in value, true = launch program with name value
+ //launching: "xxx|yyy|zzz" will run program yyy with parameters zzz in working directory xxx
+
+ static hotString* pHotStrings; // pointer to the array of hotstrings
+ static int numHotStrings; // number of hotstrings
+ static WString hsBuffer; // the buffer that is filled with letters while typing
+ // after each sent character, the end of the buffer is compared to all the hotstrings in the list
+ // if there is a match, the hotstring is activated
+ static int bufferLen; // number of letters in the buffer
+ static long lastFocusPtr; // the window that had the focus while the last character was typed
+ // if the window changes, the hotstring buffer is cleared
+
+ static void loadHotStrings();
+ static void clearBuffer(){hsBuffer = WString(0,bufferLen);};
+ static void appendBuffer(wchar c){ // appends one character to the buffer
+ int i;
+ for(i=0;i<bufferLen-1;i++){
+ hsBuffer.Set(i,(int)hsBuffer[i+1]);
+ }
+ hsBuffer.Set(bufferLen-1,(int)c);
+ };
+
+ // compare the length of two hotstrings and return the difference, so qsort can sort the hotstringlist by length
+ static int compareHotStrings(const void * pa, const void * pb){
+ hotString* a=(hotString*)pa;
+ hotString* b=(hotString*)pb;
+
+ return b->hs.GetLength() - a->hs.GetLength();
+ }
+ // the list needs to be sorted: if the user types "abcde" and both "cde" and "de" are hotstrings,
+ // always the longer one is to be used and will be picked when the list is checked from long to short
+
+ static void checkHotStrings(); // check if the typed characters activate a hotstring and activates it
+ static long getFocusWindowPtr(); // get the pointer to the object that has the focus
+ static void getFocusInfo(WString& objectClass, WString& parentTitle); // get classname of this object
+ // and the title of its parent window
+
+};
+
+#endif
diff --git a/windows/keybuddy2/src/icon.ico b/windows/keybuddy2/src/icon.ico
new file mode 100644
index 0000000..fcbb545
--- /dev/null
+++ b/windows/keybuddy2/src/icon.ico
Binary files differ
diff --git a/windows/keybuddy2/src/icon.rc b/windows/keybuddy2/src/icon.rc
new file mode 100644
index 0000000..77db3bb
--- /dev/null
+++ b/windows/keybuddy2/src/icon.rc
@@ -0,0 +1 @@
+9999 ICON "icon.ico"
diff --git a/windows/keybuddy2/src/includes.h b/windows/keybuddy2/src/includes.h
new file mode 100644
index 0000000..de54bc1
--- /dev/null
+++ b/windows/keybuddy2/src/includes.h
@@ -0,0 +1,45 @@
+#ifndef _KeyBuddy2_includes_h_
+#define _KeyBuddy2_includes_h_
+
+// custom #defines:
+//#define DEBUG
+
+#ifdef DEBUG
+ //#define SRCPATH "C:/Eigene Dateien/c-gefrickel/KeyBuddy2/"
+ #define SRCPATH ""
+#else
+ #define SRCPATH ""
+#endif
+
+#define HOTSTRING 0x80 // random number
+
+#include "keydefines.inc"
+#include "mousedefines.inc"
+
+// includes and functional defines
+
+#define WINVER 0x0500 // otherwise SendInput and KEYEVENTF_UNICODE are unknown
+#include <CtrlLib/CtrlLib.h>
+using namespace Upp;
+
+#include "keyButton.h"
+
+#ifdef DEBUG
+ #define LAYOUTFILE <KeyBuddy2/KeyBuddy2_debug.lay>
+#else
+ #define LAYOUTFILE <KeyBuddy2/KeyBuddy2.lay>
+#endif
+
+#include <CtrlCore/lay.h>
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "hookfuncs.h" // windows api specific functions needed for keyboard hook
+#include "KeyBuddy2.h" // programm class
+#include "logger.h" // logging functions for debug
+#include "hotstrings.h" // logging and replacing for hotstrings
+#include "mousecontrol.h" // well, mouse control
+
+#endif
diff --git a/windows/keybuddy2/src/init b/windows/keybuddy2/src/init
new file mode 100644
index 0000000..acd5bbe
--- /dev/null
+++ b/windows/keybuddy2/src/init
@@ -0,0 +1,4 @@
+#ifndef _KeyBuddy2_icpp_init_stub
+#define _KeyBuddy2_icpp_init_stub
+#include "CtrlLib/init"
+#endif
diff --git a/windows/keybuddy2/src/kb2images.iml b/windows/keybuddy2/src/kb2images.iml
new file mode 100644
index 0000000..893f37c
--- /dev/null
+++ b/windows/keybuddy2/src/kb2images.iml
@@ -0,0 +1,136 @@
+PREMULTIPLIED
+IMAGE_ID(b_std)
+IMAGE_ID(b_pushed)
+IMAGE_ID(b_f2)
+IMAGE_ID(b_f3)
+IMAGE_ID(b_f4)
+IMAGE_ID(b_f5)
+IMAGE_ID(b_space)
+IMAGE_ID(tray)
+
+IMAGE_BEGIN_DATA
+IMAGE_DATA(120,156,237,217,219,78,83,89,28,6,112,146,185,225,25,184,157,11,47,36,94,248,8,222,204,149,215,6,140,33,24,18)
+IMAGE_DATA(76,26,139,149,168,80,198,34,16,24,40,39,1,109,145,30,16,132,114,232,180,28,10,109,161,165,5,74,143,208,41,202)
+IMAGE_DATA(249,124,40,81,196,97,244,13,190,89,255,197,238,4,31,160,217,59,153,69,243,165,176,187,178,246,143,181,246,186,249,154)
+IMAGE_DATA(115,35,231,70,206,47,236,245,43,123,185,221,110,236,236,236,32,157,78,227,228,228,4,135,135,135,216,223,223,199,238,238)
+IMAGE_DATA(46,191,158,237,108,111,111,99,107,107,11,235,235,235,72,165,82,8,135,195,152,153,153,129,195,225,224,159,157,157,157,241)
+IMAGE_DATA(144,141,92,153,241,155,155,155,89,207,198,198,6,119,173,174,174,34,30,143,35,16,8,96,122,122,26,99,99,99,220,115)
+IMAGE_DATA(122,122,202,61,126,191,159,95,27,31,31,199,196,196,4,38,39,39,225,114,185,48,53,53,197,199,211,26,83,60,30,15)
+IMAGE_DATA(188,94,47,255,255,102,103,103,121,124,62,31,230,230,230,248,220,148,96,48,136,249,249,121,44,44,44,96,113,113,145,39)
+IMAGE_DATA(20,10,97,105,105,9,145,72,132,39,26,141,34,22,139,113,83,34,145,224,239,52,143,211,233,132,221,110,199,209,209,17)
+IMAGE_DATA(15,185,232,154,156,54,10,125,62,58,58,138,129,129,1,28,28,28,240,103,139,92,74,176,45,47,47,99,120,120,24,22)
+IMAGE_DATA(139,5,123,123,123,252,217,82,146,109,112,112,16,6,131,129,159,21,122,38,149,100,235,235,235,67,103,103,39,183,209,89)
+IMAGE_DATA(81,146,205,106,181,162,173,173,141,159,79,165,217,232,89,107,109,109,21,54,97,19,54,97,19,54,97,19,54,97,19,54)
+IMAGE_DATA(97,19,54,97,19,54,97,147,213,102,50,153,208,220,220,252,95,47,167,36,91,119,119,55,26,27,27,177,182,182,198,123)
+IMAGE_DATA(57,37,217,90,90,90,80,83,83,131,100,50,201,199,208,189,149,96,163,185,181,90,45,42,43,43,249,88,154,147,238,77)
+IMAGE_DATA(22,57,109,52,103,93,93,29,212,106,53,52,26,13,255,59,179,102,212,23,142,140,140,240,254,139,122,38,58,47,102,179)
+IMAGE_DATA(57,171,233,233,233,129,209,104,228,231,178,170,170,10,101,101,101,80,169,84,168,168,168,224,125,116,198,69,38,234,151,168)
+IMAGE_DATA(151,235,232,232,224,227,233,188,100,51,122,189,30,13,13,13,252,249,162,189,44,47,47,231,251,217,219,219,139,156,235,133)
+IMAGE_DATA(62,251,177,178,116,178,52,177,212,178,188,146,41,53,44,245,44,45,121,121,121,246,155,55,111,6,36,151,142,69,205,82)
+IMAGE_DATA(194,82,36,83,138,89,74,89,52,146,51,179,94,228,42,100,185,203,242,155,140,161,251,23,176,168,36,95,173,180,94,116)
+IMAGE_DATA(253,150,204,185,205,114,71,242,105,164,189,46,146,220,114,219,50,190,187,210,254,42,205,118,75,178,20,43,216,86,36,108)
+IMAGE_DATA(194,38,108,194,38,108,194,38,108,194,38,108,194,38,108,194,38,108,194,38,108,194,150,37,27,245,92,197,10,180,145,137)
+IMAGE_DATA(122,76,234,147,168,87,186,173,0,215,245,142,171,37,231,170,135,163,62,238,142,204,190,159,186,193,220,220,92,139,180,175)
+IMAGE_DATA(42,233,154,156,189,234,79,157,106,126,126,126,166,143,174,145,214,175,84,218,107,249,187,232,235,133,254,228,164,23,177,88)
+IMAGE_DATA(26,201,228,15,36,18,255,32,28,190,196,194,194,223,8,4,190,193,239,191,200,122,124,190,11,120,189,95,49,53,245,5)
+IMAGE_DATA(14,199,41,62,124,216,129,197,18,135,205,54,129,104,52,141,84,234,7,15,217,200,53,59,123,53,222,237,62,207,122,166)
+IMAGE_DATA(167,207,225,114,125,129,211,121,134,161,161,3,152,205,159,208,213,21,103,9,50,207,119,172,172,124,71,48,248,153,121,83)
+IMAGE_DATA(104,111,15,227,245,235,8,58,58,40,81,105,92,2,111,222,44,227,237,219,21,150,36,12,134,191,96,52,166,120,186,187)
+IMAGE_DATA(87,241,238,221,71,150,79,48,153,214,89,54,216,252,155,108,174,45,150,109,88,173,148,29,244,246,238,226,253,251,61,150)
+IMAGE_DATA(125,244,247,31,178,28,177,53,58,198,192,192,9,207,224,224,41,123,63,230,243,181,182,46,66,175,15,178,117,187,68,36)
+IMAGE_DATA(114,41,185,150,100,181,217,108,105,254,185,94,31,64,125,189,27,161,208,213,179,213,214,22,82,132,205,102,59,67,99,163)
+IMAGE_DATA(15,213,213,78,182,151,223,48,51,243,85,81,182,250,122,250,118,117,8,115,115,23,240,120,206,21,101,171,173,117,225,249)
+IMAGE_DATA(243,126,126,134,233,172,40,201,86,93,61,134,242,114,171,66,109,78,60,125,106,17,54,97,19,54,97,19,54,97,19,54)
+IMAGE_DATA(97,19,54,97,19,54,97,19,182,255,145,141,250,44,165,217,116,58,7,52,26,19,239,217,168,255,82,146,173,170,106,4)
+IMAGE_DATA(106,181,145,185,62,243,94,78,73,54,141,198,140,71,143,218,97,183,31,179,235,123,252,254,74,176,209,252,15,31,254,193)
+IMAGE_DATA(210,192,198,108,179,249,62,178,123,199,185,69,78,27,205,171,82,117,161,160,64,139,251,247,117,108,158,24,191,255,85,143)
+IMAGE_DATA(25,64,83,147,159,247,95,212,51,209,121,209,233,178,155,151,47,255,132,86,59,204,207,101,73,73,19,10,11,127,199,189)
+IMAGE_DATA(123,47,80,90,90,203,214,113,156,217,2,82,143,233,225,253,18,245,114,207,158,245,241,241,116,94,178,153,39,79,122,240)
+IMAGE_DATA(248,177,129,63,95,180,151,15,30,188,98,191,215,177,245,239,195,191,36,148,53,215,0,0,0,0,0,0,0,0,0,0)
+IMAGE_END_DATA(1216, 3)
+
+IMAGE_BEGIN_DATA
+IMAGE_DATA(120,156,237,216,105,83,154,87,24,6,96,103,250,83,250,33,63,166,211,118,58,147,109,210,137,38,105,98,107,92,26,77)
+IMAGE_DATA(130,70,19,131,138,70,227,2,136,138,32,24,86,1,77,4,55,80,92,35,136,40,40,138,251,18,101,115,137,73,127,195)
+IMAGE_DATA(221,231,156,116,50,237,183,126,40,227,59,211,51,206,61,142,204,225,125,47,120,159,199,15,119,206,149,156,43,57,223,208)
+IMAGE_DATA(207,183,244,227,241,141,96,246,56,138,247,23,113,76,159,175,194,119,186,140,161,147,16,6,211,65,188,77,207,103,53,3)
+IMAGE_DATA(148,254,212,123,56,146,179,176,28,79,162,103,127,20,170,181,126,180,206,91,97,117,59,49,115,20,65,224,211,6,15,179)
+IMAGE_DATA(49,151,43,53,135,190,228,12,236,137,105,216,18,83,89,141,53,49,9,243,177,31,61,7,99,208,108,14,162,113,201,10)
+IMAGE_DATA(249,156,30,138,113,29,102,62,198,48,119,177,142,161,100,16,173,97,59,170,103,186,241,114,86,135,151,115,58,126,166,102)
+IMAGE_DATA(190,7,181,1,3,106,131,70,212,45,244,162,46,212,11,69,232,13,234,23,77,168,15,155,208,176,100,70,195,178,5,175)
+IMAGE_DATA(34,22,52,174,216,208,180,98,71,211,170,29,175,99,125,120,189,230,64,243,186,3,45,113,39,90,54,92,104,101,217,236)
+IMAGE_DATA(71,219,246,0,148,59,111,161,218,125,7,213,222,32,212,251,44,110,254,55,187,102,165,191,3,21,94,53,38,206,162,24)
+IMAGE_DATA(63,139,160,37,108,67,245,180,246,82,109,237,7,30,180,108,186,80,62,166,198,227,193,102,140,158,134,49,152,9,226,197)
+IMAGE_DATA(148,86,18,182,246,67,15,100,35,109,40,113,212,195,147,89,128,147,102,81,74,182,39,238,22,20,152,228,180,47,1,62)
+IMAGE_DATA(243,82,178,149,14,52,34,191,167,10,3,180,195,86,218,23,41,217,74,156,13,184,175,125,198,255,191,72,206,70,179,246)
+IMAGE_DATA(75,87,185,176,9,155,176,9,155,176,9,155,176,9,155,176,9,155,176,9,155,176,101,197,54,41,73,27,235,179,44,18)
+IMAGE_DATA(179,21,219,21,184,215,33,131,35,57,3,211,177,95,82,182,66,75,13,242,212,143,97,62,250,210,203,73,201,118,175,179)
+IMAGE_DATA(28,183,154,138,161,219,29,70,123,252,45,25,12,146,176,177,235,95,171,249,21,215,228,249,80,198,92,120,21,182,64,78)
+IMAGE_DATA(6,230,185,76,27,187,246,237,214,82,124,255,244,54,126,172,184,131,214,121,11,57,244,188,199,100,125,161,108,84,201,251)
+IMAGE_DATA(47,214,51,177,125,41,238,83,100,53,69,182,58,60,52,203,249,94,94,175,251,13,63,200,114,241,93,217,207,200,173,46)
+IMAGE_DATA(228,125,180,194,167,227,46,102,98,253,18,235,229,242,245,85,252,60,219,151,108,230,174,230,41,114,149,101,124,190,216,179)
+IMAGE_DATA(252,169,234,30,242,94,22,65,103,50,32,231,239,133,190,111,104,8,201,197,69,124,94,94,198,39,250,253,113,126,30,103)
+IMAGE_DATA(211,211,56,245,251,113,58,62,158,245,156,248,124,200,140,142,34,229,241,224,131,203,133,205,55,111,16,212,233,224,233,235)
+IMAGE_DATA(67,98,97,1,127,68,163,60,204,198,92,39,94,47,63,159,25,30,70,58,219,161,239,38,229,118,227,184,191,31,59,22)
+IMAGE_DATA(11,162,90,45,130,74,37,38,85,42,238,249,188,180,132,12,153,98,189,189,8,181,183,35,164,209,96,145,18,238,232,192)
+IMAGE_DATA(114,103,39,34,93,93,252,61,43,148,213,238,110,196,232,115,177,172,233,245,88,239,233,65,156,178,97,48,96,203,104,196)
+IMAGE_DATA(54,93,99,135,62,251,46,139,201,132,61,179,25,251,148,3,186,239,161,213,138,15,148,99,187,29,9,74,146,190,155,164)
+IMAGE_DATA(195,129,20,37,237,116,242,215,163,116,175,233,166,38,76,52,52,224,34,16,224,137,209,117,23,212,234,75,181,101,232,153)
+IMAGE_DATA(30,208,89,230,26,174,169,193,249,236,44,159,173,32,185,164,96,59,161,120,21,10,244,87,85,225,108,106,10,153,177,49)
+IMAGE_DATA(73,217,70,232,59,179,202,100,56,157,152,64,102,100,68,82,182,193,234,106,244,150,149,241,29,102,187,34,37,219,192,243)
+IMAGE_DATA(231,208,63,122,36,73,27,155,53,93,73,137,176,9,155,176,9,155,176,9,155,176,9,155,176,9,155,176,9,155,176,253)
+IMAGE_DATA(159,108,94,47,210,30,143,164,108,206,202,74,104,139,139,191,244,114,110,183,164,108,246,242,114,104,10,11,145,252,171,151)
+IMAGE_DATA(147,146,173,155,158,103,203,131,7,56,160,215,183,233,189,75,228,144,130,109,133,238,165,200,203,67,29,37,78,215,98,247)
+IMAGE_DATA(254,234,186,68,27,115,169,10,10,80,126,253,58,42,111,222,68,144,238,21,104,107,251,218,99,250,20,10,222,127,177,158)
+IMAGE_DATA(137,237,139,139,230,50,155,113,60,123,6,27,205,23,219,203,250,187,119,81,113,227,6,158,92,189,138,151,244,76,221,228)
+IMAGE_DATA(247,43,149,220,197,76,172,95,98,189,156,177,172,140,159,103,251,146,205,116,81,218,233,187,98,243,197,158,229,139,91,183)
+IMAGE_DATA(80,147,159,15,51,61,139,127,22,250,190,33,36,18,33,124,254,188,140,139,139,16,206,207,223,227,236,108,10,167,167,19)
+IMAGE_DATA(56,57,241,101,61,153,140,151,50,138,100,210,141,195,67,39,54,54,122,17,8,116,195,227,161,33,72,4,201,21,165,68)
+IMAGE_DATA(184,141,185,216,249,116,122,132,50,148,245,164,82,30,114,13,226,232,200,133,237,109,51,34,145,46,178,181,193,239,87,226)
+IMAGE_DATA(211,167,69,202,18,121,166,17,139,25,17,90,160,5,9,181,99,145,18,94,212,96,121,169,3,145,229,78,68,233,61,43)
+IMAGE_DATA(209,46,172,174,104,17,91,165,229,136,117,99,45,166,195,250,154,30,241,117,61,54,226,61,216,218,52,96,123,203,136,157)
+IMAGE_DATA(237,94,236,238,80,118,223,96,111,215,132,253,61,19,14,246,205,56,60,176,224,195,161,5,199,71,54,36,142,109,72,38)
+IMAGE_DATA(104,57,146,125,72,81,210,41,7,127,61,18,233,196,212,84,35,38,38,234,241,241,99,128,50,79,247,51,96,33,168,186)
+IMAGE_DATA(84,91,38,237,164,115,38,140,143,215,99,104,72,78,243,53,75,179,229,71,48,160,146,132,237,36,227,196,216,88,29,92)
+IMAGE_DATA(174,74,114,77,242,89,148,146,109,120,88,14,139,229,41,237,202,56,205,228,176,164,108,239,222,189,128,209,88,202,247,152)
+IMAGE_DATA(237,138,148,108,253,253,85,208,235,127,39,155,87,114,54,54,107,221,221,37,194,38,108,194,38,108,194,38,108,194,38,108)
+IMAGE_DATA(194,38,108,194,38,108,194,246,31,219,88,103,36,108,255,222,230,112,60,67,87,87,17,239,217,88,255,37,37,155,205,38)
+IMAGE_DATA(131,70,243,16,137,196,151,94,78,74,54,173,182,24,205,205,247,177,191,223,135,173,45,19,194,97,141,36,108,43,209,78)
+IMAGE_DATA(212,213,229,161,182,54,23,241,184,145,119,133,65,230,10,169,47,213,198,92,42,101,1,100,178,107,168,172,188,201,123,223)
+IMAGE_DATA(64,160,149,247,152,172,47,244,122,21,188,255,98,61,19,219,23,167,51,187,113,56,42,96,181,202,248,94,214,215,223,65)
+IMAGE_DATA(69,197,13,60,121,114,21,213,213,247,225,118,219,121,239,203,92,204,196,250,37,214,203,25,12,165,252,60,219,151,108,166)
+IMAGE_DATA(179,179,8,106,117,1,159,47,246,44,159,63,191,5,185,252,1,204,230,30,252,9,55,14,171,85,0,0,0,0,0,0)
+IMAGE_END_DATA(1600, 3)
+
+IMAGE_BEGIN_DATA
+IMAGE_DATA(120,156,237,152,91,76,147,103,24,199,223,196,41,51,158,38,195,73,230,192,139,93,120,97,34,120,227,212,76,135,139,58)
+IMAGE_DATA(4,77,140,46,154,101,202,150,41,113,9,166,13,86,145,210,170,1,13,33,156,98,185,0,66,129,166,10,179,156,205,22)
+IMAGE_DATA(78,165,80,40,80,192,132,180,9,229,124,10,135,221,140,121,163,81,163,168,127,191,231,173,69,82,215,121,136,216,183,9)
+IMAGE_DATA(253,242,187,104,223,239,223,254,190,247,123,222,183,249,30,182,137,109,98,75,164,227,107,233,168,169,169,193,224,224,32,166)
+IMAGE_DATA(166,166,48,49,49,129,177,177,49,140,140,140,96,104,104,136,127,190,208,12,12,12,160,191,191,31,14,135,3,54,155,13)
+IMAGE_DATA(237,237,237,168,175,175,71,69,69,5,31,155,158,158,230,144,27,121,185,206,239,235,235,91,112,122,123,123,185,151,221,110)
+IMAGE_DATA(71,87,87,23,154,154,154,80,93,93,141,170,170,42,238,51,57,57,137,209,209,81,238,77,227,222,164,161,161,1,149,149)
+IMAGE_DATA(149,40,43,43,195,248,248,56,71,4,47,162,173,173,13,165,165,165,40,42,42,226,243,69,181,213,217,217,41,12,6,131)
+IMAGE_DATA(1,5,5,5,24,30,30,230,181,213,209,209,33,12,197,197,197,200,206,206,230,107,133,106,210,219,62,243,209,235,245,200)
+IMAGE_DATA(202,202,226,110,180,86,188,237,51,159,194,194,66,100,102,102,242,253,130,220,172,86,171,48,80,173,101,100,100,248,132,27)
+IMAGE_DATA(237,199,162,224,238,70,251,138,40,248,146,91,107,107,171,48,184,187,89,44,22,97,240,37,183,150,150,22,97,112,119,107)
+IMAGE_DATA(110,110,22,134,69,183,15,227,102,54,155,133,193,151,220,232,25,66,20,220,221,26,27,27,133,193,151,220,76,38,147,48)
+IMAGE_DATA(184,187,209,115,161,40,248,146,155,209,104,20,6,119,55,234,143,136,194,162,219,135,113,171,171,171,19,6,173,86,139,180)
+IMAGE_DATA(180,180,185,190,156,183,125,230,147,155,155,139,148,148,20,244,244,244,240,190,92,109,109,173,48,164,167,167,35,49,49,17)
+IMAGE_DATA(221,221,221,188,7,65,251,10,245,87,189,77,121,121,57,18,18,18,160,84,42,249,243,32,253,135,145,47,205,167,55,189)
+IMAGE_DATA(168,199,155,148,148,4,153,76,134,216,216,88,238,67,253,85,234,99,82,191,176,164,164,132,247,191,168,207,68,235,37,63)
+IMAGE_DATA(63,127,65,201,203,203,67,78,78,14,95,151,42,149,10,114,185,28,49,49,49,136,143,143,231,174,46,47,114,162,254,18)
+IMAGE_DATA(245,229,52,26,13,63,159,214,203,66,146,154,154,138,228,228,100,94,95,116,47,21,10,5,191,159,58,157,14,236,51,233)
+IMAGE_DATA(112,189,54,250,179,208,132,8,102,182,168,25,238,27,86,227,201,159,193,152,173,221,130,89,211,110,204,182,28,194,83,235)
+IMAGE_DATA(73,60,187,115,22,207,108,42,60,119,164,225,161,93,131,219,215,194,16,181,131,153,215,175,98,161,234,72,102,190,121,74)
+IMAGE_DATA(202,22,49,60,174,88,243,198,252,243,65,45,30,245,234,112,249,32,195,201,111,152,249,143,104,6,202,63,54,188,202,203)
+IMAGE_DATA(14,7,64,118,116,195,92,94,254,83,8,228,63,111,155,203,99,172,148,231,213,17,12,255,149,151,46,139,227,202,187,222)
+IMAGE_DATA(127,172,252,251,250,95,58,254,233,91,205,159,167,252,254,173,159,224,159,91,95,121,204,63,232,78,134,242,76,132,199,252)
+IMAGE_DATA(137,176,101,176,102,4,122,204,219,43,207,225,240,222,173,30,243,113,71,252,160,149,125,142,153,242,205,152,185,189,19,51)
+IMAGE_DATA(213,225,248,215,120,28,119,27,163,113,215,162,64,254,213,99,136,59,29,254,90,254,198,203,252,95,234,21,8,92,187,4)
+IMAGE_DATA(65,235,150,74,248,33,232,139,229,8,90,191,66,98,37,130,2,87,35,48,96,21,76,122,5,207,95,138,148,242,7,156)
+IMAGE_DATA(121,253,111,82,253,221,124,183,250,83,133,51,14,229,117,191,50,24,227,24,238,221,122,115,253,63,176,105,80,162,254,14)
+IMAGE_DATA(23,247,50,40,247,59,243,133,191,48,100,29,99,72,146,124,226,191,103,56,191,155,65,65,236,114,114,110,30,177,223,58)
+IMAGE_DATA(199,46,236,145,206,221,39,93,131,180,126,10,162,24,174,255,200,112,229,7,103,86,190,243,255,161,239,56,31,198,112,106)
+IMAGE_DATA(59,115,4,251,179,16,101,56,107,127,215,223,255,125,7,251,59,244,75,118,246,5,30,106,113,62,0,0,0,0,0,0)
+IMAGE_END_DATA(960, 2)
diff --git a/windows/keybuddy2/src/keyButton.h b/windows/keybuddy2/src/keyButton.h
new file mode 100644
index 0000000..38e9484
--- /dev/null
+++ b/windows/keybuddy2/src/keyButton.h
@@ -0,0 +1,25 @@
+#ifndef _KeyBuddy2_keyButton_h_
+#define _KeyBuddy2_keyButton_h_
+
+// custom button class, that is extended by simulated pushes and releases
+class keyButton:public Button{
+public:
+ int finger; // for which finger is this button? (determines the drawing color)
+ void simDown(){
+ if(IsReadOnly() || !IsEnabled() || IsPush()) return;
+ KeyPush();
+ Sync();
+ }
+ void simUp(){
+ if(!IsPush()) return;
+ FinishPush();
+ Sync();
+ }
+ bool isPushed(){
+ return IsPush();
+ }
+ void LeftDown(Point, dword){}; // overwrite mouse action so buttons do not react to clicking
+ void LeftUp(Point, dword){};
+};
+
+#endif
diff --git a/windows/keybuddy2/src/keybuttons.inc b/windows/keybuddy2/src/keybuttons.inc
new file mode 100644
index 0000000..d5a09d0
--- /dev/null
+++ b/windows/keybuddy2/src/keybuttons.inc
@@ -0,0 +1,121 @@
+
+// pointers to button objects on the GUI
+pKeyButton[VK_TAB]=&but_tab;
+pKeyButton[VK_CAPITAL]=&but_capslock;
+pKeyButton[VK_LSHIFT]=&but_lshift;
+pKeyButton[VK_LCONTROL]=&but_lctrl;
+pKeyButton[VK_LWIN]=&but_lwin;
+pKeyButton[VK_LMENU]=&but_lalt;
+pKeyButton[VK_SPACE]=&but_space;
+pKeyButton[VK_RMENU]=&but_altgr;
+pKeyButton[VK_RWIN]=&but_rwin;
+pKeyButton[VK_APPS]=&but_contmenu;
+pKeyButton[VK_RCONTROL]=&but_rctrl;
+pKeyButton[VK_RSHIFT]=&but_rshift;
+pKeyButton[VK_RETURN]=&but_enter;
+pKeyButton[VK_BACK]=&but_backspace;
+
+pKeyButton[VK_0]=&but_0;
+pKeyButton[VK_1]=&but_1;
+pKeyButton[VK_2]=&but_2;
+pKeyButton[VK_3]=&but_3;
+pKeyButton[VK_4]=&but_4;
+pKeyButton[VK_5]=&but_5;
+pKeyButton[VK_6]=&but_6;
+pKeyButton[VK_7]=&but_7;
+pKeyButton[VK_8]=&but_8;
+pKeyButton[VK_9]=&but_9;
+
+pKeyButton[VK_A]=&but_A;
+pKeyButton[VK_B]=&but_B;
+pKeyButton[VK_C]=&but_C;
+pKeyButton[VK_D]=&but_D;
+pKeyButton[VK_E]=&but_E;
+pKeyButton[VK_F]=&but_F;
+pKeyButton[VK_G]=&but_G;
+pKeyButton[VK_H]=&but_H;
+pKeyButton[VK_I]=&but_I;
+pKeyButton[VK_J]=&but_J;
+pKeyButton[VK_K]=&but_K;
+pKeyButton[VK_L]=&but_L;
+pKeyButton[VK_M]=&but_M;
+pKeyButton[VK_N]=&but_N;
+pKeyButton[VK_O]=&but_O;
+pKeyButton[VK_P]=&but_P;
+pKeyButton[VK_Q]=&but_Q;
+pKeyButton[VK_R]=&but_R;
+pKeyButton[VK_S]=&but_S;
+pKeyButton[VK_T]=&but_T;
+pKeyButton[VK_U]=&but_U;
+pKeyButton[VK_V]=&but_V;
+pKeyButton[VK_W]=&but_W;
+pKeyButton[VK_X]=&but_X;
+pKeyButton[VK_Y]=&but_Y;
+pKeyButton[VK_Z]=&but_Z;
+
+pKeyButton[VK_UE]=&but_UE;
+pKeyButton[VK_PLUS]=&but_plus;
+pKeyButton[VK_COMMA]=&but_comma;
+pKeyButton[VK_DASH]=&but_dash;
+pKeyButton[VK_DOT]=&but_dot;
+pKeyButton[VK_HASH]=&but_hash;
+pKeyButton[VK_OE]=&but_OE;
+pKeyButton[VK_SZ]=&but_sz;
+pKeyButton[VK_CIRCUMFLEX]=&but_circ;
+pKeyButton[VK_ACUT]=&but_acut;
+pKeyButton[VK_AE]=&but_AE;
+pKeyButton[VK_SMALLER]=&but_smaller;
+
+
+
+
+keyFinger[VK_0]=4;
+keyFinger[VK_1]=5;
+keyFinger[VK_2]=5;
+keyFinger[VK_3]=4;
+keyFinger[VK_4]=3;
+keyFinger[VK_5]=2;
+keyFinger[VK_6]=2;
+keyFinger[VK_7]=2;
+keyFinger[VK_8]=2;
+keyFinger[VK_9]=3;
+
+keyFinger[VK_A]=5;
+keyFinger[VK_B]=2;
+keyFinger[VK_C]=3;
+keyFinger[VK_D]=3;
+keyFinger[VK_E]=3;
+keyFinger[VK_F]=2;
+keyFinger[VK_G]=2;
+keyFinger[VK_H]=2;
+keyFinger[VK_I]=3;
+keyFinger[VK_J]=2;
+keyFinger[VK_K]=3;
+keyFinger[VK_L]=4;
+keyFinger[VK_M]=2;
+keyFinger[VK_N]=2;
+keyFinger[VK_O]=4;
+keyFinger[VK_P]=5;
+keyFinger[VK_Q]=5;
+keyFinger[VK_R]=2;
+keyFinger[VK_S]=4;
+keyFinger[VK_T]=2;
+keyFinger[VK_U]=2;
+keyFinger[VK_V]=2;
+keyFinger[VK_W]=4;
+keyFinger[VK_X]=4;
+keyFinger[VK_Y]=5;
+keyFinger[VK_Z]=2;
+
+keyFinger[VK_UE]=5;
+keyFinger[VK_PLUS]=5;
+keyFinger[VK_COMMA]=3;
+keyFinger[VK_DASH]=5;
+keyFinger[VK_DOT]=4;
+keyFinger[VK_OE]=5;
+keyFinger[VK_SZ]=5;
+keyFinger[VK_CIRCUMFLEX]=5;
+keyFinger[VK_ACUT]=5;
+keyFinger[VK_AE]=5;
+
+keyFinger[VK_SPACE]=6;
diff --git a/windows/keybuddy2/src/keydefines.inc b/windows/keybuddy2/src/keydefines.inc
new file mode 100644
index 0000000..b68ce5f
--- /dev/null
+++ b/windows/keybuddy2/src/keydefines.inc
@@ -0,0 +1,58 @@
+#define VK_MOD_2 VK_SHIFT
+#define VK_MOD_21 VK_LSHIFT
+#define VK_MOD_22 VK_RSHIFT
+#define VK_MOD_31 VK_CAPITAL
+#define VK_MOD_32 VK_OEM_2 // #' button on german keyboard
+#define VK_MOD_41 VK_OEM_102 // <>| button on german keyboard
+#define VK_MOD_42 VK_RMENU
+
+#define VK_0 48
+#define VK_1 49
+#define VK_2 50
+#define VK_3 51
+#define VK_4 52
+#define VK_5 53
+#define VK_6 54
+#define VK_7 55
+#define VK_8 56
+#define VK_9 57
+
+#define VK_A 65
+#define VK_B 66
+#define VK_C 67
+#define VK_D 68
+#define VK_E 69
+#define VK_F 70
+#define VK_G 71
+#define VK_H 72
+#define VK_I 73
+#define VK_J 74
+#define VK_K 75
+#define VK_L 76
+#define VK_M 77
+#define VK_N 78
+#define VK_O 79
+#define VK_P 80
+#define VK_Q 81
+#define VK_R 82
+#define VK_S 83
+#define VK_T 84
+#define VK_U 85
+#define VK_V 86
+#define VK_W 87
+#define VK_X 88
+#define VK_Y 89
+#define VK_Z 90
+
+#define VK_UE 186
+#define VK_PLUS 187
+#define VK_COMMA 188
+#define VK_DASH 189
+#define VK_DOT 190
+#define VK_HASH 191 // #
+#define VK_OE 192
+#define VK_SZ 219
+#define VK_CIRCUMFLEX 220
+#define VK_ACUT 221
+#define VK_AE 222
+#define VK_SMALLER 226
diff --git a/windows/keybuddy2/src/logger.cpp b/windows/keybuddy2/src/logger.cpp
new file mode 100644
index 0000000..936723b
--- /dev/null
+++ b/windows/keybuddy2/src/logger.cpp
@@ -0,0 +1,57 @@
+
+#include "includes.h"
+
+FILE* plogfile;
+char linebuffer[2048]={0};
+
+void startLog(const char* fname){
+ plogfile=fopen(fname, "wb");
+}
+
+void logg(const char* txt){
+ fprintf(plogfile,"%s",txt);
+ sprintf(linebuffer,"%s%s",linebuffer,txt);
+}
+
+void logg(WString txt){
+ String utf8=ToUtf8(txt);
+ fprintf(plogfile,"%s",utf8.Begin());
+ sprintf(linebuffer,"%s%s",linebuffer,utf8.Begin());
+}
+
+void logg(bool b){
+ if(b){
+ fprintf(plogfile,"true");
+ strcat(linebuffer,"true");
+ }
+ else{
+ fprintf(plogfile,"false");
+ strcat(linebuffer,"false");
+ }
+}
+
+void logg(int num){
+ fprintf(plogfile,"%d",num);
+ sprintf(linebuffer,"%s%d",linebuffer,num);
+}
+
+void logg(double num){
+ fprintf(plogfile,"%f",num);
+ sprintf(linebuffer,"%s%f",linebuffer,num);
+}
+
+void logg(wchar uni){
+ fprintf(plogfile,"&#%d;",uni);
+ sprintf(linebuffer,"%s[U+%d]",linebuffer,uni);
+}
+
+void loggnl(){
+ fprintf(plogfile,"<br>\n");
+ sprintf(linebuffer,"%s\n",linebuffer);
+ KeyBuddy2::pdisplay->Insert(0,linebuffer);
+ memset(linebuffer,0,sizeof(linebuffer));
+}
+
+void endLog(){
+ fclose(plogfile);
+}
diff --git a/windows/keybuddy2/src/logger.h b/windows/keybuddy2/src/logger.h
new file mode 100644
index 0000000..86adb02
--- /dev/null
+++ b/windows/keybuddy2/src/logger.h
@@ -0,0 +1,30 @@
+#ifndef _KeyBuddy2_logger_h_
+#define _KeyBuddy2_logger_h_
+
+#include "includes.h"
+
+// Logging functions
+// if DEBUG is enabled, these functions display debug messages in the GUI and into an html file
+
+#ifdef DEBUG
+ #define STARTLOG(FNAME) startLog(FNAME)
+ #define LOGG(ARG) logg(ARG)
+ #define LOGGNL loggnl()
+ #define ENDLOG endLog()
+
+ void startLog(const char* fname);
+ void logg(const char* txt);
+ void logg(WString txt);
+ void logg(int num);
+ void logg(double num);
+ void logg(wchar uni);
+ void loggnl();
+ void endLog();
+#else
+ #define STARTLOG(FNAME)
+ #define LOGG(ARG)
+ #define LOGGNL
+ #define ENDLOG
+#endif
+
+#endif
diff --git a/windows/keybuddy2/src/main.cpp b/windows/keybuddy2/src/main.cpp
new file mode 100644
index 0000000..fa8418f
--- /dev/null
+++ b/windows/keybuddy2/src/main.cpp
@@ -0,0 +1,819 @@
+
+#include "includes.h"
+
+#define IMAGECLASS KB2Images
+#define IMAGEFILE <KeyBuddy2/kb2images.iml>
+
+#include <Draw/iml.h>
+
+KeyBuddy2* KeyBuddy2::pKB2=NULL;
+LineEdit* KeyBuddy2::pdisplay=NULL; // pointer to the display
+keyButton* KeyBuddy2::pKeyButton[256]={0}; // pointers to gui key buttons
+BYTE KeyBuddy2::keyFinger[256]={0}; // which finger is associated to this key (=style index)
+bool KeyBuddy2::neoLevelsActive=true; // whether the additional layers of neo are active
+bool KeyBuddy2::neoRemapActive=false; // false=qwertz layout, true=neo layout
+bool KeyBuddy2::cyrillicActive=false; // if roman letters are translated into cyrillic
+bool KeyBuddy2::capslockActive=false; // if capital letters shall be sent
+bool KeyBuddy2::lockLayer4Active=false; // if neo layer 4 is locked
+bool KeyBuddy2::mouseControlActive=false; // if mouse control via keyboard is active
+bool KeyBuddy2::dummySwitch=false; // that is switched by badly assigned switch pointers to prevent memory access violation
+bool KeyBuddy2::keyPressed[256]={0}; // key states
+wchar KeyBuddy2::lastDeadKey; // buffer that stores which dead key was pressed
+wchar KeyBuddy2::ruDeadChar[2]; // the dead characters for the russian keyboard (small and capital)
+wchar KeyBuddy2::map[256][7]={0}; // character to send = map[vkCode][mod]
+wchar KeyBuddy2::symbolMap[256][7]={0}; // character to draw on keyboard = symbolMap[vkCode][mod]
+BYTE KeyBuddy2::neoRemap[256]={0}; // vkNeoKey = neoRemap[vkQWERTZKey]
+wchar KeyBuddy2::rumap[256][2]={0}; // cyrillic character = rumap[ansi of latin character][ruDeadKey toggled]
+bool* KeyBuddy2::pSwitch[256]={0}; // pointer to the switches
+WString KeyBuddy2::keyNames[256]; // names of unmodified keys
+wchar KeyBuddy2::upperCaseMap[1023][2]={0}; // mapping lowercase unicode characters to uppercase
+
+KeyBuddy2::KeyBuddy2()
+{
+ pKB2 = this;
+ #ifdef DEBUG
+ pdisplay = &display;
+ #endif
+
+ STARTLOG(SRCPATH "log.html");
+ loadMaps();
+ hotString::loadHotStrings();
+
+ int i;
+ for(i=0;i<=255;i++){
+ pSwitch[i]=&dummySwitch;
+ }
+ pSwitch[1]=&neoLevelsActive;
+ pSwitch[2]=&neoRemapActive;
+ pSwitch[3]=&cyrillicActive;
+ pSwitch[4]=&capslockActive;
+ pSwitch[5]=&lockLayer4Active;
+ pSwitch[6]=&mouseControlActive;
+
+ KeyBuddy2::Zoomable();
+
+ Icon(KB2Images::tray(),KB2Images::tray());
+ trayicon.Icon(KB2Images::tray());
+ trayicon.WhenBar=THISBACK(traymenu);
+ trayicon.WhenLeftDown=THISBACK(trayclick);
+ trayicon.Tip("KeyBuddy2 (verändert Tastatur)");
+
+ CtrlLayout(*this, "KeyBuddy2");
+ releaseAllKeys();
+ SetHook();
+ initKeyButtons();
+
+ NoAccessKeysDistribution();
+
+ #ifndef DEBUG
+ WhenClose=THISBACK(Hide);
+ #endif
+
+ ToolWindow();
+ TopMost();
+}
+
+KeyBuddy2::~KeyBuddy2()
+{
+ releaseAllKeys();
+ RemoveHook();
+ ENDLOG;
+}
+
+bool KeyBuddy2::ProcessKbdEvent(
+ WPARAM upDownInfo,
+ DWORD vkCode,
+ DWORD scanCode,
+ bool isExtended,
+ bool isInjected,
+ bool isAltDown,
+ bool isReleased,
+ ULONG_PTR dwExtraInfo)
+{
+
+ if(scanCode==0x21d){ // AltGr also presses left Strg but with scancode 0x21d, filter that out, it sucks
+ return false;
+ }
+ if(!isInjected){ // memorize physical key states
+ keyPressed[vkCode]=!isReleased;
+ if(isReleased){pKeyButton[vkCode]->simUp();}
+ else{pKeyButton[vkCode]->simDown();}
+ }
+
+ // log information about captured event:
+
+ char udi[14]; // up down info string
+ char buffer[512];
+ //bool forceRedraw=false; // force keyboard redraw
+
+ switch(upDownInfo){
+ case WM_KEYDOWN:
+ sprintf(udi,"WM_KEYDOWN");
+ break;
+ case WM_KEYUP:
+ sprintf(udi,"WM_KEYUP");
+ break;
+ case WM_SYSKEYDOWN:
+ sprintf(udi,"WM_SYSKEYDOWN");
+ break;
+ case WM_SYSKEYUP:
+ sprintf(udi,"WM_SYSKEYUP");
+ break;
+ default:
+ sprintf(udi,"UNKNOWN");
+ }
+
+ sprintf(buffer,"upDownInfo: %s\tvkCode: %d (0x%X)\tscanCode: %d (0x%X)\textended: %d\tinjected: %d\taltdown: %d\tup: %d\tdwExtraInfo: %d",
+ udi,vkCode,vkCode,scanCode,scanCode,(int)isExtended,(int)isInjected,(int)isAltDown,(int)isReleased,dwExtraInfo);
+
+ LOGG(buffer);
+ LOGGNL;
+
+ if(dwExtraInfo==HOTSTRING){ // a hotstring is being sent, dont do anything
+ return true;
+ }
+
+ // flush the hotstring buffer if certain navi or special keys are pressed (even if they are injected)
+ if(vkCode==VK_UP || vkCode==VK_LEFT || vkCode==VK_RIGHT || vkCode==VK_DOWN
+ || vkCode==VK_PRIOR || vkCode==VK_NEXT || vkCode==VK_END || vkCode==VK_HOME
+ || keyPressed[VK_LCONTROL] || keyPressed[VK_RCONTROL]
+ || keyPressed[VK_LWIN] || keyPressed[VK_RWIN] || keyPressed[VK_LMENU]){
+
+ hotString::clearBuffer();
+ }
+
+ // delete one key from hotstring buffer if backspace is pushed
+ if(vkCode==VK_BACK && !isReleased){
+ int i;
+ for(i=hotString::bufferLen-1;i>0;i--){
+ hotString::hsBuffer.Set(i,(int)hotString::hsBuffer[i-1]);
+ }
+ hotString::hsBuffer.Set(0,(int)0);
+ }
+
+ if(isInjected){ // dont stop or change generated key events
+ return true;
+ }
+
+ // check if the key combination would activate the neo levels
+ if(!neoLevelsActive && !isReleased){
+
+ neoLevelsActive=true; // only simulative to fool getNeoMod
+ int mod=getNeoMod();
+ WORD vkCode_neo;
+
+ if(neoRemapActive && (mod==1 || mod==2 || mod==5 || mod==6) || mod==3 || mod==4 || mod==7){
+ vkCode_neo=neoRemap[vkCode];
+ }
+ else{
+ vkCode_neo=vkCode;
+ }
+ if(map[vkCode_neo][mod-1]!=0xF801){ // keystroke would not activate layers, leave true otherwise
+ neoLevelsActive=false; // deactivate again
+ }
+ else{ // leave activated
+ pKB2->drawKeyButtons();
+ return false;
+ }
+ }
+
+ // check if the key combination turns off mouse control
+ if(mouseControlActive && !isReleased){
+ int mod=getNeoMod();
+ WORD vkCode_neo;
+
+ if(neoRemapActive && (mod==1 || mod==2 || mod==5 || mod==6) || mod==3 || mod==4 || mod==7){
+ vkCode_neo=neoRemap[vkCode];
+ }
+ else{
+ vkCode_neo=vkCode;
+ }
+ if(map[vkCode_neo][mod-1]==0xF806){ // keystroke deactivates mouse control
+ mouseControlActive=false; // deactivate again
+ pKB2->drawKeyButtons();
+ return false;
+ }
+ }
+
+ // dont do substitutions if neolevels are off or
+ // certain functional keys are being pressed or held (getNeoMod returns 0)
+ // this means that ctrl+a/x/c/v/z... remain on their standard position
+ // also clear hotstring buffer then
+ if(getNeoMod()==0
+ || vkCode==VK_LCONTROL || vkCode==VK_RCONTROL
+ || vkCode==VK_LWIN || vkCode==VK_RWIN
+ || vkCode==VK_LMENU){
+
+ // redraw keyboard
+ pKB2->drawKeyButtons();
+
+ return true;
+ }
+
+ // capslock
+ if(keyPressed[VK_LSHIFT] && keyPressed[VK_RSHIFT]
+ && (vkCode==VK_LSHIFT || vkCode==VK_RSHIFT)
+ && !isReleased){
+ capslockActive=!capslockActive;
+ pKB2->drawKeyButtons();
+ }
+
+ // lock 4th layer
+ if(keyPressed[VK_MOD_41] && keyPressed[VK_MOD_42]
+ && (vkCode==VK_MOD_41 || vkCode==VK_MOD_42)
+ && !isReleased){
+ lockLayer4Active=!lockLayer4Active;
+ pKB2->drawKeyButtons();
+ }
+
+ // number keys, letter keys, ",", "-", ".", dead keys, space
+ if((vkCode>=VK_A && vkCode<=VK_Z) || (vkCode>=VK_0 && vkCode<=VK_9)
+ || vkCode==VK_AE || vkCode==VK_OE || vkCode==VK_UE || vkCode==VK_SZ
+ || vkCode==VK_COMMA || vkCode==VK_DASH || vkCode==VK_DOT
+ || vkCode==VK_CIRCUMFLEX || vkCode==VK_ACUT || vkCode==VK_PLUS
+ || vkCode==VK_SPACE || vkCode==VK_TAB){
+
+ if(mouseControlActive){
+ mouseController::mouseEvent(vkCode,isReleased);
+ return false;
+ }
+
+ WORD vkCode_neo;
+ int mod=getNeoMod();
+
+ if(neoRemapActive && (mod==1 || mod==2 || mod==5 || mod==6) || mod==3 || mod==4 || mod==7){
+ vkCode_neo=neoRemap[vkCode];
+ }
+ else{
+ vkCode_neo=vkCode;
+ }
+
+ LOGG("vkCode: ");
+ LOGG((int)vkCode);
+ LOGG(" vkCode_neo: ");
+ LOGG((int)vkCode_neo);
+ LOGG(" mod: ");
+ LOGG(mod);
+
+ if(mod>=1 && mod<=7){
+ wchar charToSend=map[vkCode_neo][mod-1];
+
+ if(cyrillicActive){
+ if(charToSend==ruDeadChar[0] || charToSend==ruDeadChar[1]){
+ lastDeadKey=charToSend;
+ pKB2->drawKeyButtons();
+ return false;
+ }
+ if(charToSend>0 && charToSend<256){
+ if(lastDeadKey==ruDeadChar[0] || lastDeadKey==ruDeadChar[1]){
+ charToSend=rumap[charToSend][1];
+ lastDeadKey=0;
+ pKB2->drawKeyButtons();
+ }
+ else{
+ charToSend=rumap[charToSend][0];
+ lastDeadKey=0;
+ }
+ }
+ }
+
+ if(capslockActive){
+ charToSend=upperCase(charToSend);
+ }
+
+ LOGG(" sending: ");
+ LOGG(charToSend);
+ LOGG(" (U+");
+ LOGG((int)charToSend);
+ LOGG(")");
+ LOGGNL;
+
+ SendUNIKey(charToSend,isReleased);
+ if(!isReleased){
+ long focusPtr=hotString::getFocusWindowPtr();
+
+ if(focusPtr!=hotString::lastFocusPtr){ // if a new window has the focus, clear the buffer
+ hotString::clearBuffer();
+ hotString::lastFocusPtr=focusPtr;
+ }
+
+ hotString::appendBuffer(charToSend);
+ hotString::checkHotStrings();
+ }
+ }
+
+ return false;
+ }
+
+ if(!neoLevelsActive){
+ return true;
+ }
+
+ // redraw keyboard
+ if(vkCode==VK_LSHIFT || vkCode==VK_RSHIFT
+ || vkCode==VK_MOD_31 || vkCode==VK_MOD_32
+ || vkCode==VK_MOD_41 || vkCode==VK_MOD_42
+ || vkCode==VK_LCONTROL || vkCode==VK_RCONTROL){
+ pKB2->drawKeyButtons();
+ }
+
+ // block mod keys that have symbols
+ if(vkCode==VK_MOD_32 || vkCode==VK_MOD_41){
+ return false;
+ }
+
+ return true;
+}
+
+WString KeyBuddy2::buttonLabel(DWORD vkCode){
+
+ wchar res=0;
+
+ if(getNeoMod()==0){
+ return keyNames[vkCode];
+ }
+
+ // number keys, letter keys, ",", "-", ".", dead keys, tab, space
+ if((vkCode>=VK_A && vkCode<=VK_Z) || (vkCode>=VK_0 && vkCode<=VK_9)
+ || vkCode==VK_AE || vkCode==VK_OE || vkCode==VK_UE || vkCode==VK_SZ
+ || vkCode==VK_COMMA || vkCode==VK_DASH || vkCode==VK_DOT
+ || vkCode==VK_CIRCUMFLEX || vkCode==VK_ACUT || vkCode==VK_PLUS
+ || vkCode==VK_TAB || vkCode==VK_SPACE){
+
+ WORD vkCode_neo;
+ int mod=getNeoMod();
+
+ if(mouseControlActive){
+ int i;
+ for(i=0;i<9;i++){
+ if(vkCode==mouseController::mouseKeys[i]){
+ res=mouseController::mouseSymbols[i];
+ return WString((int)res,1);
+ }
+ }
+ return "";
+ }
+
+ if(neoRemapActive && (mod==1 || mod==2 || mod==5 || mod==6) || mod==3 || mod==4 || mod==7){
+ vkCode_neo=neoRemap[vkCode];
+ }
+ else{
+ vkCode_neo=vkCode;
+ }
+
+ if(mod>=1 && mod<=7){
+ res=symbolMap[vkCode_neo][mod-1];
+
+ if(cyrillicActive){
+ if(res==ruDeadChar[0] || res==ruDeadChar[1]){
+ return WString((int)res,1);
+ }
+ if(res>0 && res<256){
+ if(lastDeadKey==ruDeadChar[0] || lastDeadKey==ruDeadChar[1]){
+ res=rumap[res][1];
+ }
+ else{
+ res=rumap[res][0];
+ }
+ }
+ }
+
+ if(capslockActive){
+ res=upperCase(res);
+ }
+
+ return WString((int)res,1);
+ }
+
+ }
+
+ switch(vkCode){ // layer-independent keys
+ case VK_LSHIFT: case VK_RSHIFT: return WString(0x21e7,1); break;
+ case VK_MOD_31: case VK_MOD_32: return WString("Mod3"); break;
+ case VK_MOD_41: case VK_MOD_42: return WString("Mod4"); break;
+ case VK_RETURN: return WString(0x21b5,1); break;
+ case VK_BACK: return WString(0x232b,1); break;
+ case VK_LCONTROL: case VK_RCONTROL: return WString("Strg"); break;
+ case VK_LMENU: return WString("Alt"); break;
+ case VK_LWIN: case VK_RWIN: return WString(0x229e,1)+WString(0x224b,1); break;
+ case VK_APPS: return WString(0x2338,1)+WString(0x21d6,1); break;
+ }
+
+ return WString("");
+
+}
+
+int KeyBuddy2::getNeoMod(){
+
+ if(keyPressed[VK_LCONTROL] || keyPressed[VK_RCONTROL] // functional keys, disable neo stuff
+ || keyPressed[VK_LWIN] || keyPressed[VK_RWIN]
+ || keyPressed[VK_LMENU] || !neoLevelsActive){
+
+ return 0;
+ }
+
+ bool kp2=keyPressed[VK_MOD_21] || keyPressed[VK_MOD_22];
+ bool kp3=keyPressed[VK_MOD_31] || keyPressed[VK_MOD_32];
+ bool kp4=keyPressed[VK_MOD_41] || keyPressed[VK_MOD_42] || lockLayer4Active;
+
+ if(!kp2 && !kp3 && !kp4){return 1;} // small letters
+
+ if( kp2 && !kp3 && !kp4){return 2;} // capital letters
+
+ if(!kp2 && kp3 && !kp4){return 3;} // special characters
+
+ if(!kp2 && !kp3 && kp4){return 4;} // numbers/navi
+
+ if( kp2 && kp3 && !kp4){return 5;} // small greek
+
+ if(!kp2 && kp3 && kp4){return 6;} // capital greek/math
+
+ if( kp2 && !kp3 && kp4){return 7;} // pseudo layer
+
+ return 0;
+
+}
+
+void KeyBuddy2::loadMaps(){
+ FILE* pFile;
+ int i;
+ BYTE buffer;
+ wchar unibuffer;
+
+ #define FGETUC(pbuf,pfile) fread(pbuf,sizeof(wchar),1,pfile)
+
+ // QWERTZ keycode -> neo keycode
+
+ pFile = fopen(SRCPATH "neomap.txt", "rb");
+ if (pFile==NULL) {PromptOK("Can't read neomap.txt"); exit(1);}
+
+ neoRemap[0]=0;
+
+ for(i=1;i<=255;i++){ // assuming that no key has keycode 0. Otherwise the linenumber in map.txt does not match the keycode
+ buffer=fgetc(pFile);
+ if(buffer==13){ // line break, no mapping
+ neoRemap[i]=i;
+ fgetc(pFile); // skip second line break character
+ }
+ else{
+ neoRemap[i]=buffer;
+ fgetc(pFile); // skip line break characters
+ fgetc(pFile);
+ }
+ LOGG("neoRemap ");LOGG(i);LOGG("->");LOGG(neoRemap[i]);LOGGNL;
+ }
+ fclose(pFile);
+
+
+ // keycode -> unicode character to send
+
+ pFile = fopen(SRCPATH "sendmap.txt", "rb");
+ if (pFile==NULL) {PromptOK("Can't read sendmap.txt"); exit(1);}
+
+ fgetc(pFile); // skip BOM
+ fgetc(pFile);
+
+ memset(map[0],0,7);
+
+ for(i=1;i<=255;i++){ // assuming that no key has keycode 0. Otherwise the linenumber in sendmap.txt does not match the keycode
+ fread(map[i],sizeof(wchar),7,pFile); // read from file
+ fgetc(pFile); // skip line break (make sure to have a line break at the end of the file)
+ fgetc(pFile);
+ fgetc(pFile);
+ fgetc(pFile);
+
+ LOGG("key ");LOGG(i);LOGG(": ");LOGG(map[i][0]);LOGG(map[i][1]);LOGG(map[i][2]);LOGG(map[i][3]);LOGG(map[i][4]);LOGG(map[i][5]);LOGG(map[i][6]);LOGGNL;
+ }
+ fclose(pFile);
+
+
+ // keycode -> unicode character to draw on keyboard
+
+ pFile = fopen(SRCPATH "symbolmap.txt", "rb");
+ if (pFile==NULL) {PromptOK("Can't read symbolmap.txt"); exit(1);}
+
+ fgetc(pFile); // skip BOM
+ fgetc(pFile);
+
+ memset(symbolMap[0],0,7);
+
+ for(i=1;i<=255;i++){ // assuming that no key has keycode 0. Otherwise the linenumber in symbolmap.txt does not match the keycode
+ fread(symbolMap[i],sizeof(wchar),7,pFile); // read from file
+ fgetc(pFile); // skip line break (make sure to have a line break at the end of the file)
+ fgetc(pFile);
+ fgetc(pFile);
+ fgetc(pFile);
+
+ LOGG("key ");LOGG(i);LOGG(": ");LOGG(map[i][0]);LOGG(map[i][1]);LOGG(map[i][2]);LOGG(map[i][3]);LOGG(map[i][4]);LOGG(map[i][5]);LOGG(map[i][6]);LOGGNL;
+ }
+ fclose(pFile);
+
+
+ // latin character -> cyrillic character
+ pFile = fopen(SRCPATH "rumap.txt", "rb");
+ if (pFile==NULL) {PromptOK("Can't read rumap.txt"); exit(1);}
+
+ fgetc(pFile); // skip BOM
+ fgetc(pFile);
+
+ rumap[0][0]=0;
+ rumap[0][1]=0;
+
+ int idead=0;
+
+ for(i=1;i<=255;i++){
+ FGETUC(&unibuffer,pFile);
+ if(unibuffer==13){ // line break, no mapping
+ rumap[i][0]=i;
+ rumap[i][1]=i;
+ FGETUC(&unibuffer,pFile); // skip second line break character
+ }
+ else{
+ if(unibuffer==0x2020){ // dagger, symbol for the dead character
+ rumap[i][0]=0;
+ rumap[i][1]=0;
+ ruDeadChar[idead]=i;
+ idead++;
+ FGETUC(&unibuffer,pFile); // skip line break characters
+ FGETUC(&unibuffer,pFile);
+ }
+ else{
+ rumap[i][0]=unibuffer;
+ rumap[i][1]=unibuffer;
+ FGETUC(&unibuffer,pFile);
+ if(unibuffer==13){ // line break, no special character if dead key is toggled
+ FGETUC(&unibuffer,pFile); // skip second line break character
+ }
+ else{ // special character if cyrillic dead key is toggled
+ rumap[i][1]=unibuffer;
+ FGETUC(&unibuffer,pFile); // skip line break characters
+ FGETUC(&unibuffer,pFile);
+ }
+ }
+ }
+ LOGG("russianRemap ");LOGG(i);LOGG("->");LOGG(rumap[i][0]);LOGG("/");LOGG(rumap[i][1]);LOGGNL;
+ }
+ fclose(pFile);
+
+ // keycode -> keyname
+
+ pFile = fopen(SRCPATH "keynames.txt", "rb");
+ if (pFile==NULL) {PromptOK("Can't read keynames.txt"); exit(1);}
+
+ fgetc(pFile); // skip BOM
+ fgetc(pFile);
+
+ keyNames[0]="";
+ for(i=1;i<=255;i++){
+ keyNames[i]="";
+
+ FGETUC(&unibuffer,pFile);
+ while(unibuffer!=13){ // line break
+ keyNames[i]=keyNames[i]+unibuffer;
+ FGETUC(&unibuffer,pFile);
+ }
+
+ FGETUC(&unibuffer,pFile); // skip second line break character
+ }
+ fclose(pFile);
+
+ // lowercase -> uppercase
+
+ pFile = fopen(SRCPATH "uppercase.txt", "rb");
+ if (pFile==NULL) {PromptOK("Can't read uppercase.txt"); exit(1);}
+
+ fgetc(pFile); // skip BOM
+ fgetc(pFile);
+
+ i=0;
+ while(!feof(pFile) && i<1023){
+ FGETUC(&(upperCaseMap[i][0]),pFile);
+ FGETUC(&(upperCaseMap[i][1]),pFile);
+ i++;
+ }
+ fclose(pFile);
+
+ while(i<1023){
+ upperCaseMap[i][0]=0xFFFF;
+ upperCaseMap[i][1]=0xFFFF;
+ i++;
+ }
+
+ // keycode -> mouseevent
+
+ pFile = fopen(SRCPATH "mousemap.txt", "rb");
+ if (pFile==NULL) {PromptOK("Can't read mousemap.txt"); exit(1);}
+
+ fread(mouseController::mouseKeys,sizeof(byte),9,pFile);
+ fclose(pFile);
+}
+
+void KeyBuddy2::SendUNIKey(wchar key, bool release, ULONG_PTR extraInfo){
+
+ // use unicodes Personal Usage Area (E000-F8FF) specially
+ if(key/256>=0xE0 && key/256<=0xF8){ // send keystroke instead of unicode
+ byte flags=key/256;
+ bool onlyDown=flags<=0xE7;
+ bool onlyUp=flags>=0xE8 && flags<=0xEF;
+ bool swtch=(flags==0xF8);
+ bool shift=(flags & 1)!=0;
+ bool ctrl=(flags & 2)!=0;
+ bool alt=(flags & 4)!=0;
+
+ // E0-E7: only down event gets sent
+ // E8-EF: only up event gets sent (but if key is pushed down)
+ // F0-F7: down and up according to release parameter
+ // F8: switch
+ // unicode AND 0x0100 = shift also pressed
+ // unicode AND 0x0200 = ctrl also pressed
+ // unicode AND 0x0400 = alt also pressed
+
+ if(swtch && !release){
+ if(key % 256==0){ // end program
+ KeyBuddy2::pKB2->Break();
+ }
+ if(key % 256==7){ // show / hide GUI
+ KeyBuddy2::pKB2->Show(!KeyBuddy2::pKB2->IsShown());
+ return;
+ }
+ *(KeyBuddy2::pSwitch[key % 256])=!*(KeyBuddy2::pSwitch[key % 256]);
+ return;
+ }
+
+ if((onlyDown || onlyUp) && release){return;}
+
+ // first release all other keys
+ byte keyboardStateBuffer[256];
+ byte allUp[256];
+ DWORD unused;
+
+ memset(keyboardStateBuffer,0,256);
+ memset(allUp,0,256);
+
+ long myThread=GetWindowThreadProcessId(KeyBuddy2::pKB2->GetHWND(),&unused);
+ long otherThread=GetWindowThreadProcessId(GetForegroundWindow(),&unused);
+
+ if(myThread!=otherThread){
+ AttachThreadInput(otherThread,myThread,true);
+ }
+
+ GetKeyboardState(keyboardStateBuffer);
+ SetKeyboardState(allUp);
+
+ // then send the key
+
+ INPUT in[4];
+ int iIn=0;
+
+ for(iIn=0;iIn<4;iIn++){
+ in[iIn].type=INPUT_KEYBOARD;
+ in[iIn].ki.dwExtraInfo=extraInfo;
+ in[iIn].ki.time=0;
+ in[iIn].ki.wScan=0;
+ in[iIn].ki.dwFlags=0;
+ if(release){in[iIn].ki.dwFlags=KEYEVENTF_KEYUP;}
+ }
+
+ iIn=0;
+
+ if(release){ // if we release the buttons, release the key of interest first, then ctrl, alt or shift
+ in[iIn].ki.wVk=key % 256;
+ iIn++;
+ }
+ if(ctrl){
+ in[iIn].ki.wVk=VK_LCONTROL;
+ iIn++;
+ }
+ if(shift){
+ in[iIn].ki.wVk=VK_LSHIFT;
+ iIn++;
+ }
+ if(alt){
+ in[iIn].ki.wVk=VK_LMENU;
+ iIn++;
+ }
+ if(!release){ // if we push the buttons, push ctrl alt shift first, then the key of interest
+ in[iIn].ki.wVk=key % 256;
+ iIn++;
+ }
+
+ SendInput(iIn,in,sizeof(INPUT));
+
+ Sleep(1); // otherwise the other thread does not see the changed keyboard state
+
+ // revert keyboard to its original state
+ SetKeyboardState(keyboardStateBuffer);
+
+ if(myThread!=otherThread){
+ AttachThreadInput(otherThread,myThread,false);
+ }
+ }
+ else{ // only send unicode character
+ INPUT in[1];
+ in[0].type=INPUT_KEYBOARD;
+ in[0].ki.dwExtraInfo=extraInfo;
+ in[0].ki.wVk=0;
+ in[0].ki.wScan=key;
+ in[0].ki.dwFlags=KEYEVENTF_UNICODE;
+ if(release){in[0].ki.dwFlags=in[0].ki.dwFlags | KEYEVENTF_KEYUP;}
+ SendInput(1,in,sizeof(INPUT));
+ }
+}
+
+void KeyBuddy2::releaseAllKeys(){
+ BYTE zeros[256]={0};
+ SetKeyboardState(zeros);
+ for(int i=0;i<256;i++){
+ keyPressed[i]=false;
+ }
+}
+
+void KeyBuddy2::initKeyButtons(){
+ int i,j;
+
+ for(i=0; i<7; i++){
+ buttonStyle[i] = Button::StyleNormal();
+ for(j=0;j<4;j++){
+ buttonStyle[i].look[j] = KB2Images::Get(i);
+ }
+ buttonStyle[i].look[2] = KB2Images::Get(1);
+ buttonStyle[i].pressoffset = Point(0,0);
+ }
+
+ for(i=0;i<256;i++){
+ pKeyButton[i]=&but_invis;
+ keyFinger[i]=0;
+ }
+
+ but_invis.Hide();
+
+ #include "keybuttons.inc"
+
+ int bfid=buttonFont.FindFaceNameIndex("unifont");
+ buttonFont.Face(bfid);
+ buttonFontU.Face(bfid);
+ buttonFontU.Underline();
+ smallButtonFont.Face(bfid);
+ buttonFont.Height(32);
+ buttonFontU.Height(32);
+ smallButtonFont.Height(16);
+
+ for(i=0;i<256;i++){
+ pKeyButton[i]->SetStyle(buttonStyle[keyFinger[i]]);
+ if(i==VK_MOD_31 || i==VK_MOD_32 || i==VK_MOD_41 || i==VK_MOD_42
+ || i==VK_LMENU || i==VK_LCONTROL || i==VK_RCONTROL){
+ pKeyButton[i]->SetFont(smallButtonFont);
+ }
+ else{
+ if(i==VK_A || i==VK_S || i==VK_D || i==VK_F
+ || i==VK_J || i==VK_K || i==VK_L || i==VK_OE){
+ pKeyButton[i]->SetFont(buttonFontU);
+ }
+ else{
+ pKeyButton[i]->SetFont(buttonFont);
+ }
+ }
+
+ pKeyButton[i]->SetLabel(ToUtf8(buttonLabel(i)));
+ //pKeyButton[i]->Disable();
+ }
+}
+
+void KeyBuddy2::drawKeyButtons(){
+ int i;
+ String newLabel,oldLabel;
+
+ for(i=0;i<256;i++){
+ newLabel=ToUtf8(buttonLabel(i));
+ oldLabel=pKeyButton[i]->GetLabel();
+ if(!newLabel.IsEqual(oldLabel)){
+ if(!pKeyButton[i]->isPushed()){
+ pKeyButton[i]->SetLabel(newLabel);
+ }
+ else{
+ pKeyButton[i]->simUp();
+ pKeyButton[i]->SetLabel(newLabel);
+ pKeyButton[i]->simDown();
+ }
+ }
+ }
+}
+
+wchar KeyBuddy2::upperCase(wchar letter){
+ int a=0,b=1022,c;
+
+ while(a<=b){
+ c=(a+b)/2;
+ if( letter< upperCaseMap[c][0] ){b=c-1; continue;}
+ if( letter> upperCaseMap[c][0] ){a=c+1; continue;}
+ if( letter==upperCaseMap[c][0] ){return upperCaseMap[c][1];}
+ }
+
+ return letter;
+}
+
+GUI_APP_MAIN
+{
+ KeyBuddy2().Run();
+}
+
diff --git a/windows/keybuddy2/src/mousecontrol.cpp b/windows/keybuddy2/src/mousecontrol.cpp
new file mode 100644
index 0000000..34b4b97
--- /dev/null
+++ b/windows/keybuddy2/src/mousecontrol.cpp
@@ -0,0 +1,107 @@
+#include "includes.h"
+
+int mouseController::vx=0;
+int mouseController::vy=0;
+
+byte mouseController::mouseKeys[9]={0};
+bool mouseController::mouseButtonStates[3]={0};
+
+wchar mouseController::mouseSymbols[9]={0x15CF,0x15CB,0x15CC,0x15CA,0x15E1,0x15DE,0x15DD,0x15E3,0x15E2};
+
+// generate mouse event for the specified button
+void mouseController::mouseEvent(DWORD vkCode, bool isReleased){
+
+ INPUT in;
+ memset(&in,0,sizeof(INPUT));
+ in.type=INPUT_MOUSE;
+
+ if(vkCode==mouseKeys[MOUSE_MOVE_L]){
+ if(isReleased){
+ vx=0;
+ return;
+ }
+ if(vx>0){vx=0;}
+ if(vx>-20){vx--;}
+ in.mi.dx=vx;
+ in.mi.dwFlags=MOUSEEVENTF_MOVE;
+ }
+ else if(vkCode==mouseKeys[MOUSE_MOVE_R]){
+ if(isReleased){
+ vx=0;
+ return;
+ }
+ if(vx<0){vx=0;}
+ if(vx<20){vx++;}
+ in.mi.dx=vx;
+ in.mi.dwFlags=MOUSEEVENTF_MOVE;
+ }
+ else if(vkCode==mouseKeys[MOUSE_MOVE_U]){
+ if(isReleased){
+ vy=0;
+ return;
+ }
+ if(vy>0){vy=0;}
+ if(vy>-20){vy--;}
+ in.mi.dy=vy;
+ in.mi.dwFlags=MOUSEEVENTF_MOVE;
+ }
+ else if(vkCode==mouseKeys[MOUSE_MOVE_D]){
+ if(isReleased){
+ vy=0;
+ return;
+ }
+ if(vy<0){vy=0;}
+ if(vy<20){vy++;}
+ in.mi.dy=vy;
+ in.mi.dwFlags=MOUSEEVENTF_MOVE;
+ }
+ else if(vkCode==mouseKeys[MOUSE_BUTTON_L]){
+ if(!isReleased && mouseButtonStates[0]){return;} // dont resend clicks
+ if(!isReleased){
+ in.mi.dwFlags=MOUSEEVENTF_LEFTDOWN;
+ mouseButtonStates[0]=true;
+ }
+ else{
+ in.mi.dwFlags=MOUSEEVENTF_LEFTUP;
+ mouseButtonStates[0]=false;
+ }
+ }
+ else if(vkCode==mouseKeys[MOUSE_BUTTON_R]){
+ if(!isReleased && mouseButtonStates[1]){return;} // dont resend clicks
+ if(!isReleased){
+ in.mi.dwFlags=MOUSEEVENTF_RIGHTDOWN;
+ mouseButtonStates[1]=true;
+ }
+ else{
+ in.mi.dwFlags=MOUSEEVENTF_RIGHTUP;
+ mouseButtonStates[1]=false;
+ }
+ }
+ else if(vkCode==mouseKeys[MOUSE_BUTTON_M]){
+ if(!isReleased && mouseButtonStates[2]){return;} // dont resend clicks
+ if(!isReleased){
+ in.mi.dwFlags=MOUSEEVENTF_MIDDLEDOWN;
+ mouseButtonStates[2]=true;
+ }
+ else{
+ in.mi.dwFlags=MOUSEEVENTF_MIDDLEUP;
+ mouseButtonStates[2]=false;
+ }
+ }
+ else if(vkCode==mouseKeys[MOUSE_SCROLL_U]){
+ if(isReleased){return;}
+ in.mi.dwFlags=MOUSEEVENTF_WHEEL;
+ in.mi.mouseData=WHEEL_DELTA;
+ }
+ else if(vkCode==mouseKeys[MOUSE_SCROLL_D]){
+ if(isReleased){return;}
+ in.mi.dwFlags=MOUSEEVENTF_WHEEL;
+ in.mi.mouseData=-WHEEL_DELTA;
+ }
+ else{
+ return; // do not call sendinput
+ }
+
+ // send mouse event
+ SendInput(1,&in,sizeof(INPUT));
+}
diff --git a/windows/keybuddy2/src/mousecontrol.h b/windows/keybuddy2/src/mousecontrol.h
new file mode 100644
index 0000000..1b34550
--- /dev/null
+++ b/windows/keybuddy2/src/mousecontrol.h
@@ -0,0 +1,24 @@
+#ifndef _KeyBuddy2_mousecontrol_h_
+#define _KeyBuddy2_mousecontrol_h_
+
+#include "includes.h"
+
+class mouseController{
+
+public:
+ static int vx,vy; // mouse velocity
+
+ static byte mouseKeys[9];
+ static bool mouseButtonStates[3];
+ static wchar mouseSymbols[9];
+
+ static void mouseEvent(DWORD vkCode, bool isReleased);
+
+};
+
+
+
+
+
+
+#endif
diff --git a/windows/keybuddy2/src/mousedefines.inc b/windows/keybuddy2/src/mousedefines.inc
new file mode 100644
index 0000000..f063239
--- /dev/null
+++ b/windows/keybuddy2/src/mousedefines.inc
@@ -0,0 +1,9 @@
+#define MOUSE_MOVE_L 0
+#define MOUSE_MOVE_U 1
+#define MOUSE_MOVE_R 2
+#define MOUSE_MOVE_D 3
+#define MOUSE_BUTTON_L 4
+#define MOUSE_BUTTON_R 5
+#define MOUSE_BUTTON_M 6
+#define MOUSE_SCROLL_U 7
+#define MOUSE_SCROLL_D 8