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;
871 generateKeyEvent(sync, false, false);
872 #elif defined(_WIN95)
873 generateKeyEvent(sync, true, false);
879 DWORD r = WaitForSingleObject(m_eSync, 5000);
880 if (r == WAIT_TIMEOUT)
882 Acquire a(&m_log, 0);
883 m_log << _T(" *FAILED*") << std::endl;
886 m_isSynchronizing = false;
890 void Engine::funcToggle(FunctionParam *i_param, ModifierLockType i_lock,
893 if (i_param->m_isPressed) // ignore PRESS
896 Modifier::Type mt = static_cast<Modifier::Type>(i_lock);
899 case ToggleType_toggle:
900 m_currentLock.press(mt, !m_currentLock.isPressed(mt));
903 m_currentLock.press(mt, false);
906 m_currentLock.press(mt, true);
911 // edit next user input key's modifier
912 void Engine::funcEditNextModifier(FunctionParam *i_param,
913 const Modifier &i_modifier)
915 if (!i_param->m_isPressed)
919 m_doesEditNextModifier = true;
920 m_doesIgnoreModifierForPrefix = true;
921 m_modifierForNextKey = i_modifier;
925 void Engine::funcVariable(FunctionParam *i_param, int i_mag, int i_inc)
927 if (!i_param->m_isPressed)
934 void Engine::funcRepeat(FunctionParam *i_param, const KeySeq *i_keySeq,
937 if (i_param->m_isPressed)
939 int end = MIN(m_variable, i_max);
940 for (int i = 0; i < end - 1; ++ i)
941 generateKeySeqEvents(i_param->m_c, i_keySeq, Part_all);
943 generateKeySeqEvents(i_param->m_c, i_keySeq, Part_down);
946 generateKeySeqEvents(i_param->m_c, i_keySeq, Part_up);
950 void Engine::funcUndefined(FunctionParam *i_param)
952 if (!i_param->m_isPressed)
958 void Engine::funcIgnore(FunctionParam *)
964 void Engine::funcPostMessage(FunctionParam *i_param, ToWindowType i_window,
965 UINT i_message, WPARAM i_wParam, LPARAM i_lParam)
967 if (!i_param->m_isPressed)
970 int window = static_cast<int>(i_window);
972 HWND hwnd = i_param->m_hwnd;
975 for (int i = 0; i < window; ++ i)
976 hwnd = GetParent(hwnd);
978 else if (window == ToWindowType_toMainWindow)
982 HWND p = GetParent(hwnd);
988 else if (window == ToWindowType_toOverlappedWindow)
993 LONG_PTR style = GetWindowLongPtr(hwnd, GWL_STYLE);
995 LONG style = GetWindowLong(hwnd, GWL_STYLE);
997 if ((style & WS_CHILD) == 0)
999 hwnd = GetParent(hwnd);
1004 PostMessage(hwnd, i_message, i_wParam, i_lParam);
1009 void Engine::funcShellExecute(FunctionParam *i_param,
1010 const StrExprArg &/*i_operation*/,
1011 const StrExprArg &/*i_file*/,
1012 const StrExprArg &/*i_parameters*/,
1013 const StrExprArg &/*i_directory*/,
1014 ShowCommandType /*i_showCommand*/)
1016 if (!i_param->m_isPressed)
1018 m_afShellExecute = i_param->m_af;
1019 PostMessage(m_hwndAssocWindow,
1020 WM_APP_engineNotify, EngineNotify_shellExecute, 0);
1025 void Engine::shellExecute()
1029 FunctionData_ShellExecute *fd =
1030 reinterpret_cast<FunctionData_ShellExecute *>(
1031 m_afShellExecute->m_functionData);
1033 int r = (int)ShellExecute(
1035 fd->m_operation.eval().empty() ? _T("open") : fd->m_operation.eval().c_str(),
1036 fd->m_file.eval().empty() ? NULL : fd->m_file.eval().c_str(),
1037 fd->m_parameters.eval().empty() ? NULL : fd->m_parameters.eval().c_str(),
1038 fd->m_directory.eval().empty() ? NULL : fd->m_directory.eval().c_str(),
1043 typedef TypeTable<int> ErrorTable;
1044 static const ErrorTable errorTable[] =
1046 { 0, _T("The operating system is out of memory or resources.") },
1047 { ERROR_FILE_NOT_FOUND, _T("The specified file was not found.") },
1048 { ERROR_PATH_NOT_FOUND, _T("The specified path was not found.") },
1049 { ERROR_BAD_FORMAT, _T("The .exe file is invalid ")
1050 _T("(non-Win32R .exe or error in .exe image).") },
1051 { SE_ERR_ACCESSDENIED,
1052 _T("The operating system denied access to the specified file.") },
1053 { SE_ERR_ASSOCINCOMPLETE,
1054 _T("The file name association is incomplete or invalid.") },
1056 _T("The DDE transaction could not be completed ")
1057 _T("because other DDE transactions were being processed. ") },
1058 { SE_ERR_DDEFAIL, _T("The DDE transaction failed.") },
1059 { SE_ERR_DDETIMEOUT, _T("The DDE transaction could not be completed ")
1060 _T("because the request timed out.") },
1061 { SE_ERR_DLLNOTFOUND,
1062 _T("The specified dynamic-link library was not found.") },
1063 { SE_ERR_FNF, _T("The specified file was not found.") },
1064 { SE_ERR_NOASSOC, _T("There is no application associated ")
1065 _T("with the given file name extension.") },
1067 _T("There was not enough memory to complete the operation.") },
1068 { SE_ERR_PNF, _T("The specified path was not found.") },
1069 { SE_ERR_SHARE, _T("A sharing violation occurred.") },
1072 tstring errorMessage(_T("Unknown error."));
1073 getTypeName(&errorMessage, r, errorTable, NUMBER_OF(errorTable));
1075 Acquire b(&m_log, 0);
1076 m_log << _T("error: ") << fd << _T(": ") << errorMessage << std::endl;
1080 struct EnumWindowsForSetForegroundWindowParam
1082 const FunctionData_SetForegroundWindow *m_fd;
1086 EnumWindowsForSetForegroundWindowParam(
1087 const FunctionData_SetForegroundWindow *i_fd)
1095 /// enum windows for SetForegroundWindow
1096 static BOOL CALLBACK enumWindowsForSetForegroundWindow(
1097 HWND i_hwnd, LPARAM i_lParam)
1099 EnumWindowsForSetForegroundWindowParam &ep =
1100 *reinterpret_cast<EnumWindowsForSetForegroundWindowParam *>(i_lParam);
1102 _TCHAR name[GANA_MAX_ATOM_LENGTH];
1103 if (!GetClassName(i_hwnd, name, NUMBER_OF(name)))
1106 if (!boost::regex_search(tstring(name), what, ep.m_fd->m_windowClassName))
1107 if (ep.m_fd->m_logicalOp == LogicalOperatorType_and)
1108 return TRUE; // match failed
1110 if (ep.m_fd->m_logicalOp == LogicalOperatorType_and)
1112 if (GetWindowText(i_hwnd, name, NUMBER_OF(name)) == 0)
1114 if (!boost::regex_search(tstring(name), what,
1115 ep.m_fd->m_windowTitleName))
1116 return TRUE; // match failed
1124 /// SetForegroundWindow
1125 void Engine::funcSetForegroundWindow(FunctionParam *i_param, const tregex &,
1126 LogicalOperatorType , const tregex &)
1128 if (!i_param->m_isPressed)
1130 EnumWindowsForSetForegroundWindowParam
1131 ep(static_cast<const FunctionData_SetForegroundWindow *>(
1132 i_param->m_af->m_functionData));
1133 EnumWindows(enumWindowsForSetForegroundWindow,
1134 reinterpret_cast<LPARAM>(&ep));
1136 PostMessage(m_hwndAssocWindow,
1137 WM_APP_engineNotify, EngineNotify_setForegroundWindow,
1138 reinterpret_cast<LPARAM>(ep.m_hwnd));
1144 void Engine::funcLoadSetting(FunctionParam *i_param, const StrExprArg &i_name)
1146 if (!i_param->m_isPressed)
1148 if (!i_name.eval().empty())
1150 // set MAYU_REGISTRY_ROOT\.mayuIndex which name is same with i_name
1151 Registry reg(MAYU_REGISTRY_ROOT);
1153 tregex split(_T("^([^;]*);([^;]*);(.*)$"));
1155 for (size_t i = 0; i < MAX_MAYU_REGISTRY_ENTRIES; ++ i)
1158 _sntprintf(buf, NUMBER_OF(buf), _T(".mayu%d"), i);
1159 if (!reg.read(buf, &dot_mayu))
1163 if (boost::regex_match(dot_mayu, what, split) &&
1164 what.str(1) == i_name.eval())
1166 reg.write(_T(".mayuIndex"), i);
1172 Acquire a(&m_log, 0);
1173 m_log << _T("unknown setting name: ") << i_name;
1179 PostMessage(m_hwndAssocWindow,
1180 WM_APP_engineNotify, EngineNotify_loadSetting, 0);
1184 void Engine::funcVK(FunctionParam *i_param, VKey i_vkey)
1186 long key = static_cast<long>(i_vkey);
1187 BYTE vkey = static_cast<BYTE>(i_vkey);
1188 bool isExtended = !!(key & VKey_extended);
1189 bool isUp = !i_param->m_isPressed && !!(key & VKey_released);
1190 bool isDown = i_param->m_isPressed && !!(key & VKey_pressed);
1192 if (vkey == VK_LBUTTON && isDown)
1193 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
1194 else if (vkey == VK_LBUTTON && isUp)
1195 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
1196 else if (vkey == VK_MBUTTON && isDown)
1197 mouse_event(MOUSEEVENTF_MIDDLEDOWN, 0, 0, 0, 0);
1198 else if (vkey == VK_MBUTTON && isUp)
1199 mouse_event(MOUSEEVENTF_MIDDLEUP, 0, 0, 0, 0);
1200 else if (vkey == VK_RBUTTON && isDown)
1201 mouse_event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0);
1202 else if (vkey == VK_RBUTTON && isUp)
1203 mouse_event(MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0);
1204 #if(_WIN32_WINNT >= 0x0500)
1205 else if (vkey == VK_XBUTTON1 && isDown)
1206 mouse_event(MOUSEEVENTF_XDOWN, 0, 0, XBUTTON1, 0);
1207 else if (vkey == VK_XBUTTON1 && isUp)
1208 mouse_event(MOUSEEVENTF_XUP, 0, 0, XBUTTON1, 0);
1209 else if (vkey == VK_XBUTTON2 && isDown)
1210 mouse_event(MOUSEEVENTF_XDOWN, 0, 0, XBUTTON2, 0);
1211 else if (vkey == VK_XBUTTON2 && isUp)
1212 mouse_event(MOUSEEVENTF_XUP, 0, 0, XBUTTON2, 0);
1213 #endif /* _WIN32_WINNT >= 0x0500 */
1214 else if (isUp || isDown)
1216 static_cast<BYTE>(MapVirtualKey(vkey, 0)),
1217 (isExtended ? KEYEVENTF_EXTENDEDKEY : 0) |
1218 (i_param->m_isPressed ? 0 : KEYEVENTF_KEYUP), 0);
1222 void Engine::funcWait(FunctionParam *i_param, int i_milliSecond)
1224 if (!i_param->m_isPressed)
1226 if (i_milliSecond < 0 || 5000 < i_milliSecond) // too long wait
1229 m_isSynchronizing = true;
1231 Sleep(i_milliSecond);
1233 m_isSynchronizing = false;
1236 // investigate WM_COMMAND, WM_SYSCOMMAND
1237 void Engine::funcInvestigateCommand(FunctionParam *i_param)
1239 if (!i_param->m_isPressed)
1241 Acquire a(&m_log, 0);
1242 g_hookData->m_doesNotifyCommand = !g_hookData->m_doesNotifyCommand;
1243 if (g_hookData->m_doesNotifyCommand)
1244 m_log << _T(" begin") << std::endl;
1246 m_log << _T(" end") << std::endl;
1249 // show mayu dialog box
1250 void Engine::funcMayuDialog(FunctionParam *i_param, MayuDialogType i_dialog,
1251 ShowCommandType i_showCommand)
1253 if (!i_param->m_isPressed)
1255 PostMessage(getAssociatedWndow(), WM_APP_engineNotify, EngineNotify_showDlg,
1256 static_cast<LPARAM>(i_dialog) |
1257 static_cast<LPARAM>(i_showCommand));
1260 // describe bindings
1261 void Engine::funcDescribeBindings(FunctionParam *i_param)
1263 if (!i_param->m_isPressed)
1266 Acquire a(&m_log, 1);
1272 // show help message
1273 void Engine::funcHelpMessage(FunctionParam *i_param, const StrExprArg &i_title,
1274 const StrExprArg &i_message)
1276 if (!i_param->m_isPressed)
1279 m_helpTitle = i_title.eval();
1280 m_helpMessage = i_message.eval();
1281 bool doesShow = !(i_title.eval().size() == 0 && i_message.eval().size() == 0);
1282 PostMessage(getAssociatedWndow(), WM_APP_engineNotify,
1283 EngineNotify_helpMessage, doesShow);
1287 void Engine::funcHelpVariable(FunctionParam *i_param, const StrExprArg &i_title)
1289 if (!i_param->m_isPressed)
1293 _sntprintf(buf, NUMBER_OF(buf), _T("%d"), m_variable);
1295 m_helpTitle = i_title.eval();
1296 m_helpMessage = buf;
1297 PostMessage(getAssociatedWndow(), WM_APP_engineNotify,
1298 EngineNotify_helpMessage, true);
1302 void Engine::funcWindowRaise(FunctionParam *i_param,
1303 TargetWindowType i_twt)
1306 if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt))
1308 SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0,
1309 SWP_ASYNCWINDOWPOS | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOSIZE);
1313 void Engine::funcWindowLower(FunctionParam *i_param, TargetWindowType i_twt)
1316 if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt))
1318 SetWindowPos(hwnd, HWND_BOTTOM, 0, 0, 0, 0,
1319 SWP_ASYNCWINDOWPOS | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOSIZE);
1323 void Engine::funcWindowMinimize(FunctionParam *i_param, TargetWindowType i_twt)
1326 if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt))
1328 PostMessage(hwnd, WM_SYSCOMMAND,
1329 IsIconic(hwnd) ? SC_RESTORE : SC_MINIMIZE, 0);
1333 void Engine::funcWindowMaximize(FunctionParam *i_param, TargetWindowType i_twt)
1336 if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt))
1338 PostMessage(hwnd, WM_SYSCOMMAND,
1339 IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, 0);
1342 // maximize horizontally or virtically
1343 void Engine::funcWindowHVMaximize(FunctionParam *i_param,
1344 BooleanType i_isHorizontal,
1345 TargetWindowType i_twt)
1349 if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt, &rc, &rcd))
1355 WindowPositions::iterator i = m_windowPositions.begin();
1356 WindowPositions::iterator end = m_windowPositions.end();
1357 for (; i != end; ++ i)
1358 if (!IsWindow((*i).m_hwnd))
1362 m_windowPositions.erase(i);
1366 WindowPositions::iterator i = m_windowPositions.begin();
1367 WindowPositions::iterator end = m_windowPositions.end();
1368 WindowPositions::iterator target = end;
1369 for (; i != end; ++ i)
1370 if ((*i).m_hwnd == hwnd)
1377 PostMessage(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
1380 WindowPosition::Mode mode = WindowPosition::Mode_normal;
1384 WindowPosition &wp = *target;
1386 if (wp.m_mode == WindowPosition::Mode_HV)
1388 i_isHorizontal ? WindowPosition::Mode_V : WindowPosition::Mode_H;
1389 else if (( i_isHorizontal && wp.m_mode == WindowPosition::Mode_V) ||
1390 (!i_isHorizontal && wp.m_mode == WindowPosition::Mode_H))
1391 mode = wp.m_mode = WindowPosition::Mode_HV;
1393 m_windowPositions.erase(target);
1397 mode = i_isHorizontal ? WindowPosition::Mode_H : WindowPosition::Mode_V;
1398 m_windowPositions.push_front(WindowPosition(hwnd, rc, mode));
1401 if (static_cast<int>(mode) & static_cast<int>(WindowPosition::Mode_H))
1402 rc.left = rcd.left, rc.right = rcd.right;
1403 if (static_cast<int>(mode) & static_cast<int>(WindowPosition::Mode_V))
1404 rc.top = rcd.top, rc.bottom = rcd.bottom;
1406 asyncMoveWindow(hwnd, rc.left, rc.top, rcWidth(&rc), rcHeight(&rc));
1410 // maximize window horizontally
1411 void Engine::funcWindowHMaximize(FunctionParam *i_param,
1412 TargetWindowType i_twt)
1414 funcWindowHVMaximize(i_param, BooleanType_true, i_twt);
1417 // maximize window virtically
1418 void Engine::funcWindowVMaximize(FunctionParam *i_param,
1419 TargetWindowType i_twt)
1421 funcWindowHVMaximize(i_param, BooleanType_false, i_twt);
1425 void Engine::funcWindowMove(FunctionParam *i_param, int i_dx, int i_dy,
1426 TargetWindowType i_twt)
1428 funcWindowMoveTo(i_param, GravityType_C, i_dx, i_dy, i_twt);
1431 // move window to ...
1432 void Engine::funcWindowMoveTo(FunctionParam *i_param,
1433 GravityType i_gravityType,
1434 int i_dx, int i_dy, TargetWindowType i_twt)
1438 if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt, &rc, &rcd))
1441 int x = rc.left + i_dx;
1442 int y = rc.top + i_dy;
1444 if (i_gravityType & GravityType_N)
1446 if (i_gravityType & GravityType_E)
1447 x = i_dx + rcd.right - rcWidth(&rc);
1448 if (i_gravityType & GravityType_W)
1449 x = i_dx + rcd.left;
1450 if (i_gravityType & GravityType_S)
1451 y = i_dy + rcd.bottom - rcHeight(&rc);
1452 asyncMoveWindow(hwnd, x, y);
1456 // move window visibly
1457 void Engine::funcWindowMoveVisibly(FunctionParam *i_param,
1458 TargetWindowType i_twt)
1462 if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt, &rc, &rcd))
1467 if (rc.left < rcd.left)
1469 else if (rcd.right < rc.right)
1470 x = rcd.right - rcWidth(&rc);
1471 if (rc.top < rcd.top)
1473 else if (rcd.bottom < rc.bottom)
1474 y = rcd.bottom - rcHeight(&rc);
1475 asyncMoveWindow(hwnd, x, y);
1479 struct EnumDisplayMonitorsForWindowMonitorToParam
1481 std::vector<HMONITOR> m_monitors;
1482 std::vector<MONITORINFO> m_monitorinfos;
1483 int m_primaryMonitorIdx;
1484 int m_currentMonitorIdx;
1489 EnumDisplayMonitorsForWindowMonitorToParam(HMONITOR i_hmon)
1491 m_primaryMonitorIdx(-1), m_currentMonitorIdx(-1)
1496 static BOOL CALLBACK enumDisplayMonitorsForWindowMonitorTo(
1497 HMONITOR i_hmon, HDC i_hdc, LPRECT i_rcMonitor, LPARAM i_data)
1499 EnumDisplayMonitorsForWindowMonitorToParam &ep =
1500 *reinterpret_cast<EnumDisplayMonitorsForWindowMonitorToParam *>(i_data);
1502 ep.m_monitors.push_back(i_hmon);
1505 mi.cbSize = sizeof(mi);
1506 getMonitorInfo(i_hmon, &mi);
1507 ep.m_monitorinfos.push_back(mi);
1509 if(mi.dwFlags & MONITORINFOF_PRIMARY)
1510 ep.m_primaryMonitorIdx = ep.m_monitors.size() - 1;
1511 if(i_hmon == ep.m_hmon)
1512 ep.m_currentMonitorIdx = ep.m_monitors.size() - 1;
1517 /// move window to other monitor
1518 void Engine::funcWindowMonitorTo(
1519 FunctionParam *i_param, WindowMonitorFromType i_fromType, int i_monitor,
1520 BooleanType i_adjustPos, BooleanType i_adjustSize)
1523 if(! getSuitableWindow(i_param, &hwnd))
1527 hmonCur = monitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
1529 EnumDisplayMonitorsForWindowMonitorToParam ep(hmonCur);
1530 enumDisplayMonitors(NULL, NULL, enumDisplayMonitorsForWindowMonitorTo,
1531 reinterpret_cast<LPARAM>(&ep));
1532 if(ep.m_monitors.size() < 1 ||
1533 ep.m_primaryMonitorIdx < 0 || ep.m_currentMonitorIdx < 0)
1537 switch(i_fromType) {
1538 case WindowMonitorFromType_primary:
1539 targetIdx = (ep.m_primaryMonitorIdx + i_monitor) % ep.m_monitors.size();
1542 case WindowMonitorFromType_current:
1543 targetIdx = (ep.m_currentMonitorIdx + i_monitor) % ep.m_monitors.size();
1546 if(ep.m_currentMonitorIdx == targetIdx)
1549 RECT rcCur, rcTarget, rcWin;
1550 rcCur = ep.m_monitorinfos[ep.m_currentMonitorIdx].rcWork;
1551 rcTarget = ep.m_monitorinfos[targetIdx].rcWork;
1552 GetWindowRect(hwnd, &rcWin);
1554 int x = rcTarget.left + (rcWin.left - rcCur.left);
1555 int y = rcTarget.top + (rcWin.top - rcCur.top);
1556 int w = rcWidth(&rcWin);
1557 int h = rcHeight(&rcWin);
1560 if(x + w > rcTarget.right)
1561 x = rcTarget.right - w;
1562 if(x < rcTarget.left)
1564 if(w > rcWidth(&rcTarget)) {
1566 w = rcWidth(&rcTarget);
1569 if(y + h > rcTarget.bottom)
1570 y = rcTarget.bottom - h;
1571 if(y < rcTarget.top)
1573 if(h > rcHeight(&rcTarget)) {
1575 h = rcHeight(&rcTarget);
1579 if(i_adjustPos && i_adjustSize) {
1581 PostMessage(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
1582 asyncMoveWindow(hwnd, x, y, w, h);
1584 asyncMoveWindow(hwnd, x, y);
1588 /// move window to other monitor
1589 void Engine::funcWindowMonitor(
1590 FunctionParam *i_param, int i_monitor,
1591 BooleanType i_adjustPos, BooleanType i_adjustSize)
1593 funcWindowMonitorTo(i_param, WindowMonitorFromType_primary, i_monitor,
1594 i_adjustPos, i_adjustSize);
1599 void Engine::funcWindowClingToLeft(FunctionParam *i_param,
1600 TargetWindowType i_twt)
1602 funcWindowMoveTo(i_param, GravityType_W, 0, 0, i_twt);
1606 void Engine::funcWindowClingToRight(FunctionParam *i_param,
1607 TargetWindowType i_twt)
1609 funcWindowMoveTo(i_param, GravityType_E, 0, 0, i_twt);
1613 void Engine::funcWindowClingToTop(FunctionParam *i_param,
1614 TargetWindowType i_twt)
1616 funcWindowMoveTo(i_param, GravityType_N, 0, 0, i_twt);
1620 void Engine::funcWindowClingToBottom(FunctionParam *i_param,
1621 TargetWindowType i_twt)
1623 funcWindowMoveTo(i_param, GravityType_S, 0, 0, i_twt);
1627 void Engine::funcWindowClose(FunctionParam *i_param, TargetWindowType i_twt)
1630 if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt))
1632 PostMessage(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0);
1635 // toggle top-most flag of the window
1636 void Engine::funcWindowToggleTopMost(FunctionParam *i_param)
1639 if (!getSuitableWindow(i_param, &hwnd))
1644 (GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST) ?
1646 (GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST) ?
1648 HWND_NOTOPMOST : HWND_TOPMOST,
1650 SWP_ASYNCWINDOWPOS | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOSIZE);
1653 // identify the window
1654 void Engine::funcWindowIdentify(FunctionParam *i_param)
1656 if (!i_param->m_isPressed)
1659 _TCHAR className[GANA_MAX_ATOM_LENGTH];
1661 if (GetClassName(i_param->m_hwnd, className, NUMBER_OF(className)))
1663 if (_tcsicmp(className, _T("ConsoleWindowClass")) == 0)
1665 _TCHAR titleName[1024];
1666 if (GetWindowText(i_param->m_hwnd, titleName, NUMBER_OF(titleName)) == 0)
1667 titleName[0] = _T('\0');
1669 Acquire a(&m_log, 1);
1670 m_log << _T("HWND:\t") << std::hex
1671 << reinterpret_cast<int>(i_param->m_hwnd)
1672 << std::dec << std::endl;
1674 Acquire a(&m_log, 0);
1675 m_log << _T("CLASS:\t") << className << std::endl;
1676 m_log << _T("TITLE:\t") << titleName << std::endl;
1678 HWND hwnd = getToplevelWindow(i_param->m_hwnd, NULL);
1680 GetWindowRect(hwnd, &rc);
1681 m_log << _T("Toplevel Window Position/Size: (")
1682 << rc.left << _T(", ") << rc.top << _T(") / (")
1683 << rcWidth(&rc) << _T("x") << rcHeight(&rc)
1684 << _T(")") << std::endl;
1686 SystemParametersInfo(SPI_GETWORKAREA, 0, (void *)&rc, FALSE);
1687 m_log << _T("Desktop Window Position/Size: (")
1688 << rc.left << _T(", ") << rc.top << _T(") / (")
1689 << rcWidth(&rc) << _T("x") << rcHeight(&rc)
1690 << _T(")") << std::endl;
1698 UINT WM_MAYU_MESSAGE = RegisterWindowMessage(
1699 addSessionId(WM_MAYU_MESSAGE_NAME).c_str());
1700 CHECK_TRUE( PostMessage(i_param->m_hwnd, WM_MAYU_MESSAGE,
1701 MayuMessage_notifyName, 0) );
1705 // set alpha blending parameter to the window
1706 void Engine::funcWindowSetAlpha(FunctionParam *i_param, int i_alpha)
1710 if (!getSuitableWindow(i_param, &hwnd))
1713 if (i_alpha < 0) // remove all alpha
1715 for (WindowsWithAlpha::iterator i = m_windowsWithAlpha.begin();
1716 i != m_windowsWithAlpha.end(); ++ i)
1719 SetWindowLongPtr(*i, GWL_EXSTYLE,
1720 GetWindowLongPtr(*i, GWL_EXSTYLE) & ~WS_EX_LAYERED);
1722 SetWindowLong(*i, GWL_EXSTYLE,
1723 GetWindowLong(*i, GWL_EXSTYLE) & ~WS_EX_LAYERED);
1725 RedrawWindow(*i, NULL, NULL,
1726 RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);
1728 m_windowsWithAlpha.clear();
1733 LONG_PTR exStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE);
1735 LONG exStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
1737 if (exStyle & WS_EX_LAYERED) // remove alpha
1739 WindowsWithAlpha::iterator
1740 i = std::find(m_windowsWithAlpha.begin(), m_windowsWithAlpha.end(),
1742 if (i == m_windowsWithAlpha.end())
1743 return; // already layered by the application
1745 m_windowsWithAlpha.erase(i);
1748 SetWindowLongPtr(hwnd, GWL_EXSTYLE, exStyle & ~WS_EX_LAYERED);
1750 SetWindowLong(hwnd, GWL_EXSTYLE, exStyle & ~WS_EX_LAYERED);
1756 SetWindowLongPtr(hwnd, GWL_EXSTYLE, exStyle | WS_EX_LAYERED);
1758 SetWindowLong(hwnd, GWL_EXSTYLE, exStyle | WS_EX_LAYERED);
1761 if (!setLayeredWindowAttributes(hwnd, 0,
1762 (BYTE)(255 * i_alpha / 100), LWA_ALPHA))
1764 Acquire a(&m_log, 0);
1765 m_log << _T("error: &WindowSetAlpha(") << i_alpha
1766 << _T(") failed for HWND: ") << std::hex
1767 << hwnd << std::dec << std::endl;
1770 m_windowsWithAlpha.push_front(hwnd);
1772 RedrawWindow(hwnd, NULL, NULL,
1773 RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);
1779 // redraw the window
1780 void Engine::funcWindowRedraw(FunctionParam *i_param)
1783 if (!getSuitableWindow(i_param, &hwnd))
1785 RedrawWindow(hwnd, NULL, NULL,
1786 RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);
1790 void Engine::funcWindowResizeTo(FunctionParam *i_param, int i_width,
1791 int i_height, TargetWindowType i_twt)
1795 if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt, &rc, &rcd))
1799 i_width = rcWidth(&rc);
1800 else if (i_width < 0)
1801 i_width += rcWidth(&rcd);
1804 i_height = rcHeight(&rc);
1805 else if (i_height < 0)
1806 i_height += rcHeight(&rcd);
1808 asyncResize(hwnd, i_width, i_height);
1811 // move the mouse cursor
1812 void Engine::funcMouseMove(FunctionParam *i_param, int i_dx, int i_dy)
1814 if (!i_param->m_isPressed)
1818 SetCursorPos(pt.x + i_dx, pt.y + i_dy);
1821 // send a mouse-wheel-message to Windows
1822 void Engine::funcMouseWheel(FunctionParam *i_param, int i_delta)
1824 if (!i_param->m_isPressed)
1826 mouse_event(MOUSEEVENTF_WHEEL, 0, 0, i_delta, 0);
1829 // convert the contents of the Clipboard to upper case
1830 void Engine::funcClipboardChangeCase(FunctionParam *i_param,
1831 BooleanType i_doesConvertToUpperCase)
1833 if (!i_param->m_isPressed)
1837 const _TCHAR *text = getTextFromClipboard(&hdata);
1838 HGLOBAL hdataNew = NULL;
1841 int size = static_cast<int>(GlobalSize(hdata));
1842 hdataNew = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, size);
1845 if (_TCHAR *dataNew = reinterpret_cast<_TCHAR *>(GlobalLock(hdataNew)))
1847 std::memcpy(dataNew, text, size);
1848 _TCHAR *dataEnd = dataNew + size;
1849 while (dataNew < dataEnd && *dataNew)
1851 _TCHAR c = *dataNew;
1856 i_doesConvertToUpperCase ? _totupper(c) : _totlower(c);
1858 GlobalUnlock(hdataNew);
1862 closeClipboard(hdata, hdataNew);
1865 // convert the contents of the Clipboard to upper case
1866 void Engine::funcClipboardUpcaseWord(FunctionParam *i_param)
1868 funcClipboardChangeCase(i_param, BooleanType_true);
1871 // convert the contents of the Clipboard to lower case
1872 void Engine::funcClipboardDowncaseWord(FunctionParam *i_param)
1874 funcClipboardChangeCase(i_param, BooleanType_false);
1877 // set the contents of the Clipboard to the string
1878 void Engine::funcClipboardCopy(FunctionParam *i_param, const StrExprArg &i_text)
1880 if (!i_param->m_isPressed)
1882 if (!OpenClipboard(NULL))
1886 GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,
1887 (i_text.eval().size() + 1) * sizeof(_TCHAR));
1890 _TCHAR *dataNew = reinterpret_cast<_TCHAR *>(GlobalLock(hdataNew));
1891 _tcscpy(dataNew, i_text.eval().c_str());
1892 GlobalUnlock(hdataNew);
1893 closeClipboard(NULL, hdataNew);
1897 void Engine::funcEmacsEditKillLinePred(
1898 FunctionParam *i_param, const KeySeq *i_keySeq1, const KeySeq *i_keySeq2)
1900 m_emacsEditKillLine.m_doForceReset = false;
1901 if (!i_param->m_isPressed)
1904 int r = m_emacsEditKillLine.pred();
1905 const KeySeq *keySeq;
1913 generateKeySeqEvents(i_param->m_c, keySeq, Part_all);
1917 void Engine::funcEmacsEditKillLineFunc(FunctionParam *i_param)
1919 if (!i_param->m_isPressed)
1921 m_emacsEditKillLine.func();
1922 m_emacsEditKillLine.m_doForceReset = false;
1926 void Engine::funcLogClear(FunctionParam *i_param)
1928 if (!i_param->m_isPressed)
1930 PostMessage(getAssociatedWndow(), WM_APP_engineNotify,
1931 EngineNotify_clearLog, 0);
1935 void Engine::funcRecenter(FunctionParam *i_param)
1937 if (!i_param->m_isPressed)
1941 UINT WM_MAYU_MESSAGE = RegisterWindowMessage(
1942 addSessionId(WM_MAYU_MESSAGE_NAME).c_str());
1943 PostMessage(m_hwndFocus, WM_MAYU_MESSAGE, MayuMessage_funcRecenter, 0);
1947 // set IME open status
1948 void Engine::funcSetImeStatus(FunctionParam *i_param, ToggleType i_toggle)
1950 if (!i_param->m_isPressed)
1954 UINT WM_MAYU_MESSAGE = RegisterWindowMessage(
1955 addSessionId(WM_MAYU_MESSAGE_NAME).c_str());
1959 case ToggleType_toggle:
1962 case ToggleType_off:
1969 PostMessage(m_hwndFocus, WM_MAYU_MESSAGE, MayuMessage_funcSetImeStatus, status);
1973 // set IME open status
1974 void Engine::funcSetImeString(FunctionParam *i_param, const StrExprArg &i_data)
1977 if (!i_param->m_isPressed)
1981 UINT WM_MAYU_MESSAGE = RegisterWindowMessage(
1982 addSessionId(WM_MAYU_MESSAGE_NAME).c_str());
1983 PostMessage(m_hwndFocus, WM_MAYU_MESSAGE, MayuMessage_funcSetImeString, i_data.eval().size() * sizeof(_TCHAR));
1987 DisconnectNamedPipe(m_hookPipe);
1988 ConnectNamedPipe(m_hookPipe, NULL);
1989 error = WriteFile(m_hookPipe, i_data.eval().c_str(),
1990 i_data.eval().size() * sizeof(_TCHAR),
1993 //FlushFileBuffers(m_hookPipe);
1997 m_log << _T("supported on only Windows NT/2000/XP") << std::endl;
2001 // Direct SSTP Server
2002 class DirectSSTPServer
2018 class ParseDirectSSTPData
2020 typedef boost::match_results<boost::regex::const_iterator> MR;
2023 typedef std::map<tstring, DirectSSTPServer> DirectSSTPServers;
2026 DirectSSTPServers *m_directSSTPServers;
2030 ParseDirectSSTPData(DirectSSTPServers *i_directSSTPServers)
2031 : m_directSSTPServers(i_directSSTPServers)
2035 bool operator()(const MR& i_what)
2038 tstring id(to_wstring(std::string(i_what[1].first, i_what[1].second)));
2039 tstring member(to_wstring(std::string(i_what[2].first, i_what[2].second)));
2040 tstring value(to_wstring(std::string(i_what[3].first, i_what[3].second)));
2042 tstring id(i_what[1].first, i_what[1].second);
2043 tstring member(i_what[2].first, i_what[2].second);
2044 tstring value(i_what[3].first, i_what[3].second);
2047 if (member == _T("path"))
2048 (*m_directSSTPServers)[id].m_path = value;
2049 else if (member == _T("hwnd"))
2050 (*m_directSSTPServers)[id].m_hwnd =
2051 reinterpret_cast<HWND>(_ttoi(value.c_str()));
2052 else if (member == _T("name"))
2053 (*m_directSSTPServers)[id].m_name = value;
2054 else if (member == _T("keroname"))
2055 (*m_directSSTPServers)[id].m_keroname = value;
2061 void Engine::funcDirectSSTP(FunctionParam *i_param,
2062 const tregex &i_name,
2063 const StrExprArg &i_protocol,
2064 const std::list<tstringq> &i_headers)
2066 if (!i_param->m_isPressed)
2069 // check Direct SSTP server exist ?
2070 if (HANDLE hm = OpenMutex(MUTEX_ALL_ACCESS, FALSE, _T("sakura")))
2074 Acquire a(&m_log, 0);
2075 m_log << _T(" Error(1): Direct SSTP server does not exist.");
2079 HANDLE hfm = OpenFileMapping(FILE_MAP_READ, FALSE, _T("Sakura"));
2082 Acquire a(&m_log, 0);
2083 m_log << _T(" Error(2): Direct SSTP server does not provide data.");
2088 reinterpret_cast<char *>(MapViewOfFile(hfm, FILE_MAP_READ, 0, 0, 0));
2092 Acquire a(&m_log, 0);
2093 m_log << _T(" Error(3): Direct SSTP server does not provide data.");
2097 long length = *(long *)data;
2098 const char *begin = data + 4;
2099 const char *end = data + length;
2100 boost::regex getSakura("([0-9a-fA-F]{32})\\.([^\x01]+)\x01(.*?)\r\n");
2102 ParseDirectSSTPData::DirectSSTPServers servers;
2103 boost::regex_iterator<boost::regex::const_iterator>
2104 it(begin, end, getSakura), last;
2105 for (; it != last; ++it)
2106 ((ParseDirectSSTPData)(&servers))(*it);
2110 if (!i_protocol.eval().size())
2111 request += _T("NOTIFY SSTP/1.1");
2113 request += i_protocol.eval();
2114 request += _T("\r\n");
2116 bool hasSender = false;
2117 for (std::list<tstringq>::const_iterator
2118 i = i_headers.begin(); i != i_headers.end(); ++ i)
2120 if (_tcsnicmp(_T("Charset"), i->c_str(), 7) == 0 ||
2121 _tcsnicmp(_T("Hwnd"), i->c_str(), 4) == 0)
2123 if (_tcsnicmp(_T("Sender"), i->c_str(), 6) == 0)
2125 request += i->c_str();
2126 request += _T("\r\n");
2131 request += _T("Sender: ");
2132 request += loadString(IDS_mayu);
2133 request += _T("\r\n");
2137 _sntprintf(buf, NUMBER_OF(buf), _T("HWnd: %d\r\n"),
2138 reinterpret_cast<int>(m_hwndAssocWindow));
2142 request += _T("Charset: UTF-8\r\n");
2144 request += _T("Charset: Shift_JIS\r\n");
2146 request += _T("\r\n");
2149 std::string request_UTF_8 = to_UTF_8(request);
2152 // send request to Direct SSTP Server which matches i_name;
2153 for (ParseDirectSSTPData::DirectSSTPServers::iterator
2154 i = servers.begin(); i != servers.end(); ++ i)
2157 if (boost::regex_match(i->second.m_name, what, i_name))
2162 cd.cbData = request_UTF_8.size();
2163 cd.lpData = (void *)request_UTF_8.c_str();
2165 cd.cbData = request.size();
2166 cd.lpData = (void *)request.c_str();
2173 SendMessageTimeout(i->second.m_hwnd, WM_COPYDATA,
2174 reinterpret_cast<WPARAM>(m_hwndAssocWindow),
2175 reinterpret_cast<LPARAM>(&cd),
2176 SMTO_ABORTIFHUNG | SMTO_BLOCK, 5000, &result);
2180 UnmapViewOfFile(data);
2199 tstringq m_funcParam;
2202 PlugIn() : m_dll(NULL)
2211 bool load(const tstringq &i_dllName, const tstringq &i_funcName,
2212 const tstringq &i_funcParam, tomsgstream &i_log)
2214 m_dll = LoadLibrary((_T("Plugins\\") + i_dllName).c_str());
2217 m_dll = LoadLibrary((_T("Plugin\\") + i_dllName).c_str());
2220 m_dll = LoadLibrary(i_dllName.c_str());
2225 i_log << _T("error: &PlugIn() failed to load ") << i_dllName << std::endl;
2238 m_func = GetProcAddress(m_dll, to_string(_T("mayu") + i_funcName + _T("W")).c_str());
2243 = GetProcAddress(m_dll, to_string(_T("mayu") + i_funcName + _T("A")).c_str());
2246 m_func = GetProcAddress(m_dll, to_string(_T("mayu") + i_funcName).c_str());
2249 m_func = GetProcAddress(m_dll, to_string(i_funcName).c_str());
2254 i_log << _T("error: &PlugIn() failed to find function: ")
2255 << i_funcName << std::endl;
2262 m_funcParam = i_funcParam;
2271 typedef void (WINAPI * PLUGIN_FUNCTION_A)(const char *i_arg);
2272 typedef void (WINAPI * PLUGIN_FUNCTION_W)(const wchar_t *i_arg);
2276 reinterpret_cast<PLUGIN_FUNCTION_A>(m_func)(to_string(m_funcParam).c_str());
2279 reinterpret_cast<PLUGIN_FUNCTION_W>(m_func)(to_wstring(m_funcParam).c_str());
2287 static void plugInThread(void *i_plugin)
2289 PlugIn *plugin = static_cast<PlugIn *>(i_plugin);
2295 void Engine::funcPlugIn(FunctionParam *i_param,
2296 const StrExprArg &i_dllName,
2297 const StrExprArg &i_funcName,
2298 const StrExprArg &i_funcParam,
2299 BooleanType i_doesCreateThread)
2301 if (!i_param->m_isPressed)
2304 shu::PlugIn *plugin = new shu::PlugIn();
2305 if (!plugin->load(i_dllName.eval(), i_funcName.eval(), i_funcParam.eval(), m_log))
2310 if (i_doesCreateThread)
2312 if (_beginthread(shu::plugInThread, 0, plugin) == -1)
2317 m_log << _T("error: &PlugIn() failed to create thread.");
2326 void Engine::funcMouseHook(FunctionParam *i_param,
2327 MouseHookType i_hookType, int i_hookParam)
2329 GetCursorPos(&g_hookData->m_mousePos);
2330 g_hookData->m_mouseHookType = i_hookType;
2331 g_hookData->m_mouseHookParam = i_hookParam;
2335 case MouseHookType_WindowMove:
2337 // For this type, g_hookData->m_mouseHookParam means
2338 // target window type to move.
2342 // i_hooParam < 0 means target window to move is MDI.
2343 if (i_hookParam < 0)
2348 // abs(i_hookParam) == 2: target is window under mouse cursor
2349 // otherwise: target is current focus window
2350 if (i_hookParam == 2 || i_hookParam == -2)
2351 target = WindowFromPoint(g_hookData->m_mousePos);
2353 target = i_param->m_hwnd;
2355 g_hookData->m_hwndMouseHookTarget =
2356 reinterpret_cast<DWORD>(getToplevelWindow(target, &isMDI));
2359 g_hookData->m_hwndMouseHookTarget = NULL;
2367 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2374 static const Engine *s_engine;
2376 StrExpr(const tstringq &i_symbol) : m_symbol(i_symbol) {};
2378 virtual ~StrExpr() {};
2380 virtual StrExpr *clone() const
2382 return new StrExpr(*this);
2385 virtual tstringq eval() const
2390 static void setEngine(const Engine *i_engine) { s_engine = i_engine; }
2393 const Engine *StrExpr::s_engine = NULL;
2395 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2397 class StrExprClipboard : public StrExpr
2400 StrExprClipboard(const tstringq &i_symbol) : StrExpr(i_symbol) {};
2402 ~StrExprClipboard() {};
2404 StrExpr *clone() const
2406 return new StrExprClipboard(*this);
2409 tstringq eval() const
2412 const _TCHAR *text = getTextFromClipboard(&g);
2413 const tstring value(text == NULL ? _T("") : text);
2420 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2421 // StrExprWindowClassName
2422 class StrExprWindowClassName : public StrExpr
2425 StrExprWindowClassName(const tstringq &i_symbol) : StrExpr(i_symbol) {};
2427 ~StrExprWindowClassName() {};
2429 StrExpr *clone() const
2431 return new StrExprWindowClassName(*this);
2434 tstringq eval() const
2436 return s_engine->getCurrentWindowClassName();
2441 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2442 // StrExprWindowTitleName
2443 class StrExprWindowTitleName : public StrExpr
2446 StrExprWindowTitleName(const tstringq &i_symbol) : StrExpr(i_symbol) {};
2448 ~StrExprWindowTitleName() {};
2450 StrExpr *clone() const
2452 return new StrExprWindowTitleName(*this);
2455 tstringq eval() const
2457 return s_engine->getCurrentWindowTitleName();
2462 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2466 // default constructor
2467 StrExprArg::StrExprArg()
2469 m_expr = new StrExpr(_T(""));
2474 StrExprArg::StrExprArg(const StrExprArg &i_data)
2476 m_expr = i_data.m_expr->clone();
2480 StrExprArg &StrExprArg::operator=(const StrExprArg &i_data)
2482 if (i_data.m_expr == m_expr)
2486 m_expr = i_data.m_expr->clone();
2493 StrExprArg::StrExprArg(const tstringq &i_symbol, Type i_type)
2498 m_expr = new StrExpr(i_symbol);
2501 if (i_symbol == _T("Clipboard"))
2502 m_expr = new StrExprClipboard(i_symbol);
2503 else if (i_symbol == _T("WindowClassName"))
2504 m_expr = new StrExprWindowClassName(i_symbol);
2505 else if (i_symbol == _T("WindowTitleName"))
2506 m_expr = new StrExprWindowTitleName(i_symbol);
2514 StrExprArg::~StrExprArg()
2520 tstringq StrExprArg::eval() const
2522 return m_expr->eval();
2525 void StrExprArg::setEngine(const Engine *i_engine)
2527 StrExpr::setEngine(i_engine);
2531 tostream &operator<<(tostream &i_ost, const StrExprArg &i_data)
2533 i_ost << i_data.eval();