OSDN Git Service

fix ticket #18663
[yamy/yamy.git] / function.cpp
1 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
2 // function.cpp\r
3 \r
4 \r
5 #include "engine.h"\r
6 #include "hook.h"\r
7 #include "mayu.h"\r
8 #include "mayurc.h"\r
9 #include "misc.h"\r
10 #include "registry.h"\r
11 #include "vkeytable.h"\r
12 #include "windowstool.h"\r
13 #include <algorithm>\r
14 #include <process.h>\r
15 \r
16 #define FUNCTION_DATA\r
17 #include "functions.h"\r
18 #undef FUNCTION_DATA\r
19 \r
20 \r
21 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
22 // TypeTable\r
23 \r
24 \r
25 template <class T> class TypeTable\r
26 {\r
27 public:\r
28         T m_type;\r
29         const _TCHAR *m_name;\r
30 };\r
31 \r
32 \r
33 template <class T> static inline\r
34 bool getTypeName(tstring *o_name, T i_type,\r
35                                  const TypeTable<T> *i_table, size_t i_n)\r
36 {\r
37         for (size_t i = 0; i < i_n; ++ i)\r
38                 if (i_table[i].m_type == i_type) {\r
39                         *o_name = i_table[i].m_name;\r
40                         return true;\r
41                 }\r
42         return false;\r
43 }\r
44 \r
45 template <class T> static inline\r
46 bool getTypeValue(T *o_type, const tstringi &i_name,\r
47                                   const TypeTable<T> *i_table, size_t i_n)\r
48 {\r
49         for (size_t i = 0; i < i_n; ++ i)\r
50                 if (i_table[i].m_name == i_name) {\r
51                         *o_type = i_table[i].m_type;\r
52                         return true;\r
53                 }\r
54         return false;\r
55 }\r
56 \r
57 \r
58 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
59 // VKey\r
60 \r
61 \r
62 // stream output\r
63 tostream &operator<<(tostream &i_ost, VKey i_data)\r
64 {\r
65         if (i_data & VKey_extended)\r
66                 i_ost << _T("E-");\r
67         if (i_data & VKey_released)\r
68                 i_ost << _T("U-");\r
69         if (i_data & VKey_pressed)\r
70                 i_ost << _T("D-");\r
71 \r
72         u_int8 code = i_data & ~(VKey_extended | VKey_released | VKey_pressed);\r
73         const VKeyTable *vkt;\r
74         for (vkt = g_vkeyTable; vkt->m_name; ++ vkt)\r
75                 if (vkt->m_code == code)\r
76                         break;\r
77         if (vkt->m_name)\r
78                 i_ost << vkt->m_name;\r
79         else\r
80                 i_ost << _T("0x") << std::hex << code << std::dec;\r
81         return i_ost;\r
82 }\r
83 \r
84 \r
85 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
86 // ToWindowType\r
87 \r
88 \r
89 // ToWindowType table\r
90 typedef TypeTable<ToWindowType> TypeTable_ToWindowType;\r
91 static const TypeTable_ToWindowType g_toWindowTypeTable[] = {\r
92         { ToWindowType_toOverlappedWindow, _T("toOverlappedWindow") },\r
93         { ToWindowType_toMainWindow,       _T("toMainWindow")       },\r
94         { ToWindowType_toItself,           _T("toItself")           },\r
95         { ToWindowType_toParentWindow,     _T("toParentWindow")     },\r
96 };\r
97 \r
98 \r
99 // stream output\r
100 tostream &operator<<(tostream &i_ost, ToWindowType i_data)\r
101 {\r
102         tstring name;\r
103         if (getTypeName(&name, i_data,\r
104                                         g_toWindowTypeTable, NUMBER_OF(g_toWindowTypeTable)))\r
105                 i_ost << name;\r
106         else\r
107                 i_ost << static_cast<int>(i_data);\r
108         return i_ost;\r
109 }\r
110 \r
111 \r
112 // get value of ToWindowType\r
113 bool getTypeValue(ToWindowType *o_type, const tstring &i_name)\r
114 {\r
115         return getTypeValue(o_type, i_name,\r
116                                                 g_toWindowTypeTable, NUMBER_OF(g_toWindowTypeTable));\r
117 }\r
118 \r
119 \r
120 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
121 // GravityType\r
122 \r
123 \r
124 // GravityType table\r
125 typedef TypeTable<GravityType> TypeTable_GravityType;\r
126 static const TypeTable_GravityType g_gravityTypeTable[] = {\r
127         { GravityType_C,  _T("C")  },\r
128         { GravityType_N,  _T("N")  },\r
129         { GravityType_E,  _T("E")  },\r
130         { GravityType_W,  _T("W")  },\r
131         { GravityType_S,  _T("S")  },\r
132         { GravityType_NW, _T("NW") },\r
133         { GravityType_NW, _T("WN") },\r
134         { GravityType_NE, _T("NE") },\r
135         { GravityType_NE, _T("EN") },\r
136         { GravityType_SW, _T("SW") },\r
137         { GravityType_SW, _T("WS") },\r
138         { GravityType_SE, _T("SE") },\r
139         { GravityType_SE, _T("ES") },\r
140 };\r
141 \r
142 \r
143 // stream output\r
144 tostream &operator<<(tostream &i_ost, GravityType i_data)\r
145 {\r
146         tstring name;\r
147         if (getTypeName(&name, i_data,\r
148                                         g_gravityTypeTable, NUMBER_OF(g_gravityTypeTable)))\r
149                 i_ost << name;\r
150         else\r
151                 i_ost << _T("(GravityType internal error)");\r
152         return i_ost;\r
153 }\r
154 \r
155 \r
156 // get value of GravityType\r
157 bool getTypeValue(GravityType *o_type, const tstring &i_name)\r
158 {\r
159         return getTypeValue(o_type, i_name,\r
160                                                 g_gravityTypeTable, NUMBER_OF(g_gravityTypeTable));\r
161 }\r
162 \r
163 \r
164 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
165 // MouseHookType\r
166 \r
167 \r
168 // MouseHookType table\r
169 typedef TypeTable<MouseHookType> TypeTable_MouseHookType;\r
170 static const TypeTable_MouseHookType g_mouseHookTypeTable[] = {\r
171         { MouseHookType_None,  _T("None")  },\r
172         { MouseHookType_Wheel,  _T("Wheel")  },\r
173         { MouseHookType_WindowMove,  _T("WindowMove")  },\r
174 };\r
175 \r
176 \r
177 // stream output\r
178 tostream &operator<<(tostream &i_ost, MouseHookType i_data)\r
179 {\r
180         tstring name;\r
181         if (getTypeName(&name, i_data,\r
182                                         g_mouseHookTypeTable, NUMBER_OF(g_mouseHookTypeTable)))\r
183                 i_ost << name;\r
184         else\r
185                 i_ost << _T("(MouseHookType internal error)");\r
186         return i_ost;\r
187 }\r
188 \r
189 \r
190 // get value of MouseHookType\r
191 bool getTypeValue(MouseHookType *o_type, const tstring &i_name)\r
192 {\r
193         return getTypeValue(o_type, i_name, g_mouseHookTypeTable,\r
194                                                 NUMBER_OF(g_mouseHookTypeTable));\r
195 }\r
196 \r
197 \r
198 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
199 // MayuDialogType\r
200 \r
201 \r
202 // ModifierLockType table\r
203 typedef TypeTable<MayuDialogType> TypeTable_MayuDialogType;\r
204 static const TypeTable_MayuDialogType g_mayuDialogTypeTable[] = {\r
205         { MayuDialogType_investigate, _T("investigate")  },\r
206         { MayuDialogType_log,         _T("log")          },\r
207 };\r
208 \r
209 \r
210 // stream output\r
211 tostream &operator<<(tostream &i_ost, MayuDialogType i_data)\r
212 {\r
213         tstring name;\r
214         if (getTypeName(&name, i_data,\r
215                                         g_mayuDialogTypeTable, NUMBER_OF(g_mayuDialogTypeTable)))\r
216                 i_ost << name;\r
217         else\r
218                 i_ost << _T("(MayuDialogType internal error)");\r
219         return i_ost;\r
220 }\r
221 \r
222 \r
223 // get value of MayuDialogType\r
224 bool getTypeValue(MayuDialogType *o_type, const tstring &i_name)\r
225 {\r
226         return getTypeValue(o_type, i_name, g_mayuDialogTypeTable,\r
227                                                 NUMBER_OF(g_mayuDialogTypeTable));\r
228 }\r
229 \r
230 \r
231 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
232 // ToggleType\r
233 \r
234 \r
235 // ToggleType table\r
236 typedef TypeTable<ToggleType> TypeTable_ToggleType;\r
237 static const TypeTable_ToggleType g_toggleType[] = {\r
238         { ToggleType_toggle, _T("toggle") },\r
239         { ToggleType_off, _T("off") },\r
240         { ToggleType_off, _T("false") },\r
241         { ToggleType_off, _T("released") },\r
242         { ToggleType_on,  _T("on")  },\r
243         { ToggleType_on,  _T("true")  },\r
244         { ToggleType_on,  _T("pressed")  },\r
245 };\r
246 \r
247 \r
248 // stream output\r
249 tostream &operator<<(tostream &i_ost, ToggleType i_data)\r
250 {\r
251         tstring name;\r
252         if (getTypeName(&name, i_data, g_toggleType, NUMBER_OF(g_toggleType)))\r
253                 i_ost << name;\r
254         else\r
255                 i_ost << _T("(ToggleType internal error)");\r
256         return i_ost;\r
257 }\r
258 \r
259 \r
260 // get value of ToggleType\r
261 bool getTypeValue(ToggleType *o_type, const tstring &i_name)\r
262 {\r
263         return getTypeValue(o_type, i_name, g_toggleType,\r
264                                                 NUMBER_OF(g_toggleType));\r
265 }\r
266 \r
267 \r
268 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
269 // ModifierLockType\r
270 \r
271 \r
272 // ModifierLockType table\r
273 typedef TypeTable<ModifierLockType> TypeTable_ModifierLockType;\r
274 static const TypeTable_ModifierLockType g_modifierLockTypeTable[] = {\r
275         { ModifierLockType_Lock0, _T("lock0") },\r
276         { ModifierLockType_Lock1, _T("lock1") },\r
277         { ModifierLockType_Lock2, _T("lock2") },\r
278         { ModifierLockType_Lock3, _T("lock3") },\r
279         { ModifierLockType_Lock4, _T("lock4") },\r
280         { ModifierLockType_Lock5, _T("lock5") },\r
281         { ModifierLockType_Lock6, _T("lock6") },\r
282         { ModifierLockType_Lock7, _T("lock7") },\r
283         { ModifierLockType_Lock8, _T("lock8") },\r
284         { ModifierLockType_Lock9, _T("lock9") },\r
285 };\r
286 \r
287 \r
288 // stream output\r
289 tostream &operator<<(tostream &i_ost, ModifierLockType i_data)\r
290 {\r
291         tstring name;\r
292         if (getTypeName(&name, i_data,\r
293                                         g_modifierLockTypeTable, NUMBER_OF(g_modifierLockTypeTable)))\r
294                 i_ost << name;\r
295         else\r
296                 i_ost << _T("(ModifierLockType internal error)");\r
297         return i_ost;\r
298 }\r
299 \r
300 \r
301 // get value of ModifierLockType\r
302 bool getTypeValue(ModifierLockType *o_type, const tstring &i_name)\r
303 {\r
304         return getTypeValue(o_type, i_name, g_modifierLockTypeTable,\r
305                                                 NUMBER_OF(g_modifierLockTypeTable));\r
306 }\r
307 \r
308 \r
309 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
310 // ShowCommandType\r
311 \r
312 \r
313 // ShowCommandType table\r
314 typedef TypeTable<ShowCommandType> TypeTable_ShowCommandType;\r
315 static const TypeTable_ShowCommandType g_showCommandTypeTable[] = {\r
316         { ShowCommandType_hide,            _T("hide")            },\r
317         { ShowCommandType_maximize,        _T("maximize")        },\r
318         { ShowCommandType_minimize,        _T("minimize")        },\r
319         { ShowCommandType_restore,         _T("restore")         },\r
320         { ShowCommandType_show,            _T("show")            },\r
321         { ShowCommandType_showDefault,     _T("showDefault")     },\r
322         { ShowCommandType_showMaximized,   _T("showMaximized")   },\r
323         { ShowCommandType_showMinimized,   _T("showMinimized")   },\r
324         { ShowCommandType_showMinNoActive, _T("showMinNoActive") },\r
325         { ShowCommandType_showNA,          _T("showNA")          },\r
326         { ShowCommandType_showNoActivate,  _T("showNoActivate")  },\r
327         { ShowCommandType_showNormal,      _T("showNormal")      },\r
328 };\r
329 \r
330 \r
331 // stream output\r
332 tostream &operator<<(tostream &i_ost, ShowCommandType i_data)\r
333 {\r
334         tstring name;\r
335         if (getTypeName(&name, i_data,\r
336                                         g_showCommandTypeTable, NUMBER_OF(g_showCommandTypeTable)))\r
337                 i_ost << name;\r
338         else\r
339                 i_ost << _T("(ShowCommandType internal error)");\r
340         return i_ost;\r
341 }\r
342 \r
343 \r
344 // get value of ShowCommandType\r
345 bool getTypeValue(ShowCommandType *o_type, const tstring &i_name)\r
346 {\r
347         return getTypeValue(o_type, i_name, g_showCommandTypeTable,\r
348                                                 NUMBER_OF(g_showCommandTypeTable));\r
349 }\r
350 \r
351 \r
352 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
353 // TargetWindowType\r
354 \r
355 \r
356 // ModifierLockType table\r
357 typedef TypeTable<TargetWindowType> TypeTable_TargetWindowType;\r
358 static const TypeTable_TargetWindowType g_targetWindowType[] = {\r
359         { TargetWindowType_overlapped, _T("overlapped") },\r
360         { TargetWindowType_mdi,        _T("mdi")        },\r
361 };\r
362 \r
363 \r
364 // stream output\r
365 tostream &operator<<(tostream &i_ost, TargetWindowType i_data)\r
366 {\r
367         tstring name;\r
368         if (getTypeName(&name, i_data,\r
369                                         g_targetWindowType, NUMBER_OF(g_targetWindowType)))\r
370                 i_ost << name;\r
371         else\r
372                 i_ost << _T("(TargetWindowType internal error)");\r
373         return i_ost;\r
374 }\r
375 \r
376 \r
377 // get value of TargetWindowType\r
378 bool getTypeValue(TargetWindowType *o_type, const tstring &i_name)\r
379 {\r
380         return getTypeValue(o_type, i_name, g_targetWindowType,\r
381                                                 NUMBER_OF(g_targetWindowType));\r
382 }\r
383 \r
384 \r
385 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
386 // BooleanType\r
387 \r
388 \r
389 // BooleanType table\r
390 typedef TypeTable<BooleanType> TypeTable_BooleanType;\r
391 static const TypeTable_BooleanType g_booleanType[] = {\r
392         { BooleanType_false, _T("false") },\r
393         { BooleanType_true,  _T("true")  },\r
394 };\r
395 \r
396 \r
397 // stream output\r
398 tostream &operator<<(tostream &i_ost, BooleanType i_data)\r
399 {\r
400         tstring name;\r
401         if (getTypeName(&name, i_data, g_booleanType, NUMBER_OF(g_booleanType)))\r
402                 i_ost << name;\r
403         else\r
404                 i_ost << _T("(BooleanType internal error)");\r
405         return i_ost;\r
406 }\r
407 \r
408 \r
409 // get value of BooleanType\r
410 bool getTypeValue(BooleanType *o_type, const tstring &i_name)\r
411 {\r
412         return getTypeValue(o_type, i_name, g_booleanType,\r
413                                                 NUMBER_OF(g_booleanType));\r
414 }\r
415 \r
416 \r
417 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
418 // LogicalOperatorType\r
419 \r
420 \r
421 // LogicalOperatorType table\r
422 typedef TypeTable<LogicalOperatorType> TypeTable_LogicalOperatorType;\r
423 static const TypeTable_LogicalOperatorType g_logicalOperatorType[] = {\r
424         { LogicalOperatorType_or, _T("||") },\r
425         { LogicalOperatorType_and,  _T("&&")  },\r
426 };\r
427 \r
428 \r
429 // stream output\r
430 tostream &operator<<(tostream &i_ost, LogicalOperatorType i_data)\r
431 {\r
432         tstring name;\r
433         if (getTypeName(&name, i_data, g_logicalOperatorType,\r
434                                         NUMBER_OF(g_logicalOperatorType)))\r
435                 i_ost << name;\r
436         else\r
437                 i_ost << _T("(LogicalOperatorType internal error)");\r
438         return i_ost;\r
439 }\r
440 \r
441 \r
442 // get value of LogicalOperatorType\r
443 bool getTypeValue(LogicalOperatorType *o_type, const tstring &i_name)\r
444 {\r
445         return getTypeValue(o_type, i_name, g_logicalOperatorType,\r
446                                                 NUMBER_OF(g_logicalOperatorType));\r
447 }\r
448 \r
449 \r
450 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
451 // WindowMonitorFromType\r
452 \r
453 \r
454 // WindowMonitorFromType table\r
455 typedef TypeTable<WindowMonitorFromType> TypeTable_WindowMonitorFromType;\r
456 static const TypeTable_WindowMonitorFromType g_windowMonitorFromType[] = {\r
457         { WindowMonitorFromType_primary, _T("primary") },\r
458         { WindowMonitorFromType_current, _T("current") },\r
459 };\r
460 \r
461 \r
462 // stream output\r
463 tostream &operator<<(tostream &i_ost, WindowMonitorFromType i_data)\r
464 {\r
465         tstring name;\r
466         if (getTypeName(&name, i_data, g_windowMonitorFromType,\r
467                                         NUMBER_OF(g_windowMonitorFromType)))\r
468                 i_ost << name;\r
469         else\r
470                 i_ost << _T("(WindowMonitorFromType internal error)");\r
471         return i_ost;\r
472 }\r
473 \r
474 \r
475 // get value of WindowMonitorFromType\r
476 bool getTypeValue(WindowMonitorFromType *o_type, const tstring &i_name)\r
477 {\r
478         return getTypeValue(o_type, i_name, g_windowMonitorFromType,\r
479                                                 NUMBER_OF(g_windowMonitorFromType));\r
480 }\r
481 \r
482 \r
483 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
484 // std::list<tstringq>\r
485 \r
486 \r
487 /// stream output\r
488 tostream &operator<<(tostream &i_ost, const std::list<tstringq> &i_data)\r
489 {\r
490         for (std::list<tstringq>::const_iterator\r
491                         i = i_data.begin(); i != i_data.end(); ++ i) {\r
492                 i_ost << *i << _T(", ");\r
493         }\r
494         return i_ost;\r
495 }\r
496 \r
497 \r
498 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
499 // FunctionData\r
500 \r
501 \r
502 //\r
503 FunctionData::~FunctionData()\r
504 {\r
505 }\r
506 \r
507 \r
508 // stream output\r
509 tostream &operator<<(tostream &i_ost, const FunctionData *i_data)\r
510 {\r
511         return i_data->output(i_ost);\r
512 }\r
513 \r
514 \r
515 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
516 // FunctionCreator\r
517 \r
518 \r
519 ///\r
520 class FunctionCreator\r
521 {\r
522 public:\r
523         typedef FunctionData *(*Creator)();             ///\r
524 \r
525 public:\r
526         const _TCHAR *m_name;                           /// function name\r
527         Creator m_creator;                              /// function data creator\r
528 };\r
529 \r
530 \r
531 // create function\r
532 FunctionData *createFunctionData(const tstring &i_name)\r
533 {\r
534         static\r
535 #define FUNCTION_CREATOR\r
536 #include "functions.h"\r
537 #undef FUNCTION_CREATOR\r
538         ;\r
539 \r
540         for (size_t i = 0; i != NUMBER_OF(functionCreators); ++ i)\r
541                 if (i_name == functionCreators[i].m_name)\r
542                         return functionCreators[i].m_creator();\r
543         return NULL;\r
544 }\r
545 \r
546 \r
547 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
548 // misc. functions\r
549 \r
550 \r
551 //\r
552 bool getSuitableWindow(FunctionParam *i_param, HWND *o_hwnd)\r
553 {\r
554         if (!i_param->m_isPressed)\r
555                 return false;\r
556         *o_hwnd = getToplevelWindow(i_param->m_hwnd, NULL);\r
557         if (!*o_hwnd)\r
558                 return false;\r
559         return true;\r
560 }\r
561 \r
562 //\r
563 bool getSuitableMdiWindow(FunctionParam *i_param, HWND *o_hwnd,\r
564                                                   TargetWindowType *io_twt,\r
565                                                   RECT *o_rcWindow = NULL, RECT *o_rcParent = NULL)\r
566 {\r
567         if (!i_param->m_isPressed)\r
568                 return false;\r
569         bool isMdi = *io_twt == TargetWindowType_mdi;\r
570         *o_hwnd = getToplevelWindow(i_param->m_hwnd, &isMdi);\r
571         *io_twt = isMdi ? TargetWindowType_mdi : TargetWindowType_overlapped;\r
572         if (!*o_hwnd)\r
573                 return false;\r
574         switch (*io_twt) {\r
575         case TargetWindowType_overlapped:\r
576                 if (o_rcWindow)\r
577                         GetWindowRect(*o_hwnd, o_rcWindow);\r
578                 if (o_rcParent) {\r
579                         HMONITOR hm = monitorFromWindow(i_param->m_hwnd,\r
580                                                                                         MONITOR_DEFAULTTONEAREST);\r
581                         MONITORINFO mi;\r
582                         mi.cbSize = sizeof(mi);\r
583                         getMonitorInfo(hm, &mi);\r
584                         *o_rcParent = mi.rcWork;\r
585                 }\r
586                 break;\r
587         case TargetWindowType_mdi:\r
588                 if (o_rcWindow)\r
589                         getChildWindowRect(*o_hwnd, o_rcWindow);\r
590                 if (o_rcParent)\r
591                         GetClientRect(GetParent(*o_hwnd), o_rcParent);\r
592                 break;\r
593         }\r
594         return true;\r
595 }\r
596 \r
597 // get clipboard text (you must call closeClopboard())\r
598 static const _TCHAR *getTextFromClipboard(HGLOBAL *o_hdata)\r
599 {\r
600         *o_hdata = NULL;\r
601 \r
602         if (!OpenClipboard(NULL))\r
603                 return NULL;\r
604 \r
605 #ifdef UNICODE\r
606         *o_hdata = GetClipboardData(CF_UNICODETEXT);\r
607 #else\r
608         *o_hdata = GetClipboardData(CF_TEXT);\r
609 #endif\r
610         if (!*o_hdata)\r
611                 return NULL;\r
612 \r
613         _TCHAR *data = reinterpret_cast<_TCHAR *>(GlobalLock(*o_hdata));\r
614         if (!data)\r
615                 return NULL;\r
616         return data;\r
617 }\r
618 \r
619 // close clipboard that opend by getTextFromClipboard()\r
620 static void closeClipboard(HGLOBAL i_hdata, HGLOBAL i_hdataNew = NULL)\r
621 {\r
622         if (i_hdata)\r
623                 GlobalUnlock(i_hdata);\r
624         if (i_hdataNew) {\r
625                 EmptyClipboard();\r
626 #ifdef UNICODE\r
627                 SetClipboardData(CF_UNICODETEXT, i_hdataNew);\r
628 #else\r
629                 SetClipboardData(CF_TEXT, i_hdataNew);\r
630 #endif\r
631         }\r
632         CloseClipboard();\r
633 }\r
634 \r
635 \r
636 // EmacsEditKillLineFunc.\r
637 // clear the contents of the clopboard\r
638 // at that time, confirm if it is the result of the previous kill-line\r
639 void Engine::EmacsEditKillLine::func()\r
640 {\r
641         if (!m_buf.empty()) {\r
642                 HGLOBAL g;\r
643                 const _TCHAR *text = getTextFromClipboard(&g);\r
644                 if (text == NULL || m_buf != text)\r
645                         reset();\r
646                 closeClipboard(g);\r
647         }\r
648         if (OpenClipboard(NULL)) {\r
649                 EmptyClipboard();\r
650                 CloseClipboard();\r
651         }\r
652 }\r
653 \r
654 \r
655 /** if the text of the clipboard is\r
656 @doc\r
657 <pre>\r
658 1: EDIT Control (at EOL C-K): ""            =&gt; buf + "\r\n", Delete\r
659 0: EDIT Control (other  C-K): "(.+)"        =&gt; buf + "\1"\r
660 0: IE FORM TEXTAREA (at EOL C-K): "\r\n"    =&gt; buf + "\r\n"\r
661 2: IE FORM TEXTAREA (other C-K): "(.+)\r\n" =&gt; buf + "\1", Return Left\r
662 ^retval\r
663 </pre>\r
664 */\r
665 HGLOBAL Engine::EmacsEditKillLine::makeNewKillLineBuf(\r
666         const _TCHAR *i_data, int *o_retval)\r
667 {\r
668         size_t len = m_buf.size();\r
669         len += _tcslen(i_data) + 3;\r
670 \r
671         HGLOBAL hdata = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,\r
672                                                                 len * sizeof(_TCHAR));\r
673         if (!hdata)\r
674                 return NULL;\r
675         _TCHAR *dataNew = reinterpret_cast<_TCHAR *>(GlobalLock(hdata));\r
676         *dataNew = _T('\0');\r
677         if (!m_buf.empty())\r
678                 _tcscpy(dataNew, m_buf.c_str());\r
679 \r
680         len = _tcslen(i_data);\r
681         if (3 <= len &&\r
682                         i_data[len - 2] == _T('\r') && i_data[len - 1] == _T('\n')) {\r
683                 _tcscat(dataNew, i_data);\r
684                 len = _tcslen(dataNew);\r
685                 dataNew[len - 2] = _T('\0'); // chomp\r
686                 *o_retval = 2;\r
687         } else if (len == 0) {\r
688                 _tcscat(dataNew, _T("\r\n"));\r
689                 *o_retval = 1;\r
690         } else {\r
691                 _tcscat(dataNew, i_data);\r
692                 *o_retval = 0;\r
693         }\r
694 \r
695         m_buf = dataNew;\r
696 \r
697         GlobalUnlock(hdata);\r
698         return hdata;\r
699 }\r
700 \r
701 \r
702 // EmacsEditKillLinePred\r
703 int Engine::EmacsEditKillLine::pred()\r
704 {\r
705         HGLOBAL g;\r
706         const _TCHAR *text = getTextFromClipboard(&g);\r
707         int retval;\r
708         HGLOBAL hdata = makeNewKillLineBuf(text ? text : _T(""), &retval);\r
709         closeClipboard(g, hdata);\r
710         return retval;\r
711 }\r
712 \r
713 \r
714 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
715 // functions\r
716 \r
717 \r
718 // send a default key to Windows\r
719 void Engine::funcDefault(FunctionParam *i_param)\r
720 {\r
721         {\r
722                 Acquire a(&m_log, 1);\r
723                 m_log << std::endl;\r
724                 i_param->m_doesNeedEndl = false;\r
725         }\r
726         if (i_param->m_isPressed)\r
727                 generateModifierEvents(i_param->m_c.m_mkey.m_modifier);\r
728         generateKeyEvent(i_param->m_c.m_mkey.m_key, i_param->m_isPressed, true);\r
729 }\r
730 \r
731 // use a corresponding key of a parent keymap\r
732 void Engine::funcKeymapParent(FunctionParam *i_param)\r
733 {\r
734         Current c(i_param->m_c);\r
735         c.m_keymap = c.m_keymap->getParentKeymap();\r
736         if (!c.m_keymap) {\r
737                 funcDefault(i_param);\r
738                 return;\r
739         }\r
740 \r
741         {\r
742                 Acquire a(&m_log, 1);\r
743                 m_log << _T("(") << c.m_keymap->getName() << _T(")") << std::endl;\r
744         }\r
745         i_param->m_doesNeedEndl = false;\r
746         generateKeyboardEvents(c);\r
747 }\r
748 \r
749 // use a corresponding key of a current window\r
750 void Engine::funcKeymapWindow(FunctionParam *i_param)\r
751 {\r
752         Current c(i_param->m_c);\r
753         c.m_keymap = m_currentFocusOfThread->m_keymaps.front();\r
754         c.m_i = m_currentFocusOfThread->m_keymaps.begin();\r
755         generateKeyboardEvents(c);\r
756 }\r
757 \r
758 // use a corresponding key of the previous prefixed keymap\r
759 void Engine::funcKeymapPrevPrefix(FunctionParam *i_param, int i_previous)\r
760 {\r
761         Current c(i_param->m_c);\r
762         if (0 < i_previous && 0 <= m_keymapPrefixHistory.size() - i_previous) {\r
763                 int n = i_previous - 1;\r
764                 KeymapPtrList::reverse_iterator i = m_keymapPrefixHistory.rbegin();\r
765                 while (0 < n && i != m_keymapPrefixHistory.rend())\r
766                         --n, ++i;\r
767                 c.m_keymap = *i;\r
768                 generateKeyboardEvents(c);\r
769         }\r
770 }\r
771 \r
772 // use a corresponding key of an other window class, or use a default key\r
773 void Engine::funcOtherWindowClass(FunctionParam *i_param)\r
774 {\r
775         Current c(i_param->m_c);\r
776         ++ c.m_i;\r
777         if (c.m_i == m_currentFocusOfThread->m_keymaps.end()) {\r
778                 funcDefault(i_param);\r
779                 return;\r
780         }\r
781 \r
782         c.m_keymap = *c.m_i;\r
783         {\r
784                 Acquire a(&m_log, 1);\r
785                 m_log << _T("(") << c.m_keymap->getName() << _T(")") << std::endl;\r
786         }\r
787         i_param->m_doesNeedEndl = false;\r
788         generateKeyboardEvents(c);\r
789 }\r
790 \r
791 // prefix key\r
792 void Engine::funcPrefix(FunctionParam *i_param, const Keymap *i_keymap,\r
793                                                 BooleanType i_doesIgnoreModifiers)\r
794 {\r
795         if (!i_param->m_isPressed)\r
796                 return;\r
797 \r
798         setCurrentKeymap(i_keymap, true);\r
799 \r
800         // generate prefixed event\r
801         generateEvents(i_param->m_c, m_currentKeymap, &Event::prefixed);\r
802 \r
803         m_isPrefix = true;\r
804         m_doesEditNextModifier = false;\r
805         m_doesIgnoreModifierForPrefix = !!i_doesIgnoreModifiers;\r
806 \r
807         {\r
808                 Acquire a(&m_log, 1);\r
809                 m_log << _T("(") << i_keymap->getName() << _T(", ")\r
810                 << (i_doesIgnoreModifiers ? _T("true") : _T("false")) << _T(")");\r
811         }\r
812 }\r
813 \r
814 // other keymap's key\r
815 void Engine::funcKeymap(FunctionParam *i_param, const Keymap *i_keymap)\r
816 {\r
817         Current c(i_param->m_c);\r
818         c.m_keymap = i_keymap;\r
819         {\r
820                 Acquire a(&m_log, 1);\r
821                 m_log << _T("(") << c.m_keymap->getName() << _T(")") << std::endl;\r
822                 i_param->m_doesNeedEndl = false;\r
823         }\r
824         generateKeyboardEvents(c);\r
825 }\r
826 \r
827 // sync\r
828 void Engine::funcSync(FunctionParam *i_param)\r
829 {\r
830         if (i_param->m_isPressed)\r
831                 generateModifierEvents(i_param->m_af->m_modifier);\r
832         if (!i_param->m_isPressed || m_currentFocusOfThread->m_isConsole)\r
833                 return;\r
834 \r
835         Key *sync = m_setting->m_keyboard.getSyncKey();\r
836         if (sync->getScanCodesSize() == 0)\r
837                 return;\r
838         const ScanCode *sc = sync->getScanCodes();\r
839 \r
840         // set variables exported from mayu.dll\r
841         g_hookData->m_syncKey = sc->m_scan;\r
842         g_hookData->m_syncKeyIsExtended = !!(sc->m_flags & ScanCode::E0E1);\r
843         m_isSynchronizing = true;\r
844         generateKeyEvent(sync, false, false);\r
845 \r
846         m_cs.release();\r
847         DWORD r = WaitForSingleObject(m_eSync, 5000);\r
848         if (r == WAIT_TIMEOUT) {\r
849                 Acquire a(&m_log, 0);\r
850                 m_log << _T(" *FAILED*") << std::endl;\r
851         }\r
852         m_cs.acquire();\r
853         m_isSynchronizing = false;\r
854 }\r
855 \r
856 // toggle lock\r
857 void Engine::funcToggle(FunctionParam *i_param, ModifierLockType i_lock,\r
858                                                 ToggleType i_toggle)\r
859 {\r
860         if (i_param->m_isPressed)                       // ignore PRESS\r
861                 return;\r
862 \r
863         Modifier::Type mt = static_cast<Modifier::Type>(i_lock);\r
864         switch (i_toggle) {\r
865         case ToggleType_toggle:\r
866                 m_currentLock.press(mt, !m_currentLock.isPressed(mt));\r
867                 break;\r
868         case ToggleType_off:\r
869                 m_currentLock.press(mt, false);\r
870                 break;\r
871         case ToggleType_on:\r
872                 m_currentLock.press(mt, true);\r
873                 break;\r
874         }\r
875 }\r
876 \r
877 // edit next user input key's modifier\r
878 void Engine::funcEditNextModifier(FunctionParam *i_param,\r
879                                                                   const Modifier &i_modifier)\r
880 {\r
881         if (!i_param->m_isPressed)\r
882                 return;\r
883 \r
884         m_isPrefix = true;\r
885         m_doesEditNextModifier = true;\r
886         m_doesIgnoreModifierForPrefix = true;\r
887         m_modifierForNextKey = i_modifier;\r
888 }\r
889 \r
890 // variable\r
891 void Engine::funcVariable(FunctionParam *i_param, int i_mag, int i_inc)\r
892 {\r
893         if (!i_param->m_isPressed)\r
894                 return;\r
895         m_variable *= i_mag;\r
896         m_variable += i_inc;\r
897 }\r
898 \r
899 // repeat N times\r
900 void Engine::funcRepeat(FunctionParam *i_param, const KeySeq *i_keySeq,\r
901                                                 int i_max)\r
902 {\r
903         if (i_param->m_isPressed) {\r
904                 int end = MIN(m_variable, i_max);\r
905                 for (int i = 0; i < end - 1; ++ i)\r
906                         generateKeySeqEvents(i_param->m_c, i_keySeq, Part_all);\r
907                 if (0 < end)\r
908                         generateKeySeqEvents(i_param->m_c, i_keySeq, Part_down);\r
909         } else\r
910                 generateKeySeqEvents(i_param->m_c, i_keySeq, Part_up);\r
911 }\r
912 \r
913 // undefined (bell)\r
914 void Engine::funcUndefined(FunctionParam *i_param)\r
915 {\r
916         if (!i_param->m_isPressed)\r
917                 return;\r
918         MessageBeep(MB_OK);\r
919 }\r
920 \r
921 // ignore\r
922 void Engine::funcIgnore(FunctionParam *)\r
923 {\r
924         // do nothing\r
925 }\r
926 \r
927 // post message\r
928 void Engine::funcPostMessage(FunctionParam *i_param, ToWindowType i_window,\r
929                                                          UINT i_message, WPARAM i_wParam, LPARAM i_lParam)\r
930 {\r
931         if (!i_param->m_isPressed)\r
932                 return;\r
933 \r
934         int window = static_cast<int>(i_window);\r
935 \r
936         HWND hwnd = i_param->m_hwnd;\r
937         if (0 < window) {\r
938                 for (int i = 0; i < window; ++ i)\r
939                         hwnd = GetParent(hwnd);\r
940         } else if (window == ToWindowType_toMainWindow) {\r
941                 while (true) {\r
942                         HWND p = GetParent(hwnd);\r
943                         if (!p)\r
944                                 break;\r
945                         hwnd = p;\r
946                 }\r
947         } else if (window == ToWindowType_toOverlappedWindow) {\r
948                 while (hwnd) {\r
949 #ifdef MAYU64\r
950                         LONG_PTR style = GetWindowLongPtr(hwnd, GWL_STYLE);\r
951 #else\r
952                         LONG style = GetWindowLong(hwnd, GWL_STYLE);\r
953 #endif\r
954                         if ((style & WS_CHILD) == 0)\r
955                                 break;\r
956                         hwnd = GetParent(hwnd);\r
957                 }\r
958         }\r
959 \r
960         if (hwnd)\r
961                 PostMessage(hwnd, i_message, i_wParam, i_lParam);\r
962 }\r
963 \r
964 \r
965 // ShellExecute\r
966 void Engine::funcShellExecute(FunctionParam *i_param,\r
967                                                           const StrExprArg &/*i_operation*/,\r
968                                                           const StrExprArg &/*i_file*/,\r
969                                                           const StrExprArg &/*i_parameters*/,\r
970                                                           const StrExprArg &/*i_directory*/,\r
971                                                           ShowCommandType /*i_showCommand*/)\r
972 {\r
973         if (!i_param->m_isPressed)\r
974                 return;\r
975         m_afShellExecute = i_param->m_af;\r
976         PostMessage(m_hwndAssocWindow,\r
977                                 WM_APP_engineNotify, EngineNotify_shellExecute, 0);\r
978 }\r
979 \r
980 \r
981 // shell execute\r
982 void Engine::shellExecute()\r
983 {\r
984         Acquire a(&m_cs);\r
985 \r
986         FunctionData_ShellExecute *fd =\r
987                 reinterpret_cast<FunctionData_ShellExecute *>(\r
988                         m_afShellExecute->m_functionData);\r
989 \r
990         int r = (int)ShellExecute(\r
991                                 NULL,\r
992                                 fd->m_operation.eval().empty() ? _T("open") : fd->m_operation.eval().c_str(),\r
993                                 fd->m_file.eval().empty() ? NULL : fd->m_file.eval().c_str(),\r
994                                 fd->m_parameters.eval().empty() ? NULL : fd->m_parameters.eval().c_str(),\r
995                                 fd->m_directory.eval().empty() ? NULL : fd->m_directory.eval().c_str(),\r
996                                 fd->m_showCommand);\r
997         if (32 < r)\r
998                 return; // success\r
999 \r
1000         typedef TypeTable<int> ErrorTable;\r
1001         static const ErrorTable errorTable[] = {\r
1002                 { 0, _T("The operating system is out of memory or resources.") },\r
1003                 { ERROR_FILE_NOT_FOUND, _T("The specified file was not found.") },\r
1004                 { ERROR_PATH_NOT_FOUND, _T("The specified path was not found.") },\r
1005                 { ERROR_BAD_FORMAT, _T("The .exe file is invalid ")\r
1006                   _T("(non-Win32R .exe or error in .exe image).") },\r
1007                 { SE_ERR_ACCESSDENIED,\r
1008                   _T("The operating system denied access to the specified file.") },\r
1009                 { SE_ERR_ASSOCINCOMPLETE,\r
1010                   _T("The file name association is incomplete or invalid.") },\r
1011                 { SE_ERR_DDEBUSY,\r
1012                   _T("The DDE transaction could not be completed ")\r
1013                   _T("because other DDE transactions were being processed. ") },\r
1014                 { SE_ERR_DDEFAIL, _T("The DDE transaction failed.") },\r
1015                 { SE_ERR_DDETIMEOUT, _T("The DDE transaction could not be completed ")\r
1016                   _T("because the request timed out.") },\r
1017                 { SE_ERR_DLLNOTFOUND,\r
1018                   _T("The specified dynamic-link library was not found.") },\r
1019                 { SE_ERR_FNF, _T("The specified file was not found.") },\r
1020                 { SE_ERR_NOASSOC, _T("There is no application associated ")\r
1021                   _T("with the given file name extension.") },\r
1022                 { SE_ERR_OOM,\r
1023                   _T("There was not enough memory to complete the operation.") },\r
1024                 { SE_ERR_PNF, _T("The specified path was not found.") },\r
1025                 { SE_ERR_SHARE, _T("A sharing violation occurred.") },\r
1026         };\r
1027 \r
1028         tstring errorMessage(_T("Unknown error."));\r
1029         getTypeName(&errorMessage, r, errorTable, NUMBER_OF(errorTable));\r
1030 \r
1031         Acquire b(&m_log, 0);\r
1032         m_log << _T("error: ") << fd << _T(": ") << errorMessage << std::endl;\r
1033 }\r
1034 \r
1035 \r
1036 struct EnumWindowsForSetForegroundWindowParam {\r
1037         const FunctionData_SetForegroundWindow *m_fd;\r
1038         HWND m_hwnd;\r
1039 \r
1040 public:\r
1041         EnumWindowsForSetForegroundWindowParam(\r
1042                 const FunctionData_SetForegroundWindow *i_fd)\r
1043                         : m_fd(i_fd),\r
1044                         m_hwnd(NULL) {\r
1045         }\r
1046 };\r
1047 \r
1048 \r
1049 /// enum windows for SetForegroundWindow\r
1050 static BOOL CALLBACK enumWindowsForSetForegroundWindow(\r
1051         HWND i_hwnd, LPARAM i_lParam)\r
1052 {\r
1053         EnumWindowsForSetForegroundWindowParam &ep =\r
1054                 *reinterpret_cast<EnumWindowsForSetForegroundWindowParam *>(i_lParam);\r
1055 \r
1056         _TCHAR name[GANA_MAX_ATOM_LENGTH];\r
1057         if (!GetClassName(i_hwnd, name, NUMBER_OF(name)))\r
1058                 return TRUE;\r
1059         tsmatch what;\r
1060         if (!boost::regex_search(tstring(name), what, ep.m_fd->m_windowClassName))\r
1061                 if (ep.m_fd->m_logicalOp == LogicalOperatorType_and)\r
1062                         return TRUE;                            // match failed\r
1063 \r
1064         if (ep.m_fd->m_logicalOp == LogicalOperatorType_and) {\r
1065                 if (GetWindowText(i_hwnd, name, NUMBER_OF(name)) == 0)\r
1066                         name[0] = _T('\0');\r
1067                 if (!boost::regex_search(tstring(name), what,\r
1068                                                                  ep.m_fd->m_windowTitleName))\r
1069                         return TRUE;                            // match failed\r
1070         }\r
1071 \r
1072         ep.m_hwnd = i_hwnd;\r
1073         return FALSE;\r
1074 }\r
1075 \r
1076 \r
1077 /// SetForegroundWindow\r
1078 void Engine::funcSetForegroundWindow(FunctionParam *i_param, const tregex &,\r
1079                                                                          LogicalOperatorType , const tregex &)\r
1080 {\r
1081         if (!i_param->m_isPressed)\r
1082                 return;\r
1083         EnumWindowsForSetForegroundWindowParam\r
1084         ep(static_cast<const FunctionData_SetForegroundWindow *>(\r
1085                    i_param->m_af->m_functionData));\r
1086         EnumWindows(enumWindowsForSetForegroundWindow,\r
1087                                 reinterpret_cast<LPARAM>(&ep));\r
1088         if (ep.m_hwnd)\r
1089                 PostMessage(m_hwndAssocWindow,\r
1090                                         WM_APP_engineNotify, EngineNotify_setForegroundWindow,\r
1091                                         reinterpret_cast<LPARAM>(ep.m_hwnd));\r
1092 \r
1093 }\r
1094 \r
1095 \r
1096 // load setting\r
1097 void Engine::funcLoadSetting(FunctionParam *i_param, const StrExprArg &i_name)\r
1098 {\r
1099         if (!i_param->m_isPressed)\r
1100                 return;\r
1101         if (!i_name.eval().empty()) {\r
1102                 // set MAYU_REGISTRY_ROOT\.mayuIndex which name is same with i_name\r
1103                 Registry reg(MAYU_REGISTRY_ROOT);\r
1104 \r
1105                 tregex split(_T("^([^;]*);([^;]*);(.*)$"));\r
1106                 tstringi dot_mayu;\r
1107                 for (size_t i = 0; i < MAX_MAYU_REGISTRY_ENTRIES; ++ i) {\r
1108                         _TCHAR buf[100];\r
1109                         _sntprintf(buf, NUMBER_OF(buf), _T(".mayu%d"), i);\r
1110                         if (!reg.read(buf, &dot_mayu))\r
1111                                 break;\r
1112 \r
1113                         tsmatch what;\r
1114                         if (boost::regex_match(dot_mayu, what, split) &&\r
1115                                         what.str(1) == i_name.eval()) {\r
1116                                 reg.write(_T(".mayuIndex"), i);\r
1117                                 goto success;\r
1118                         }\r
1119                 }\r
1120 \r
1121                 {\r
1122                         Acquire a(&m_log, 0);\r
1123                         m_log << _T("unknown setting name: ") << i_name;\r
1124                 }\r
1125                 return;\r
1126 \r
1127 success:\r
1128                 ;\r
1129         }\r
1130         PostMessage(m_hwndAssocWindow,\r
1131                                 WM_APP_engineNotify, EngineNotify_loadSetting, 0);\r
1132 }\r
1133 \r
1134 // virtual key\r
1135 void Engine::funcVK(FunctionParam *i_param, VKey i_vkey)\r
1136 {\r
1137         long key = static_cast<long>(i_vkey);\r
1138         BYTE vkey = static_cast<BYTE>(i_vkey);\r
1139         bool isExtended = !!(key & VKey_extended);\r
1140         bool isUp       = !i_param->m_isPressed && !!(key & VKey_released);\r
1141         bool isDown     = i_param->m_isPressed && !!(key & VKey_pressed);\r
1142 \r
1143         if (vkey == VK_LBUTTON && isDown)\r
1144                 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);\r
1145         else if (vkey == VK_LBUTTON && isUp)\r
1146                 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);\r
1147         else if (vkey == VK_MBUTTON && isDown)\r
1148                 mouse_event(MOUSEEVENTF_MIDDLEDOWN, 0, 0, 0, 0);\r
1149         else if (vkey == VK_MBUTTON && isUp)\r
1150                 mouse_event(MOUSEEVENTF_MIDDLEUP, 0, 0, 0, 0);\r
1151         else if (vkey == VK_RBUTTON && isDown)\r
1152                 mouse_event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0);\r
1153         else if (vkey == VK_RBUTTON && isUp)\r
1154                 mouse_event(MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0);\r
1155         else if (vkey == VK_XBUTTON1 && isDown)\r
1156                 mouse_event(MOUSEEVENTF_XDOWN, 0, 0, XBUTTON1, 0);\r
1157         else if (vkey == VK_XBUTTON1 && isUp)\r
1158                 mouse_event(MOUSEEVENTF_XUP, 0, 0, XBUTTON1, 0);\r
1159         else if (vkey == VK_XBUTTON2 && isDown)\r
1160                 mouse_event(MOUSEEVENTF_XDOWN, 0, 0, XBUTTON2, 0);\r
1161         else if (vkey == VK_XBUTTON2 && isUp)\r
1162                 mouse_event(MOUSEEVENTF_XUP, 0, 0, XBUTTON2, 0);\r
1163         else if (isUp || isDown)\r
1164                 keybd_event(vkey,\r
1165                                         static_cast<BYTE>(MapVirtualKey(vkey, 0)),\r
1166                                         (isExtended ? KEYEVENTF_EXTENDEDKEY : 0) |\r
1167                                         (i_param->m_isPressed ? 0 : KEYEVENTF_KEYUP), 0);\r
1168 }\r
1169 \r
1170 // wait\r
1171 void Engine::funcWait(FunctionParam *i_param, int i_milliSecond)\r
1172 {\r
1173         if (!i_param->m_isPressed)\r
1174                 return;\r
1175         if (i_milliSecond < 0 || 5000 < i_milliSecond)  // too long wait\r
1176                 return;\r
1177 \r
1178         m_isSynchronizing = true;\r
1179         m_cs.release();\r
1180         Sleep(i_milliSecond);\r
1181         m_cs.acquire();\r
1182         m_isSynchronizing = false;\r
1183 }\r
1184 \r
1185 // investigate WM_COMMAND, WM_SYSCOMMAND\r
1186 void Engine::funcInvestigateCommand(FunctionParam *i_param)\r
1187 {\r
1188         if (!i_param->m_isPressed)\r
1189                 return;\r
1190         Acquire a(&m_log, 0);\r
1191         g_hookData->m_doesNotifyCommand = !g_hookData->m_doesNotifyCommand;\r
1192         if (g_hookData->m_doesNotifyCommand)\r
1193                 m_log << _T(" begin") << std::endl;\r
1194         else\r
1195                 m_log << _T(" end") << std::endl;\r
1196 }\r
1197 \r
1198 // show mayu dialog box\r
1199 void Engine::funcMayuDialog(FunctionParam *i_param, MayuDialogType i_dialog,\r
1200                                                         ShowCommandType i_showCommand)\r
1201 {\r
1202         if (!i_param->m_isPressed)\r
1203                 return;\r
1204         PostMessage(getAssociatedWndow(), WM_APP_engineNotify, EngineNotify_showDlg,\r
1205                                 static_cast<LPARAM>(i_dialog) |\r
1206                                 static_cast<LPARAM>(i_showCommand));\r
1207 }\r
1208 \r
1209 // describe bindings\r
1210 void Engine::funcDescribeBindings(FunctionParam *i_param)\r
1211 {\r
1212         if (!i_param->m_isPressed)\r
1213                 return;\r
1214         {\r
1215                 Acquire a(&m_log, 1);\r
1216                 m_log << std::endl;\r
1217         }\r
1218         describeBindings();\r
1219 }\r
1220 \r
1221 // show help message\r
1222 void Engine::funcHelpMessage(FunctionParam *i_param, const StrExprArg &i_title,\r
1223                                                          const StrExprArg &i_message)\r
1224 {\r
1225         if (!i_param->m_isPressed)\r
1226                 return;\r
1227 \r
1228         m_helpTitle = i_title.eval();\r
1229         m_helpMessage = i_message.eval();\r
1230         bool doesShow = !(i_title.eval().size() == 0 && i_message.eval().size() == 0);\r
1231         PostMessage(getAssociatedWndow(), WM_APP_engineNotify,\r
1232                                 EngineNotify_helpMessage, doesShow);\r
1233 }\r
1234 \r
1235 // show variable\r
1236 void Engine::funcHelpVariable(FunctionParam *i_param, const StrExprArg &i_title)\r
1237 {\r
1238         if (!i_param->m_isPressed)\r
1239                 return;\r
1240 \r
1241         _TCHAR buf[20];\r
1242         _sntprintf(buf, NUMBER_OF(buf), _T("%d"), m_variable);\r
1243 \r
1244         m_helpTitle = i_title.eval();\r
1245         m_helpMessage = buf;\r
1246         PostMessage(getAssociatedWndow(), WM_APP_engineNotify,\r
1247                                 EngineNotify_helpMessage, true);\r
1248 }\r
1249 \r
1250 // raise window\r
1251 void Engine::funcWindowRaise(FunctionParam *i_param,\r
1252                                                          TargetWindowType i_twt)\r
1253 {\r
1254         HWND hwnd;\r
1255         if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt))\r
1256                 return;\r
1257         SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0,\r
1258                                  SWP_ASYNCWINDOWPOS | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOSIZE);\r
1259 }\r
1260 \r
1261 // lower window\r
1262 void Engine::funcWindowLower(FunctionParam *i_param, TargetWindowType i_twt)\r
1263 {\r
1264         HWND hwnd;\r
1265         if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt))\r
1266                 return;\r
1267         SetWindowPos(hwnd, HWND_BOTTOM, 0, 0, 0, 0,\r
1268                                  SWP_ASYNCWINDOWPOS | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOSIZE);\r
1269 }\r
1270 \r
1271 // minimize window\r
1272 void Engine::funcWindowMinimize(FunctionParam *i_param, TargetWindowType i_twt)\r
1273 {\r
1274         HWND hwnd;\r
1275         if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt))\r
1276                 return;\r
1277         PostMessage(hwnd, WM_SYSCOMMAND,\r
1278                                 IsIconic(hwnd) ? SC_RESTORE : SC_MINIMIZE, 0);\r
1279 }\r
1280 \r
1281 // maximize window\r
1282 void Engine::funcWindowMaximize(FunctionParam *i_param, TargetWindowType i_twt)\r
1283 {\r
1284         HWND hwnd;\r
1285         if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt))\r
1286                 return;\r
1287         PostMessage(hwnd, WM_SYSCOMMAND,\r
1288                                 IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, 0);\r
1289 }\r
1290 \r
1291 // maximize horizontally or virtically\r
1292 void Engine::funcWindowHVMaximize(FunctionParam *i_param,\r
1293                                                                   BooleanType i_isHorizontal,\r
1294                                                                   TargetWindowType i_twt)\r
1295 {\r
1296         HWND hwnd;\r
1297         RECT rc, rcd;\r
1298         if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt, &rc, &rcd))\r
1299                 return;\r
1300 \r
1301         // erase non window\r
1302         while (true) {\r
1303                 WindowPositions::iterator i = m_windowPositions.begin();\r
1304                 WindowPositions::iterator end = m_windowPositions.end();\r
1305                 for (; i != end; ++ i)\r
1306                         if (!IsWindow((*i).m_hwnd))\r
1307                                 break;\r
1308                 if (i == end)\r
1309                         break;\r
1310                 m_windowPositions.erase(i);\r
1311         }\r
1312 \r
1313         // find target\r
1314         WindowPositions::iterator i = m_windowPositions.begin();\r
1315         WindowPositions::iterator end = m_windowPositions.end();\r
1316         WindowPositions::iterator target = end;\r
1317         for (; i != end; ++ i)\r
1318                 if ((*i).m_hwnd == hwnd) {\r
1319                         target = i;\r
1320                         break;\r
1321                 }\r
1322 \r
1323         if (IsZoomed(hwnd))\r
1324                 PostMessage(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);\r
1325         else {\r
1326                 WindowPosition::Mode mode = WindowPosition::Mode_normal;\r
1327 \r
1328                 if (target != end) {\r
1329                         WindowPosition &wp = *target;\r
1330                         rc = wp.m_rc;\r
1331                         if (wp.m_mode == WindowPosition::Mode_HV)\r
1332                                 mode = wp.m_mode =\r
1333                                                    i_isHorizontal ? WindowPosition::Mode_V : WindowPosition::Mode_H;\r
1334                         else if (( i_isHorizontal && wp.m_mode == WindowPosition::Mode_V) ||\r
1335                                          (!i_isHorizontal && wp.m_mode == WindowPosition::Mode_H))\r
1336                                 mode = wp.m_mode = WindowPosition::Mode_HV;\r
1337                         else\r
1338                                 m_windowPositions.erase(target);\r
1339                 } else {\r
1340                         mode = i_isHorizontal ? WindowPosition::Mode_H : WindowPosition::Mode_V;\r
1341                         m_windowPositions.push_front(WindowPosition(hwnd, rc, mode));\r
1342                 }\r
1343 \r
1344                 if (static_cast<int>(mode) & static_cast<int>(WindowPosition::Mode_H))\r
1345                         rc.left = rcd.left, rc.right = rcd.right;\r
1346                 if (static_cast<int>(mode) & static_cast<int>(WindowPosition::Mode_V))\r
1347                         rc.top = rcd.top, rc.bottom = rcd.bottom;\r
1348 \r
1349                 asyncMoveWindow(hwnd, rc.left, rc.top, rcWidth(&rc), rcHeight(&rc));\r
1350         }\r
1351 }\r
1352 \r
1353 // maximize window horizontally\r
1354 void Engine::funcWindowHMaximize(FunctionParam *i_param,\r
1355                                                                  TargetWindowType i_twt)\r
1356 {\r
1357         funcWindowHVMaximize(i_param, BooleanType_true, i_twt);\r
1358 }\r
1359 \r
1360 // maximize window virtically\r
1361 void Engine::funcWindowVMaximize(FunctionParam *i_param,\r
1362                                                                  TargetWindowType i_twt)\r
1363 {\r
1364         funcWindowHVMaximize(i_param, BooleanType_false, i_twt);\r
1365 }\r
1366 \r
1367 // move window\r
1368 void Engine::funcWindowMove(FunctionParam *i_param, int i_dx, int i_dy,\r
1369                                                         TargetWindowType i_twt)\r
1370 {\r
1371         funcWindowMoveTo(i_param, GravityType_C, i_dx, i_dy, i_twt);\r
1372 }\r
1373 \r
1374 // move window to ...\r
1375 void Engine::funcWindowMoveTo(FunctionParam *i_param,\r
1376                                                           GravityType i_gravityType,\r
1377                                                           int i_dx, int i_dy, TargetWindowType i_twt)\r
1378 {\r
1379         HWND hwnd;\r
1380         RECT rc, rcd;\r
1381         if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt, &rc, &rcd))\r
1382                 return;\r
1383 \r
1384         int x = rc.left + i_dx;\r
1385         int y = rc.top + i_dy;\r
1386 \r
1387         if (i_gravityType & GravityType_N)\r
1388                 y = i_dy + rcd.top;\r
1389         if (i_gravityType & GravityType_E)\r
1390                 x = i_dx + rcd.right - rcWidth(&rc);\r
1391         if (i_gravityType & GravityType_W)\r
1392                 x = i_dx + rcd.left;\r
1393         if (i_gravityType & GravityType_S)\r
1394                 y = i_dy + rcd.bottom - rcHeight(&rc);\r
1395         asyncMoveWindow(hwnd, x, y);\r
1396 }\r
1397 \r
1398 \r
1399 // move window visibly\r
1400 void Engine::funcWindowMoveVisibly(FunctionParam *i_param,\r
1401                                                                    TargetWindowType i_twt)\r
1402 {\r
1403         HWND hwnd;\r
1404         RECT rc, rcd;\r
1405         if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt, &rc, &rcd))\r
1406                 return;\r
1407 \r
1408         int x = rc.left;\r
1409         int y = rc.top;\r
1410         if (rc.left < rcd.left)\r
1411                 x = rcd.left;\r
1412         else if (rcd.right < rc.right)\r
1413                 x = rcd.right - rcWidth(&rc);\r
1414         if (rc.top < rcd.top)\r
1415                 y = rcd.top;\r
1416         else if (rcd.bottom < rc.bottom)\r
1417                 y = rcd.bottom - rcHeight(&rc);\r
1418         asyncMoveWindow(hwnd, x, y);\r
1419 }\r
1420 \r
1421 \r
1422 struct EnumDisplayMonitorsForWindowMonitorToParam {\r
1423         std::vector<HMONITOR> m_monitors;\r
1424         std::vector<MONITORINFO> m_monitorinfos;\r
1425         int m_primaryMonitorIdx;\r
1426         int m_currentMonitorIdx;\r
1427 \r
1428         HMONITOR m_hmon;\r
1429 \r
1430 public:\r
1431         EnumDisplayMonitorsForWindowMonitorToParam(HMONITOR i_hmon)\r
1432                         : m_hmon(i_hmon),\r
1433                         m_primaryMonitorIdx(-1), m_currentMonitorIdx(-1) {\r
1434         }\r
1435 };\r
1436 \r
1437 static BOOL CALLBACK enumDisplayMonitorsForWindowMonitorTo(\r
1438         HMONITOR i_hmon, HDC i_hdc, LPRECT i_rcMonitor, LPARAM i_data)\r
1439 {\r
1440         EnumDisplayMonitorsForWindowMonitorToParam &ep =\r
1441                 *reinterpret_cast<EnumDisplayMonitorsForWindowMonitorToParam *>(i_data);\r
1442 \r
1443         ep.m_monitors.push_back(i_hmon);\r
1444 \r
1445         MONITORINFO mi;\r
1446         mi.cbSize = sizeof(mi);\r
1447         getMonitorInfo(i_hmon, &mi);\r
1448         ep.m_monitorinfos.push_back(mi);\r
1449 \r
1450         if (mi.dwFlags & MONITORINFOF_PRIMARY)\r
1451                 ep.m_primaryMonitorIdx = ep.m_monitors.size() - 1;\r
1452         if (i_hmon == ep.m_hmon)\r
1453                 ep.m_currentMonitorIdx = ep.m_monitors.size() - 1;\r
1454 \r
1455         return TRUE;\r
1456 }\r
1457 \r
1458 /// move window to other monitor\r
1459 void Engine::funcWindowMonitorTo(\r
1460         FunctionParam *i_param, WindowMonitorFromType i_fromType, int i_monitor,\r
1461         BooleanType i_adjustPos, BooleanType i_adjustSize)\r
1462 {\r
1463         HWND hwnd;\r
1464         if (! getSuitableWindow(i_param, &hwnd))\r
1465                 return;\r
1466 \r
1467         HMONITOR hmonCur;\r
1468         hmonCur = monitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);\r
1469 \r
1470         EnumDisplayMonitorsForWindowMonitorToParam ep(hmonCur);\r
1471         enumDisplayMonitors(NULL, NULL, enumDisplayMonitorsForWindowMonitorTo,\r
1472                                                 reinterpret_cast<LPARAM>(&ep));\r
1473         if (ep.m_monitors.size() < 1 ||\r
1474                         ep.m_primaryMonitorIdx < 0 || ep.m_currentMonitorIdx < 0)\r
1475                 return;\r
1476 \r
1477         int targetIdx;\r
1478         switch (i_fromType) {\r
1479         case WindowMonitorFromType_primary:\r
1480                 targetIdx = (ep.m_primaryMonitorIdx + i_monitor) % ep.m_monitors.size();\r
1481                 break;\r
1482 \r
1483         case WindowMonitorFromType_current:\r
1484                 targetIdx = (ep.m_currentMonitorIdx + i_monitor) % ep.m_monitors.size();\r
1485                 break;\r
1486         }\r
1487         if (ep.m_currentMonitorIdx == targetIdx)\r
1488                 return;\r
1489 \r
1490         RECT rcCur, rcTarget, rcWin;\r
1491         rcCur = ep.m_monitorinfos[ep.m_currentMonitorIdx].rcWork;\r
1492         rcTarget = ep.m_monitorinfos[targetIdx].rcWork;\r
1493         GetWindowRect(hwnd, &rcWin);\r
1494 \r
1495         int x = rcTarget.left + (rcWin.left - rcCur.left);\r
1496         int y = rcTarget.top + (rcWin.top - rcCur.top);\r
1497         int w = rcWidth(&rcWin);\r
1498         int h = rcHeight(&rcWin);\r
1499 \r
1500         if (i_adjustPos) {\r
1501                 if (x + w > rcTarget.right)\r
1502                         x = rcTarget.right - w;\r
1503                 if (x < rcTarget.left)\r
1504                         x = rcTarget.left;\r
1505                 if (w > rcWidth(&rcTarget)) {\r
1506                         x = rcTarget.left;\r
1507                         w = rcWidth(&rcTarget);\r
1508                 }\r
1509 \r
1510                 if (y + h > rcTarget.bottom)\r
1511                         y = rcTarget.bottom - h;\r
1512                 if (y < rcTarget.top)\r
1513                         y = rcTarget.top;\r
1514                 if (h > rcHeight(&rcTarget)) {\r
1515                         y = rcTarget.top;\r
1516                         h = rcHeight(&rcTarget);\r
1517                 }\r
1518         }\r
1519 \r
1520         if (i_adjustPos && i_adjustSize) {\r
1521                 if (IsZoomed(hwnd))\r
1522                         PostMessage(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);\r
1523                 asyncMoveWindow(hwnd, x, y, w, h);\r
1524         } else {\r
1525                 asyncMoveWindow(hwnd, x, y);\r
1526         }\r
1527 }\r
1528 \r
1529 /// move window to other monitor\r
1530 void Engine::funcWindowMonitor(\r
1531         FunctionParam *i_param, int i_monitor,\r
1532         BooleanType i_adjustPos, BooleanType i_adjustSize)\r
1533 {\r
1534         funcWindowMonitorTo(i_param, WindowMonitorFromType_primary, i_monitor,\r
1535                                                 i_adjustPos, i_adjustSize);\r
1536 }\r
1537 \r
1538 \r
1539 //\r
1540 void Engine::funcWindowClingToLeft(FunctionParam *i_param,\r
1541                                                                    TargetWindowType i_twt)\r
1542 {\r
1543         funcWindowMoveTo(i_param, GravityType_W, 0, 0, i_twt);\r
1544 }\r
1545 \r
1546 //\r
1547 void Engine::funcWindowClingToRight(FunctionParam *i_param,\r
1548                                                                         TargetWindowType i_twt)\r
1549 {\r
1550         funcWindowMoveTo(i_param, GravityType_E, 0, 0, i_twt);\r
1551 }\r
1552 \r
1553 //\r
1554 void Engine::funcWindowClingToTop(FunctionParam *i_param,\r
1555                                                                   TargetWindowType i_twt)\r
1556 {\r
1557         funcWindowMoveTo(i_param, GravityType_N, 0, 0, i_twt);\r
1558 }\r
1559 \r
1560 //\r
1561 void Engine::funcWindowClingToBottom(FunctionParam *i_param,\r
1562                                                                          TargetWindowType i_twt)\r
1563 {\r
1564         funcWindowMoveTo(i_param, GravityType_S, 0, 0, i_twt);\r
1565 }\r
1566 \r
1567 // close window\r
1568 void Engine::funcWindowClose(FunctionParam *i_param, TargetWindowType i_twt)\r
1569 {\r
1570         HWND hwnd;\r
1571         if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt))\r
1572                 return;\r
1573         PostMessage(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0);\r
1574 }\r
1575 \r
1576 // toggle top-most flag of the window\r
1577 void Engine::funcWindowToggleTopMost(FunctionParam *i_param)\r
1578 {\r
1579         HWND hwnd;\r
1580         if (!getSuitableWindow(i_param, &hwnd))\r
1581                 return;\r
1582         SetWindowPos(\r
1583                 hwnd,\r
1584 #ifdef MAYU64\r
1585                 (GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST) ?\r
1586 #else\r
1587                 (GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST) ?\r
1588 #endif\r
1589                 HWND_NOTOPMOST : HWND_TOPMOST,\r
1590                 0, 0, 0, 0,\r
1591                 SWP_ASYNCWINDOWPOS | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOSIZE);\r
1592 }\r
1593 \r
1594 // identify the window\r
1595 void Engine::funcWindowIdentify(FunctionParam *i_param)\r
1596 {\r
1597         if (!i_param->m_isPressed)\r
1598                 return;\r
1599 \r
1600         _TCHAR className[GANA_MAX_ATOM_LENGTH];\r
1601         bool ok = false;\r
1602         if (GetClassName(i_param->m_hwnd, className, NUMBER_OF(className))) {\r
1603                 if (_tcsicmp(className, _T("ConsoleWindowClass")) == 0) {\r
1604                         _TCHAR titleName[1024];\r
1605                         if (GetWindowText(i_param->m_hwnd, titleName, NUMBER_OF(titleName)) == 0)\r
1606                                 titleName[0] = _T('\0');\r
1607                         {\r
1608                                 Acquire a(&m_log, 1);\r
1609                                 m_log << _T("HWND:\t") << std::hex\r
1610                                 << reinterpret_cast<int>(i_param->m_hwnd)\r
1611                                 << std::dec << std::endl;\r
1612                         }\r
1613                         Acquire a(&m_log, 0);\r
1614                         m_log << _T("CLASS:\t") << className << std::endl;\r
1615                         m_log << _T("TITLE:\t") << titleName << std::endl;\r
1616 \r
1617                         HWND hwnd = getToplevelWindow(i_param->m_hwnd, NULL);\r
1618                         RECT rc;\r
1619                         GetWindowRect(hwnd, &rc);\r
1620                         m_log << _T("Toplevel Window Position/Size: (")\r
1621                         << rc.left << _T(", ") << rc.top << _T(") / (")\r
1622                         << rcWidth(&rc) << _T("x") << rcHeight(&rc)\r
1623                         << _T(")") << std::endl;\r
1624 \r
1625                         SystemParametersInfo(SPI_GETWORKAREA, 0, (void *)&rc, FALSE);\r
1626                         m_log << _T("Desktop Window Position/Size: (")\r
1627                         << rc.left << _T(", ") << rc.top << _T(") / (")\r
1628                         << rcWidth(&rc) << _T("x") << rcHeight(&rc)\r
1629                         << _T(")") << std::endl;\r
1630 \r
1631                         m_log << std::endl;\r
1632                         ok = true;\r
1633                 }\r
1634         }\r
1635         if (!ok) {\r
1636                 UINT WM_MAYU_MESSAGE = RegisterWindowMessage(\r
1637                                                                    addSessionId(WM_MAYU_MESSAGE_NAME).c_str());\r
1638                 CHECK_TRUE( PostMessage(i_param->m_hwnd, WM_MAYU_MESSAGE,\r
1639                                                                 MayuMessage_notifyName, 0) );\r
1640         }\r
1641 }\r
1642 \r
1643 // set alpha blending parameter to the window\r
1644 void Engine::funcWindowSetAlpha(FunctionParam *i_param, int i_alpha)\r
1645 {\r
1646         HWND hwnd;\r
1647         if (!getSuitableWindow(i_param, &hwnd))\r
1648                 return;\r
1649 \r
1650         if (i_alpha < 0) {      // remove all alpha\r
1651                 for (WindowsWithAlpha::iterator i = m_windowsWithAlpha.begin();\r
1652                                 i != m_windowsWithAlpha.end(); ++ i) {\r
1653 #ifdef MAYU64\r
1654                         SetWindowLongPtr(*i, GWL_EXSTYLE,\r
1655                                                          GetWindowLongPtr(*i, GWL_EXSTYLE) & ~WS_EX_LAYERED);\r
1656 #else\r
1657                         SetWindowLong(*i, GWL_EXSTYLE,\r
1658                                                   GetWindowLong(*i, GWL_EXSTYLE) & ~WS_EX_LAYERED);\r
1659 #endif\r
1660                         RedrawWindow(*i, NULL, NULL,\r
1661                                                  RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);\r
1662                 }\r
1663                 m_windowsWithAlpha.clear();\r
1664         } else {\r
1665 #ifdef MAYU64\r
1666                 LONG_PTR exStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE);\r
1667 #else\r
1668                 LONG exStyle = GetWindowLong(hwnd, GWL_EXSTYLE);\r
1669 #endif\r
1670                 if (exStyle & WS_EX_LAYERED) {  // remove alpha\r
1671                         WindowsWithAlpha::iterator\r
1672                         i = std::find(m_windowsWithAlpha.begin(), m_windowsWithAlpha.end(),\r
1673                                                   hwnd);\r
1674                         if (i == m_windowsWithAlpha.end())\r
1675                                 return; // already layered by the application\r
1676 \r
1677                         m_windowsWithAlpha.erase(i);\r
1678 \r
1679 #ifdef MAYU64\r
1680                         SetWindowLongPtr(hwnd, GWL_EXSTYLE, exStyle & ~WS_EX_LAYERED);\r
1681 #else\r
1682                         SetWindowLong(hwnd, GWL_EXSTYLE, exStyle & ~WS_EX_LAYERED);\r
1683 #endif\r
1684                 } else {        // add alpha\r
1685 #ifdef MAYU64\r
1686                         SetWindowLongPtr(hwnd, GWL_EXSTYLE, exStyle | WS_EX_LAYERED);\r
1687 #else\r
1688                         SetWindowLong(hwnd, GWL_EXSTYLE, exStyle | WS_EX_LAYERED);\r
1689 #endif\r
1690                         i_alpha %= 101;\r
1691                         if (!setLayeredWindowAttributes(hwnd, 0,\r
1692                                                                                         (BYTE)(255 * i_alpha / 100), LWA_ALPHA)) {\r
1693                                 Acquire a(&m_log, 0);\r
1694                                 m_log << _T("error: &WindowSetAlpha(") << i_alpha\r
1695                                 << _T(") failed for HWND: ") << std::hex\r
1696                                 << hwnd << std::dec << std::endl;\r
1697                                 return;\r
1698                         }\r
1699                         m_windowsWithAlpha.push_front(hwnd);\r
1700                 }\r
1701                 RedrawWindow(hwnd, NULL, NULL,\r
1702                                          RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);\r
1703         }\r
1704 }\r
1705 \r
1706 \r
1707 // redraw the window\r
1708 void Engine::funcWindowRedraw(FunctionParam *i_param)\r
1709 {\r
1710         HWND hwnd;\r
1711         if (!getSuitableWindow(i_param, &hwnd))\r
1712                 return;\r
1713         RedrawWindow(hwnd, NULL, NULL,\r
1714                                  RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);\r
1715 }\r
1716 \r
1717 // resize window to\r
1718 void Engine::funcWindowResizeTo(FunctionParam *i_param, int i_width,\r
1719                                                                 int i_height, TargetWindowType i_twt)\r
1720 {\r
1721         HWND hwnd;\r
1722         RECT rc, rcd;\r
1723         if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt, &rc, &rcd))\r
1724                 return;\r
1725 \r
1726         if (i_width == 0)\r
1727                 i_width = rcWidth(&rc);\r
1728         else if (i_width < 0)\r
1729                 i_width += rcWidth(&rcd);\r
1730 \r
1731         if (i_height == 0)\r
1732                 i_height = rcHeight(&rc);\r
1733         else if (i_height < 0)\r
1734                 i_height += rcHeight(&rcd);\r
1735 \r
1736         asyncResize(hwnd, i_width, i_height);\r
1737 }\r
1738 \r
1739 // move the mouse cursor\r
1740 void Engine::funcMouseMove(FunctionParam *i_param, int i_dx, int i_dy)\r
1741 {\r
1742         if (!i_param->m_isPressed)\r
1743                 return;\r
1744         POINT pt;\r
1745         GetCursorPos(&pt);\r
1746         SetCursorPos(pt.x + i_dx, pt.y + i_dy);\r
1747 }\r
1748 \r
1749 // send a mouse-wheel-message to Windows\r
1750 void Engine::funcMouseWheel(FunctionParam *i_param, int i_delta)\r
1751 {\r
1752         if (!i_param->m_isPressed)\r
1753                 return;\r
1754         mouse_event(MOUSEEVENTF_WHEEL, 0, 0, i_delta, 0);\r
1755 }\r
1756 \r
1757 // convert the contents of the Clipboard to upper case\r
1758 void Engine::funcClipboardChangeCase(FunctionParam *i_param,\r
1759                                                                          BooleanType i_doesConvertToUpperCase)\r
1760 {\r
1761         if (!i_param->m_isPressed)\r
1762                 return;\r
1763 \r
1764         HGLOBAL hdata;\r
1765         const _TCHAR *text = getTextFromClipboard(&hdata);\r
1766         HGLOBAL hdataNew = NULL;\r
1767         if (text) {\r
1768                 int size = static_cast<int>(GlobalSize(hdata));\r
1769                 hdataNew = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, size);\r
1770                 if (hdataNew) {\r
1771                         if (_TCHAR *dataNew = reinterpret_cast<_TCHAR *>(GlobalLock(hdataNew))) {\r
1772                                 std::memcpy(dataNew, text, size);\r
1773                                 _TCHAR *dataEnd = dataNew + size;\r
1774                                 while (dataNew < dataEnd && *dataNew) {\r
1775                                         _TCHAR c = *dataNew;\r
1776                                         if (_istlead(c))\r
1777                                                 dataNew += 2;\r
1778                                         else\r
1779                                                 *dataNew++ =\r
1780                                                         i_doesConvertToUpperCase ? _totupper(c) : _totlower(c);\r
1781                                 }\r
1782                                 GlobalUnlock(hdataNew);\r
1783                         }\r
1784                 }\r
1785         }\r
1786         closeClipboard(hdata, hdataNew);\r
1787 }\r
1788 \r
1789 // convert the contents of the Clipboard to upper case\r
1790 void Engine::funcClipboardUpcaseWord(FunctionParam *i_param)\r
1791 {\r
1792         funcClipboardChangeCase(i_param, BooleanType_true);\r
1793 }\r
1794 \r
1795 // convert the contents of the Clipboard to lower case\r
1796 void Engine::funcClipboardDowncaseWord(FunctionParam *i_param)\r
1797 {\r
1798         funcClipboardChangeCase(i_param, BooleanType_false);\r
1799 }\r
1800 \r
1801 // set the contents of the Clipboard to the string\r
1802 void Engine::funcClipboardCopy(FunctionParam *i_param, const StrExprArg &i_text)\r
1803 {\r
1804         if (!i_param->m_isPressed)\r
1805                 return;\r
1806         if (!OpenClipboard(NULL))\r
1807                 return;\r
1808 \r
1809         HGLOBAL hdataNew =\r
1810                 GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,\r
1811                                         (i_text.eval().size() + 1) * sizeof(_TCHAR));\r
1812         if (!hdataNew)\r
1813                 return;\r
1814         _TCHAR *dataNew = reinterpret_cast<_TCHAR *>(GlobalLock(hdataNew));\r
1815         _tcscpy(dataNew, i_text.eval().c_str());\r
1816         GlobalUnlock(hdataNew);\r
1817         closeClipboard(NULL, hdataNew);\r
1818 }\r
1819 \r
1820 //\r
1821 void Engine::funcEmacsEditKillLinePred(\r
1822         FunctionParam *i_param, const KeySeq *i_keySeq1, const KeySeq *i_keySeq2)\r
1823 {\r
1824         m_emacsEditKillLine.m_doForceReset = false;\r
1825         if (!i_param->m_isPressed)\r
1826                 return;\r
1827 \r
1828         int r = m_emacsEditKillLine.pred();\r
1829         const KeySeq *keySeq;\r
1830         if (r == 1)\r
1831                 keySeq = i_keySeq1;\r
1832         else if (r == 2)\r
1833                 keySeq = i_keySeq2;\r
1834         else // r == 0\r
1835                 return;\r
1836         ASSERT(keySeq);\r
1837         generateKeySeqEvents(i_param->m_c, keySeq, Part_all);\r
1838 }\r
1839 \r
1840 //\r
1841 void Engine::funcEmacsEditKillLineFunc(FunctionParam *i_param)\r
1842 {\r
1843         if (!i_param->m_isPressed)\r
1844                 return;\r
1845         m_emacsEditKillLine.func();\r
1846         m_emacsEditKillLine.m_doForceReset = false;\r
1847 }\r
1848 \r
1849 // clear log\r
1850 void Engine::funcLogClear(FunctionParam *i_param)\r
1851 {\r
1852         if (!i_param->m_isPressed)\r
1853                 return;\r
1854         PostMessage(getAssociatedWndow(), WM_APP_engineNotify,\r
1855                                 EngineNotify_clearLog, 0);\r
1856 }\r
1857 \r
1858 // recenter\r
1859 void Engine::funcRecenter(FunctionParam *i_param)\r
1860 {\r
1861         if (!i_param->m_isPressed)\r
1862                 return;\r
1863         if (m_hwndFocus) {\r
1864                 UINT WM_MAYU_MESSAGE = RegisterWindowMessage(\r
1865                                                                    addSessionId(WM_MAYU_MESSAGE_NAME).c_str());\r
1866                 PostMessage(m_hwndFocus, WM_MAYU_MESSAGE, MayuMessage_funcRecenter, 0);\r
1867         }\r
1868 }\r
1869 \r
1870 // set IME open status\r
1871 void Engine::funcSetImeStatus(FunctionParam *i_param, ToggleType i_toggle)\r
1872 {\r
1873         if (!i_param->m_isPressed)\r
1874                 return;\r
1875         if (m_hwndFocus) {\r
1876                 UINT WM_MAYU_MESSAGE = RegisterWindowMessage(\r
1877                                                                    addSessionId(WM_MAYU_MESSAGE_NAME).c_str());\r
1878                 int status = -1;\r
1879                 switch (i_toggle) {\r
1880                 case ToggleType_toggle:\r
1881                         status = -1;\r
1882                         break;\r
1883                 case ToggleType_off:\r
1884                         status = 0;\r
1885                         break;\r
1886                 case ToggleType_on:\r
1887                         status = 1;\r
1888                         break;\r
1889                 }\r
1890                 PostMessage(m_hwndFocus, WM_MAYU_MESSAGE, MayuMessage_funcSetImeStatus, status);\r
1891         }\r
1892 }\r
1893 \r
1894 // set IME open status\r
1895 void Engine::funcSetImeString(FunctionParam *i_param, const StrExprArg &i_data)\r
1896 {\r
1897         if (!i_param->m_isPressed)\r
1898                 return;\r
1899         if (m_hwndFocus) {\r
1900                 UINT WM_MAYU_MESSAGE = RegisterWindowMessage(\r
1901                                                                    addSessionId(WM_MAYU_MESSAGE_NAME).c_str());\r
1902                 PostMessage(m_hwndFocus, WM_MAYU_MESSAGE, MayuMessage_funcSetImeString, i_data.eval().size() * sizeof(_TCHAR));\r
1903 \r
1904                 DWORD len = 0;\r
1905                 DWORD error;\r
1906                 DisconnectNamedPipe(m_hookPipe);\r
1907                 ConnectNamedPipe(m_hookPipe, NULL);\r
1908                 error = WriteFile(m_hookPipe, i_data.eval().c_str(),\r
1909                                                   i_data.eval().size() * sizeof(_TCHAR),\r
1910                                                   &len, NULL);\r
1911 \r
1912                 //FlushFileBuffers(m_hookPipe);\r
1913         }\r
1914 }\r
1915 \r
1916 // Direct SSTP Server\r
1917 class DirectSSTPServer\r
1918 {\r
1919 public:\r
1920         tstring m_path;\r
1921         HWND m_hwnd;\r
1922         tstring m_name;\r
1923         tstring m_keroname;\r
1924 \r
1925 public:\r
1926         DirectSSTPServer()\r
1927                         : m_hwnd(NULL) {\r
1928         }\r
1929 };\r
1930 \r
1931 \r
1932 class ParseDirectSSTPData\r
1933 {\r
1934         typedef boost::match_results<boost::regex::const_iterator> MR;\r
1935 \r
1936 public:\r
1937         typedef std::map<tstring, DirectSSTPServer> DirectSSTPServers;\r
1938 \r
1939 private:\r
1940         DirectSSTPServers *m_directSSTPServers;\r
1941 \r
1942 public:\r
1943         // constructor\r
1944         ParseDirectSSTPData(DirectSSTPServers *i_directSSTPServers)\r
1945                         : m_directSSTPServers(i_directSSTPServers) {\r
1946         }\r
1947 \r
1948         bool operator()(const MR& i_what) {\r
1949 #ifdef _UNICODE\r
1950                 tstring id(to_wstring(std::string(i_what[1].first, i_what[1].second)));\r
1951                 tstring member(to_wstring(std::string(i_what[2].first, i_what[2].second)));\r
1952                 tstring value(to_wstring(std::string(i_what[3].first, i_what[3].second)));\r
1953 #else\r
1954                 tstring id(i_what[1].first, i_what[1].second);\r
1955                 tstring member(i_what[2].first, i_what[2].second);\r
1956                 tstring value(i_what[3].first, i_what[3].second);\r
1957 #endif\r
1958 \r
1959                 if (member == _T("path"))\r
1960                         (*m_directSSTPServers)[id].m_path = value;\r
1961                 else if (member == _T("hwnd"))\r
1962                         (*m_directSSTPServers)[id].m_hwnd =\r
1963                                 reinterpret_cast<HWND>(_ttoi(value.c_str()));\r
1964                 else if (member == _T("name"))\r
1965                         (*m_directSSTPServers)[id].m_name = value;\r
1966                 else if (member == _T("keroname"))\r
1967                         (*m_directSSTPServers)[id].m_keroname = value;\r
1968                 return true;\r
1969         }\r
1970 };\r
1971 \r
1972 // Direct SSTP\r
1973 void Engine::funcDirectSSTP(FunctionParam *i_param,\r
1974                                                         const tregex &i_name,\r
1975                                                         const StrExprArg &i_protocol,\r
1976                                                         const std::list<tstringq> &i_headers)\r
1977 {\r
1978         if (!i_param->m_isPressed)\r
1979                 return;\r
1980 \r
1981         // check Direct SSTP server exist ?\r
1982         if (HANDLE hm = OpenMutex(MUTEX_ALL_ACCESS, FALSE, _T("sakura")))\r
1983                 CloseHandle(hm);\r
1984         else {\r
1985                 Acquire a(&m_log, 0);\r
1986                 m_log << _T(" Error(1): Direct SSTP server does not exist.");\r
1987                 return;\r
1988         }\r
1989 \r
1990         HANDLE hfm = OpenFileMapping(FILE_MAP_READ, FALSE, _T("Sakura"));\r
1991         if (!hfm) {\r
1992                 Acquire a(&m_log, 0);\r
1993                 m_log << _T(" Error(2): Direct SSTP server does not provide data.");\r
1994                 return;\r
1995         }\r
1996 \r
1997         char *data =\r
1998                 reinterpret_cast<char *>(MapViewOfFile(hfm, FILE_MAP_READ, 0, 0, 0));\r
1999         if (!data) {\r
2000                 CloseHandle(hfm);\r
2001                 Acquire a(&m_log, 0);\r
2002                 m_log << _T(" Error(3): Direct SSTP server does not provide data.");\r
2003                 return;\r
2004         }\r
2005 \r
2006         long length = *(long *)data;\r
2007         const char *begin = data + 4;\r
2008         const char *end = data + length;\r
2009         boost::regex getSakura("([0-9a-fA-F]{32})\\.([^\x01]+)\x01(.*?)\r\n");\r
2010 \r
2011         ParseDirectSSTPData::DirectSSTPServers servers;\r
2012         boost::regex_iterator<boost::regex::const_iterator>\r
2013         it(begin, end, getSakura), last;\r
2014         for (; it != last; ++it)\r
2015                 ((ParseDirectSSTPData)(&servers))(*it);\r
2016 \r
2017         // make request\r
2018         tstring request;\r
2019         if (!i_protocol.eval().size())\r
2020                 request += _T("NOTIFY SSTP/1.1");\r
2021         else\r
2022                 request += i_protocol.eval();\r
2023         request += _T("\r\n");\r
2024 \r
2025         bool hasSender = false;\r
2026         for (std::list<tstringq>::const_iterator\r
2027                         i = i_headers.begin(); i != i_headers.end(); ++ i) {\r
2028                 if (_tcsnicmp(_T("Charset"), i->c_str(), 7) == 0 ||\r
2029                                 _tcsnicmp(_T("Hwnd"),    i->c_str(), 4) == 0)\r
2030                         continue;\r
2031                 if (_tcsnicmp(_T("Sender"), i->c_str(), 6) == 0)\r
2032                         hasSender = true;\r
2033                 request += i->c_str();\r
2034                 request += _T("\r\n");\r
2035         }\r
2036 \r
2037         if (!hasSender) {\r
2038                 request += _T("Sender: ");\r
2039                 request += loadString(IDS_mayu);\r
2040                 request += _T("\r\n");\r
2041         }\r
2042 \r
2043         _TCHAR buf[100];\r
2044         _sntprintf(buf, NUMBER_OF(buf), _T("HWnd: %d\r\n"),\r
2045                            reinterpret_cast<int>(m_hwndAssocWindow));\r
2046         request += buf;\r
2047 \r
2048 #ifdef _UNICODE\r
2049         request += _T("Charset: UTF-8\r\n");\r
2050 #else\r
2051         request += _T("Charset: Shift_JIS\r\n");\r
2052 #endif\r
2053         request += _T("\r\n");\r
2054 \r
2055 #ifdef _UNICODE\r
2056         std::string request_UTF_8 = to_UTF_8(request);\r
2057 #endif\r
2058 \r
2059         // send request to Direct SSTP Server which matches i_name;\r
2060         for (ParseDirectSSTPData::DirectSSTPServers::iterator\r
2061                         i = servers.begin(); i != servers.end(); ++ i) {\r
2062                 tsmatch what;\r
2063                 if (boost::regex_match(i->second.m_name, what, i_name)) {\r
2064                         COPYDATASTRUCT cd;\r
2065                         cd.dwData = 9801;\r
2066 #ifdef _UNICODE\r
2067                         cd.cbData = request_UTF_8.size();\r
2068                         cd.lpData = (void *)request_UTF_8.c_str();\r
2069 #else\r
2070                         cd.cbData = request.size();\r
2071                         cd.lpData = (void *)request.c_str();\r
2072 #endif\r
2073 #ifdef MAYU64\r
2074                         DWORD_PTR result;\r
2075 #else\r
2076                         DWORD result;\r
2077 #endif\r
2078                         SendMessageTimeout(i->second.m_hwnd, WM_COPYDATA,\r
2079                                                            reinterpret_cast<WPARAM>(m_hwndAssocWindow),\r
2080                                                            reinterpret_cast<LPARAM>(&cd),\r
2081                                                            SMTO_ABORTIFHUNG | SMTO_BLOCK, 5000, &result);\r
2082                 }\r
2083         }\r
2084 \r
2085         UnmapViewOfFile(data);\r
2086         CloseHandle(hfm);\r
2087 }\r
2088 \r
2089 \r
2090 namespace shu\r
2091 {\r
2092 class PlugIn\r
2093 {\r
2094         enum Type {\r
2095                 Type_A,\r
2096                 Type_W\r
2097         };\r
2098 \r
2099 private:\r
2100         HMODULE m_dll;\r
2101         FARPROC m_func;\r
2102         Type m_type;\r
2103         tstringq m_funcParam;\r
2104 \r
2105 public:\r
2106         PlugIn() : m_dll(NULL) {\r
2107         }\r
2108 \r
2109         ~PlugIn() {\r
2110                 FreeLibrary(m_dll);\r
2111         }\r
2112 \r
2113         bool load(const tstringq &i_dllName, const tstringq &i_funcName,\r
2114                           const tstringq &i_funcParam, tomsgstream &i_log) {\r
2115                 m_dll = LoadLibrary((_T("Plugins\\") + i_dllName).c_str());\r
2116                 if (!m_dll) {\r
2117                         m_dll = LoadLibrary((_T("Plugin\\") + i_dllName).c_str());\r
2118                         if (!m_dll) {\r
2119                                 m_dll = LoadLibrary(i_dllName.c_str());\r
2120                                 if (!m_dll) {\r
2121                                         Acquire a(&i_log);\r
2122                                         i_log << std::endl;\r
2123                                         i_log << _T("error: &PlugIn() failed to load ") << i_dllName << std::endl;\r
2124                                         return false;\r
2125                                 }\r
2126                         }\r
2127                 }\r
2128 \r
2129                 // get function\r
2130 #ifdef UNICODE\r
2131 #  define to_wstring\r
2132 #else\r
2133 #  define to_string\r
2134 #endif\r
2135                 m_type = Type_W;\r
2136                 m_func = GetProcAddress(m_dll, to_string(_T("mayu") + i_funcName + _T("W")).c_str());\r
2137                 if (!m_func) {\r
2138                         m_type = Type_A;\r
2139                         m_func\r
2140                         = GetProcAddress(m_dll, to_string(_T("mayu") + i_funcName + _T("A")).c_str());\r
2141                         if (!m_func) {\r
2142                                 m_func = GetProcAddress(m_dll, to_string(_T("mayu") + i_funcName).c_str());\r
2143                                 if (!m_func) {\r
2144                                         m_func = GetProcAddress(m_dll, to_string(i_funcName).c_str());\r
2145                                         if (!m_func) {\r
2146                                                 Acquire a(&i_log);\r
2147                                                 i_log << std::endl;\r
2148                                                 i_log << _T("error: &PlugIn() failed to find function: ")\r
2149                                                 << i_funcName << std::endl;\r
2150                                                 return false;\r
2151                                         }\r
2152                                 }\r
2153                         }\r
2154                 }\r
2155 \r
2156                 m_funcParam = i_funcParam;\r
2157                 return true;\r
2158         }\r
2159 \r
2160         void exec() {\r
2161                 ASSERT( m_dll );\r
2162                 ASSERT( m_func );\r
2163 \r
2164                 typedef void (WINAPI * PLUGIN_FUNCTION_A)(const char *i_arg);\r
2165                 typedef void (WINAPI * PLUGIN_FUNCTION_W)(const wchar_t *i_arg);\r
2166                 switch (m_type) {\r
2167                 case Type_A:\r
2168                         reinterpret_cast<PLUGIN_FUNCTION_A>(m_func)(to_string(m_funcParam).c_str());\r
2169                         break;\r
2170                 case Type_W:\r
2171                         reinterpret_cast<PLUGIN_FUNCTION_W>(m_func)(to_wstring(m_funcParam).c_str());\r
2172                         break;\r
2173                 }\r
2174         }\r
2175 #undef to_string\r
2176 #undef to_wstring\r
2177 };\r
2178 \r
2179 static void plugInThread(void *i_plugin)\r
2180 {\r
2181         PlugIn *plugin = static_cast<PlugIn *>(i_plugin);\r
2182         plugin->exec();\r
2183         delete plugin;\r
2184 }\r
2185 }\r
2186 \r
2187 void Engine::funcPlugIn(FunctionParam *i_param,\r
2188                                                 const StrExprArg &i_dllName,\r
2189                                                 const StrExprArg &i_funcName,\r
2190                                                 const StrExprArg &i_funcParam,\r
2191                                                 BooleanType i_doesCreateThread)\r
2192 {\r
2193         if (!i_param->m_isPressed)\r
2194                 return;\r
2195 \r
2196         shu::PlugIn *plugin = new shu::PlugIn();\r
2197         if (!plugin->load(i_dllName.eval(), i_funcName.eval(), i_funcParam.eval(), m_log)) {\r
2198                 delete plugin;\r
2199                 return;\r
2200         }\r
2201         if (i_doesCreateThread) {\r
2202                 if (_beginthread(shu::plugInThread, 0, plugin) == -1) {\r
2203                         delete plugin;\r
2204                         Acquire a(&m_log);\r
2205                         m_log << std::endl;\r
2206                         m_log << _T("error: &PlugIn() failed to create thread.");\r
2207                 }\r
2208                 return;\r
2209         } else\r
2210                 plugin->exec();\r
2211 }\r
2212 \r
2213 \r
2214 void Engine::funcMouseHook(FunctionParam *i_param,\r
2215                                                    MouseHookType i_hookType, int i_hookParam)\r
2216 {\r
2217         GetCursorPos(&g_hookData->m_mousePos);\r
2218         g_hookData->m_mouseHookType = i_hookType;\r
2219         g_hookData->m_mouseHookParam = i_hookParam;\r
2220 \r
2221         switch (i_hookType) {\r
2222         case MouseHookType_WindowMove: {\r
2223                 // For this type, g_hookData->m_mouseHookParam means\r
2224                 // target window type to move.\r
2225                 HWND target;\r
2226                 bool isMDI;\r
2227 \r
2228                 // i_hooParam < 0 means target window to move is MDI.\r
2229                 if (i_hookParam < 0)\r
2230                         isMDI = true;\r
2231                 else\r
2232                         isMDI = false;\r
2233 \r
2234                 // abs(i_hookParam) == 2: target is window under mouse cursor\r
2235                 // otherwise: target is current focus window\r
2236                 if (i_hookParam == 2 || i_hookParam == -2)\r
2237                         target = WindowFromPoint(g_hookData->m_mousePos);\r
2238                 else\r
2239                         target = i_param->m_hwnd;\r
2240 \r
2241                 g_hookData->m_hwndMouseHookTarget =\r
2242                         reinterpret_cast<DWORD>(getToplevelWindow(target, &isMDI));\r
2243                 break;\r
2244                 default:\r
2245                         g_hookData->m_hwndMouseHookTarget = NULL;\r
2246                         break;\r
2247                 }\r
2248         }\r
2249         return;\r
2250 }\r
2251 \r
2252 \r
2253 // cancel prefix\r
2254 void Engine::funcCancelPrefix(FunctionParam *i_param)\r
2255 {\r
2256         m_isPrefix = false;\r
2257 }\r
2258 \r
2259 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
2260 // StrExpr\r
2261 class StrExpr\r
2262 {\r
2263 private:\r
2264         tstringq m_symbol;\r
2265 protected:\r
2266         static const Engine *s_engine;\r
2267 public:\r
2268         StrExpr(const tstringq &i_symbol) : m_symbol(i_symbol) {};\r
2269 \r
2270         virtual ~StrExpr() {};\r
2271 \r
2272         virtual StrExpr *clone() const {\r
2273                 return new StrExpr(*this);\r
2274         }\r
2275 \r
2276         virtual tstringq eval() const {\r
2277                 return m_symbol;\r
2278         }\r
2279 \r
2280         static void setEngine(const Engine *i_engine) {\r
2281                 s_engine = i_engine;\r
2282         }\r
2283 };\r
2284 \r
2285 const Engine *StrExpr::s_engine = NULL;\r
2286 \r
2287 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
2288 // StrExprClipboard\r
2289 class StrExprClipboard : public StrExpr\r
2290 {\r
2291 public:\r
2292         StrExprClipboard(const tstringq &i_symbol) : StrExpr(i_symbol) {};\r
2293 \r
2294         ~StrExprClipboard() {};\r
2295 \r
2296         StrExpr *clone() const {\r
2297                 return new StrExprClipboard(*this);\r
2298         }\r
2299 \r
2300         tstringq eval() const {\r
2301                 HGLOBAL g;\r
2302                 const _TCHAR *text = getTextFromClipboard(&g);\r
2303                 const tstring value(text == NULL ? _T("") : text);\r
2304                 closeClipboard(g);\r
2305                 return value;\r
2306         }\r
2307 };\r
2308 \r
2309 \r
2310 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
2311 // StrExprWindowClassName\r
2312 class StrExprWindowClassName : public StrExpr\r
2313 {\r
2314 public:\r
2315         StrExprWindowClassName(const tstringq &i_symbol) : StrExpr(i_symbol) {};\r
2316 \r
2317         ~StrExprWindowClassName() {};\r
2318 \r
2319         StrExpr *clone() const {\r
2320                 return new StrExprWindowClassName(*this);\r
2321         }\r
2322 \r
2323         tstringq eval() const {\r
2324                 return s_engine->getCurrentWindowClassName();\r
2325         }\r
2326 };\r
2327 \r
2328 \r
2329 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
2330 // StrExprWindowTitleName\r
2331 class StrExprWindowTitleName : public StrExpr\r
2332 {\r
2333 public:\r
2334         StrExprWindowTitleName(const tstringq &i_symbol) : StrExpr(i_symbol) {};\r
2335 \r
2336         ~StrExprWindowTitleName() {};\r
2337 \r
2338         StrExpr *clone() const {\r
2339                 return new StrExprWindowTitleName(*this);\r
2340         }\r
2341 \r
2342         tstringq eval() const {\r
2343                 return s_engine->getCurrentWindowTitleName();\r
2344         }\r
2345 };\r
2346 \r
2347 \r
2348 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
2349 // StrExprArg\r
2350 \r
2351 \r
2352 // default constructor\r
2353 StrExprArg::StrExprArg()\r
2354 {\r
2355         m_expr = new StrExpr(_T(""));\r
2356 }\r
2357 \r
2358 \r
2359 // copy contructor\r
2360 StrExprArg::StrExprArg(const StrExprArg &i_data)\r
2361 {\r
2362         m_expr = i_data.m_expr->clone();\r
2363 }\r
2364 \r
2365 \r
2366 StrExprArg &StrExprArg::operator=(const StrExprArg &i_data)\r
2367 {\r
2368         if (i_data.m_expr == m_expr)\r
2369                 return *this;\r
2370 \r
2371         delete m_expr;\r
2372         m_expr = i_data.m_expr->clone();\r
2373 \r
2374         return *this;\r
2375 }\r
2376 \r
2377 \r
2378 // initializer\r
2379 StrExprArg::StrExprArg(const tstringq &i_symbol, Type i_type)\r
2380 {\r
2381         switch (i_type) {\r
2382         case Literal:\r
2383                 m_expr = new StrExpr(i_symbol);\r
2384                 break;\r
2385         case Builtin:\r
2386                 if (i_symbol == _T("Clipboard"))\r
2387                         m_expr = new StrExprClipboard(i_symbol);\r
2388                 else if (i_symbol == _T("WindowClassName"))\r
2389                         m_expr = new StrExprWindowClassName(i_symbol);\r
2390                 else if (i_symbol == _T("WindowTitleName"))\r
2391                         m_expr = new StrExprWindowTitleName(i_symbol);\r
2392                 break;\r
2393         default:\r
2394                 break;\r
2395         }\r
2396 }\r
2397 \r
2398 \r
2399 StrExprArg::~StrExprArg()\r
2400 {\r
2401         delete m_expr;\r
2402 }\r
2403 \r
2404 \r
2405 tstringq StrExprArg::eval() const\r
2406 {\r
2407         return m_expr->eval();\r
2408 }\r
2409 \r
2410 void StrExprArg::setEngine(const Engine *i_engine)\r
2411 {\r
2412         StrExpr::setEngine(i_engine);\r
2413 }\r
2414 \r
2415 // stream output\r
2416 tostream &operator<<(tostream &i_ost, const StrExprArg &i_data)\r
2417 {\r
2418         i_ost << i_data.eval();\r
2419         return i_ost;\r
2420 }\r