1 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11 #include "vkeytable.h"
12 #include "windowstool.h"
17 #include "functions.h"
21 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25 template <class T> class TypeTable
33 template <class T> static inline
34 bool getTypeName(tstring *o_name, T i_type,
35 const TypeTable<T> *i_table, size_t i_n)
37 for (size_t i = 0; i < i_n; ++ i)
38 if (i_table[i].m_type == i_type)
40 *o_name = i_table[i].m_name;
46 template <class T> static inline
47 bool getTypeValue(T *o_type, const tstringi &i_name,
48 const TypeTable<T> *i_table, size_t i_n)
50 for (size_t i = 0; i < i_n; ++ i)
51 if (i_table[i].m_name == i_name)
53 *o_type = i_table[i].m_type;
60 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
65 tostream &operator<<(tostream &i_ost, VKey i_data)
67 if (i_data & VKey_extended)
69 if (i_data & VKey_released)
71 if (i_data & VKey_pressed)
74 u_int8 code = i_data & ~(VKey_extended | VKey_released | VKey_pressed);
76 for (vkt = g_vkeyTable; vkt->m_name; ++ vkt)
77 if (vkt->m_code == code)
82 i_ost << _T("0x") << std::hex << code << std::dec;
87 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
92 typedef TypeTable<ToWindowType> TypeTable_ToWindowType;
93 static const TypeTable_ToWindowType g_toWindowTypeTable[] =
95 { ToWindowType_toOverlappedWindow, _T("toOverlappedWindow") },
96 { ToWindowType_toMainWindow, _T("toMainWindow") },
97 { ToWindowType_toItself, _T("toItself") },
98 { ToWindowType_toParentWindow, _T("toParentWindow") },
103 tostream &operator<<(tostream &i_ost, ToWindowType i_data)
106 if (getTypeName(&name, i_data,
107 g_toWindowTypeTable, NUMBER_OF(g_toWindowTypeTable)))
110 i_ost << static_cast<int>(i_data);
115 // get value of ToWindowType
116 bool getTypeValue(ToWindowType *o_type, const tstring &i_name)
118 return getTypeValue(o_type, i_name,
119 g_toWindowTypeTable, NUMBER_OF(g_toWindowTypeTable));
123 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
128 typedef TypeTable<GravityType> TypeTable_GravityType;
129 static const TypeTable_GravityType g_gravityTypeTable[] =
131 { GravityType_C, _T("C") },
132 { GravityType_N, _T("N") },
133 { GravityType_E, _T("E") },
134 { GravityType_W, _T("W") },
135 { GravityType_S, _T("S") },
136 { GravityType_NW, _T("NW") },
137 { GravityType_NW, _T("WN") },
138 { GravityType_NE, _T("NE") },
139 { GravityType_NE, _T("EN") },
140 { GravityType_SW, _T("SW") },
141 { GravityType_SW, _T("WS") },
142 { GravityType_SE, _T("SE") },
143 { GravityType_SE, _T("ES") },
148 tostream &operator<<(tostream &i_ost, GravityType i_data)
151 if (getTypeName(&name, i_data,
152 g_gravityTypeTable, NUMBER_OF(g_gravityTypeTable)))
155 i_ost << _T("(GravityType internal error)");
160 // get value of GravityType
161 bool getTypeValue(GravityType *o_type, const tstring &i_name)
163 return getTypeValue(o_type, i_name,
164 g_gravityTypeTable, NUMBER_OF(g_gravityTypeTable));
168 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
172 // MouseHookType table
173 typedef TypeTable<MouseHookType> TypeTable_MouseHookType;
174 static const TypeTable_MouseHookType g_mouseHookTypeTable[] =
176 { MouseHookType_None, _T("None") },
177 { MouseHookType_Wheel, _T("Wheel") },
178 { MouseHookType_WindowMove, _T("WindowMove") },
183 tostream &operator<<(tostream &i_ost, MouseHookType i_data)
186 if (getTypeName(&name, i_data,
187 g_mouseHookTypeTable, NUMBER_OF(g_mouseHookTypeTable)))
190 i_ost << _T("(MouseHookType internal error)");
195 // get value of MouseHookType
196 bool getTypeValue(MouseHookType *o_type, const tstring &i_name)
198 return getTypeValue(o_type, i_name, g_mouseHookTypeTable,
199 NUMBER_OF(g_mouseHookTypeTable));
203 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
207 // ModifierLockType table
208 typedef TypeTable<MayuDialogType> TypeTable_MayuDialogType;
209 static const TypeTable_MayuDialogType g_mayuDialogTypeTable[] =
211 { MayuDialogType_investigate, _T("investigate") },
212 { MayuDialogType_log, _T("log") },
217 tostream &operator<<(tostream &i_ost, MayuDialogType i_data)
220 if (getTypeName(&name, i_data,
221 g_mayuDialogTypeTable, NUMBER_OF(g_mayuDialogTypeTable)))
224 i_ost << _T("(MayuDialogType internal error)");
229 // get value of MayuDialogType
230 bool getTypeValue(MayuDialogType *o_type, const tstring &i_name)
232 return getTypeValue(o_type, i_name, g_mayuDialogTypeTable,
233 NUMBER_OF(g_mayuDialogTypeTable));
237 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
242 typedef TypeTable<ToggleType> TypeTable_ToggleType;
243 static const TypeTable_ToggleType g_toggleType[] =
245 { ToggleType_toggle, _T("toggle") },
246 { ToggleType_off, _T("off") },
247 { ToggleType_off, _T("false") },
248 { ToggleType_off, _T("released") },
249 { ToggleType_on, _T("on") },
250 { ToggleType_on, _T("true") },
251 { ToggleType_on, _T("pressed") },
256 tostream &operator<<(tostream &i_ost, ToggleType i_data)
259 if (getTypeName(&name, i_data, g_toggleType, NUMBER_OF(g_toggleType)))
262 i_ost << _T("(ToggleType internal error)");
267 // get value of ToggleType
268 bool getTypeValue(ToggleType *o_type, const tstring &i_name)
270 return getTypeValue(o_type, i_name, g_toggleType,
271 NUMBER_OF(g_toggleType));
275 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
279 // ModifierLockType table
280 typedef TypeTable<ModifierLockType> TypeTable_ModifierLockType;
281 static const TypeTable_ModifierLockType g_modifierLockTypeTable[] =
283 { ModifierLockType_Lock0, _T("lock0") },
284 { ModifierLockType_Lock1, _T("lock1") },
285 { ModifierLockType_Lock2, _T("lock2") },
286 { ModifierLockType_Lock3, _T("lock3") },
287 { ModifierLockType_Lock4, _T("lock4") },
288 { ModifierLockType_Lock5, _T("lock5") },
289 { ModifierLockType_Lock6, _T("lock6") },
290 { ModifierLockType_Lock7, _T("lock7") },
291 { ModifierLockType_Lock8, _T("lock8") },
292 { ModifierLockType_Lock9, _T("lock9") },
297 tostream &operator<<(tostream &i_ost, ModifierLockType i_data)
300 if (getTypeName(&name, i_data,
301 g_modifierLockTypeTable, NUMBER_OF(g_modifierLockTypeTable)))
304 i_ost << _T("(ModifierLockType internal error)");
309 // get value of ModifierLockType
310 bool getTypeValue(ModifierLockType *o_type, const tstring &i_name)
312 return getTypeValue(o_type, i_name, g_modifierLockTypeTable,
313 NUMBER_OF(g_modifierLockTypeTable));
317 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
321 // ShowCommandType table
322 typedef TypeTable<ShowCommandType> TypeTable_ShowCommandType;
323 static const TypeTable_ShowCommandType g_showCommandTypeTable[] =
325 { ShowCommandType_hide, _T("hide") },
326 { ShowCommandType_maximize, _T("maximize") },
327 { ShowCommandType_minimize, _T("minimize") },
328 { ShowCommandType_restore, _T("restore") },
329 { ShowCommandType_show, _T("show") },
330 { ShowCommandType_showDefault, _T("showDefault") },
331 { ShowCommandType_showMaximized, _T("showMaximized") },
332 { ShowCommandType_showMinimized, _T("showMinimized") },
333 { ShowCommandType_showMinNoActive, _T("showMinNoActive") },
334 { ShowCommandType_showNA, _T("showNA") },
335 { ShowCommandType_showNoActivate, _T("showNoActivate") },
336 { ShowCommandType_showNormal, _T("showNormal") },
341 tostream &operator<<(tostream &i_ost, ShowCommandType i_data)
344 if (getTypeName(&name, i_data,
345 g_showCommandTypeTable, NUMBER_OF(g_showCommandTypeTable)))
348 i_ost << _T("(ShowCommandType internal error)");
353 // get value of ShowCommandType
354 bool getTypeValue(ShowCommandType *o_type, const tstring &i_name)
356 return getTypeValue(o_type, i_name, g_showCommandTypeTable,
357 NUMBER_OF(g_showCommandTypeTable));
361 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
365 // ModifierLockType table
366 typedef TypeTable<TargetWindowType> TypeTable_TargetWindowType;
367 static const TypeTable_TargetWindowType g_targetWindowType[] =
369 { TargetWindowType_overlapped, _T("overlapped") },
370 { TargetWindowType_mdi, _T("mdi") },
375 tostream &operator<<(tostream &i_ost, TargetWindowType i_data)
378 if (getTypeName(&name, i_data,
379 g_targetWindowType, NUMBER_OF(g_targetWindowType)))
382 i_ost << _T("(TargetWindowType internal error)");
387 // get value of TargetWindowType
388 bool getTypeValue(TargetWindowType *o_type, const tstring &i_name)
390 return getTypeValue(o_type, i_name, g_targetWindowType,
391 NUMBER_OF(g_targetWindowType));
395 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
400 typedef TypeTable<BooleanType> TypeTable_BooleanType;
401 static const TypeTable_BooleanType g_booleanType[] =
403 { BooleanType_false, _T("false") },
404 { BooleanType_true, _T("true") },
409 tostream &operator<<(tostream &i_ost, BooleanType i_data)
412 if (getTypeName(&name, i_data, g_booleanType, NUMBER_OF(g_booleanType)))
415 i_ost << _T("(BooleanType internal error)");
420 // get value of BooleanType
421 bool getTypeValue(BooleanType *o_type, const tstring &i_name)
423 return getTypeValue(o_type, i_name, g_booleanType,
424 NUMBER_OF(g_booleanType));
428 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
429 // LogicalOperatorType
432 // LogicalOperatorType table
433 typedef TypeTable<LogicalOperatorType> TypeTable_LogicalOperatorType;
434 static const TypeTable_LogicalOperatorType g_logicalOperatorType[] =
436 { LogicalOperatorType_or, _T("||") },
437 { LogicalOperatorType_and, _T("&&") },
442 tostream &operator<<(tostream &i_ost, LogicalOperatorType i_data)
445 if (getTypeName(&name, i_data, g_logicalOperatorType,
446 NUMBER_OF(g_logicalOperatorType)))
449 i_ost << _T("(LogicalOperatorType internal error)");
454 // get value of LogicalOperatorType
455 bool getTypeValue(LogicalOperatorType *o_type, const tstring &i_name)
457 return getTypeValue(o_type, i_name, g_logicalOperatorType,
458 NUMBER_OF(g_logicalOperatorType));
462 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
463 // WindowMonitorFromType
466 // WindowMonitorFromType table
467 typedef TypeTable<WindowMonitorFromType> TypeTable_WindowMonitorFromType;
468 static const TypeTable_WindowMonitorFromType g_windowMonitorFromType[] =
470 { WindowMonitorFromType_primary, _T("primary") },
471 { WindowMonitorFromType_current, _T("current") },
476 tostream &operator<<(tostream &i_ost, WindowMonitorFromType i_data)
479 if(getTypeName(&name, i_data, g_windowMonitorFromType,
480 NUMBER_OF(g_windowMonitorFromType)))
483 i_ost << _T("(WindowMonitorFromType internal error)");
488 // get value of WindowMonitorFromType
489 bool getTypeValue(WindowMonitorFromType *o_type, const tstring &i_name)
491 return getTypeValue(o_type, i_name, g_windowMonitorFromType,
492 NUMBER_OF(g_windowMonitorFromType));
496 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
497 // std::list<tstringq>
501 tostream &operator<<(tostream &i_ost, const std::list<tstringq> &i_data)
503 for (std::list<tstringq>::const_iterator
504 i = i_data.begin(); i != i_data.end(); ++ i)
506 i_ost << *i << _T(", ");
512 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
517 FunctionData::~FunctionData()
523 tostream &operator<<(tostream &i_ost, const FunctionData *i_data)
525 return i_data->output(i_ost);
529 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
534 class FunctionCreator
537 typedef FunctionData *(*Creator)(); ///
540 const _TCHAR *m_name; /// function name
541 Creator m_creator; /// function data creator
546 FunctionData *createFunctionData(const tstring &i_name)
549 #define FUNCTION_CREATOR
550 #include "functions.h"
551 #undef FUNCTION_CREATOR
554 for (size_t i = 0; i != NUMBER_OF(functionCreators); ++ i)
555 if (i_name == functionCreators[i].m_name)
556 return functionCreators[i].m_creator();
561 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
566 bool getSuitableWindow(FunctionParam *i_param, HWND *o_hwnd)
568 if (!i_param->m_isPressed)
570 *o_hwnd = getToplevelWindow(i_param->m_hwnd, NULL);
577 bool getSuitableMdiWindow(FunctionParam *i_param, HWND *o_hwnd,
578 TargetWindowType *io_twt,
579 RECT *o_rcWindow = NULL, RECT *o_rcParent = NULL)
581 if (!i_param->m_isPressed)
583 bool isMdi = *io_twt == TargetWindowType_mdi;
584 *o_hwnd = getToplevelWindow(i_param->m_hwnd, &isMdi);
585 *io_twt = isMdi ? TargetWindowType_mdi : TargetWindowType_overlapped;
590 case TargetWindowType_overlapped:
592 GetWindowRect(*o_hwnd, o_rcWindow);
594 HMONITOR hm = monitorFromWindow(i_param->m_hwnd,
595 MONITOR_DEFAULTTONEAREST);
597 mi.cbSize = sizeof(mi);
598 getMonitorInfo(hm, &mi);
599 *o_rcParent = mi.rcWork;
602 case TargetWindowType_mdi:
604 getChildWindowRect(*o_hwnd, o_rcWindow);
606 GetClientRect(GetParent(*o_hwnd), o_rcParent);
612 // get clipboard text (you must call closeClopboard())
613 static const _TCHAR *getTextFromClipboard(HGLOBAL *o_hdata)
617 if (!OpenClipboard(NULL))
621 *o_hdata = GetClipboardData(CF_UNICODETEXT);
623 *o_hdata = GetClipboardData(CF_TEXT);
628 _TCHAR *data = reinterpret_cast<_TCHAR *>(GlobalLock(*o_hdata));
634 // close clipboard that opend by getTextFromClipboard()
635 static void closeClipboard(HGLOBAL i_hdata, HGLOBAL i_hdataNew = NULL)
638 GlobalUnlock(i_hdata);
643 SetClipboardData(CF_UNICODETEXT, i_hdataNew);
645 SetClipboardData(CF_TEXT, i_hdataNew);
652 // EmacsEditKillLineFunc.
653 // clear the contents of the clopboard
654 // at that time, confirm if it is the result of the previous kill-line
655 void Engine::EmacsEditKillLine::func()
660 const _TCHAR *text = getTextFromClipboard(&g);
661 if (text == NULL || m_buf != text)
665 if (OpenClipboard(NULL))
673 /** if the text of the clipboard is
676 1: EDIT Control (at EOL C-K): "" => buf + "\r\n", Delete
677 0: EDIT Control (other C-K): "(.+)" => buf + "\1"
678 0: IE FORM TEXTAREA (at EOL C-K): "\r\n" => buf + "\r\n"
679 2: IE FORM TEXTAREA (other C-K): "(.+)\r\n" => buf + "\1", Return Left
683 HGLOBAL Engine::EmacsEditKillLine::makeNewKillLineBuf(
684 const _TCHAR *i_data, int *o_retval)
686 size_t len = m_buf.size();
687 len += _tcslen(i_data) + 3;
689 HGLOBAL hdata = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,
690 len * sizeof(_TCHAR));
693 _TCHAR *dataNew = reinterpret_cast<_TCHAR *>(GlobalLock(hdata));
696 _tcscpy(dataNew, m_buf.c_str());
698 len = _tcslen(i_data);
700 i_data[len - 2] == _T('\r') && i_data[len - 1] == _T('\n'))
702 _tcscat(dataNew, i_data);
703 len = _tcslen(dataNew);
704 dataNew[len - 2] = _T('\0'); // chomp
709 _tcscat(dataNew, _T("\r\n"));
714 _tcscat(dataNew, i_data);
725 // EmacsEditKillLinePred
726 int Engine::EmacsEditKillLine::pred()
729 const _TCHAR *text = getTextFromClipboard(&g);
731 HGLOBAL hdata = makeNewKillLineBuf(text ? text : _T(""), &retval);
732 closeClipboard(g, hdata);
737 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
741 // send a default key to Windows
742 void Engine::funcDefault(FunctionParam *i_param)
745 Acquire a(&m_log, 1);
747 i_param->m_doesNeedEndl = false;
749 if (i_param->m_isPressed)
750 generateModifierEvents(i_param->m_c.m_mkey.m_modifier);
751 generateKeyEvent(i_param->m_c.m_mkey.m_key, i_param->m_isPressed, true);
754 // use a corresponding key of a parent keymap
755 void Engine::funcKeymapParent(FunctionParam *i_param)
757 Current c(i_param->m_c);
758 c.m_keymap = c.m_keymap->getParentKeymap();
761 funcDefault(i_param);
766 Acquire a(&m_log, 1);
767 m_log << _T("(") << c.m_keymap->getName() << _T(")") << std::endl;
769 i_param->m_doesNeedEndl = false;
770 generateKeyboardEvents(c);
773 // use a corresponding key of a current window
774 void Engine::funcKeymapWindow(FunctionParam *i_param)
776 Current c(i_param->m_c);
777 c.m_keymap = m_currentFocusOfThread->m_keymaps.front();
778 c.m_i = m_currentFocusOfThread->m_keymaps.begin();
779 generateKeyboardEvents(c);
782 // use a corresponding key of the previous prefixed keymap
783 void Engine::funcKeymapPrevPrefix(FunctionParam *i_param, int i_previous)
785 Current c(i_param->m_c);
786 if (0 < i_previous && 0 <= m_keymapPrefixHistory.size() - i_previous)
788 int n = i_previous - 1;
789 KeymapPtrList::reverse_iterator i = m_keymapPrefixHistory.rbegin();
790 while (0 < n && i != m_keymapPrefixHistory.rend())
793 generateKeyboardEvents(c);
797 // use a corresponding key of an other window class, or use a default key
798 void Engine::funcOtherWindowClass(FunctionParam *i_param)
800 Current c(i_param->m_c);
802 if (c.m_i == m_currentFocusOfThread->m_keymaps.end())
804 funcDefault(i_param);
810 Acquire a(&m_log, 1);
811 m_log << _T("(") << c.m_keymap->getName() << _T(")") << std::endl;
813 i_param->m_doesNeedEndl = false;
814 generateKeyboardEvents(c);
818 void Engine::funcPrefix(FunctionParam *i_param, const Keymap *i_keymap,
819 BooleanType i_doesIgnoreModifiers)
821 if (!i_param->m_isPressed)
824 setCurrentKeymap(i_keymap, true);
826 // generate prefixed event
827 generateEvents(i_param->m_c, m_currentKeymap, &Event::prefixed);
830 m_doesEditNextModifier = false;
831 m_doesIgnoreModifierForPrefix = !!i_doesIgnoreModifiers;
834 Acquire a(&m_log, 1);
835 m_log << _T("(") << i_keymap->getName() << _T(", ")
836 << (i_doesIgnoreModifiers ? _T("true") : _T("false")) << _T(")");
840 // other keymap's key
841 void Engine::funcKeymap(FunctionParam *i_param, const Keymap *i_keymap)
843 Current c(i_param->m_c);
844 c.m_keymap = i_keymap;
846 Acquire a(&m_log, 1);
847 m_log << _T("(") << c.m_keymap->getName() << _T(")") << std::endl;
848 i_param->m_doesNeedEndl = false;
850 generateKeyboardEvents(c);
854 void Engine::funcSync(FunctionParam *i_param)
856 if (i_param->m_isPressed)
857 generateModifierEvents(i_param->m_af->m_modifier);
858 if (!i_param->m_isPressed || m_currentFocusOfThread->m_isConsole)
861 Key *sync = m_setting->m_keyboard.getSyncKey();
862 if (sync->getScanCodesSize() == 0)
864 const ScanCode *sc = sync->getScanCodes();
866 // set variables exported from mayu.dll
867 g_hookData->m_syncKey = sc->m_scan;
868 g_hookData->m_syncKeyIsExtended = !!(sc->m_flags & ScanCode::E0E1);
869 m_isSynchronizing = true;
870 generateKeyEvent(sync, false, false);
873 DWORD r = WaitForSingleObject(m_eSync, 5000);
874 if (r == WAIT_TIMEOUT)
876 Acquire a(&m_log, 0);
877 m_log << _T(" *FAILED*") << std::endl;
880 m_isSynchronizing = false;
884 void Engine::funcToggle(FunctionParam *i_param, ModifierLockType i_lock,
887 if (i_param->m_isPressed) // ignore PRESS
890 Modifier::Type mt = static_cast<Modifier::Type>(i_lock);
893 case ToggleType_toggle:
894 m_currentLock.press(mt, !m_currentLock.isPressed(mt));
897 m_currentLock.press(mt, false);
900 m_currentLock.press(mt, true);
905 // edit next user input key's modifier
906 void Engine::funcEditNextModifier(FunctionParam *i_param,
907 const Modifier &i_modifier)
909 if (!i_param->m_isPressed)
913 m_doesEditNextModifier = true;
914 m_doesIgnoreModifierForPrefix = true;
915 m_modifierForNextKey = i_modifier;
919 void Engine::funcVariable(FunctionParam *i_param, int i_mag, int i_inc)
921 if (!i_param->m_isPressed)
928 void Engine::funcRepeat(FunctionParam *i_param, const KeySeq *i_keySeq,
931 if (i_param->m_isPressed)
933 int end = MIN(m_variable, i_max);
934 for (int i = 0; i < end - 1; ++ i)
935 generateKeySeqEvents(i_param->m_c, i_keySeq, Part_all);
937 generateKeySeqEvents(i_param->m_c, i_keySeq, Part_down);
940 generateKeySeqEvents(i_param->m_c, i_keySeq, Part_up);
944 void Engine::funcUndefined(FunctionParam *i_param)
946 if (!i_param->m_isPressed)
952 void Engine::funcIgnore(FunctionParam *)
958 void Engine::funcPostMessage(FunctionParam *i_param, ToWindowType i_window,
959 UINT i_message, WPARAM i_wParam, LPARAM i_lParam)
961 if (!i_param->m_isPressed)
964 int window = static_cast<int>(i_window);
966 HWND hwnd = i_param->m_hwnd;
969 for (int i = 0; i < window; ++ i)
970 hwnd = GetParent(hwnd);
972 else if (window == ToWindowType_toMainWindow)
976 HWND p = GetParent(hwnd);
982 else if (window == ToWindowType_toOverlappedWindow)
987 LONG_PTR style = GetWindowLongPtr(hwnd, GWL_STYLE);
989 LONG style = GetWindowLong(hwnd, GWL_STYLE);
991 if ((style & WS_CHILD) == 0)
993 hwnd = GetParent(hwnd);
998 PostMessage(hwnd, i_message, i_wParam, i_lParam);
1003 void Engine::funcShellExecute(FunctionParam *i_param,
1004 const StrExprArg &/*i_operation*/,
1005 const StrExprArg &/*i_file*/,
1006 const StrExprArg &/*i_parameters*/,
1007 const StrExprArg &/*i_directory*/,
1008 ShowCommandType /*i_showCommand*/)
1010 if (!i_param->m_isPressed)
1012 m_afShellExecute = i_param->m_af;
1013 PostMessage(m_hwndAssocWindow,
1014 WM_APP_engineNotify, EngineNotify_shellExecute, 0);
1019 void Engine::shellExecute()
1023 FunctionData_ShellExecute *fd =
1024 reinterpret_cast<FunctionData_ShellExecute *>(
1025 m_afShellExecute->m_functionData);
1027 int r = (int)ShellExecute(
1029 fd->m_operation.eval().empty() ? _T("open") : fd->m_operation.eval().c_str(),
1030 fd->m_file.eval().empty() ? NULL : fd->m_file.eval().c_str(),
1031 fd->m_parameters.eval().empty() ? NULL : fd->m_parameters.eval().c_str(),
1032 fd->m_directory.eval().empty() ? NULL : fd->m_directory.eval().c_str(),
1037 typedef TypeTable<int> ErrorTable;
1038 static const ErrorTable errorTable[] =
1040 { 0, _T("The operating system is out of memory or resources.") },
1041 { ERROR_FILE_NOT_FOUND, _T("The specified file was not found.") },
1042 { ERROR_PATH_NOT_FOUND, _T("The specified path was not found.") },
1043 { ERROR_BAD_FORMAT, _T("The .exe file is invalid ")
1044 _T("(non-Win32R .exe or error in .exe image).") },
1045 { SE_ERR_ACCESSDENIED,
1046 _T("The operating system denied access to the specified file.") },
1047 { SE_ERR_ASSOCINCOMPLETE,
1048 _T("The file name association is incomplete or invalid.") },
1050 _T("The DDE transaction could not be completed ")
1051 _T("because other DDE transactions were being processed. ") },
1052 { SE_ERR_DDEFAIL, _T("The DDE transaction failed.") },
1053 { SE_ERR_DDETIMEOUT, _T("The DDE transaction could not be completed ")
1054 _T("because the request timed out.") },
1055 { SE_ERR_DLLNOTFOUND,
1056 _T("The specified dynamic-link library was not found.") },
1057 { SE_ERR_FNF, _T("The specified file was not found.") },
1058 { SE_ERR_NOASSOC, _T("There is no application associated ")
1059 _T("with the given file name extension.") },
1061 _T("There was not enough memory to complete the operation.") },
1062 { SE_ERR_PNF, _T("The specified path was not found.") },
1063 { SE_ERR_SHARE, _T("A sharing violation occurred.") },
1066 tstring errorMessage(_T("Unknown error."));
1067 getTypeName(&errorMessage, r, errorTable, NUMBER_OF(errorTable));
1069 Acquire b(&m_log, 0);
1070 m_log << _T("error: ") << fd << _T(": ") << errorMessage << std::endl;
1074 struct EnumWindowsForSetForegroundWindowParam
1076 const FunctionData_SetForegroundWindow *m_fd;
1080 EnumWindowsForSetForegroundWindowParam(
1081 const FunctionData_SetForegroundWindow *i_fd)
1089 /// enum windows for SetForegroundWindow
1090 static BOOL CALLBACK enumWindowsForSetForegroundWindow(
1091 HWND i_hwnd, LPARAM i_lParam)
1093 EnumWindowsForSetForegroundWindowParam &ep =
1094 *reinterpret_cast<EnumWindowsForSetForegroundWindowParam *>(i_lParam);
1096 _TCHAR name[GANA_MAX_ATOM_LENGTH];
1097 if (!GetClassName(i_hwnd, name, NUMBER_OF(name)))
1100 if (!boost::regex_search(tstring(name), what, ep.m_fd->m_windowClassName))
1101 if (ep.m_fd->m_logicalOp == LogicalOperatorType_and)
1102 return TRUE; // match failed
1104 if (ep.m_fd->m_logicalOp == LogicalOperatorType_and)
1106 if (GetWindowText(i_hwnd, name, NUMBER_OF(name)) == 0)
1108 if (!boost::regex_search(tstring(name), what,
1109 ep.m_fd->m_windowTitleName))
1110 return TRUE; // match failed
1118 /// SetForegroundWindow
1119 void Engine::funcSetForegroundWindow(FunctionParam *i_param, const tregex &,
1120 LogicalOperatorType , const tregex &)
1122 if (!i_param->m_isPressed)
1124 EnumWindowsForSetForegroundWindowParam
1125 ep(static_cast<const FunctionData_SetForegroundWindow *>(
1126 i_param->m_af->m_functionData));
1127 EnumWindows(enumWindowsForSetForegroundWindow,
1128 reinterpret_cast<LPARAM>(&ep));
1130 PostMessage(m_hwndAssocWindow,
1131 WM_APP_engineNotify, EngineNotify_setForegroundWindow,
1132 reinterpret_cast<LPARAM>(ep.m_hwnd));
1138 void Engine::funcLoadSetting(FunctionParam *i_param, const StrExprArg &i_name)
1140 if (!i_param->m_isPressed)
1142 if (!i_name.eval().empty())
1144 // set MAYU_REGISTRY_ROOT\.mayuIndex which name is same with i_name
1145 Registry reg(MAYU_REGISTRY_ROOT);
1147 tregex split(_T("^([^;]*);([^;]*);(.*)$"));
1149 for (size_t i = 0; i < MAX_MAYU_REGISTRY_ENTRIES; ++ i)
1152 _sntprintf(buf, NUMBER_OF(buf), _T(".mayu%d"), i);
1153 if (!reg.read(buf, &dot_mayu))
1157 if (boost::regex_match(dot_mayu, what, split) &&
1158 what.str(1) == i_name.eval())
1160 reg.write(_T(".mayuIndex"), i);
1166 Acquire a(&m_log, 0);
1167 m_log << _T("unknown setting name: ") << i_name;
1173 PostMessage(m_hwndAssocWindow,
1174 WM_APP_engineNotify, EngineNotify_loadSetting, 0);
1178 void Engine::funcVK(FunctionParam *i_param, VKey i_vkey)
1180 long key = static_cast<long>(i_vkey);
1181 BYTE vkey = static_cast<BYTE>(i_vkey);
1182 bool isExtended = !!(key & VKey_extended);
1183 bool isUp = !i_param->m_isPressed && !!(key & VKey_released);
1184 bool isDown = i_param->m_isPressed && !!(key & VKey_pressed);
1186 if (vkey == VK_LBUTTON && isDown)
1187 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
1188 else if (vkey == VK_LBUTTON && isUp)
1189 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
1190 else if (vkey == VK_MBUTTON && isDown)
1191 mouse_event(MOUSEEVENTF_MIDDLEDOWN, 0, 0, 0, 0);
1192 else if (vkey == VK_MBUTTON && isUp)
1193 mouse_event(MOUSEEVENTF_MIDDLEUP, 0, 0, 0, 0);
1194 else if (vkey == VK_RBUTTON && isDown)
1195 mouse_event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0);
1196 else if (vkey == VK_RBUTTON && isUp)
1197 mouse_event(MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0);
1198 else if (vkey == VK_XBUTTON1 && isDown)
1199 mouse_event(MOUSEEVENTF_XDOWN, 0, 0, XBUTTON1, 0);
1200 else if (vkey == VK_XBUTTON1 && isUp)
1201 mouse_event(MOUSEEVENTF_XUP, 0, 0, XBUTTON1, 0);
1202 else if (vkey == VK_XBUTTON2 && isDown)
1203 mouse_event(MOUSEEVENTF_XDOWN, 0, 0, XBUTTON2, 0);
1204 else if (vkey == VK_XBUTTON2 && isUp)
1205 mouse_event(MOUSEEVENTF_XUP, 0, 0, XBUTTON2, 0);
1206 else if (isUp || isDown)
1208 static_cast<BYTE>(MapVirtualKey(vkey, 0)),
1209 (isExtended ? KEYEVENTF_EXTENDEDKEY : 0) |
1210 (i_param->m_isPressed ? 0 : KEYEVENTF_KEYUP), 0);
1214 void Engine::funcWait(FunctionParam *i_param, int i_milliSecond)
1216 if (!i_param->m_isPressed)
1218 if (i_milliSecond < 0 || 5000 < i_milliSecond) // too long wait
1221 m_isSynchronizing = true;
1223 Sleep(i_milliSecond);
1225 m_isSynchronizing = false;
1228 // investigate WM_COMMAND, WM_SYSCOMMAND
1229 void Engine::funcInvestigateCommand(FunctionParam *i_param)
1231 if (!i_param->m_isPressed)
1233 Acquire a(&m_log, 0);
1234 g_hookData->m_doesNotifyCommand = !g_hookData->m_doesNotifyCommand;
1235 if (g_hookData->m_doesNotifyCommand)
1236 m_log << _T(" begin") << std::endl;
1238 m_log << _T(" end") << std::endl;
1241 // show mayu dialog box
1242 void Engine::funcMayuDialog(FunctionParam *i_param, MayuDialogType i_dialog,
1243 ShowCommandType i_showCommand)
1245 if (!i_param->m_isPressed)
1247 PostMessage(getAssociatedWndow(), WM_APP_engineNotify, EngineNotify_showDlg,
1248 static_cast<LPARAM>(i_dialog) |
1249 static_cast<LPARAM>(i_showCommand));
1252 // describe bindings
1253 void Engine::funcDescribeBindings(FunctionParam *i_param)
1255 if (!i_param->m_isPressed)
1258 Acquire a(&m_log, 1);
1264 // show help message
1265 void Engine::funcHelpMessage(FunctionParam *i_param, const StrExprArg &i_title,
1266 const StrExprArg &i_message)
1268 if (!i_param->m_isPressed)
1271 m_helpTitle = i_title.eval();
1272 m_helpMessage = i_message.eval();
1273 bool doesShow = !(i_title.eval().size() == 0 && i_message.eval().size() == 0);
1274 PostMessage(getAssociatedWndow(), WM_APP_engineNotify,
1275 EngineNotify_helpMessage, doesShow);
1279 void Engine::funcHelpVariable(FunctionParam *i_param, const StrExprArg &i_title)
1281 if (!i_param->m_isPressed)
1285 _sntprintf(buf, NUMBER_OF(buf), _T("%d"), m_variable);
1287 m_helpTitle = i_title.eval();
1288 m_helpMessage = buf;
1289 PostMessage(getAssociatedWndow(), WM_APP_engineNotify,
1290 EngineNotify_helpMessage, true);
1294 void Engine::funcWindowRaise(FunctionParam *i_param,
1295 TargetWindowType i_twt)
1298 if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt))
1300 SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0,
1301 SWP_ASYNCWINDOWPOS | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOSIZE);
1305 void Engine::funcWindowLower(FunctionParam *i_param, TargetWindowType i_twt)
1308 if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt))
1310 SetWindowPos(hwnd, HWND_BOTTOM, 0, 0, 0, 0,
1311 SWP_ASYNCWINDOWPOS | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOSIZE);
1315 void Engine::funcWindowMinimize(FunctionParam *i_param, TargetWindowType i_twt)
1318 if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt))
1320 PostMessage(hwnd, WM_SYSCOMMAND,
1321 IsIconic(hwnd) ? SC_RESTORE : SC_MINIMIZE, 0);
1325 void Engine::funcWindowMaximize(FunctionParam *i_param, TargetWindowType i_twt)
1328 if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt))
1330 PostMessage(hwnd, WM_SYSCOMMAND,
1331 IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, 0);
1334 // maximize horizontally or virtically
1335 void Engine::funcWindowHVMaximize(FunctionParam *i_param,
1336 BooleanType i_isHorizontal,
1337 TargetWindowType i_twt)
1341 if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt, &rc, &rcd))
1347 WindowPositions::iterator i = m_windowPositions.begin();
1348 WindowPositions::iterator end = m_windowPositions.end();
1349 for (; i != end; ++ i)
1350 if (!IsWindow((*i).m_hwnd))
1354 m_windowPositions.erase(i);
1358 WindowPositions::iterator i = m_windowPositions.begin();
1359 WindowPositions::iterator end = m_windowPositions.end();
1360 WindowPositions::iterator target = end;
1361 for (; i != end; ++ i)
1362 if ((*i).m_hwnd == hwnd)
1369 PostMessage(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
1372 WindowPosition::Mode mode = WindowPosition::Mode_normal;
1376 WindowPosition &wp = *target;
1378 if (wp.m_mode == WindowPosition::Mode_HV)
1380 i_isHorizontal ? WindowPosition::Mode_V : WindowPosition::Mode_H;
1381 else if (( i_isHorizontal && wp.m_mode == WindowPosition::Mode_V) ||
1382 (!i_isHorizontal && wp.m_mode == WindowPosition::Mode_H))
1383 mode = wp.m_mode = WindowPosition::Mode_HV;
1385 m_windowPositions.erase(target);
1389 mode = i_isHorizontal ? WindowPosition::Mode_H : WindowPosition::Mode_V;
1390 m_windowPositions.push_front(WindowPosition(hwnd, rc, mode));
1393 if (static_cast<int>(mode) & static_cast<int>(WindowPosition::Mode_H))
1394 rc.left = rcd.left, rc.right = rcd.right;
1395 if (static_cast<int>(mode) & static_cast<int>(WindowPosition::Mode_V))
1396 rc.top = rcd.top, rc.bottom = rcd.bottom;
1398 asyncMoveWindow(hwnd, rc.left, rc.top, rcWidth(&rc), rcHeight(&rc));
1402 // maximize window horizontally
1403 void Engine::funcWindowHMaximize(FunctionParam *i_param,
1404 TargetWindowType i_twt)
1406 funcWindowHVMaximize(i_param, BooleanType_true, i_twt);
1409 // maximize window virtically
1410 void Engine::funcWindowVMaximize(FunctionParam *i_param,
1411 TargetWindowType i_twt)
1413 funcWindowHVMaximize(i_param, BooleanType_false, i_twt);
1417 void Engine::funcWindowMove(FunctionParam *i_param, int i_dx, int i_dy,
1418 TargetWindowType i_twt)
1420 funcWindowMoveTo(i_param, GravityType_C, i_dx, i_dy, i_twt);
1423 // move window to ...
1424 void Engine::funcWindowMoveTo(FunctionParam *i_param,
1425 GravityType i_gravityType,
1426 int i_dx, int i_dy, TargetWindowType i_twt)
1430 if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt, &rc, &rcd))
1433 int x = rc.left + i_dx;
1434 int y = rc.top + i_dy;
1436 if (i_gravityType & GravityType_N)
1438 if (i_gravityType & GravityType_E)
1439 x = i_dx + rcd.right - rcWidth(&rc);
1440 if (i_gravityType & GravityType_W)
1441 x = i_dx + rcd.left;
1442 if (i_gravityType & GravityType_S)
1443 y = i_dy + rcd.bottom - rcHeight(&rc);
1444 asyncMoveWindow(hwnd, x, y);
1448 // move window visibly
1449 void Engine::funcWindowMoveVisibly(FunctionParam *i_param,
1450 TargetWindowType i_twt)
1454 if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt, &rc, &rcd))
1459 if (rc.left < rcd.left)
1461 else if (rcd.right < rc.right)
1462 x = rcd.right - rcWidth(&rc);
1463 if (rc.top < rcd.top)
1465 else if (rcd.bottom < rc.bottom)
1466 y = rcd.bottom - rcHeight(&rc);
1467 asyncMoveWindow(hwnd, x, y);
1471 struct EnumDisplayMonitorsForWindowMonitorToParam
1473 std::vector<HMONITOR> m_monitors;
1474 std::vector<MONITORINFO> m_monitorinfos;
1475 int m_primaryMonitorIdx;
1476 int m_currentMonitorIdx;
1481 EnumDisplayMonitorsForWindowMonitorToParam(HMONITOR i_hmon)
1483 m_primaryMonitorIdx(-1), m_currentMonitorIdx(-1)
1488 static BOOL CALLBACK enumDisplayMonitorsForWindowMonitorTo(
1489 HMONITOR i_hmon, HDC i_hdc, LPRECT i_rcMonitor, LPARAM i_data)
1491 EnumDisplayMonitorsForWindowMonitorToParam &ep =
1492 *reinterpret_cast<EnumDisplayMonitorsForWindowMonitorToParam *>(i_data);
1494 ep.m_monitors.push_back(i_hmon);
1497 mi.cbSize = sizeof(mi);
1498 getMonitorInfo(i_hmon, &mi);
1499 ep.m_monitorinfos.push_back(mi);
1501 if(mi.dwFlags & MONITORINFOF_PRIMARY)
1502 ep.m_primaryMonitorIdx = ep.m_monitors.size() - 1;
1503 if(i_hmon == ep.m_hmon)
1504 ep.m_currentMonitorIdx = ep.m_monitors.size() - 1;
1509 /// move window to other monitor
1510 void Engine::funcWindowMonitorTo(
1511 FunctionParam *i_param, WindowMonitorFromType i_fromType, int i_monitor,
1512 BooleanType i_adjustPos, BooleanType i_adjustSize)
1515 if(! getSuitableWindow(i_param, &hwnd))
1519 hmonCur = monitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
1521 EnumDisplayMonitorsForWindowMonitorToParam ep(hmonCur);
1522 enumDisplayMonitors(NULL, NULL, enumDisplayMonitorsForWindowMonitorTo,
1523 reinterpret_cast<LPARAM>(&ep));
1524 if(ep.m_monitors.size() < 1 ||
1525 ep.m_primaryMonitorIdx < 0 || ep.m_currentMonitorIdx < 0)
1529 switch(i_fromType) {
1530 case WindowMonitorFromType_primary:
1531 targetIdx = (ep.m_primaryMonitorIdx + i_monitor) % ep.m_monitors.size();
1534 case WindowMonitorFromType_current:
1535 targetIdx = (ep.m_currentMonitorIdx + i_monitor) % ep.m_monitors.size();
1538 if(ep.m_currentMonitorIdx == targetIdx)
1541 RECT rcCur, rcTarget, rcWin;
1542 rcCur = ep.m_monitorinfos[ep.m_currentMonitorIdx].rcWork;
1543 rcTarget = ep.m_monitorinfos[targetIdx].rcWork;
1544 GetWindowRect(hwnd, &rcWin);
1546 int x = rcTarget.left + (rcWin.left - rcCur.left);
1547 int y = rcTarget.top + (rcWin.top - rcCur.top);
1548 int w = rcWidth(&rcWin);
1549 int h = rcHeight(&rcWin);
1552 if(x + w > rcTarget.right)
1553 x = rcTarget.right - w;
1554 if(x < rcTarget.left)
1556 if(w > rcWidth(&rcTarget)) {
1558 w = rcWidth(&rcTarget);
1561 if(y + h > rcTarget.bottom)
1562 y = rcTarget.bottom - h;
1563 if(y < rcTarget.top)
1565 if(h > rcHeight(&rcTarget)) {
1567 h = rcHeight(&rcTarget);
1571 if(i_adjustPos && i_adjustSize) {
1573 PostMessage(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
1574 asyncMoveWindow(hwnd, x, y, w, h);
1576 asyncMoveWindow(hwnd, x, y);
1580 /// move window to other monitor
1581 void Engine::funcWindowMonitor(
1582 FunctionParam *i_param, int i_monitor,
1583 BooleanType i_adjustPos, BooleanType i_adjustSize)
1585 funcWindowMonitorTo(i_param, WindowMonitorFromType_primary, i_monitor,
1586 i_adjustPos, i_adjustSize);
1591 void Engine::funcWindowClingToLeft(FunctionParam *i_param,
1592 TargetWindowType i_twt)
1594 funcWindowMoveTo(i_param, GravityType_W, 0, 0, i_twt);
1598 void Engine::funcWindowClingToRight(FunctionParam *i_param,
1599 TargetWindowType i_twt)
1601 funcWindowMoveTo(i_param, GravityType_E, 0, 0, i_twt);
1605 void Engine::funcWindowClingToTop(FunctionParam *i_param,
1606 TargetWindowType i_twt)
1608 funcWindowMoveTo(i_param, GravityType_N, 0, 0, i_twt);
1612 void Engine::funcWindowClingToBottom(FunctionParam *i_param,
1613 TargetWindowType i_twt)
1615 funcWindowMoveTo(i_param, GravityType_S, 0, 0, i_twt);
1619 void Engine::funcWindowClose(FunctionParam *i_param, TargetWindowType i_twt)
1622 if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt))
1624 PostMessage(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0);
1627 // toggle top-most flag of the window
1628 void Engine::funcWindowToggleTopMost(FunctionParam *i_param)
1631 if (!getSuitableWindow(i_param, &hwnd))
1636 (GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST) ?
1638 (GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST) ?
1640 HWND_NOTOPMOST : HWND_TOPMOST,
1642 SWP_ASYNCWINDOWPOS | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOSIZE);
1645 // identify the window
1646 void Engine::funcWindowIdentify(FunctionParam *i_param)
1648 if (!i_param->m_isPressed)
1651 _TCHAR className[GANA_MAX_ATOM_LENGTH];
1653 if (GetClassName(i_param->m_hwnd, className, NUMBER_OF(className)))
1655 if (_tcsicmp(className, _T("ConsoleWindowClass")) == 0)
1657 _TCHAR titleName[1024];
1658 if (GetWindowText(i_param->m_hwnd, titleName, NUMBER_OF(titleName)) == 0)
1659 titleName[0] = _T('\0');
1661 Acquire a(&m_log, 1);
1662 m_log << _T("HWND:\t") << std::hex
1663 << reinterpret_cast<int>(i_param->m_hwnd)
1664 << std::dec << std::endl;
1666 Acquire a(&m_log, 0);
1667 m_log << _T("CLASS:\t") << className << std::endl;
1668 m_log << _T("TITLE:\t") << titleName << std::endl;
1670 HWND hwnd = getToplevelWindow(i_param->m_hwnd, NULL);
1672 GetWindowRect(hwnd, &rc);
1673 m_log << _T("Toplevel Window Position/Size: (")
1674 << rc.left << _T(", ") << rc.top << _T(") / (")
1675 << rcWidth(&rc) << _T("x") << rcHeight(&rc)
1676 << _T(")") << std::endl;
1678 SystemParametersInfo(SPI_GETWORKAREA, 0, (void *)&rc, FALSE);
1679 m_log << _T("Desktop Window Position/Size: (")
1680 << rc.left << _T(", ") << rc.top << _T(") / (")
1681 << rcWidth(&rc) << _T("x") << rcHeight(&rc)
1682 << _T(")") << std::endl;
1690 UINT WM_MAYU_MESSAGE = RegisterWindowMessage(
1691 addSessionId(WM_MAYU_MESSAGE_NAME).c_str());
1692 CHECK_TRUE( PostMessage(i_param->m_hwnd, WM_MAYU_MESSAGE,
1693 MayuMessage_notifyName, 0) );
1697 // set alpha blending parameter to the window
1698 void Engine::funcWindowSetAlpha(FunctionParam *i_param, int i_alpha)
1701 if (!getSuitableWindow(i_param, &hwnd))
1704 if (i_alpha < 0) // remove all alpha
1706 for (WindowsWithAlpha::iterator i = m_windowsWithAlpha.begin();
1707 i != m_windowsWithAlpha.end(); ++ i)
1710 SetWindowLongPtr(*i, GWL_EXSTYLE,
1711 GetWindowLongPtr(*i, GWL_EXSTYLE) & ~WS_EX_LAYERED);
1713 SetWindowLong(*i, GWL_EXSTYLE,
1714 GetWindowLong(*i, GWL_EXSTYLE) & ~WS_EX_LAYERED);
1716 RedrawWindow(*i, NULL, NULL,
1717 RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);
1719 m_windowsWithAlpha.clear();
1724 LONG_PTR exStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE);
1726 LONG exStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
1728 if (exStyle & WS_EX_LAYERED) // remove alpha
1730 WindowsWithAlpha::iterator
1731 i = std::find(m_windowsWithAlpha.begin(), m_windowsWithAlpha.end(),
1733 if (i == m_windowsWithAlpha.end())
1734 return; // already layered by the application
1736 m_windowsWithAlpha.erase(i);
1739 SetWindowLongPtr(hwnd, GWL_EXSTYLE, exStyle & ~WS_EX_LAYERED);
1741 SetWindowLong(hwnd, GWL_EXSTYLE, exStyle & ~WS_EX_LAYERED);
1747 SetWindowLongPtr(hwnd, GWL_EXSTYLE, exStyle | WS_EX_LAYERED);
1749 SetWindowLong(hwnd, GWL_EXSTYLE, exStyle | WS_EX_LAYERED);
1752 if (!setLayeredWindowAttributes(hwnd, 0,
1753 (BYTE)(255 * i_alpha / 100), LWA_ALPHA))
1755 Acquire a(&m_log, 0);
1756 m_log << _T("error: &WindowSetAlpha(") << i_alpha
1757 << _T(") failed for HWND: ") << std::hex
1758 << hwnd << std::dec << std::endl;
1761 m_windowsWithAlpha.push_front(hwnd);
1763 RedrawWindow(hwnd, NULL, NULL,
1764 RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);
1769 // redraw the window
1770 void Engine::funcWindowRedraw(FunctionParam *i_param)
1773 if (!getSuitableWindow(i_param, &hwnd))
1775 RedrawWindow(hwnd, NULL, NULL,
1776 RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);
1780 void Engine::funcWindowResizeTo(FunctionParam *i_param, int i_width,
1781 int i_height, TargetWindowType i_twt)
1785 if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt, &rc, &rcd))
1789 i_width = rcWidth(&rc);
1790 else if (i_width < 0)
1791 i_width += rcWidth(&rcd);
1794 i_height = rcHeight(&rc);
1795 else if (i_height < 0)
1796 i_height += rcHeight(&rcd);
1798 asyncResize(hwnd, i_width, i_height);
1801 // move the mouse cursor
1802 void Engine::funcMouseMove(FunctionParam *i_param, int i_dx, int i_dy)
1804 if (!i_param->m_isPressed)
1808 SetCursorPos(pt.x + i_dx, pt.y + i_dy);
1811 // send a mouse-wheel-message to Windows
1812 void Engine::funcMouseWheel(FunctionParam *i_param, int i_delta)
1814 if (!i_param->m_isPressed)
1816 mouse_event(MOUSEEVENTF_WHEEL, 0, 0, i_delta, 0);
1819 // convert the contents of the Clipboard to upper case
1820 void Engine::funcClipboardChangeCase(FunctionParam *i_param,
1821 BooleanType i_doesConvertToUpperCase)
1823 if (!i_param->m_isPressed)
1827 const _TCHAR *text = getTextFromClipboard(&hdata);
1828 HGLOBAL hdataNew = NULL;
1831 int size = static_cast<int>(GlobalSize(hdata));
1832 hdataNew = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, size);
1835 if (_TCHAR *dataNew = reinterpret_cast<_TCHAR *>(GlobalLock(hdataNew)))
1837 std::memcpy(dataNew, text, size);
1838 _TCHAR *dataEnd = dataNew + size;
1839 while (dataNew < dataEnd && *dataNew)
1841 _TCHAR c = *dataNew;
1846 i_doesConvertToUpperCase ? _totupper(c) : _totlower(c);
1848 GlobalUnlock(hdataNew);
1852 closeClipboard(hdata, hdataNew);
1855 // convert the contents of the Clipboard to upper case
1856 void Engine::funcClipboardUpcaseWord(FunctionParam *i_param)
1858 funcClipboardChangeCase(i_param, BooleanType_true);
1861 // convert the contents of the Clipboard to lower case
1862 void Engine::funcClipboardDowncaseWord(FunctionParam *i_param)
1864 funcClipboardChangeCase(i_param, BooleanType_false);
1867 // set the contents of the Clipboard to the string
1868 void Engine::funcClipboardCopy(FunctionParam *i_param, const StrExprArg &i_text)
1870 if (!i_param->m_isPressed)
1872 if (!OpenClipboard(NULL))
1876 GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,
1877 (i_text.eval().size() + 1) * sizeof(_TCHAR));
1880 _TCHAR *dataNew = reinterpret_cast<_TCHAR *>(GlobalLock(hdataNew));
1881 _tcscpy(dataNew, i_text.eval().c_str());
1882 GlobalUnlock(hdataNew);
1883 closeClipboard(NULL, hdataNew);
1887 void Engine::funcEmacsEditKillLinePred(
1888 FunctionParam *i_param, const KeySeq *i_keySeq1, const KeySeq *i_keySeq2)
1890 m_emacsEditKillLine.m_doForceReset = false;
1891 if (!i_param->m_isPressed)
1894 int r = m_emacsEditKillLine.pred();
1895 const KeySeq *keySeq;
1903 generateKeySeqEvents(i_param->m_c, keySeq, Part_all);
1907 void Engine::funcEmacsEditKillLineFunc(FunctionParam *i_param)
1909 if (!i_param->m_isPressed)
1911 m_emacsEditKillLine.func();
1912 m_emacsEditKillLine.m_doForceReset = false;
1916 void Engine::funcLogClear(FunctionParam *i_param)
1918 if (!i_param->m_isPressed)
1920 PostMessage(getAssociatedWndow(), WM_APP_engineNotify,
1921 EngineNotify_clearLog, 0);
1925 void Engine::funcRecenter(FunctionParam *i_param)
1927 if (!i_param->m_isPressed)
1931 UINT WM_MAYU_MESSAGE = RegisterWindowMessage(
1932 addSessionId(WM_MAYU_MESSAGE_NAME).c_str());
1933 PostMessage(m_hwndFocus, WM_MAYU_MESSAGE, MayuMessage_funcRecenter, 0);
1937 // set IME open status
1938 void Engine::funcSetImeStatus(FunctionParam *i_param, ToggleType i_toggle)
1940 if (!i_param->m_isPressed)
1944 UINT WM_MAYU_MESSAGE = RegisterWindowMessage(
1945 addSessionId(WM_MAYU_MESSAGE_NAME).c_str());
1949 case ToggleType_toggle:
1952 case ToggleType_off:
1959 PostMessage(m_hwndFocus, WM_MAYU_MESSAGE, MayuMessage_funcSetImeStatus, status);
1963 // set IME open status
1964 void Engine::funcSetImeString(FunctionParam *i_param, const StrExprArg &i_data)
1966 if (!i_param->m_isPressed)
1970 UINT WM_MAYU_MESSAGE = RegisterWindowMessage(
1971 addSessionId(WM_MAYU_MESSAGE_NAME).c_str());
1972 PostMessage(m_hwndFocus, WM_MAYU_MESSAGE, MayuMessage_funcSetImeString, i_data.eval().size() * sizeof(_TCHAR));
1976 DisconnectNamedPipe(m_hookPipe);
1977 ConnectNamedPipe(m_hookPipe, NULL);
1978 error = WriteFile(m_hookPipe, i_data.eval().c_str(),
1979 i_data.eval().size() * sizeof(_TCHAR),
1982 //FlushFileBuffers(m_hookPipe);
1986 // Direct SSTP Server
1987 class DirectSSTPServer
2003 class ParseDirectSSTPData
2005 typedef boost::match_results<boost::regex::const_iterator> MR;
2008 typedef std::map<tstring, DirectSSTPServer> DirectSSTPServers;
2011 DirectSSTPServers *m_directSSTPServers;
2015 ParseDirectSSTPData(DirectSSTPServers *i_directSSTPServers)
2016 : m_directSSTPServers(i_directSSTPServers)
2020 bool operator()(const MR& i_what)
2023 tstring id(to_wstring(std::string(i_what[1].first, i_what[1].second)));
2024 tstring member(to_wstring(std::string(i_what[2].first, i_what[2].second)));
2025 tstring value(to_wstring(std::string(i_what[3].first, i_what[3].second)));
2027 tstring id(i_what[1].first, i_what[1].second);
2028 tstring member(i_what[2].first, i_what[2].second);
2029 tstring value(i_what[3].first, i_what[3].second);
2032 if (member == _T("path"))
2033 (*m_directSSTPServers)[id].m_path = value;
2034 else if (member == _T("hwnd"))
2035 (*m_directSSTPServers)[id].m_hwnd =
2036 reinterpret_cast<HWND>(_ttoi(value.c_str()));
2037 else if (member == _T("name"))
2038 (*m_directSSTPServers)[id].m_name = value;
2039 else if (member == _T("keroname"))
2040 (*m_directSSTPServers)[id].m_keroname = value;
2046 void Engine::funcDirectSSTP(FunctionParam *i_param,
2047 const tregex &i_name,
2048 const StrExprArg &i_protocol,
2049 const std::list<tstringq> &i_headers)
2051 if (!i_param->m_isPressed)
2054 // check Direct SSTP server exist ?
2055 if (HANDLE hm = OpenMutex(MUTEX_ALL_ACCESS, FALSE, _T("sakura")))
2059 Acquire a(&m_log, 0);
2060 m_log << _T(" Error(1): Direct SSTP server does not exist.");
2064 HANDLE hfm = OpenFileMapping(FILE_MAP_READ, FALSE, _T("Sakura"));
2067 Acquire a(&m_log, 0);
2068 m_log << _T(" Error(2): Direct SSTP server does not provide data.");
2073 reinterpret_cast<char *>(MapViewOfFile(hfm, FILE_MAP_READ, 0, 0, 0));
2077 Acquire a(&m_log, 0);
2078 m_log << _T(" Error(3): Direct SSTP server does not provide data.");
2082 long length = *(long *)data;
2083 const char *begin = data + 4;
2084 const char *end = data + length;
2085 boost::regex getSakura("([0-9a-fA-F]{32})\\.([^\x01]+)\x01(.*?)\r\n");
2087 ParseDirectSSTPData::DirectSSTPServers servers;
2088 boost::regex_iterator<boost::regex::const_iterator>
2089 it(begin, end, getSakura), last;
2090 for (; it != last; ++it)
2091 ((ParseDirectSSTPData)(&servers))(*it);
2095 if (!i_protocol.eval().size())
2096 request += _T("NOTIFY SSTP/1.1");
2098 request += i_protocol.eval();
2099 request += _T("\r\n");
2101 bool hasSender = false;
2102 for (std::list<tstringq>::const_iterator
2103 i = i_headers.begin(); i != i_headers.end(); ++ i)
2105 if (_tcsnicmp(_T("Charset"), i->c_str(), 7) == 0 ||
2106 _tcsnicmp(_T("Hwnd"), i->c_str(), 4) == 0)
2108 if (_tcsnicmp(_T("Sender"), i->c_str(), 6) == 0)
2110 request += i->c_str();
2111 request += _T("\r\n");
2116 request += _T("Sender: ");
2117 request += loadString(IDS_mayu);
2118 request += _T("\r\n");
2122 _sntprintf(buf, NUMBER_OF(buf), _T("HWnd: %d\r\n"),
2123 reinterpret_cast<int>(m_hwndAssocWindow));
2127 request += _T("Charset: UTF-8\r\n");
2129 request += _T("Charset: Shift_JIS\r\n");
2131 request += _T("\r\n");
2134 std::string request_UTF_8 = to_UTF_8(request);
2137 // send request to Direct SSTP Server which matches i_name;
2138 for (ParseDirectSSTPData::DirectSSTPServers::iterator
2139 i = servers.begin(); i != servers.end(); ++ i)
2142 if (boost::regex_match(i->second.m_name, what, i_name))
2147 cd.cbData = request_UTF_8.size();
2148 cd.lpData = (void *)request_UTF_8.c_str();
2150 cd.cbData = request.size();
2151 cd.lpData = (void *)request.c_str();
2158 SendMessageTimeout(i->second.m_hwnd, WM_COPYDATA,
2159 reinterpret_cast<WPARAM>(m_hwndAssocWindow),
2160 reinterpret_cast<LPARAM>(&cd),
2161 SMTO_ABORTIFHUNG | SMTO_BLOCK, 5000, &result);
2165 UnmapViewOfFile(data);
2184 tstringq m_funcParam;
2187 PlugIn() : m_dll(NULL)
2196 bool load(const tstringq &i_dllName, const tstringq &i_funcName,
2197 const tstringq &i_funcParam, tomsgstream &i_log)
2199 m_dll = LoadLibrary((_T("Plugins\\") + i_dllName).c_str());
2202 m_dll = LoadLibrary((_T("Plugin\\") + i_dllName).c_str());
2205 m_dll = LoadLibrary(i_dllName.c_str());
2210 i_log << _T("error: &PlugIn() failed to load ") << i_dllName << std::endl;
2223 m_func = GetProcAddress(m_dll, to_string(_T("mayu") + i_funcName + _T("W")).c_str());
2228 = GetProcAddress(m_dll, to_string(_T("mayu") + i_funcName + _T("A")).c_str());
2231 m_func = GetProcAddress(m_dll, to_string(_T("mayu") + i_funcName).c_str());
2234 m_func = GetProcAddress(m_dll, to_string(i_funcName).c_str());
2239 i_log << _T("error: &PlugIn() failed to find function: ")
2240 << i_funcName << std::endl;
2247 m_funcParam = i_funcParam;
2256 typedef void (WINAPI * PLUGIN_FUNCTION_A)(const char *i_arg);
2257 typedef void (WINAPI * PLUGIN_FUNCTION_W)(const wchar_t *i_arg);
2261 reinterpret_cast<PLUGIN_FUNCTION_A>(m_func)(to_string(m_funcParam).c_str());
2264 reinterpret_cast<PLUGIN_FUNCTION_W>(m_func)(to_wstring(m_funcParam).c_str());
2272 static void plugInThread(void *i_plugin)
2274 PlugIn *plugin = static_cast<PlugIn *>(i_plugin);
2280 void Engine::funcPlugIn(FunctionParam *i_param,
2281 const StrExprArg &i_dllName,
2282 const StrExprArg &i_funcName,
2283 const StrExprArg &i_funcParam,
2284 BooleanType i_doesCreateThread)
2286 if (!i_param->m_isPressed)
2289 shu::PlugIn *plugin = new shu::PlugIn();
2290 if (!plugin->load(i_dllName.eval(), i_funcName.eval(), i_funcParam.eval(), m_log))
2295 if (i_doesCreateThread)
2297 if (_beginthread(shu::plugInThread, 0, plugin) == -1)
2302 m_log << _T("error: &PlugIn() failed to create thread.");
2311 void Engine::funcMouseHook(FunctionParam *i_param,
2312 MouseHookType i_hookType, int i_hookParam)
2314 GetCursorPos(&g_hookData->m_mousePos);
2315 g_hookData->m_mouseHookType = i_hookType;
2316 g_hookData->m_mouseHookParam = i_hookParam;
2320 case MouseHookType_WindowMove:
2322 // For this type, g_hookData->m_mouseHookParam means
2323 // target window type to move.
2327 // i_hooParam < 0 means target window to move is MDI.
2328 if (i_hookParam < 0)
2333 // abs(i_hookParam) == 2: target is window under mouse cursor
2334 // otherwise: target is current focus window
2335 if (i_hookParam == 2 || i_hookParam == -2)
2336 target = WindowFromPoint(g_hookData->m_mousePos);
2338 target = i_param->m_hwnd;
2340 g_hookData->m_hwndMouseHookTarget =
2341 reinterpret_cast<DWORD>(getToplevelWindow(target, &isMDI));
2344 g_hookData->m_hwndMouseHookTarget = NULL;
2352 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2359 static const Engine *s_engine;
2361 StrExpr(const tstringq &i_symbol) : m_symbol(i_symbol) {};
2363 virtual ~StrExpr() {};
2365 virtual StrExpr *clone() const
2367 return new StrExpr(*this);
2370 virtual tstringq eval() const
2375 static void setEngine(const Engine *i_engine) { s_engine = i_engine; }
2378 const Engine *StrExpr::s_engine = NULL;
2380 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2382 class StrExprClipboard : public StrExpr
2385 StrExprClipboard(const tstringq &i_symbol) : StrExpr(i_symbol) {};
2387 ~StrExprClipboard() {};
2389 StrExpr *clone() const
2391 return new StrExprClipboard(*this);
2394 tstringq eval() const
2397 const _TCHAR *text = getTextFromClipboard(&g);
2398 const tstring value(text == NULL ? _T("") : text);
2405 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2406 // StrExprWindowClassName
2407 class StrExprWindowClassName : public StrExpr
2410 StrExprWindowClassName(const tstringq &i_symbol) : StrExpr(i_symbol) {};
2412 ~StrExprWindowClassName() {};
2414 StrExpr *clone() const
2416 return new StrExprWindowClassName(*this);
2419 tstringq eval() const
2421 return s_engine->getCurrentWindowClassName();
2426 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2427 // StrExprWindowTitleName
2428 class StrExprWindowTitleName : public StrExpr
2431 StrExprWindowTitleName(const tstringq &i_symbol) : StrExpr(i_symbol) {};
2433 ~StrExprWindowTitleName() {};
2435 StrExpr *clone() const
2437 return new StrExprWindowTitleName(*this);
2440 tstringq eval() const
2442 return s_engine->getCurrentWindowTitleName();
2447 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2451 // default constructor
2452 StrExprArg::StrExprArg()
2454 m_expr = new StrExpr(_T(""));
2459 StrExprArg::StrExprArg(const StrExprArg &i_data)
2461 m_expr = i_data.m_expr->clone();
2465 StrExprArg &StrExprArg::operator=(const StrExprArg &i_data)
2467 if (i_data.m_expr == m_expr)
2471 m_expr = i_data.m_expr->clone();
2478 StrExprArg::StrExprArg(const tstringq &i_symbol, Type i_type)
2483 m_expr = new StrExpr(i_symbol);
2486 if (i_symbol == _T("Clipboard"))
2487 m_expr = new StrExprClipboard(i_symbol);
2488 else if (i_symbol == _T("WindowClassName"))
2489 m_expr = new StrExprWindowClassName(i_symbol);
2490 else if (i_symbol == _T("WindowTitleName"))
2491 m_expr = new StrExprWindowTitleName(i_symbol);
2499 StrExprArg::~StrExprArg()
2505 tstringq StrExprArg::eval() const
2507 return m_expr->eval();
2510 void StrExprArg::setEngine(const Engine *i_engine)
2512 StrExpr::setEngine(i_engine);
2516 tostream &operator<<(tostream &i_ost, const StrExprArg &i_data)
2518 i_ost << i_data.eval();