OSDN Git Service

delete Win9x/NT support code
[yamy/yamy.git] / engine.cpp
1 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2 // engine.cpp
3
4
5 #include "misc.h"
6
7 #include "engine.h"
8 #include "errormessage.h"
9 #include "hook.h"
10 #include "mayurc.h"
11 #include "windowstool.h"
12
13 #include <iomanip>
14
15 #include <process.h>
16
17
18 // check focus window
19 void Engine::checkFocusWindow()
20 {
21   int count = 0;
22   
23   restart:
24   count ++;
25   
26   HWND hwndFore = GetForegroundWindow();
27   DWORD threadId = GetWindowThreadProcessId(hwndFore, NULL);
28
29   if (hwndFore)
30   {
31     {
32       Acquire a(&m_cs);
33       if (m_currentFocusOfThread &&
34           m_currentFocusOfThread->m_threadId == threadId &&
35           m_currentFocusOfThread->m_hwndFocus == m_hwndFocus)
36         return;
37
38       m_emacsEditKillLine.reset();
39       
40       // erase dead thread
41       if (!m_detachedThreadIds.empty())
42       {
43         for (DetachedThreadIds::iterator i = m_detachedThreadIds.begin();
44              i != m_detachedThreadIds.end(); i ++)
45         {
46           FocusOfThreads::iterator j = m_focusOfThreads.find((*i));
47           if (j != m_focusOfThreads.end())
48           {
49             FocusOfThread *fot = &((*j).second);
50             Acquire a(&m_log, 1);
51             m_log << _T("RemoveThread") << std::endl;
52             m_log << _T("\tHWND:\t") << std::hex << (int)fot->m_hwndFocus
53                   << std::dec << std::endl;
54             m_log << _T("\tTHREADID:") << fot->m_threadId << std::endl;
55             m_log << _T("\tCLASS:\t") << fot->m_className << std::endl;
56             m_log << _T("\tTITLE:\t") << fot->m_titleName << std::endl;
57             m_log << std::endl;
58             m_focusOfThreads.erase(j);
59           }
60         }
61         m_detachedThreadIds.erase
62           (m_detachedThreadIds.begin(), m_detachedThreadIds.end());
63       }
64       
65       FocusOfThreads::iterator i = m_focusOfThreads.find(threadId);
66       if (i != m_focusOfThreads.end())
67       {
68         m_currentFocusOfThread = &((*i).second);
69         if (!m_currentFocusOfThread->m_isConsole || 2 <= count)
70         {
71           if (m_currentFocusOfThread->m_keymaps.empty())
72             setCurrentKeymap(NULL);
73           else
74             setCurrentKeymap(*m_currentFocusOfThread->m_keymaps.begin());
75           m_hwndFocus = m_currentFocusOfThread->m_hwndFocus;
76           checkShow(m_hwndFocus);
77         
78           Acquire a(&m_log, 1);
79           m_log << _T("FocusChanged") << std::endl;
80           m_log << _T("\tHWND:\t")
81                 << std::hex << (int)m_currentFocusOfThread->m_hwndFocus
82                 << std::dec << std::endl;
83           m_log << _T("\tTHREADID:")
84                 << m_currentFocusOfThread->m_threadId << std::endl;
85           m_log << _T("\tCLASS:\t")
86                 << m_currentFocusOfThread->m_className << std::endl;
87           m_log << _T("\tTITLE:\t")
88                 << m_currentFocusOfThread->m_titleName << std::endl;
89           m_log << std::endl;
90           return;
91         }
92       }
93     }
94     
95     _TCHAR className[GANA_MAX_ATOM_LENGTH];
96     if (GetClassName(hwndFore, className, NUMBER_OF(className)))
97     {
98       if (_tcsicmp(className, _T("ConsoleWindowClass")) == 0)
99       {
100         _TCHAR titleName[1024];
101         if (GetWindowText(hwndFore, titleName, NUMBER_OF(titleName)) == 0)
102           titleName[0] = _T('\0');
103         setFocus(hwndFore, threadId, className, titleName, true);
104         Acquire a(&m_log, 1);
105         m_log << _T("HWND:\t") << std::hex << reinterpret_cast<int>(hwndFore)
106               << std::dec << std::endl;
107         m_log << _T("THREADID:") << threadId << std::endl;
108         m_log << _T("CLASS:\t") << className << std::endl;
109         m_log << _T("TITLE:\t") << titleName << std::endl << std::endl;
110         goto restart;
111       }
112     }
113   }
114   
115   Acquire a(&m_cs);
116   if (m_globalFocus.m_keymaps.empty())
117   {
118     Acquire a(&m_log, 1);
119     m_log << _T("NO GLOBAL FOCUS") << std::endl;
120     m_currentFocusOfThread = NULL;
121     setCurrentKeymap(NULL);
122   }
123   else
124   {
125     if (m_currentFocusOfThread != &m_globalFocus)
126     {
127       Acquire a(&m_log, 1);
128       m_log << _T("GLOBAL FOCUS") << std::endl;
129       m_currentFocusOfThread = &m_globalFocus;
130       setCurrentKeymap(m_globalFocus.m_keymaps.front());
131     }
132   }
133   m_hwndFocus = NULL;
134 }
135
136
137
138 // is modifier pressed ?
139 bool Engine::isPressed(Modifier::Type i_mt)
140 {
141   const Keymap::ModAssignments &ma = m_currentKeymap->getModAssignments(i_mt);
142   for (Keymap::ModAssignments::const_iterator i = ma.begin();
143        i != ma.end(); ++ i)
144     if ((*i).m_key->m_isPressed)
145       return true;
146   return false;
147 }
148
149
150 // fix modifier key (if fixed, return true)
151 bool Engine::fixModifierKey(ModifiedKey *io_mkey, Keymap::AssignMode *o_am)
152 {
153   // for all modifier ...
154   for (int i = Modifier::Type_begin; i != Modifier::Type_end; ++ i)
155   {
156     // get modifier assignments (list of modifier keys)
157     const Keymap::ModAssignments &ma =
158       m_currentKeymap->getModAssignments(static_cast<Modifier::Type>(i));
159     
160     for (Keymap::ModAssignments::const_iterator
161            j = ma.begin(); j != ma.end(); ++ j)
162       if (io_mkey->m_key == (*j).m_key) // is io_mkey a modifier ?
163       {
164         {
165           Acquire a(&m_log, 1);
166           m_log << _T("* Modifier Key") << std::endl;
167         }
168         // set dontcare for this modifier
169         io_mkey->m_modifier.dontcare(static_cast<Modifier::Type>(i));
170         *o_am = (*j).m_assignMode;
171         return true;
172       }
173   }
174   *o_am = Keymap::AM_notModifier;
175   return false;
176 }
177
178
179 // output to m_log
180 void Engine::outputToLog(const Key *i_key, const ModifiedKey &i_mkey,
181                          int i_debugLevel)
182 {
183   size_t i;
184   Acquire a(&m_log, i_debugLevel);
185
186   // output scan codes
187   for (i = 0; i < i_key->getScanCodesSize(); ++ i)
188   {
189     if (i_key->getScanCodes()[i].m_flags & ScanCode::E0) m_log << _T("E0-");
190     if (i_key->getScanCodes()[i].m_flags & ScanCode::E1) m_log << _T("E1-");
191     if (!(i_key->getScanCodes()[i].m_flags & ScanCode::E0E1))
192       m_log << _T("   ");
193     m_log << _T("0x") << std::hex << std::setw(2) << std::setfill(_T('0'))
194           << static_cast<int>(i_key->getScanCodes()[i].m_scan)
195           << std::dec << _T(" ");
196   }
197   
198   if (!i_mkey.m_key) // key corresponds to no phisical key
199   {
200     m_log << std::endl;
201     return;
202   }
203   
204   m_log << _T("  ") << i_mkey << std::endl;
205 }
206
207
208 // describe bindings
209 void Engine::describeBindings()
210 {
211   Acquire a(&m_log, 0);
212
213   Keymap::DescribeParam dp;
214   for (KeymapPtrList::iterator i = m_currentFocusOfThread->m_keymaps.begin();
215        i != m_currentFocusOfThread->m_keymaps.end(); ++ i)
216     (*i)->describe(m_log, &dp);
217   m_log << std::endl;
218 }
219
220
221 // update m_lastPressedKey
222 void Engine::updateLastPressedKey(Key *i_key)
223 {
224   m_lastPressedKey[1] = m_lastPressedKey[0];
225   m_lastPressedKey[0] = i_key;
226 }
227
228 // set current keymap
229 void Engine::setCurrentKeymap(const Keymap *i_keymap, bool i_doesAddToHistory)
230 {
231   if (i_doesAddToHistory)
232   {
233     m_keymapPrefixHistory.push_back(const_cast<Keymap *>(m_currentKeymap));
234     if (MAX_KEYMAP_PREFIX_HISTORY < m_keymapPrefixHistory.size())
235       m_keymapPrefixHistory.pop_front();
236   }
237   else
238     m_keymapPrefixHistory.clear();
239   m_currentKeymap = i_keymap;
240 }
241
242
243 // get current modifiers
244 Modifier Engine::getCurrentModifiers(Key *i_key, bool i_isPressed)
245 {
246   Modifier cmods;
247   cmods.add(m_currentLock);
248
249   cmods.press(Modifier::Type_Shift  , isPressed(Modifier::Type_Shift  ));
250   cmods.press(Modifier::Type_Alt    , isPressed(Modifier::Type_Alt    ));
251   cmods.press(Modifier::Type_Control, isPressed(Modifier::Type_Control));
252   cmods.press(Modifier::Type_Windows, isPressed(Modifier::Type_Windows));
253   cmods.press(Modifier::Type_Up     , !i_isPressed);
254   cmods.press(Modifier::Type_Down   , i_isPressed);
255
256   cmods.press(Modifier::Type_Repeat , false);
257   if (m_lastPressedKey[0] == i_key)
258   {
259     if (i_isPressed)
260       cmods.press(Modifier::Type_Repeat, true);
261     else
262       if (m_lastPressedKey[1] == i_key)
263         cmods.press(Modifier::Type_Repeat, true);
264   }
265
266   for (int i = Modifier::Type_Mod0; i <= Modifier::Type_Mod9; ++ i)
267     cmods.press(static_cast<Modifier::Type>(i),
268                 isPressed(static_cast<Modifier::Type>(i)));
269   
270   return cmods;
271 }
272
273
274 // generate keyboard event for a key
275 void Engine::generateKeyEvent(Key *i_key, bool i_doPress, bool i_isByAssign)
276 {
277   // check if key is event
278   bool isEvent = false;
279   for (Key **e = Event::events; *e; ++ e)
280     if (*e == i_key)
281     {
282       isEvent = true;
283       break;
284     }
285
286   bool isAlreadyReleased = false;
287     
288   if (!isEvent)
289   {
290     if (i_doPress && !i_key->m_isPressedOnWin32)
291       ++ m_currentKeyPressCountOnWin32;
292     else if (!i_doPress)
293     {
294       if (i_key->m_isPressedOnWin32)
295         -- m_currentKeyPressCountOnWin32;
296       else
297         isAlreadyReleased = true;
298     }
299     i_key->m_isPressedOnWin32 = i_doPress;
300     
301     if (i_isByAssign)
302       i_key->m_isPressedByAssign = i_doPress;
303
304     Key *sync = m_setting->m_keyboard.getSyncKey();
305     
306     if (!isAlreadyReleased || i_key == sync)
307     {
308       KEYBOARD_INPUT_DATA kid = { 0, 0, 0, 0, 0 };
309       const ScanCode *sc = i_key->getScanCodes();
310       for (size_t i = 0; i < i_key->getScanCodesSize(); ++ i)
311       {
312         kid.MakeCode = sc[i].m_scan;
313         kid.Flags = sc[i].m_flags;
314         if (!i_doPress)
315           kid.Flags |= KEYBOARD_INPUT_DATA::BREAK;
316 #ifdef NO_DRIVER
317         injectInput(&kid, NULL);
318 #else // !NO_DRIVER
319         DWORD len;
320         WriteFile(m_device, &kid, sizeof(kid), &len, &m_ol);
321         CHECK_TRUE( GetOverlappedResult(m_device, &m_ol, &len, TRUE) );
322 #endif // !NO_DRIVER
323       }
324       
325       m_lastGeneratedKey = i_doPress ? i_key : NULL;
326     }
327   }
328   
329   {
330     Acquire a(&m_log, 1);
331     m_log << _T("\t\t    =>\t");
332     if (isAlreadyReleased)
333       m_log << _T("(already released) ");
334   }
335   ModifiedKey mkey(i_key);
336   mkey.m_modifier.on(Modifier::Type_Up, !i_doPress);
337   mkey.m_modifier.on(Modifier::Type_Down, i_doPress);
338   outputToLog(i_key, mkey, 1);
339 }
340
341
342 // genete event
343 void Engine::generateEvents(Current i_c, const Keymap *i_keymap, Key *i_event)
344 {
345   // generate
346   i_c.m_keymap = i_keymap;
347   i_c.m_mkey.m_key = i_event;
348   if (const Keymap::KeyAssignment *keyAssign =
349       i_c.m_keymap->searchAssignment(i_c.m_mkey))
350   {
351     {
352       Acquire a(&m_log, 1);
353       m_log << std::endl << _T("           ")
354             << i_event->getName() << std::endl;
355     }
356     generateKeySeqEvents(i_c, keyAssign->m_keySeq, Part_all);
357   }
358 }
359
360
361 // genete modifier events
362 void Engine::generateModifierEvents(const Modifier &i_mod)
363 {
364   {
365     Acquire a(&m_log, 1);
366     m_log << _T("* Gen Modifiers\t{") << std::endl;
367   }
368
369   for (int i = Modifier::Type_begin; i < Modifier::Type_BASIC; ++ i)
370   {
371     Keyboard::Mods &mods =
372       m_setting->m_keyboard.getModifiers(static_cast<Modifier::Type>(i));
373
374     if (i_mod.isDontcare(static_cast<Modifier::Type>(i)))
375       // no need to process
376       ;
377     else if (i_mod.isPressed(static_cast<Modifier::Type>(i)))
378       // we have to press this modifier
379     {
380       bool noneIsPressed = true;
381       bool noneIsPressedByAssign = true;
382       for (Keyboard::Mods::iterator i = mods.begin(); i != mods.end(); ++ i)
383       {
384         if ((*i)->m_isPressedOnWin32)
385           noneIsPressed = false;
386         if ((*i)->m_isPressedByAssign)
387           noneIsPressedByAssign = false;
388       }
389       if (noneIsPressed)
390       {
391         if (noneIsPressedByAssign)
392           generateKeyEvent(mods.front(), true, false);
393         else
394           for (Keyboard::Mods::iterator
395                  i = mods.begin(); i != mods.end(); ++ i)
396             if ((*i)->m_isPressedByAssign)
397               generateKeyEvent((*i), true, false);
398       }
399     }
400
401     else
402       // we have to release this modifier
403     {
404       // avoid such sequences as  "Alt U-ALt" or "Windows U-Windows"
405       if (i == Modifier::Type_Alt || i == Modifier::Type_Windows)
406       {
407         for (Keyboard::Mods::iterator j = mods.begin(); j != mods.end(); ++ j)
408           if ((*j) == m_lastGeneratedKey)
409           {
410             Keyboard::Mods *mods =
411               &m_setting->m_keyboard.getModifiers(Modifier::Type_Shift);
412             if (mods->size() == 0)
413               mods = &m_setting->m_keyboard.getModifiers(
414                 Modifier::Type_Control);
415             if (0 < mods->size())
416             {
417               generateKeyEvent(mods->front(), true, false);
418               generateKeyEvent(mods->front(), false, false);
419             }
420             break;
421           }
422       }
423       
424       for (Keyboard::Mods::iterator j = mods.begin(); j != mods.end(); ++ j)
425       {
426         if ((*j)->m_isPressedOnWin32)
427           generateKeyEvent((*j), false, false);
428       }
429     }
430   }
431   
432   {
433     Acquire a(&m_log, 1);
434     m_log << _T("\t\t}") << std::endl;
435   }
436 }
437
438
439 // generate keyboard events for action
440 void Engine::generateActionEvents(const Current &i_c, const Action *i_a,
441                                   bool i_doPress)
442 {
443   switch (i_a->getType())
444   {
445     // key
446     case Action::Type_key:
447     {
448       const ModifiedKey &mkey
449         = reinterpret_cast<ActionKey *>(
450           const_cast<Action *>(i_a))->m_modifiedKey;
451
452       // release
453       if (!i_doPress &&
454           (mkey.m_modifier.isOn(Modifier::Type_Up) ||
455            mkey.m_modifier.isDontcare(Modifier::Type_Up)))
456         generateKeyEvent(mkey.m_key, false, true);
457
458       // press
459       else if (i_doPress &&
460                (mkey.m_modifier.isOn(Modifier::Type_Down) ||
461                 mkey.m_modifier.isDontcare(Modifier::Type_Down)))
462       {
463         Modifier modifier = mkey.m_modifier;
464         modifier.add(i_c.m_mkey.m_modifier);
465         generateModifierEvents(modifier);
466         generateKeyEvent(mkey.m_key, true, true);
467       }
468       break;
469     }
470
471     // keyseq
472     case Action::Type_keySeq:
473     {
474       const ActionKeySeq *aks = reinterpret_cast<const ActionKeySeq *>(i_a);
475       generateKeySeqEvents(i_c, aks->m_keySeq,
476                            i_doPress ? Part_down : Part_up);
477       break;
478     }
479
480     // function
481     case Action::Type_function:
482     {
483       const ActionFunction *af = reinterpret_cast<const ActionFunction *>(i_a);
484       bool is_up = (!i_doPress &&
485                     (af->m_modifier.isOn(Modifier::Type_Up) ||
486                      af->m_modifier.isDontcare(Modifier::Type_Up)));
487       bool is_down = (i_doPress &&
488                       (af->m_modifier.isOn(Modifier::Type_Down) ||
489                        af->m_modifier.isDontcare(Modifier::Type_Down)));
490
491       if (!is_down && !is_up)
492         break;
493       
494       {
495         Acquire a(&m_log, 1);
496         m_log << _T("\t\t     >\t") << af->m_functionData;
497       }
498       
499       FunctionParam param;
500       param.m_isPressed = i_doPress;
501       param.m_hwnd = m_currentFocusOfThread->m_hwndFocus;
502       param.m_c = i_c;
503       param.m_doesNeedEndl = true;
504       param.m_af = af;
505       
506       param.m_c.m_mkey.m_modifier.on(Modifier::Type_Up, !i_doPress);
507       param.m_c.m_mkey.m_modifier.on(Modifier::Type_Down, i_doPress);
508
509       af->m_functionData->exec(this, &param);
510       
511       if (param.m_doesNeedEndl)
512       {
513         Acquire a(&m_log, 1);
514         m_log << std::endl;
515       }
516       break;
517     }
518   }
519 }
520
521
522 // generate keyboard events for keySeq
523 void Engine::generateKeySeqEvents(const Current &i_c, const KeySeq *i_keySeq,
524                                   Part i_part)
525 {
526   const KeySeq::Actions &actions = i_keySeq->getActions();
527   if (actions.empty())
528     return;
529   if (i_part == Part_up)
530     generateActionEvents(i_c, actions[actions.size() - 1], false);
531   else
532   {
533     size_t i;
534     for (i = 0 ; i < actions.size() - 1; ++ i)
535     {
536       generateActionEvents(i_c, actions[i], true);
537       generateActionEvents(i_c, actions[i], false);
538     }
539     generateActionEvents(i_c, actions[i], true);
540     if (i_part == Part_all)
541       generateActionEvents(i_c, actions[i], false);
542   }
543 }
544
545
546 // generate keyboard events for current key
547 void Engine::generateKeyboardEvents(const Current &i_c)
548 {
549   if (++ m_generateKeyboardEventsRecursionGuard ==
550       MAX_GENERATE_KEYBOARD_EVENTS_RECURSION_COUNT)
551   {
552     Acquire a(&m_log);
553     m_log << _T("error: too deep keymap recursion.  there may be a loop.")
554           << std::endl;
555     return;
556   }
557
558   const Keymap::KeyAssignment *keyAssign
559     = i_c.m_keymap->searchAssignment(i_c.m_mkey);
560   if (!keyAssign)
561   {
562     const KeySeq *keySeq = i_c.m_keymap->getDefaultKeySeq();
563     ASSERT( keySeq );
564     generateKeySeqEvents(i_c, keySeq, i_c.isPressed() ? Part_down : Part_up);
565   }
566   else
567   {
568     if (keyAssign->m_modifiedKey.m_modifier.isOn(Modifier::Type_Up) ||
569         keyAssign->m_modifiedKey.m_modifier.isOn(Modifier::Type_Down))
570       generateKeySeqEvents(i_c, keyAssign->m_keySeq, Part_all);
571     else
572       generateKeySeqEvents(i_c, keyAssign->m_keySeq,
573                            i_c.isPressed() ? Part_down : Part_up);
574   }
575   m_generateKeyboardEventsRecursionGuard --;
576 }
577
578
579 // generate keyboard events for current key
580 void Engine::beginGeneratingKeyboardEvents(
581   const Current &i_c, bool i_isModifier)
582 {
583   //             (1)             (2)             (3)  (4)   (1)
584   // up/down:    D-              U-              D-   U-    D-
585   // keymap:     m_currentKeymap m_currentKeymap X    X     m_currentKeymap
586   // memo:       &Prefix(X)      ...             ...  ...   ...
587   // m_isPrefix: false           true            true false false
588
589   Current cnew(i_c);
590
591   bool isPhysicallyPressed
592     = cnew.m_mkey.m_modifier.isPressed(Modifier::Type_Down);
593   
594   // substitute
595   ModifiedKey mkey = m_setting->m_keyboard.searchSubstitute(cnew.m_mkey);
596   if (mkey.m_key)
597   {
598     cnew.m_mkey = mkey;
599     if (isPhysicallyPressed)
600     {
601       cnew.m_mkey.m_modifier.off(Modifier::Type_Up);
602       cnew.m_mkey.m_modifier.on(Modifier::Type_Down);
603     }
604     else
605     {
606       cnew.m_mkey.m_modifier.on(Modifier::Type_Up);
607       cnew.m_mkey.m_modifier.off(Modifier::Type_Down);
608     }
609     for (int i = Modifier::Type_begin; i != Modifier::Type_end; ++ i)
610     {
611       Modifier::Type type = static_cast<Modifier::Type>(i);
612       if (cnew.m_mkey.m_modifier.isDontcare(type) &&
613           !i_c.m_mkey.m_modifier.isDontcare(type))
614         cnew.m_mkey.m_modifier.press(
615           type, i_c.m_mkey.m_modifier.isPressed(type));
616     }
617     
618     {
619       Acquire a(&m_log, 1);
620       m_log << _T("* substitute") << std::endl;
621     }
622     outputToLog(mkey.m_key, cnew.m_mkey, 1);
623   }
624   
625   // for prefix key
626   const Keymap *tmpKeymap = m_currentKeymap;
627   if (i_isModifier || !m_isPrefix) ; 
628   else if (isPhysicallyPressed)                 // when (3)
629     m_isPrefix = false;
630   else if (!isPhysicallyPressed)                // when (2)
631     m_currentKeymap = m_currentFocusOfThread->m_keymaps.front();
632   
633   // for m_emacsEditKillLine function
634   m_emacsEditKillLine.m_doForceReset = !i_isModifier;
635
636   // generate key event !
637   m_generateKeyboardEventsRecursionGuard = 0;
638   if (isPhysicallyPressed)
639     generateEvents(cnew, cnew.m_keymap, &Event::before_key_down);
640   generateKeyboardEvents(cnew);
641   if (!isPhysicallyPressed)
642     generateEvents(cnew, cnew.m_keymap, &Event::after_key_up);
643       
644   // for m_emacsEditKillLine function
645   if (m_emacsEditKillLine.m_doForceReset)
646     m_emacsEditKillLine.reset();
647
648   // for prefix key
649   if (i_isModifier)
650     ;
651   else if (!m_isPrefix)                         // when (1), (4)
652     m_currentKeymap = m_currentFocusOfThread->m_keymaps.front();
653   else if (!isPhysicallyPressed)                // when (2)
654     m_currentKeymap = tmpKeymap;
655 }
656
657
658 #ifdef NO_DRIVER
659 unsigned int Engine::injectInput(const KEYBOARD_INPUT_DATA *i_kid, const KBDLLHOOKSTRUCT *i_kidRaw)
660 {
661   INPUT kid;
662   kid.type = INPUT_KEYBOARD;
663   kid.ki.wVk = 0;
664   kid.ki.wScan = i_kid->MakeCode;
665   kid.ki.dwFlags = KEYEVENTF_SCANCODE;
666   kid.ki.time = i_kidRaw ? i_kidRaw->time : 0;
667   kid.ki.dwExtraInfo = i_kidRaw ? i_kidRaw->dwExtraInfo : 0;
668   if (i_kid->Flags & KEYBOARD_INPUT_DATA::BREAK)
669   {
670     kid.ki.dwFlags |= KEYEVENTF_KEYUP;
671   }
672   if (i_kid->Flags & KEYBOARD_INPUT_DATA::E0)
673   {
674     kid.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY;
675   }
676   SendInput(1, &kid, sizeof(kid));
677   return 1;
678 }
679 #endif // NO_DRIVER
680
681
682 // pop all pressed key on win32
683 void Engine::keyboardResetOnWin32()
684 {
685   for (Keyboard::KeyIterator
686          i = m_setting->m_keyboard.getKeyIterator();  *i; ++ i)
687   {
688     if ((*i)->m_isPressedOnWin32)
689       generateKeyEvent((*i), false, true);
690   }
691 }
692
693
694 #ifdef NO_DRIVER
695 unsigned int WINAPI Engine::keyboardDetour(Engine *i_this, KBDLLHOOKSTRUCT *i_kid)
696 {
697   return i_this->keyboardDetour(i_kid);
698 }
699
700 unsigned int Engine::keyboardDetour(KBDLLHOOKSTRUCT *i_kid)
701 {
702 #if 0
703   Acquire a(&m_log, 1);
704   m_log << std::hex
705         << _T("keyboardDetour: vkCode=") << i_kid->vkCode
706         << _T(" scanCode=") << i_kid->scanCode
707         << _T(" flags=") << i_kid->flags << std::endl;
708 #endif
709   if (i_kid->flags & LLKHF_INJECTED)
710   {
711     return 0;
712   }
713   else
714   {
715     Key key;
716     KEYBOARD_INPUT_DATA kid;
717
718     kid.UnitId = 0;
719     kid.MakeCode = i_kid->scanCode;
720     kid.Flags = 0;
721     if (i_kid->flags & LLKHF_UP)
722     {
723       kid.Flags |= KEYBOARD_INPUT_DATA::BREAK;
724     }
725     if (i_kid->flags & LLKHF_EXTENDED)
726     {
727           kid.Flags |= KEYBOARD_INPUT_DATA::E0;
728     }
729     kid.Reserved = 0;
730     kid.ExtraInformation = 0;
731
732     Acquire a(&m_cskidq);
733     m_kidq.push_back(kid);
734     SetEvent(m_readEvent);
735     return 1;
736   }
737 }
738 #endif // NO_DRIVER
739
740 // keyboard handler thread
741 unsigned int WINAPI Engine::keyboardHandler(void *i_this)
742 {
743   reinterpret_cast<Engine *>(i_this)->keyboardHandler();
744   _endthreadex(0);
745   return 0;
746 }
747 void Engine::keyboardHandler()
748 {
749   // initialize ok
750   CHECK_TRUE( SetEvent(m_threadEvent) );
751     
752   // loop
753   Key key;
754   while (!m_doForceTerminate)
755   {
756     KEYBOARD_INPUT_DATA kid;
757     
758 #ifndef NO_DRIVER
759     DWORD len;
760 #endif // !NO_DRIVER
761     {
762       Acquire a(&m_log, 1);
763       m_log << _T("begin ReadFile();") << std::endl;
764     }
765 #ifdef NO_DRIVER
766     if (1)
767     {
768 #else // !NO_DRIVER
769     if (!ReadFile(m_device, &kid, sizeof(kid), &len, &m_ol))
770     {
771       if (GetLastError() != ERROR_IO_PENDING)
772         continue;
773 #endif // !NO_DRIVER
774       
775       HANDLE handles[] = { m_readEvent, m_interruptThreadEvent };
776     rewait:
777       switch (MsgWaitForMultipleObjects(NUMBER_OF(handles), &handles[0],
778                                      FALSE, INFINITE, QS_POSTMESSAGE))
779       {
780         case WAIT_OBJECT_0:                     // m_readEvent
781 #ifdef NO_DRIVER
782         {
783           Acquire a(&m_cskidq);
784           if (m_kidq.empty())
785           {
786             goto rewait;
787           }
788           kid = m_kidq.front();
789           m_kidq.pop_front();
790           if (!m_kidq.empty())
791           {
792             SetEvent(m_readEvent);
793           }
794         }
795 #else // !NO_DRIVER
796           if (!GetOverlappedResult(m_device, &m_ol, &len, FALSE))
797             continue;
798 #endif // !NO_DRIVER
799           break;
800           
801         case WAIT_OBJECT_0 + 1:                 // m_interruptThreadEvent
802           CancelIo(m_device);
803           switch (m_interruptThreadReason) {
804             default: {
805               ASSERT( false );
806               Acquire a(&m_log, 0);
807               m_log << _T("internal error: m_interruptThreadReason == ")
808                     << m_interruptThreadReason << std::endl;
809               break;
810             }
811               
812             case InterruptThreadReason_Terminate:
813               goto break_while;
814               
815             case InterruptThreadReason_Pause: {
816               CHECK_TRUE( SetEvent(m_threadEvent) );
817               while (WaitForMultipleObjects(1, &m_interruptThreadEvent,
818                                             FALSE, INFINITE) != WAIT_OBJECT_0)
819                 ;
820               switch (m_interruptThreadReason) {
821                 case InterruptThreadReason_Terminate:
822                   goto break_while;
823
824                 case InterruptThreadReason_Resume:
825                   break;
826
827                 default:
828                   ASSERT( false );
829                   break;
830               }
831               CHECK_TRUE( SetEvent(m_threadEvent) );
832               break;
833             }
834           }
835           break;
836           
837         case WAIT_OBJECT_0 + NUMBER_OF(handles):
838         {
839           MSG message;
840
841           while (PeekMessage(&message, NULL, 0, 0, PM_REMOVE))
842           {
843             switch (message.message)
844             {
845               case WM_APP + 201:
846               {
847                 if (message.wParam)
848                 {
849                   m_currentLock.on(Modifier::Type_Touchpad);
850                   m_currentLock.on(Modifier::Type_TouchpadSticky);
851                 }
852                 else
853                   m_currentLock.off(Modifier::Type_Touchpad);
854                 Acquire a(&m_log, 1);
855                 m_log << _T("touchpad: ") << message.wParam
856                       << _T(".") << (message.lParam & 0xffff)
857                       << _T(".") << (message.lParam >> 16 & 0xffff)
858                       << std::endl;
859                 break;
860               }
861               default:
862                 break;
863             }
864           }
865           goto rewait;
866         }
867
868         default:
869           ASSERT( false );
870           continue;
871       }
872     }
873     {
874       Acquire a(&m_log, 1);
875       m_log << _T("end ReadFile();") << std::endl;
876     }
877
878     checkFocusWindow();
879
880     if (!m_setting ||   // m_setting has not been loaded
881         !m_isEnabled)   // disabled
882     {
883       if (m_isLogMode)
884       {
885         Key key;
886         key.addScanCode(ScanCode(kid.MakeCode, kid.Flags));
887         outputToLog(&key, ModifiedKey(), 0);
888       }
889       else
890       {
891 #ifdef NO_DRIVER
892         injectInput(&kid, NULL);
893 #else // !NO_DRIVER
894         WriteFile(m_device, &kid, sizeof(kid), &len, &m_ol);
895         GetOverlappedResult(m_device, &m_ol, &len, TRUE);
896 #endif // !NO_DRIVER
897       }
898       updateLastPressedKey(NULL);
899       continue;
900     }
901     
902     Acquire a(&m_cs);
903
904     if (!m_currentFocusOfThread ||
905         !m_currentKeymap)
906     {
907 #ifndef NO_DRIVER
908       WriteFile(m_device, &kid, sizeof(kid), &len, &m_ol);
909       GetOverlappedResult(m_device, &m_ol, &len, TRUE);
910 #endif // !NO_DRIVER
911       Acquire a(&m_log, 0);
912       if (!m_currentFocusOfThread)
913         m_log << _T("internal error: m_currentFocusOfThread == NULL")
914               << std::endl;
915       if (!m_currentKeymap)
916         m_log << _T("internal error: m_currentKeymap == NULL")
917               << std::endl;
918       updateLastPressedKey(NULL);
919       continue;
920     }
921     
922     Current c;
923     c.m_keymap = m_currentKeymap;
924     c.m_i = m_currentFocusOfThread->m_keymaps.begin();
925     
926     // search key
927     key.addScanCode(ScanCode(kid.MakeCode, kid.Flags));
928     c.m_mkey = m_setting->m_keyboard.searchKey(key);
929     if (!c.m_mkey.m_key)
930     {
931       c.m_mkey.m_key = m_setting->m_keyboard.searchPrefixKey(key);
932       if (c.m_mkey.m_key)
933         continue;
934     }
935
936     // press the key and update counter
937     bool isPhysicallyPressed
938       = !(key.getScanCodes()[0].m_flags & ScanCode::BREAK);
939     if (c.m_mkey.m_key)
940     {
941       if (!c.m_mkey.m_key->m_isPressed && isPhysicallyPressed)
942         ++ m_currentKeyPressCount;
943       else if (c.m_mkey.m_key->m_isPressed && !isPhysicallyPressed)
944         -- m_currentKeyPressCount;
945       c.m_mkey.m_key->m_isPressed = isPhysicallyPressed;
946     }
947     
948     // create modifiers
949     c.m_mkey.m_modifier = getCurrentModifiers(c.m_mkey.m_key,
950                                               isPhysicallyPressed);
951     Keymap::AssignMode am;
952     bool isModifier = fixModifierKey(&c.m_mkey, &am);
953     if (m_isPrefix)
954     {
955       if (isModifier && m_doesIgnoreModifierForPrefix)
956         am = Keymap::AM_true;
957       if (m_doesEditNextModifier)
958       {
959         Modifier modifier = m_modifierForNextKey;
960         modifier.add(c.m_mkey.m_modifier);
961         c.m_mkey.m_modifier = modifier;
962       }
963     }
964     
965     if (m_isLogMode)
966       outputToLog(&key, c.m_mkey, 0);
967     else if (am == Keymap::AM_true)
968     {
969       {
970         Acquire a(&m_log, 1);
971         m_log << _T("* true modifier") << std::endl;
972       }
973       // true modifier doesn't generate scan code
974       outputToLog(&key, c.m_mkey, 1);
975     }
976     else if (am == Keymap::AM_oneShot || am == Keymap::AM_oneShotRepeatable)
977     {
978       {
979         Acquire a(&m_log, 1);
980         if (am == Keymap::AM_oneShot)
981           m_log << _T("* one shot modifier") << std::endl;
982         else
983           m_log << _T("* one shot repeatable modifier") << std::endl;
984       }
985       // oneShot modifier doesn't generate scan code
986       outputToLog(&key, c.m_mkey, 1);
987       if (isPhysicallyPressed)
988       {
989         if (am == Keymap::AM_oneShotRepeatable  // the key is repeating
990             && m_oneShotKey.m_key == c.m_mkey.m_key)
991         {
992           if (m_oneShotRepeatableRepeatCount <
993               m_setting->m_oneShotRepeatableDelay) {
994             ; // delay
995           } else {
996             Current cnew = c;
997             beginGeneratingKeyboardEvents(cnew, false);
998           }
999           ++ m_oneShotRepeatableRepeatCount;
1000         } else {
1001           m_oneShotKey = c.m_mkey;
1002           m_oneShotRepeatableRepeatCount = 0;
1003         }
1004       }
1005       else
1006       {
1007         if (m_oneShotKey.m_key)
1008         {
1009           Current cnew = c;
1010           cnew.m_mkey.m_modifier = m_oneShotKey.m_modifier;
1011           cnew.m_mkey.m_modifier.off(Modifier::Type_Up);
1012           cnew.m_mkey.m_modifier.on(Modifier::Type_Down);
1013           beginGeneratingKeyboardEvents(cnew, false);
1014           
1015           cnew = c;
1016           cnew.m_mkey.m_modifier = m_oneShotKey.m_modifier;
1017           cnew.m_mkey.m_modifier.on(Modifier::Type_Up);
1018           cnew.m_mkey.m_modifier.off(Modifier::Type_Down);
1019           beginGeneratingKeyboardEvents(cnew, false);
1020         }
1021         m_oneShotKey.m_key = NULL;
1022         m_oneShotRepeatableRepeatCount = 0;
1023       }
1024     }
1025     else if (c.m_mkey.m_key)
1026       // normal key
1027     {
1028       outputToLog(&key, c.m_mkey, 1);
1029       if (isPhysicallyPressed)
1030         m_oneShotKey.m_key = NULL;
1031       beginGeneratingKeyboardEvents(c, isModifier);
1032     }
1033     
1034     // if counter is zero, reset modifiers and keys on win32
1035     if (m_currentKeyPressCount <= 0)
1036     {
1037       {
1038         Acquire a(&m_log, 1);
1039         m_log << _T("* No key is pressed") << std::endl;
1040       }
1041       generateModifierEvents(Modifier());
1042       if (0 < m_currentKeyPressCountOnWin32)
1043         keyboardResetOnWin32();
1044       m_currentKeyPressCount = 0;
1045       m_currentKeyPressCountOnWin32 = 0;
1046       m_oneShotKey.m_key = NULL;
1047       if (m_currentLock.isOn(Modifier::Type_Touchpad) == false)
1048         m_currentLock.off(Modifier::Type_TouchpadSticky);
1049     }
1050     
1051     key.initialize();
1052     updateLastPressedKey(isPhysicallyPressed ? c.m_mkey.m_key : NULL);
1053   }
1054   break_while:
1055   CHECK_TRUE( SetEvent(m_threadEvent) );
1056 }
1057   
1058
1059 Engine::Engine(tomsgstream &i_log)
1060   : m_hwndAssocWindow(NULL),
1061     m_setting(NULL),
1062     m_device(INVALID_HANDLE_VALUE),
1063     m_didMayuStartDevice(false),
1064     m_threadEvent(NULL),
1065     m_mayudVersion(_T("unknown")),
1066     m_readEvent(NULL),
1067     m_interruptThreadEvent(NULL),
1068     m_sts4mayu(NULL),
1069     m_cts4mayu(NULL),
1070     m_doForceTerminate(false),
1071     m_isLogMode(false),
1072     m_isEnabled(true),
1073     m_isSynchronizing(false),
1074     m_eSync(NULL),
1075     m_generateKeyboardEventsRecursionGuard(0),
1076     m_currentKeyPressCount(0),
1077     m_currentKeyPressCountOnWin32(0),
1078     m_lastGeneratedKey(NULL),
1079     m_oneShotRepeatableRepeatCount(0),
1080     m_isPrefix(false),
1081     m_currentKeymap(NULL),
1082     m_currentFocusOfThread(NULL),
1083     m_hwndFocus(NULL),
1084     m_afShellExecute(NULL),
1085     m_variable(0),
1086     m_log(i_log)
1087 {
1088   for (size_t i = 0; i < NUMBER_OF(m_lastPressedKey); ++ i)
1089     m_lastPressedKey[i] = NULL;
1090     
1091   // set default lock state
1092   for (int i = 0; i < Modifier::Type_end; ++ i)
1093     m_currentLock.dontcare(static_cast<Modifier::Type>(i));
1094   for (int i = Modifier::Type_Lock0; i <= Modifier::Type_Lock9; ++ i)
1095     m_currentLock.release(static_cast<Modifier::Type>(i));
1096
1097 #ifndef NO_DRIVER
1098   if (!open()) {
1099       throw ErrorMessage() << loadString(IDS_driverNotInstalled);
1100   }
1101 #endif // !NO_DRIVER
1102   
1103 #ifndef NO_DRIVER
1104   {
1105     TCHAR versionBuf[256];
1106     DWORD length = 0;
1107
1108     if (DeviceIoControl(m_device, IOCTL_MAYU_GET_VERSION, NULL, 0,
1109                         versionBuf, sizeof(versionBuf), &length, NULL)
1110         && length
1111         && length < sizeof(versionBuf))                 // fail safe
1112         m_mayudVersion = tstring(versionBuf, length / 2);
1113   }
1114 #endif // !NO_DRIVER
1115   // create event for sync
1116   CHECK_TRUE( m_eSync = CreateEvent(NULL, FALSE, FALSE, NULL) );
1117   // create named pipe for &SetImeString
1118   m_hookPipe = CreateNamedPipe(addSessionId(HOOK_PIPE_NAME).c_str(),
1119                                PIPE_ACCESS_OUTBOUND,
1120                                PIPE_TYPE_BYTE, 1,
1121                                0, 0, 0, NULL);
1122   StrExprArg::setEngine(this);
1123 }
1124
1125
1126 // open mayu device
1127 bool Engine::open()
1128 {
1129   // open mayu m_device
1130 #ifndef NO_DRIVER
1131   m_device = CreateFile(MAYU_DEVICE_FILE_NAME, GENERIC_READ | GENERIC_WRITE,
1132                         0, NULL, OPEN_EXISTING,
1133                         FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
1134 #endif // !NO_DRIVER
1135
1136   if (m_device != INVALID_HANDLE_VALUE) {
1137     return true;
1138   }
1139
1140 #ifndef NO_DRIVER
1141   // start mayud
1142   SC_HANDLE hscm = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
1143   if (hscm)
1144   {
1145     SC_HANDLE hs = OpenService(hscm, MAYU_DRIVER_NAME, SERVICE_START);
1146     if (hs)
1147     {
1148       StartService(hs, 0, NULL);
1149       CloseServiceHandle(hs);
1150       m_didMayuStartDevice = true;
1151     }
1152     CloseServiceHandle(hscm);
1153   }
1154   
1155   // open mayu m_device
1156   m_device = CreateFile(MAYU_DEVICE_FILE_NAME, GENERIC_READ | GENERIC_WRITE,
1157                         0, NULL, OPEN_EXISTING,
1158                         FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
1159 #endif // !NO_DRIVER
1160   return (m_device != INVALID_HANDLE_VALUE);
1161 }
1162
1163
1164 // close mayu device
1165 void Engine::close()
1166 {
1167   if (m_device != INVALID_HANDLE_VALUE) {
1168 #ifndef NO_DRIVER
1169     CHECK_TRUE( CloseHandle(m_device) );
1170 #endif // !NO_DRIVER
1171   }
1172   m_device = INVALID_HANDLE_VALUE;
1173 }
1174
1175
1176 // start keyboard handler thread
1177 void Engine::start()
1178 {
1179   CHECK_TRUE( m_threadEvent = CreateEvent(NULL, FALSE, FALSE, NULL) );
1180   
1181   CHECK_TRUE( m_readEvent = CreateEvent(NULL, FALSE, FALSE, NULL) );
1182   CHECK_TRUE( m_interruptThreadEvent = CreateEvent(NULL, FALSE, FALSE, NULL) );
1183   m_ol.Offset = 0;
1184   m_ol.OffsetHigh = 0;
1185   m_ol.hEvent = m_readEvent;
1186   
1187   CHECK_TRUE( m_threadHandle = (HANDLE)_beginthreadex(NULL, 0, keyboardHandler, this, 0, &m_threadId) );
1188   CHECK( WAIT_OBJECT_0 ==, WaitForSingleObject(m_threadEvent, INFINITE) );
1189 }
1190
1191
1192 // stop keyboard handler thread
1193 void Engine::stop()
1194 {
1195   if (m_threadEvent)
1196   {
1197     m_doForceTerminate = true;
1198     do
1199     {
1200       m_interruptThreadReason = InterruptThreadReason_Terminate;
1201       SetEvent(m_interruptThreadEvent);
1202       //DWORD buf;
1203       //M_DeviceIoControl(m_device, IOCTL_MAYU_DETOUR_CANCEL,
1204       //                &buf, sizeof(buf), &buf, sizeof(buf), &buf, NULL);
1205       
1206       // wait for message handler thread terminate
1207     } while (WaitForSingleObject(m_threadEvent, 100) != WAIT_OBJECT_0);
1208     CHECK_TRUE( CloseHandle(m_threadEvent) );
1209     m_threadEvent = NULL;
1210     WaitForSingleObject(m_threadHandle, 100);
1211     CHECK_TRUE( CloseHandle(m_threadHandle) );
1212     m_threadHandle = NULL;
1213
1214     // stop mayud
1215     if (m_didMayuStartDevice)
1216     {
1217       SC_HANDLE hscm = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
1218       if (hscm)
1219       {
1220         SC_HANDLE hs = OpenService(hscm, MAYU_DRIVER_NAME, SERVICE_STOP);
1221         if (hs)
1222         {
1223           SERVICE_STATUS ss;
1224           ControlService(hs, SERVICE_CONTROL_STOP, &ss);
1225           CloseServiceHandle(hs);
1226         }
1227         CloseServiceHandle(hscm);
1228       }
1229     }
1230     
1231     CHECK_TRUE( CloseHandle(m_readEvent) );
1232     m_readEvent = NULL;
1233     CHECK_TRUE( CloseHandle(m_interruptThreadEvent) );
1234     m_interruptThreadEvent = NULL;
1235   }
1236 }
1237
1238 bool Engine::pause()
1239 {
1240   if (m_device != INVALID_HANDLE_VALUE) {
1241     do {
1242       m_interruptThreadReason = InterruptThreadReason_Pause;
1243       SetEvent(m_interruptThreadEvent);
1244     } while (WaitForSingleObject(m_threadEvent, 100) != WAIT_OBJECT_0);
1245 #ifndef NO_DRIVER
1246     close();
1247 #endif // !NO_DRIVER
1248   }
1249   return true;
1250 }
1251
1252
1253 bool Engine::resume()
1254 {
1255   if (m_device == INVALID_HANDLE_VALUE) {
1256 #ifndef NO_DRIVER
1257     if (!open()) {
1258       return false;                             // FIXME
1259     }
1260 #endif // !NO_DRIVER
1261     do {
1262       m_interruptThreadReason = InterruptThreadReason_Resume;
1263       SetEvent(m_interruptThreadEvent);
1264     } while (WaitForSingleObject(m_threadEvent, 100) != WAIT_OBJECT_0);
1265   }
1266   return true;
1267 }
1268
1269
1270 bool Engine::prepairQuit()
1271 {
1272   // terminate and unload DLL for ThumbSense support if loaded
1273   manageTs4mayu(_T("sts4mayu.dll"), _T("SynCOM.dll"),
1274                 false, &m_sts4mayu);
1275   manageTs4mayu(_T("cts4mayu.dll"), _T("TouchPad.dll"),
1276                 false, &m_cts4mayu);
1277   return true;
1278 }
1279
1280
1281 Engine::~Engine()
1282 {
1283   stop();
1284   CHECK_TRUE( CloseHandle(m_eSync) );
1285   
1286   // close m_device
1287 #ifndef NO_DRIVER
1288   close();
1289 #endif // !NO_DRIVER
1290   // destroy named pipe for &SetImeString
1291   if (m_hookPipe && m_hookPipe != INVALID_HANDLE_VALUE)
1292   {
1293     DisconnectNamedPipe(m_hookPipe);
1294     CHECK_TRUE( CloseHandle(m_hookPipe) );
1295   }
1296 }
1297
1298
1299 void Engine::manageTs4mayu(TCHAR *i_ts4mayuDllName,
1300                            TCHAR *i_dependDllName,
1301                            bool i_load, HMODULE *i_pTs4mayu)
1302 {
1303   Acquire a(&m_log, 0);
1304
1305   if (i_load == false)
1306   {
1307     if (*i_pTs4mayu)
1308     {
1309       bool (WINAPI *pTs4mayuTerm)();
1310
1311       pTs4mayuTerm = (bool (WINAPI*)())GetProcAddress(*i_pTs4mayu, "ts4mayuTerm");
1312       if (pTs4mayuTerm() == true)
1313         FreeLibrary(*i_pTs4mayu);
1314       *i_pTs4mayu = NULL;
1315       m_log << i_ts4mayuDllName <<_T(" unloaded") << std::endl;
1316     }
1317   }
1318   else
1319   {
1320     if (*i_pTs4mayu)
1321     {
1322       m_log << i_ts4mayuDllName << _T(" already loaded") << std::endl;
1323     }
1324     else
1325     {
1326       if (SearchPath(NULL, i_dependDllName, NULL, 0, NULL, NULL) == 0)
1327       {
1328         m_log << _T("load ") << i_ts4mayuDllName
1329               << _T(" failed: can't find ") << i_dependDllName
1330               << std::endl;
1331       }
1332       else
1333       {
1334         *i_pTs4mayu = LoadLibrary(i_ts4mayuDllName);
1335         if (*i_pTs4mayu == NULL)
1336         {
1337           m_log << _T("load ") << i_ts4mayuDllName
1338                 << _T(" failed: can't find it") << std::endl;
1339         }
1340         else
1341         {
1342           bool (WINAPI *pTs4mayuInit)(UINT);    
1343
1344           pTs4mayuInit = (bool (WINAPI*)(UINT))GetProcAddress(*i_pTs4mayu, "ts4mayuInit");
1345           if (pTs4mayuInit(m_threadId) == true)
1346             m_log << i_ts4mayuDllName <<_T(" loaded") << std::endl;
1347           else
1348             m_log << i_ts4mayuDllName
1349                   <<_T(" load failed: can't initialize") << std::endl;
1350         }
1351       }
1352     }
1353   }
1354 }
1355
1356
1357 // set m_setting
1358 bool Engine::setSetting(Setting *i_setting)
1359 {
1360   Acquire a(&m_cs);
1361   if (m_isSynchronizing)
1362     return false;
1363
1364   if (m_setting)
1365   {
1366     for (Keyboard::KeyIterator i = m_setting->m_keyboard.getKeyIterator();
1367          *i; ++ i)
1368     {
1369       Key *key = i_setting->m_keyboard.searchKey(*(*i));
1370       if (key)
1371       {
1372         key->m_isPressed = (*i)->m_isPressed;
1373         key->m_isPressedOnWin32 = (*i)->m_isPressedOnWin32;
1374         key->m_isPressedByAssign = (*i)->m_isPressedByAssign;
1375       }
1376     }
1377     if (m_lastGeneratedKey)
1378       m_lastGeneratedKey =
1379         i_setting->m_keyboard.searchKey(*m_lastGeneratedKey);
1380     for (size_t i = 0; i < NUMBER_OF(m_lastPressedKey); ++ i)
1381       if (m_lastPressedKey[i])
1382         m_lastPressedKey[i] =
1383           i_setting->m_keyboard.searchKey(*m_lastPressedKey[i]);
1384   }
1385   
1386   m_setting = i_setting;
1387
1388   manageTs4mayu(_T("sts4mayu.dll"), _T("SynCOM.dll"),
1389                 m_setting->m_sts4mayu, &m_sts4mayu);
1390   manageTs4mayu(_T("cts4mayu.dll"), _T("TouchPad.dll"),
1391                 m_setting->m_cts4mayu, &m_cts4mayu);
1392
1393   g_hookData->m_correctKanaLockHandling = m_setting->m_correctKanaLockHandling;
1394   if (m_currentFocusOfThread)
1395   {
1396     for (FocusOfThreads::iterator i = m_focusOfThreads.begin();
1397          i != m_focusOfThreads.end(); i ++)
1398     {
1399       FocusOfThread *fot = &(*i).second;
1400       m_setting->m_keymaps.searchWindow(&fot->m_keymaps,
1401                                         fot->m_className, fot->m_titleName);
1402     }
1403   }
1404   m_setting->m_keymaps.searchWindow(&m_globalFocus.m_keymaps, _T(""), _T(""));
1405   if (m_globalFocus.m_keymaps.empty())
1406   {
1407     Acquire a(&m_log, 0);
1408     m_log << _T("internal error: m_globalFocus.m_keymap is empty")
1409           << std::endl;
1410   }
1411   m_currentFocusOfThread = &m_globalFocus;
1412   setCurrentKeymap(m_globalFocus.m_keymaps.front());
1413   m_hwndFocus = NULL;
1414   return true;
1415 }
1416
1417
1418 void Engine::checkShow(HWND i_hwnd)
1419 {
1420   // update show style of window
1421   // this update should be done in hook DLL, but to
1422   // avoid update-loss for some applications(such as
1423   // cmd.exe), we update here.
1424   bool isMaximized = false;
1425   bool isMinimized = false;
1426   bool isMDIMaximized = false;
1427   bool isMDIMinimized = false;
1428   while (i_hwnd)
1429   {
1430 #ifdef MAYU64
1431     LONG_PTR exStyle = GetWindowLongPtr(i_hwnd, GWL_EXSTYLE);
1432 #else
1433     LONG exStyle = GetWindowLong(i_hwnd, GWL_EXSTYLE);
1434 #endif
1435     if (exStyle & WS_EX_MDICHILD)
1436     {
1437       WINDOWPLACEMENT placement;
1438       placement.length = sizeof(WINDOWPLACEMENT);
1439       if (GetWindowPlacement(i_hwnd, &placement))
1440       {
1441          switch (placement.showCmd)
1442          {
1443            case SW_SHOWMAXIMIZED:
1444              isMDIMaximized = true;
1445              break;
1446            case SW_SHOWMINIMIZED:
1447              isMDIMinimized = true;
1448              break;
1449            case SW_SHOWNORMAL:
1450            default:
1451              break;
1452          }
1453       }
1454     }
1455
1456 #ifdef MAYU64
1457     LONG_PTR style = GetWindowLongPtr(i_hwnd, GWL_STYLE);
1458 #else
1459     LONG style = GetWindowLong(i_hwnd, GWL_STYLE);
1460 #endif
1461     if ((style & WS_CHILD) == 0)
1462     {
1463       WINDOWPLACEMENT placement;
1464       placement.length = sizeof(WINDOWPLACEMENT);
1465       if (GetWindowPlacement(i_hwnd, &placement))
1466       {
1467          switch (placement.showCmd)
1468          {
1469            case SW_SHOWMAXIMIZED:
1470              isMaximized = true;
1471              break;
1472            case SW_SHOWMINIMIZED:
1473              isMinimized = true;
1474              break;
1475            case SW_SHOWNORMAL:
1476            default:
1477              break;
1478          }
1479       }
1480     }  
1481     i_hwnd = GetParent(i_hwnd);
1482   }
1483   setShow(isMDIMaximized, isMDIMinimized, true);
1484   setShow(isMaximized, isMinimized, false);
1485 }
1486
1487
1488 // focus
1489 bool Engine::setFocus(HWND i_hwndFocus, DWORD i_threadId, 
1490                       const tstringi &i_className, const tstringi &i_titleName,
1491                       bool i_isConsole)
1492 {
1493   Acquire a(&m_cs);
1494   if (m_isSynchronizing)
1495     return false;
1496   if (i_hwndFocus == NULL)
1497     return true;
1498
1499   // remove newly created thread's id from m_detachedThreadIds
1500   if (!m_detachedThreadIds.empty())
1501   {
1502     DetachedThreadIds::iterator i;
1503     bool retry;
1504     do
1505     {
1506       retry = false;
1507       for (i = m_detachedThreadIds.begin();
1508            i != m_detachedThreadIds.end(); ++ i)
1509         if (*i == i_threadId)
1510         {
1511           m_detachedThreadIds.erase(i);
1512           retry = true;
1513           break;
1514         }
1515     } while (retry);
1516   }
1517   
1518   FocusOfThread *fot;
1519   FocusOfThreads::iterator i = m_focusOfThreads.find(i_threadId);
1520   if (i != m_focusOfThreads.end())
1521   {
1522     fot = &(*i).second;
1523     if (fot->m_hwndFocus == i_hwndFocus &&
1524         fot->m_isConsole == i_isConsole &&
1525         fot->m_className == i_className &&
1526         fot->m_titleName == i_titleName)
1527       return true;
1528   }
1529   else
1530   {
1531     i = m_focusOfThreads.insert(
1532       FocusOfThreads::value_type(i_threadId, FocusOfThread())).first;
1533     fot = &(*i).second;
1534     fot->m_threadId = i_threadId;
1535   }
1536   fot->m_hwndFocus = i_hwndFocus;
1537   fot->m_isConsole = i_isConsole;
1538   fot->m_className = i_className;
1539   fot->m_titleName = i_titleName;
1540   
1541   if (m_setting)
1542   {
1543     m_setting->m_keymaps.searchWindow(&fot->m_keymaps,
1544                                       i_className, i_titleName);
1545     ASSERT(0 < fot->m_keymaps.size());
1546   }
1547   else
1548     fot->m_keymaps.clear();
1549   checkShow(i_hwndFocus);
1550   return true;
1551 }
1552
1553
1554 // lock state
1555 bool Engine::setLockState(bool i_isNumLockToggled,
1556                           bool i_isCapsLockToggled,
1557                           bool i_isScrollLockToggled,
1558                           bool i_isKanaLockToggled,
1559                           bool i_isImeLockToggled,
1560                           bool i_isImeCompToggled)
1561 {
1562   Acquire a(&m_cs);
1563   if (m_isSynchronizing)
1564     return false;
1565   m_currentLock.on(Modifier::Type_NumLock, i_isNumLockToggled);
1566   m_currentLock.on(Modifier::Type_CapsLock, i_isCapsLockToggled);
1567   m_currentLock.on(Modifier::Type_ScrollLock, i_isScrollLockToggled);
1568   m_currentLock.on(Modifier::Type_KanaLock, i_isKanaLockToggled);
1569   m_currentLock.on(Modifier::Type_ImeLock, i_isImeLockToggled);
1570   m_currentLock.on(Modifier::Type_ImeComp, i_isImeCompToggled);
1571   return true;
1572 }
1573
1574
1575 // show
1576 bool Engine::setShow(bool i_isMaximized, bool i_isMinimized,
1577                      bool i_isMDI)
1578 {
1579   Acquire a(&m_cs);
1580   if (m_isSynchronizing)
1581     return false;
1582   Acquire b(&m_log, 1);
1583   Modifier::Type max, min;
1584   if (i_isMDI == true) {
1585     max = Modifier::Type_MdiMaximized;
1586     min = Modifier::Type_MdiMinimized;
1587   }
1588   else
1589   {
1590     max = Modifier::Type_Maximized;
1591     min = Modifier::Type_Minimized;
1592   }
1593   m_currentLock.on(max, i_isMaximized);
1594   m_currentLock.on(min, i_isMinimized);
1595   m_log << _T("Set show to ") << (i_isMaximized ? _T("Maximized") :
1596                                   i_isMinimized ? _T("Minimized") : _T("Normal"));
1597   if (i_isMDI == true)
1598   {
1599     m_log << _T(" (MDI)");
1600   }
1601   m_log << std::endl;
1602   return true;
1603 }
1604
1605
1606 // sync
1607 bool Engine::syncNotify()
1608 {
1609   Acquire a(&m_cs);
1610   if (!m_isSynchronizing)
1611     return false;
1612   CHECK_TRUE( SetEvent(m_eSync) );
1613   return true;
1614 }
1615
1616
1617 // thread detach notify
1618 bool Engine::threadDetachNotify(DWORD i_threadId)
1619 {
1620   Acquire a(&m_cs);
1621   m_detachedThreadIds.push_back(i_threadId);
1622   return true;
1623 }
1624
1625
1626 // get help message
1627 void Engine::getHelpMessages(tstring *o_helpMessage, tstring *o_helpTitle)
1628 {
1629   Acquire a(&m_cs);
1630   *o_helpMessage = m_helpMessage;
1631   *o_helpTitle = m_helpTitle;
1632 }
1633
1634
1635 // command notify
1636 void Engine::commandNotify(
1637   HWND i_hwnd, UINT i_message, WPARAM i_wParam, LPARAM i_lParam)
1638 {
1639   Acquire b(&m_log, 0);
1640   HWND hf = m_hwndFocus;
1641   if (!hf)
1642     return;
1643
1644   if (GetWindowThreadProcessId(hf, NULL) == 
1645       GetWindowThreadProcessId(m_hwndAssocWindow, NULL))
1646     return;     // inhibit the investigation of MADO TSUKAI NO YUUTSU
1647
1648   const _TCHAR *target = NULL;
1649   int number_target = 0;
1650   
1651   if (i_hwnd == hf)
1652     target = _T("ToItself");
1653   else if (i_hwnd == GetParent(hf))
1654     target = _T("ToParentWindow");
1655   else
1656   {
1657     // Function::toMainWindow
1658     HWND h = hf;
1659     while (true)
1660     {
1661       HWND p = GetParent(h);
1662       if (!p)
1663         break;
1664       h = p;
1665     }
1666     if (i_hwnd == h)
1667       target = _T("ToMainWindow");
1668     else
1669     {
1670       // Function::toOverlappedWindow
1671       HWND h = hf;
1672       while (h)
1673       {
1674 #ifdef MAYU64
1675         LONG_PTR style = GetWindowLongPtr(h, GWL_STYLE);
1676 #else
1677         LONG style = GetWindowLong(h, GWL_STYLE);
1678 #endif
1679         if ((style & WS_CHILD) == 0)
1680           break;
1681         h = GetParent(h);
1682       }
1683       if (i_hwnd == h)
1684         target = _T("ToOverlappedWindow");
1685       else
1686       {
1687         // number
1688         HWND h = hf;
1689         for (number_target = 0; h; number_target ++, h = GetParent(h))
1690           if (i_hwnd == h)
1691             break;
1692         return;
1693       }
1694     }
1695   }
1696
1697   m_log << _T("&PostMessage(");
1698   if (target)
1699     m_log << target;
1700   else
1701     m_log << number_target;
1702   m_log << _T(", ") << i_message
1703         << _T(", 0x") << std::hex << i_wParam
1704         << _T(", 0x") << i_lParam << _T(") # hwnd = ")
1705         << reinterpret_cast<int>(i_hwnd) << _T(", ")
1706         << _T("message = ") << std::dec;
1707   if (i_message == WM_COMMAND)
1708     m_log << _T("WM_COMMAND, ");
1709   else if (i_message == WM_SYSCOMMAND)
1710     m_log << _T("WM_SYSCOMMAND, ");
1711   else
1712     m_log << i_message << _T(", ");
1713   m_log << _T("wNotifyCode = ") << HIWORD(i_wParam) << _T(", ")
1714         << _T("wID = ") << LOWORD(i_wParam) << _T(", ")
1715         << _T("hwndCtrl = 0x") << std::hex << i_lParam << std::dec << std::endl;
1716 }