OSDN Git Service

fix ticket #18663
[yamy/yamy.git] / function.cpp
index 16f7294..15ddb46 100644 (file)
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// function.cpp
-
-
-#include "engine.h"
-#include "hook.h"
-#include "mayu.h"
-#include "mayurc.h"
-#include "misc.h"
-#include "registry.h"
-#include "vkeytable.h"
-#include "windowstool.h"
-#include <algorithm>
-#include <process.h>
-
-#define FUNCTION_DATA
-#include "functions.h"
-#undef FUNCTION_DATA
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// TypeTable
-
-
-template <class T> class TypeTable
-{
-public:
-  T m_type;
-  const _TCHAR *m_name;
-};
-
-
-template <class T> static inline
-bool getTypeName(tstring *o_name, T i_type,
-                const TypeTable<T> *i_table, size_t i_n)
-{
-  for (size_t i = 0; i < i_n; ++ i)
-    if (i_table[i].m_type == i_type)
-    {
-      *o_name = i_table[i].m_name;
-      return true;
-    }
-  return false;
-}
-
-template <class T> static inline
-bool getTypeValue(T *o_type, const tstringi &i_name,
-                 const TypeTable<T> *i_table, size_t i_n)
-{
-  for (size_t i = 0; i < i_n; ++ i)
-    if (i_table[i].m_name == i_name)
-    {
-      *o_type = i_table[i].m_type;
-      return true;
-    }
-  return false;
-}
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// VKey
-
-
-// stream output
-tostream &operator<<(tostream &i_ost, VKey i_data)
-{
-  if (i_data & VKey_extended)
-    i_ost << _T("E-");
-  if (i_data & VKey_released)
-    i_ost << _T("U-");
-  if (i_data & VKey_pressed)
-    i_ost << _T("D-");
-
-  u_int8 code = i_data & ~(VKey_extended | VKey_released | VKey_pressed);
-  const VKeyTable *vkt;
-  for (vkt = g_vkeyTable; vkt->m_name; ++ vkt)
-    if (vkt->m_code == code)
-      break;
-  if (vkt->m_name)
-    i_ost << vkt->m_name;
-  else
-    i_ost << _T("0x") << std::hex << code << std::dec;
-  return i_ost;
-}
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// ToWindowType
-
-
-// ToWindowType table
-typedef TypeTable<ToWindowType> TypeTable_ToWindowType;
-static const TypeTable_ToWindowType g_toWindowTypeTable[] =
-{
-  { ToWindowType_toOverlappedWindow, _T("toOverlappedWindow") },
-  { ToWindowType_toMainWindow,       _T("toMainWindow")       },
-  { ToWindowType_toItself,           _T("toItself")           },
-  { ToWindowType_toParentWindow,     _T("toParentWindow")     },
-};
-
-
-// stream output
-tostream &operator<<(tostream &i_ost, ToWindowType i_data)
-{
-  tstring name;
-  if (getTypeName(&name, i_data,
-                 g_toWindowTypeTable, NUMBER_OF(g_toWindowTypeTable)))
-    i_ost << name;
-  else
-    i_ost << static_cast<int>(i_data);
-  return i_ost;
-}
-
-
-// get value of ToWindowType
-bool getTypeValue(ToWindowType *o_type, const tstring &i_name)
-{
-  return getTypeValue(o_type, i_name,
-                     g_toWindowTypeTable, NUMBER_OF(g_toWindowTypeTable));
-}
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// GravityType
-
-
-// GravityType table
-typedef TypeTable<GravityType> TypeTable_GravityType;
-static const TypeTable_GravityType g_gravityTypeTable[] =
-{
-  { GravityType_C,  _T("C")  },
-  { GravityType_N,  _T("N")  },
-  { GravityType_E,  _T("E")  },
-  { GravityType_W,  _T("W")  },
-  { GravityType_S,  _T("S")  },
-  { GravityType_NW, _T("NW") },
-  { GravityType_NW, _T("WN") },
-  { GravityType_NE, _T("NE") },
-  { GravityType_NE, _T("EN") },
-  { GravityType_SW, _T("SW") },
-  { GravityType_SW, _T("WS") },
-  { GravityType_SE, _T("SE") },
-  { GravityType_SE, _T("ES") },
-};
-
-
-// stream output
-tostream &operator<<(tostream &i_ost, GravityType i_data)
-{
-  tstring name;
-  if (getTypeName(&name, i_data,
-                 g_gravityTypeTable, NUMBER_OF(g_gravityTypeTable)))
-    i_ost << name;
-  else
-    i_ost << _T("(GravityType internal error)");
-  return i_ost;
-}
-
-
-// get value of GravityType
-bool getTypeValue(GravityType *o_type, const tstring &i_name)
-{
-  return getTypeValue(o_type, i_name,
-                     g_gravityTypeTable, NUMBER_OF(g_gravityTypeTable));
-}
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// MouseHookType
-
-
-// MouseHookType table
-typedef TypeTable<MouseHookType> TypeTable_MouseHookType;
-static const TypeTable_MouseHookType g_mouseHookTypeTable[] =
-{
-  { MouseHookType_None,  _T("None")  },
-  { MouseHookType_Wheel,  _T("Wheel")  },
-  { MouseHookType_WindowMove,  _T("WindowMove")  },
-};
-
-
-// stream output
-tostream &operator<<(tostream &i_ost, MouseHookType i_data)
-{
-  tstring name;
-  if (getTypeName(&name, i_data,
-                 g_mouseHookTypeTable, NUMBER_OF(g_mouseHookTypeTable)))
-    i_ost << name;
-  else
-    i_ost << _T("(MouseHookType internal error)");
-  return i_ost;
-}
-
-
-// get value of MouseHookType
-bool getTypeValue(MouseHookType *o_type, const tstring &i_name)
-{
-  return getTypeValue(o_type, i_name, g_mouseHookTypeTable,
-                     NUMBER_OF(g_mouseHookTypeTable));
-}
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// MayuDialogType
-
-
-// ModifierLockType table
-typedef TypeTable<MayuDialogType> TypeTable_MayuDialogType;
-static const TypeTable_MayuDialogType g_mayuDialogTypeTable[] =
-{
-  { MayuDialogType_investigate, _T("investigate")  },
-  { MayuDialogType_log,         _T("log")          },
-};
-
-
-// stream output
-tostream &operator<<(tostream &i_ost, MayuDialogType i_data)
-{
-  tstring name;
-  if (getTypeName(&name, i_data,
-                 g_mayuDialogTypeTable, NUMBER_OF(g_mayuDialogTypeTable)))
-    i_ost << name;
-  else
-    i_ost << _T("(MayuDialogType internal error)");
-  return i_ost;
-}
-
-
-// get value of MayuDialogType
-bool getTypeValue(MayuDialogType *o_type, const tstring &i_name)
-{
-  return getTypeValue(o_type, i_name, g_mayuDialogTypeTable,
-                     NUMBER_OF(g_mayuDialogTypeTable));
-}
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// ToggleType
-
-
-// ToggleType table
-typedef TypeTable<ToggleType> TypeTable_ToggleType;
-static const TypeTable_ToggleType g_toggleType[] =
-{
-  { ToggleType_toggle, _T("toggle") },
-  { ToggleType_off, _T("off") },
-  { ToggleType_off, _T("false") },
-  { ToggleType_off, _T("released") },
-  { ToggleType_on,  _T("on")  },
-  { ToggleType_on,  _T("true")  },
-  { ToggleType_on,  _T("pressed")  },
-};
-
-
-// stream output
-tostream &operator<<(tostream &i_ost, ToggleType i_data)
-{
-  tstring name;
-  if (getTypeName(&name, i_data, g_toggleType, NUMBER_OF(g_toggleType)))
-    i_ost << name;
-  else
-    i_ost << _T("(ToggleType internal error)");
-  return i_ost;
-}
-
-
-// get value of ToggleType
-bool getTypeValue(ToggleType *o_type, const tstring &i_name)
-{
-  return getTypeValue(o_type, i_name, g_toggleType,
-                     NUMBER_OF(g_toggleType));
-}
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// ModifierLockType
-
-
-// ModifierLockType table
-typedef TypeTable<ModifierLockType> TypeTable_ModifierLockType;
-static const TypeTable_ModifierLockType g_modifierLockTypeTable[] =
-{
-  { ModifierLockType_Lock0, _T("lock0") },
-  { ModifierLockType_Lock1, _T("lock1") },
-  { ModifierLockType_Lock2, _T("lock2") },
-  { ModifierLockType_Lock3, _T("lock3") },
-  { ModifierLockType_Lock4, _T("lock4") },
-  { ModifierLockType_Lock5, _T("lock5") },
-  { ModifierLockType_Lock6, _T("lock6") },
-  { ModifierLockType_Lock7, _T("lock7") },
-  { ModifierLockType_Lock8, _T("lock8") },
-  { ModifierLockType_Lock9, _T("lock9") },
-};
-
-
-// stream output
-tostream &operator<<(tostream &i_ost, ModifierLockType i_data)
-{
-  tstring name;
-  if (getTypeName(&name, i_data,
-                 g_modifierLockTypeTable, NUMBER_OF(g_modifierLockTypeTable)))
-    i_ost << name;
-  else
-    i_ost << _T("(ModifierLockType internal error)");
-  return i_ost;
-}
-
-
-// get value of ModifierLockType
-bool getTypeValue(ModifierLockType *o_type, const tstring &i_name)
-{
-  return getTypeValue(o_type, i_name, g_modifierLockTypeTable,
-                     NUMBER_OF(g_modifierLockTypeTable));
-}
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// ShowCommandType
-
-
-// ShowCommandType table
-typedef TypeTable<ShowCommandType> TypeTable_ShowCommandType;
-static const TypeTable_ShowCommandType g_showCommandTypeTable[] =
-{
-  { ShowCommandType_hide,            _T("hide")            },
-  { ShowCommandType_maximize,        _T("maximize")        },
-  { ShowCommandType_minimize,        _T("minimize")        },
-  { ShowCommandType_restore,         _T("restore")         },
-  { ShowCommandType_show,            _T("show")            },
-  { ShowCommandType_showDefault,     _T("showDefault")     },
-  { ShowCommandType_showMaximized,   _T("showMaximized")   },
-  { ShowCommandType_showMinimized,   _T("showMinimized")   },
-  { ShowCommandType_showMinNoActive, _T("showMinNoActive") },
-  { ShowCommandType_showNA,          _T("showNA")          },
-  { ShowCommandType_showNoActivate,  _T("showNoActivate")  },
-  { ShowCommandType_showNormal,      _T("showNormal")      },
-};
-
-
-// stream output
-tostream &operator<<(tostream &i_ost, ShowCommandType i_data)
-{
-  tstring name;
-  if (getTypeName(&name, i_data,
-                 g_showCommandTypeTable, NUMBER_OF(g_showCommandTypeTable)))
-    i_ost << name;
-  else
-    i_ost << _T("(ShowCommandType internal error)");
-  return i_ost;
-}
-
-
-// get value of ShowCommandType
-bool getTypeValue(ShowCommandType *o_type, const tstring &i_name)
-{
-  return getTypeValue(o_type, i_name, g_showCommandTypeTable,
-                     NUMBER_OF(g_showCommandTypeTable));
-}
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// TargetWindowType
-
-
-// ModifierLockType table
-typedef TypeTable<TargetWindowType> TypeTable_TargetWindowType;
-static const TypeTable_TargetWindowType g_targetWindowType[] =
-{
-  { TargetWindowType_overlapped, _T("overlapped") },
-  { TargetWindowType_mdi,        _T("mdi")        },
-};
-
-
-// stream output
-tostream &operator<<(tostream &i_ost, TargetWindowType i_data)
-{
-  tstring name;
-  if (getTypeName(&name, i_data,
-                 g_targetWindowType, NUMBER_OF(g_targetWindowType)))
-    i_ost << name;
-  else
-    i_ost << _T("(TargetWindowType internal error)");
-  return i_ost;
-}
-
-
-// get value of TargetWindowType
-bool getTypeValue(TargetWindowType *o_type, const tstring &i_name)
-{
-  return getTypeValue(o_type, i_name, g_targetWindowType,
-                     NUMBER_OF(g_targetWindowType));
-}
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// BooleanType
-
-
-// BooleanType table
-typedef TypeTable<BooleanType> TypeTable_BooleanType;
-static const TypeTable_BooleanType g_booleanType[] =
-{
-  { BooleanType_false, _T("false") },
-  { BooleanType_true,  _T("true")  },
-};
-
-
-// stream output
-tostream &operator<<(tostream &i_ost, BooleanType i_data)
-{
-  tstring name;
-  if (getTypeName(&name, i_data, g_booleanType, NUMBER_OF(g_booleanType)))
-    i_ost << name;
-  else
-    i_ost << _T("(BooleanType internal error)");
-  return i_ost;
-}
-
-
-// get value of BooleanType
-bool getTypeValue(BooleanType *o_type, const tstring &i_name)
-{
-  return getTypeValue(o_type, i_name, g_booleanType,
-                     NUMBER_OF(g_booleanType));
-}
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// LogicalOperatorType
-
-
-// LogicalOperatorType table
-typedef TypeTable<LogicalOperatorType> TypeTable_LogicalOperatorType;
-static const TypeTable_LogicalOperatorType g_logicalOperatorType[] =
-{
-  { LogicalOperatorType_or, _T("||") },
-  { LogicalOperatorType_and,  _T("&&")  },
-};
-
-
-// stream output
-tostream &operator<<(tostream &i_ost, LogicalOperatorType i_data)
-{
-  tstring name;
-  if (getTypeName(&name, i_data, g_logicalOperatorType,
-                 NUMBER_OF(g_logicalOperatorType)))
-    i_ost << name;
-  else
-    i_ost << _T("(LogicalOperatorType internal error)");
-  return i_ost;
-}
-
-
-// get value of LogicalOperatorType
-bool getTypeValue(LogicalOperatorType *o_type, const tstring &i_name)
-{
-  return getTypeValue(o_type, i_name, g_logicalOperatorType,
-                     NUMBER_OF(g_logicalOperatorType));
-}
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// WindowMonitorFromType
-
-
-// WindowMonitorFromType table
-typedef TypeTable<WindowMonitorFromType> TypeTable_WindowMonitorFromType;
-static const TypeTable_WindowMonitorFromType g_windowMonitorFromType[] =
-{
-  { WindowMonitorFromType_primary, _T("primary") },
-  { WindowMonitorFromType_current, _T("current") },
-};
-
-
-// stream output
-tostream &operator<<(tostream &i_ost, WindowMonitorFromType i_data)
-{
-  tstring name;
-  if(getTypeName(&name, i_data, g_windowMonitorFromType,
-                 NUMBER_OF(g_windowMonitorFromType)))
-    i_ost << name;
-  else
-    i_ost << _T("(WindowMonitorFromType internal error)");
-  return i_ost;
-}
-
-
-// get value of WindowMonitorFromType
-bool getTypeValue(WindowMonitorFromType *o_type, const tstring &i_name)
-{
-  return getTypeValue(o_type, i_name, g_windowMonitorFromType,
-                      NUMBER_OF(g_windowMonitorFromType));
-}
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// std::list<tstringq>
-
-
-/// stream output
-tostream &operator<<(tostream &i_ost, const std::list<tstringq> &i_data)
-{
-  for (std::list<tstringq>::const_iterator
-        i = i_data.begin(); i != i_data.end(); ++ i)
-  {
-    i_ost << *i << _T(", ");
-  }
-  return i_ost;
-}
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// FunctionData
-
-
-//
-FunctionData::~FunctionData()
-{
-}
-
-
-// stream output
-tostream &operator<<(tostream &i_ost, const FunctionData *i_data)
-{
-  return i_data->output(i_ost);
-}
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// FunctionCreator
-
-
-///
-class FunctionCreator
-{
-public:
-  typedef FunctionData *(*Creator)();          /// 
-  
-public:
-  const _TCHAR *m_name;                                /// function name
-  Creator m_creator;                           /// function data creator
-};
-
-
-// create function
-FunctionData *createFunctionData(const tstring &i_name)
-{
-  static 
-#define FUNCTION_CREATOR
-#include "functions.h"
-#undef FUNCTION_CREATOR
-    ;
-
-  for (size_t i = 0; i != NUMBER_OF(functionCreators); ++ i)
-    if (i_name == functionCreators[i].m_name)
-      return functionCreators[i].m_creator();
-  return NULL;
-}
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// misc. functions
-
-
-//
-bool getSuitableWindow(FunctionParam *i_param, HWND *o_hwnd)
-{
-  if (!i_param->m_isPressed)
-    return false;
-  *o_hwnd = getToplevelWindow(i_param->m_hwnd, NULL);
-  if (!*o_hwnd)
-    return false;
-  return true;
-}
-
-//
-bool getSuitableMdiWindow(FunctionParam *i_param, HWND *o_hwnd,
-                         TargetWindowType *io_twt,
-                         RECT *o_rcWindow = NULL, RECT *o_rcParent = NULL)
-{
-  if (!i_param->m_isPressed)
-    return false;
-  bool isMdi = *io_twt == TargetWindowType_mdi;
-  *o_hwnd = getToplevelWindow(i_param->m_hwnd, &isMdi);
-  *io_twt = isMdi ? TargetWindowType_mdi : TargetWindowType_overlapped;
-  if (!*o_hwnd)
-    return false;
-  switch (*io_twt)
-  {
-    case TargetWindowType_overlapped:
-      if (o_rcWindow)
-       GetWindowRect(*o_hwnd, o_rcWindow);
-      if (o_rcParent) {
-        HMONITOR hm = monitorFromWindow(i_param->m_hwnd,
-                                        MONITOR_DEFAULTTONEAREST);
-        MONITORINFO mi;
-        mi.cbSize = sizeof(mi);
-        getMonitorInfo(hm, &mi);
-        *o_rcParent = mi.rcWork;
-      }
-      break;
-    case TargetWindowType_mdi:
-      if (o_rcWindow)
-       getChildWindowRect(*o_hwnd, o_rcWindow);
-      if (o_rcParent)
-       GetClientRect(GetParent(*o_hwnd), o_rcParent);
-      break;
-  }
-  return true;
-}
-
-// get clipboard text (you must call closeClopboard())
-static const _TCHAR *getTextFromClipboard(HGLOBAL *o_hdata)
-{
-  *o_hdata = NULL;
-  
-  if (!OpenClipboard(NULL))
-    return NULL;
-
-#ifdef UNICODE
-  *o_hdata = GetClipboardData(CF_UNICODETEXT);
-#else
-  *o_hdata = GetClipboardData(CF_TEXT);
-#endif
-  if (!*o_hdata)
-    return NULL;
-  
-  _TCHAR *data = reinterpret_cast<_TCHAR *>(GlobalLock(*o_hdata));
-  if (!data)
-    return NULL;
-  return data;
-}
-
-// close clipboard that opend by getTextFromClipboard()
-static void closeClipboard(HGLOBAL i_hdata, HGLOBAL i_hdataNew = NULL)
-{
-  if (i_hdata)
-    GlobalUnlock(i_hdata);
-  if (i_hdataNew)
-  {
-    EmptyClipboard();
-#ifdef UNICODE
-    SetClipboardData(CF_UNICODETEXT, i_hdataNew);
-#else
-    SetClipboardData(CF_TEXT, i_hdataNew);
-#endif
-  }
-  CloseClipboard();
-}
-
-
-// EmacsEditKillLineFunc.
-// clear the contents of the clopboard
-// at that time, confirm if it is the result of the previous kill-line
-void Engine::EmacsEditKillLine::func()
-{
-  if (!m_buf.empty())
-  {
-    HGLOBAL g;
-    const _TCHAR *text = getTextFromClipboard(&g);
-    if (text == NULL || m_buf != text)
-      reset();
-    closeClipboard(g);
-  }
-  if (OpenClipboard(NULL))
-  {
-    EmptyClipboard();
-    CloseClipboard();
-  }
-}
-
-
-/** if the text of the clipboard is
-@doc
-<pre>
-1: EDIT Control (at EOL C-K): ""            =&gt; buf + "\r\n", Delete   
-0: EDIT Control (other  C-K): "(.+)"        =&gt; buf + "\1"             
-0: IE FORM TEXTAREA (at EOL C-K): "\r\n"    =&gt; buf + "\r\n"           
-2: IE FORM TEXTAREA (other C-K): "(.+)\r\n" =&gt; buf + "\1", Return Left
-^retval
-</pre>
-*/
-HGLOBAL Engine::EmacsEditKillLine::makeNewKillLineBuf(
-  const _TCHAR *i_data, int *o_retval)
-{
-  size_t len = m_buf.size();
-  len += _tcslen(i_data) + 3;
-  
-  HGLOBAL hdata = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,
-                             len * sizeof(_TCHAR));
-  if (!hdata)
-    return NULL;
-  _TCHAR *dataNew = reinterpret_cast<_TCHAR *>(GlobalLock(hdata));
-  *dataNew = _T('\0');
-  if (!m_buf.empty())
-    _tcscpy(dataNew, m_buf.c_str());
-  
-  len = _tcslen(i_data);
-  if (3 <= len &&
-      i_data[len - 2] == _T('\r') && i_data[len - 1] == _T('\n'))
-  {
-    _tcscat(dataNew, i_data);
-    len = _tcslen(dataNew);
-    dataNew[len - 2] = _T('\0'); // chomp
-    *o_retval = 2;
-  }
-  else if (len == 0)
-  {
-    _tcscat(dataNew, _T("\r\n"));
-    *o_retval = 1;
-  }
-  else
-  {
-    _tcscat(dataNew, i_data);
-    *o_retval = 0;
-  }
-  
-  m_buf = dataNew;
-  
-  GlobalUnlock(hdata);
-  return hdata;
-}
-
-
-// EmacsEditKillLinePred
-int Engine::EmacsEditKillLine::pred()
-{
-  HGLOBAL g;
-  const _TCHAR *text = getTextFromClipboard(&g);
-  int retval;
-  HGLOBAL hdata = makeNewKillLineBuf(text ? text : _T(""), &retval);
-  closeClipboard(g, hdata);
-  return retval;
-}
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// functions
-
-
-// send a default key to Windows
-void Engine::funcDefault(FunctionParam *i_param)
-{
-  {
-    Acquire a(&m_log, 1);
-    m_log << std::endl;
-    i_param->m_doesNeedEndl = false;
-  }
-  if (i_param->m_isPressed)
-    generateModifierEvents(i_param->m_c.m_mkey.m_modifier);
-  generateKeyEvent(i_param->m_c.m_mkey.m_key, i_param->m_isPressed, true);
-}
-
-// use a corresponding key of a parent keymap
-void Engine::funcKeymapParent(FunctionParam *i_param)
-{
-  Current c(i_param->m_c);
-  c.m_keymap = c.m_keymap->getParentKeymap();
-  if (!c.m_keymap)
-  {
-    funcDefault(i_param);
-    return;
-  }
-  
-  {
-    Acquire a(&m_log, 1);
-    m_log << _T("(") << c.m_keymap->getName() << _T(")") << std::endl;
-  }
-  i_param->m_doesNeedEndl = false;
-  generateKeyboardEvents(c);
-}
-
-// use a corresponding key of a current window
-void Engine::funcKeymapWindow(FunctionParam *i_param)
-{
-  Current c(i_param->m_c);
-  c.m_keymap = m_currentFocusOfThread->m_keymaps.front();
-  c.m_i = m_currentFocusOfThread->m_keymaps.begin();
-  generateKeyboardEvents(c);
-}
-
-// use a corresponding key of the previous prefixed keymap
-void Engine::funcKeymapPrevPrefix(FunctionParam *i_param, int i_previous)
-{
-  Current c(i_param->m_c);
-  if (0 < i_previous && 0 <= m_keymapPrefixHistory.size() - i_previous)
-  {
-    int n = i_previous - 1;
-    KeymapPtrList::reverse_iterator i = m_keymapPrefixHistory.rbegin();
-    while (0 < n && i != m_keymapPrefixHistory.rend())
-      --n, ++i;
-    c.m_keymap = *i;
-    generateKeyboardEvents(c);
-  }
-}
-
-// use a corresponding key of an other window class, or use a default key
-void Engine::funcOtherWindowClass(FunctionParam *i_param)
-{
-  Current c(i_param->m_c);
-  ++ c.m_i;
-  if (c.m_i == m_currentFocusOfThread->m_keymaps.end())
-  {
-    funcDefault(i_param);
-    return;
-  }
-  
-  c.m_keymap = *c.m_i;
-  {
-    Acquire a(&m_log, 1);
-    m_log << _T("(") << c.m_keymap->getName() << _T(")") << std::endl;
-  }
-  i_param->m_doesNeedEndl = false;
-  generateKeyboardEvents(c);
-}
-
-// prefix key
-void Engine::funcPrefix(FunctionParam *i_param, const Keymap *i_keymap,
-                       BooleanType i_doesIgnoreModifiers)
-{
-  if (!i_param->m_isPressed)
-    return;
-  
-  setCurrentKeymap(i_keymap, true);
-  
-  // generate prefixed event
-  generateEvents(i_param->m_c, m_currentKeymap, &Event::prefixed);
-  
-  m_isPrefix = true;
-  m_doesEditNextModifier = false;
-  m_doesIgnoreModifierForPrefix = !!i_doesIgnoreModifiers;
-
-  {
-    Acquire a(&m_log, 1);
-    m_log << _T("(") << i_keymap->getName() << _T(", ")
-         << (i_doesIgnoreModifiers ? _T("true") : _T("false")) << _T(")");
-  }
-}
-
-// other keymap's key
-void Engine::funcKeymap(FunctionParam *i_param, const Keymap *i_keymap)
-{
-  Current c(i_param->m_c);
-  c.m_keymap = i_keymap;
-  {
-    Acquire a(&m_log, 1);
-    m_log << _T("(") << c.m_keymap->getName() << _T(")") << std::endl;
-    i_param->m_doesNeedEndl = false;
-  }
-  generateKeyboardEvents(c);
-}
-
-// sync
-void Engine::funcSync(FunctionParam *i_param)
-{
-  if (i_param->m_isPressed)
-    generateModifierEvents(i_param->m_af->m_modifier);
-  if (!i_param->m_isPressed || m_currentFocusOfThread->m_isConsole)
-    return;
-  
-  Key *sync = m_setting->m_keyboard.getSyncKey();
-  if (sync->getScanCodesSize() == 0)
-    return;
-  const ScanCode *sc = sync->getScanCodes();
-  
-  // set variables exported from mayu.dll
-  g_hookData->m_syncKey = sc->m_scan;
-  g_hookData->m_syncKeyIsExtended = !!(sc->m_flags & ScanCode::E0E1);
-  m_isSynchronizing = true;
-#if defined(_WINNT)
-  generateKeyEvent(sync, false, false);
-#elif defined(_WIN95)
-  generateKeyEvent(sync, true, false);
-#else
-#  error
-#endif
-  
-  m_cs.release();
-  DWORD r = WaitForSingleObject(m_eSync, 5000);
-  if (r == WAIT_TIMEOUT)
-  {
-    Acquire a(&m_log, 0);
-    m_log << _T(" *FAILED*") << std::endl;
-  }
-  m_cs.acquire();
-  m_isSynchronizing = false;
-}
-
-// toggle lock
-void Engine::funcToggle(FunctionParam *i_param, ModifierLockType i_lock,
-                       ToggleType i_toggle)
-{
-  if (i_param->m_isPressed)                    // ignore PRESS
-    return;
-
-  Modifier::Type mt = static_cast<Modifier::Type>(i_lock);
-  switch (i_toggle)
-  {
-    case ToggleType_toggle:
-      m_currentLock.press(mt, !m_currentLock.isPressed(mt));
-      break;
-    case ToggleType_off:
-      m_currentLock.press(mt, false);
-      break;
-    case ToggleType_on:
-      m_currentLock.press(mt, true);
-      break;
-  }
-}
-
-// edit next user input key's modifier
-void Engine::funcEditNextModifier(FunctionParam *i_param,
-                                 const Modifier &i_modifier)
-{
-  if (!i_param->m_isPressed)
-    return;
-  
-  m_isPrefix = true;
-  m_doesEditNextModifier = true;
-  m_doesIgnoreModifierForPrefix = true;
-  m_modifierForNextKey = i_modifier;
-}
-
-// variable
-void Engine::funcVariable(FunctionParam *i_param, int i_mag, int i_inc)
-{
-  if (!i_param->m_isPressed)
-    return;
-  m_variable *= i_mag;
-  m_variable += i_inc;
-}
-
-// repeat N times
-void Engine::funcRepeat(FunctionParam *i_param, const KeySeq *i_keySeq,
-                       int i_max)
-{
-  if (i_param->m_isPressed)
-  {
-    int end = MIN(m_variable, i_max);
-    for (int i = 0; i < end - 1; ++ i)
-      generateKeySeqEvents(i_param->m_c, i_keySeq, Part_all);
-    if (0 < end)
-      generateKeySeqEvents(i_param->m_c, i_keySeq, Part_down);
-  }
-  else
-    generateKeySeqEvents(i_param->m_c, i_keySeq, Part_up);
-}
-
-// undefined (bell)
-void Engine::funcUndefined(FunctionParam *i_param)
-{
-  if (!i_param->m_isPressed)
-    return;
-  MessageBeep(MB_OK);
-}
-
-// ignore
-void Engine::funcIgnore(FunctionParam *)
-{
-  // do nothing
-}
-
-// post message
-void Engine::funcPostMessage(FunctionParam *i_param, ToWindowType i_window,
-                            UINT i_message, WPARAM i_wParam, LPARAM i_lParam)
-{
-  if (!i_param->m_isPressed)
-    return;
-
-  int window = static_cast<int>(i_window);
-  
-  HWND hwnd = i_param->m_hwnd;
-  if (0 < window)
-  {
-    for (int i = 0; i < window; ++ i)
-      hwnd = GetParent(hwnd);
-  }
-  else if (window == ToWindowType_toMainWindow)
-  {
-    while (true)
-    {
-      HWND p = GetParent(hwnd);
-      if (!p)
-       break;
-      hwnd = p;
-    }
-  }
-  else if (window == ToWindowType_toOverlappedWindow)
-  {
-    while (hwnd)
-    {
-      LONG style = GetWindowLong(hwnd, GWL_STYLE);
-      if ((style & WS_CHILD) == 0)
-       break;
-      hwnd = GetParent(hwnd);
-    }
-  }
-
-  if (hwnd)
-    PostMessage(hwnd, i_message, i_wParam, i_lParam);
-}
-
-
-// ShellExecute
-void Engine::funcShellExecute(FunctionParam *i_param,
-                             const StrExprArg &/*i_operation*/,
-                             const StrExprArg &/*i_file*/,
-                             const StrExprArg &/*i_parameters*/,
-                             const StrExprArg &/*i_directory*/,
-                             ShowCommandType /*i_showCommand*/)
-{
-  if (!i_param->m_isPressed)
-    return;
-  m_afShellExecute = i_param->m_af;
-  PostMessage(m_hwndAssocWindow,
-             WM_APP_engineNotify, EngineNotify_shellExecute, 0);
-}
-
-
-// shell execute
-void Engine::shellExecute()
-{
-  Acquire a(&m_cs);
-  
-  FunctionData_ShellExecute *fd =
-    reinterpret_cast<FunctionData_ShellExecute *>(
-      m_afShellExecute->m_functionData);
-  
-  int r = (int)ShellExecute(
-    NULL,
-    fd->m_operation.eval().empty() ? _T("open") : fd->m_operation.eval().c_str(),
-    fd->m_file.eval().empty() ? NULL : fd->m_file.eval().c_str(),
-    fd->m_parameters.eval().empty() ? NULL : fd->m_parameters.eval().c_str(),
-    fd->m_directory.eval().empty() ? NULL : fd->m_directory.eval().c_str(),
-    fd->m_showCommand);
-  if (32 < r)
-    return; // success
-
-  typedef TypeTable<int> ErrorTable;
-  static const ErrorTable errorTable[] =
-  {
-    { 0, _T("The operating system is out of memory or resources.") },
-    { ERROR_FILE_NOT_FOUND, _T("The specified file was not found.") },
-    { ERROR_PATH_NOT_FOUND, _T("The specified path was not found.") },
-    { ERROR_BAD_FORMAT, _T("The .exe file is invalid ")
-      _T("(non-Win32R .exe or error in .exe image).") },
-    { SE_ERR_ACCESSDENIED,
-      _T("The operating system denied access to the specified file.") },
-    { SE_ERR_ASSOCINCOMPLETE,
-      _T("The file name association is incomplete or invalid.") },
-    { SE_ERR_DDEBUSY,
-      _T("The DDE transaction could not be completed ")
-      _T("because other DDE transactions were being processed. ") },
-    { SE_ERR_DDEFAIL, _T("The DDE transaction failed.") },
-    { SE_ERR_DDETIMEOUT, _T("The DDE transaction could not be completed ")
-      _T("because the request timed out.") },
-    { SE_ERR_DLLNOTFOUND,
-      _T("The specified dynamic-link library was not found.") },
-    { SE_ERR_FNF, _T("The specified file was not found.") },
-    { SE_ERR_NOASSOC, _T("There is no application associated ")
-      _T("with the given file name extension.") },
-    { SE_ERR_OOM,
-      _T("There was not enough memory to complete the operation.") },
-    { SE_ERR_PNF, _T("The specified path was not found.") },
-    { SE_ERR_SHARE, _T("A sharing violation occurred.") },
-  };
-
-  tstring errorMessage(_T("Unknown error."));
-  getTypeName(&errorMessage, r, errorTable, NUMBER_OF(errorTable));
-  
-  Acquire b(&m_log, 0);
-  m_log << _T("error: ") << fd << _T(": ") << errorMessage << std::endl;
-}
-
-
-struct EnumWindowsForSetForegroundWindowParam
-{
-  const FunctionData_SetForegroundWindow *m_fd;
-  HWND m_hwnd;
-
-public:
-  EnumWindowsForSetForegroundWindowParam(
-    const FunctionData_SetForegroundWindow *i_fd)
-    : m_fd(i_fd),
-      m_hwnd(NULL)
-  {
-  }
-};
-
-
-/// enum windows for SetForegroundWindow
-static BOOL CALLBACK enumWindowsForSetForegroundWindow(
-  HWND i_hwnd, LPARAM i_lParam)
-{
-  EnumWindowsForSetForegroundWindowParam &ep =
-    *reinterpret_cast<EnumWindowsForSetForegroundWindowParam *>(i_lParam);
-
-  _TCHAR name[GANA_MAX_ATOM_LENGTH];
-  if (!GetClassName(i_hwnd, name, NUMBER_OF(name)))
-    return TRUE;
-  tsmatch what;
-  if (!boost::regex_search(tstring(name), what, ep.m_fd->m_windowClassName))
-    if (ep.m_fd->m_logicalOp == LogicalOperatorType_and)
-      return TRUE;                             // match failed
-
-  if (ep.m_fd->m_logicalOp == LogicalOperatorType_and)
-  {
-    if (GetWindowText(i_hwnd, name, NUMBER_OF(name)) == 0)
-      name[0] = _T('\0');
-    if (!boost::regex_search(tstring(name), what,
-                            ep.m_fd->m_windowTitleName))
-      return TRUE;                             // match failed
-  }
-
-  ep.m_hwnd = i_hwnd;
-  return FALSE;
-}
-
-
-/// SetForegroundWindow
-void Engine::funcSetForegroundWindow(FunctionParam *i_param, const tregex &,
-                                    LogicalOperatorType , const tregex &)
-{
-  if (!i_param->m_isPressed)
-    return;
-  EnumWindowsForSetForegroundWindowParam
-    ep(static_cast<const FunctionData_SetForegroundWindow *>(
-      i_param->m_af->m_functionData));
-  EnumWindows(enumWindowsForSetForegroundWindow,
-             reinterpret_cast<LPARAM>(&ep));
-  if (ep.m_hwnd)
-    PostMessage(m_hwndAssocWindow,
-               WM_APP_engineNotify, EngineNotify_setForegroundWindow,
-               reinterpret_cast<LPARAM>(ep.m_hwnd));
-
-}
-
-
-// load setting
-void Engine::funcLoadSetting(FunctionParam *i_param, const StrExprArg &i_name)
-{
-  if (!i_param->m_isPressed)
-    return;
-  if (!i_name.eval().empty())
-  {
-    // set MAYU_REGISTRY_ROOT\.mayuIndex which name is same with i_name
-    Registry reg(MAYU_REGISTRY_ROOT);
-
-    tregex split(_T("^([^;]*);([^;]*);(.*)$"));
-    tstringi dot_mayu;
-    for (size_t i = 0; i < MAX_MAYU_REGISTRY_ENTRIES; ++ i)
-    {
-      _TCHAR buf[100];
-      _sntprintf(buf, NUMBER_OF(buf), _T(".mayu%d"), i);
-      if (!reg.read(buf, &dot_mayu))
-       break;
-      
-      tsmatch what;
-      if (boost::regex_match(dot_mayu, what, split) &&
-         what.str(1) == i_name.eval())
-      {        
-       reg.write(_T(".mayuIndex"), i);
-       goto success;
-      }
-    }
-
-    {
-      Acquire a(&m_log, 0);
-      m_log << _T("unknown setting name: ") << i_name;
-    }
-    return;
-    
-    success: ;
-  }
-  PostMessage(m_hwndAssocWindow,
-             WM_APP_engineNotify, EngineNotify_loadSetting, 0);
-}
-
-// virtual key
-void Engine::funcVK(FunctionParam *i_param, VKey i_vkey)
-{
-  long key = static_cast<long>(i_vkey);
-  BYTE vkey = static_cast<BYTE>(i_vkey);
-  bool isExtended = !!(key & VKey_extended);
-  bool isUp       = !i_param->m_isPressed && !!(key & VKey_released);
-  bool isDown     = i_param->m_isPressed && !!(key & VKey_pressed);
-  
-  if (vkey == VK_LBUTTON && isDown)
-    mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
-  else if (vkey == VK_LBUTTON && isUp)
-    mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
-  else if (vkey == VK_MBUTTON && isDown)
-    mouse_event(MOUSEEVENTF_MIDDLEDOWN, 0, 0, 0, 0);
-  else if (vkey == VK_MBUTTON && isUp)
-    mouse_event(MOUSEEVENTF_MIDDLEUP, 0, 0, 0, 0);
-  else if (vkey == VK_RBUTTON && isDown)
-    mouse_event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0);
-  else if (vkey == VK_RBUTTON && isUp)
-    mouse_event(MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0);
-#if(_WIN32_WINNT >= 0x0500)
-  else if (vkey == VK_XBUTTON1 && isDown)
-    mouse_event(MOUSEEVENTF_XDOWN, 0, 0, XBUTTON1, 0);
-  else if (vkey == VK_XBUTTON1 && isUp)
-    mouse_event(MOUSEEVENTF_XUP, 0, 0, XBUTTON1, 0);
-  else if (vkey == VK_XBUTTON2 && isDown)
-    mouse_event(MOUSEEVENTF_XDOWN, 0, 0, XBUTTON2, 0);
-  else if (vkey == VK_XBUTTON2 && isUp)
-    mouse_event(MOUSEEVENTF_XUP, 0, 0, XBUTTON2, 0);
-#endif /* _WIN32_WINNT >= 0x0500 */
-  else if (isUp || isDown)
-    keybd_event(vkey,
-               static_cast<BYTE>(MapVirtualKey(vkey, 0)),
-               (isExtended ? KEYEVENTF_EXTENDEDKEY : 0) |
-               (i_param->m_isPressed ? 0 : KEYEVENTF_KEYUP), 0);
-}
-
-// wait
-void Engine::funcWait(FunctionParam *i_param, int i_milliSecond)
-{
-  if (!i_param->m_isPressed)
-    return;
-  if (i_milliSecond < 0 || 5000 < i_milliSecond)       // too long wait
-    return;
-  
-  m_isSynchronizing = true;
-  m_cs.release();
-  Sleep(i_milliSecond);
-  m_cs.acquire();
-  m_isSynchronizing = false;
-}
-
-// investigate WM_COMMAND, WM_SYSCOMMAND
-void Engine::funcInvestigateCommand(FunctionParam *i_param)
-{
-  if (!i_param->m_isPressed)
-    return;
-  Acquire a(&m_log, 0);
-  g_hookData->m_doesNotifyCommand = !g_hookData->m_doesNotifyCommand;
-  if (g_hookData->m_doesNotifyCommand)
-    m_log << _T(" begin") << std::endl;
-  else
-    m_log << _T(" end") << std::endl;
-}
-
-// show mayu dialog box
-void Engine::funcMayuDialog(FunctionParam *i_param, MayuDialogType i_dialog,
-                           ShowCommandType i_showCommand)
-{
-  if (!i_param->m_isPressed)
-    return;
-  PostMessage(getAssociatedWndow(), WM_APP_engineNotify, EngineNotify_showDlg,
-             static_cast<LPARAM>(i_dialog) |
-             static_cast<LPARAM>(i_showCommand));
-}
-
-// describe bindings
-void Engine::funcDescribeBindings(FunctionParam *i_param)
-{
-  if (!i_param->m_isPressed)
-    return;
-  {
-    Acquire a(&m_log, 1);
-    m_log << std::endl;
-  }
-  describeBindings();
-}
-
-// show help message
-void Engine::funcHelpMessage(FunctionParam *i_param, const StrExprArg &i_title,
-                            const StrExprArg &i_message)
-{
-  if (!i_param->m_isPressed)
-    return;
-
-  m_helpTitle = i_title.eval();
-  m_helpMessage = i_message.eval();
-  bool doesShow = !(i_title.eval().size() == 0 && i_message.eval().size() == 0);
-  PostMessage(getAssociatedWndow(), WM_APP_engineNotify,
-             EngineNotify_helpMessage, doesShow);
-}
-
-// show variable
-void Engine::funcHelpVariable(FunctionParam *i_param, const StrExprArg &i_title)
-{
-  if (!i_param->m_isPressed)
-    return;
-
-  _TCHAR buf[20];
-  _sntprintf(buf, NUMBER_OF(buf), _T("%d"), m_variable);
-
-  m_helpTitle = i_title.eval();
-  m_helpMessage = buf;
-  PostMessage(getAssociatedWndow(), WM_APP_engineNotify,
-             EngineNotify_helpMessage, true);
-}
-
-// raise window
-void Engine::funcWindowRaise(FunctionParam *i_param,
-                            TargetWindowType i_twt)
-{
-  HWND hwnd;
-  if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt))
-    return;
-  SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0,
-              SWP_ASYNCWINDOWPOS | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOSIZE);
-}
-
-// lower window
-void Engine::funcWindowLower(FunctionParam *i_param, TargetWindowType i_twt)
-{
-  HWND hwnd;
-  if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt))
-    return;
-  SetWindowPos(hwnd, HWND_BOTTOM, 0, 0, 0, 0,
-              SWP_ASYNCWINDOWPOS | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOSIZE);
-}
-
-// minimize window
-void Engine::funcWindowMinimize(FunctionParam *i_param, TargetWindowType i_twt)
-{
-  HWND hwnd;
-  if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt))
-    return;
-  PostMessage(hwnd, WM_SYSCOMMAND,
-             IsIconic(hwnd) ? SC_RESTORE : SC_MINIMIZE, 0);
-}
-
-// maximize window
-void Engine::funcWindowMaximize(FunctionParam *i_param, TargetWindowType i_twt)
-{
-  HWND hwnd;
-  if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt))
-    return;
-  PostMessage(hwnd, WM_SYSCOMMAND,
-             IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, 0);
-}
-
-// maximize horizontally or virtically
-void Engine::funcWindowHVMaximize(FunctionParam *i_param,
-                                 BooleanType i_isHorizontal,
-                                 TargetWindowType i_twt)
-{
-  HWND hwnd;
-  RECT rc, rcd;
-  if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt, &rc, &rcd))
-    return;
-
-  // erase non window
-  while (true)
-  {
-    WindowPositions::iterator i = m_windowPositions.begin();
-    WindowPositions::iterator end = m_windowPositions.end();
-    for (; i != end; ++ i)
-      if (!IsWindow((*i).m_hwnd))
-       break;
-    if (i == end)
-      break;
-    m_windowPositions.erase(i);
-  }
-
-  // find target
-  WindowPositions::iterator i = m_windowPositions.begin();
-  WindowPositions::iterator end = m_windowPositions.end();
-  WindowPositions::iterator target = end;
-  for (; i != end; ++ i)
-    if ((*i).m_hwnd == hwnd)
-    {
-      target = i;
-      break;
-    }
-  
-  if (IsZoomed(hwnd))
-    PostMessage(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
-  else
-  {
-    WindowPosition::Mode mode = WindowPosition::Mode_normal;
-    
-    if (target != end)
-    {
-      WindowPosition &wp = *target;
-      rc = wp.m_rc;
-      if (wp.m_mode == WindowPosition::Mode_HV)
-       mode = wp.m_mode =
-         i_isHorizontal ? WindowPosition::Mode_V : WindowPosition::Mode_H;
-      else if (( i_isHorizontal && wp.m_mode == WindowPosition::Mode_V) ||
-              (!i_isHorizontal && wp.m_mode == WindowPosition::Mode_H))
-       mode = wp.m_mode = WindowPosition::Mode_HV;
-      else
-       m_windowPositions.erase(target);
-    }
-    else
-    {
-      mode = i_isHorizontal ? WindowPosition::Mode_H : WindowPosition::Mode_V;
-      m_windowPositions.push_front(WindowPosition(hwnd, rc, mode));
-    }
-    
-    if (static_cast<int>(mode) & static_cast<int>(WindowPosition::Mode_H))
-      rc.left = rcd.left, rc.right = rcd.right;
-    if (static_cast<int>(mode) & static_cast<int>(WindowPosition::Mode_V))
-      rc.top = rcd.top, rc.bottom = rcd.bottom;
-    
-    asyncMoveWindow(hwnd, rc.left, rc.top, rcWidth(&rc), rcHeight(&rc));
-  }
-}
-
-// maximize window horizontally
-void Engine::funcWindowHMaximize(FunctionParam *i_param,
-                                TargetWindowType i_twt)
-{
-  funcWindowHVMaximize(i_param, BooleanType_true, i_twt);
-}
-
-// maximize window virtically
-void Engine::funcWindowVMaximize(FunctionParam *i_param,
-                                TargetWindowType i_twt)
-{
-  funcWindowHVMaximize(i_param, BooleanType_false, i_twt);
-}
-
-// move window
-void Engine::funcWindowMove(FunctionParam *i_param, int i_dx, int i_dy,
-                           TargetWindowType i_twt)
-{
-  funcWindowMoveTo(i_param, GravityType_C, i_dx, i_dy, i_twt);
-}
-
-// move window to ...
-void Engine::funcWindowMoveTo(FunctionParam *i_param,
-                             GravityType i_gravityType,
-                             int i_dx, int i_dy, TargetWindowType i_twt)
-{
-  HWND hwnd;
-  RECT rc, rcd;
-  if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt, &rc, &rcd))
-    return;
-  
-  int x = rc.left + i_dx;
-  int y = rc.top + i_dy;
-
-  if (i_gravityType & GravityType_N)
-    y = i_dy + rcd.top;
-  if (i_gravityType & GravityType_E)
-    x = i_dx + rcd.right - rcWidth(&rc);
-  if (i_gravityType & GravityType_W)
-    x = i_dx + rcd.left;
-  if (i_gravityType & GravityType_S)
-    y = i_dy + rcd.bottom - rcHeight(&rc);
-  asyncMoveWindow(hwnd, x, y);
-}
-
-
-// move window visibly
-void Engine::funcWindowMoveVisibly(FunctionParam *i_param,
-                                  TargetWindowType i_twt)
-{
-  HWND hwnd;
-  RECT rc, rcd;
-  if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt, &rc, &rcd))
-    return;
-
-  int x = rc.left;
-  int y = rc.top;
-  if (rc.left < rcd.left)
-    x = rcd.left;
-  else if (rcd.right < rc.right)
-    x = rcd.right - rcWidth(&rc);
-  if (rc.top < rcd.top)
-    y = rcd.top;
-  else if (rcd.bottom < rc.bottom)
-    y = rcd.bottom - rcHeight(&rc);
-  asyncMoveWindow(hwnd, x, y);
-}
-
-
-struct EnumDisplayMonitorsForWindowMonitorToParam
-{
-  std::vector<HMONITOR> m_monitors;
-  std::vector<MONITORINFO> m_monitorinfos;
-  int m_primaryMonitorIdx;
-  int m_currentMonitorIdx;
-
-  HMONITOR m_hmon;
-
-public:
-  EnumDisplayMonitorsForWindowMonitorToParam(HMONITOR i_hmon)
-    : m_hmon(i_hmon),
-      m_primaryMonitorIdx(-1), m_currentMonitorIdx(-1)
-  {
-  }
-};
-
-static BOOL CALLBACK enumDisplayMonitorsForWindowMonitorTo(
-  HMONITOR i_hmon, HDC i_hdc, LPRECT i_rcMonitor, LPARAM i_data)
-{
-  EnumDisplayMonitorsForWindowMonitorToParam &ep =
-    *reinterpret_cast<EnumDisplayMonitorsForWindowMonitorToParam *>(i_data);
-
-  ep.m_monitors.push_back(i_hmon);
-
-  MONITORINFO mi;
-  mi.cbSize = sizeof(mi);
-  getMonitorInfo(i_hmon, &mi);
-  ep.m_monitorinfos.push_back(mi);
-
-  if(mi.dwFlags & MONITORINFOF_PRIMARY)
-    ep.m_primaryMonitorIdx = ep.m_monitors.size() - 1;
-  if(i_hmon == ep.m_hmon)
-    ep.m_currentMonitorIdx = ep.m_monitors.size() - 1;
-
-  return TRUE;
-}
-
-/// move window to other monitor
-void Engine::funcWindowMonitorTo(
-    FunctionParam *i_param, WindowMonitorFromType i_fromType, int i_monitor,
-    BooleanType i_adjustPos, BooleanType i_adjustSize)
-{
-  HWND hwnd;
-  if(! getSuitableWindow(i_param, &hwnd))
-    return;
-
-  HMONITOR hmonCur;
-  hmonCur = monitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
-
-  EnumDisplayMonitorsForWindowMonitorToParam ep(hmonCur);
-  enumDisplayMonitors(NULL, NULL, enumDisplayMonitorsForWindowMonitorTo,
-                      reinterpret_cast<LPARAM>(&ep));
-  if(ep.m_monitors.size() < 1 ||
-     ep.m_primaryMonitorIdx < 0 || ep.m_currentMonitorIdx < 0)
-    return;
-
-  int targetIdx;
-  switch(i_fromType) {
-  case WindowMonitorFromType_primary:
-    targetIdx = (ep.m_primaryMonitorIdx + i_monitor) % ep.m_monitors.size();
-    break;
-
-  case WindowMonitorFromType_current:
-    targetIdx = (ep.m_currentMonitorIdx + i_monitor) % ep.m_monitors.size();
-    break;
-  }
-  if(ep.m_currentMonitorIdx == targetIdx)
-    return;
-
-  RECT rcCur, rcTarget, rcWin;
-  rcCur = ep.m_monitorinfos[ep.m_currentMonitorIdx].rcWork;
-  rcTarget = ep.m_monitorinfos[targetIdx].rcWork;
-  GetWindowRect(hwnd, &rcWin);
-
-  int x = rcTarget.left + (rcWin.left - rcCur.left);
-  int y = rcTarget.top + (rcWin.top - rcCur.top);
-  int w = rcWidth(&rcWin);
-  int h = rcHeight(&rcWin);
-
-  if(i_adjustPos) {
-    if(x + w > rcTarget.right)
-      x = rcTarget.right - w;
-    if(x < rcTarget.left)
-      x = rcTarget.left;
-    if(w > rcWidth(&rcTarget)) {
-      x = rcTarget.left;
-      w = rcWidth(&rcTarget);
-    }
-
-    if(y + h > rcTarget.bottom)
-      y = rcTarget.bottom - h;
-    if(y < rcTarget.top)
-      y = rcTarget.top;
-    if(h > rcHeight(&rcTarget)) {
-      y = rcTarget.top;
-      h = rcHeight(&rcTarget);
-    }
-  }
-
-  if(i_adjustPos && i_adjustSize) {
-    if(IsZoomed(hwnd))
-      PostMessage(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
-    asyncMoveWindow(hwnd, x, y, w, h);
-  } else {
-    asyncMoveWindow(hwnd, x, y);
-  }
-}
-
-/// move window to other monitor
-void Engine::funcWindowMonitor(
-    FunctionParam *i_param, int i_monitor,
-    BooleanType i_adjustPos, BooleanType i_adjustSize)
-{
-  funcWindowMonitorTo(i_param, WindowMonitorFromType_primary, i_monitor,
-                      i_adjustPos, i_adjustSize);
-}
-
-
-//
-void Engine::funcWindowClingToLeft(FunctionParam *i_param,
-                                  TargetWindowType i_twt)
-{
-  funcWindowMoveTo(i_param, GravityType_W, 0, 0, i_twt);
-}
-
-//
-void Engine::funcWindowClingToRight(FunctionParam *i_param,
-                                   TargetWindowType i_twt)
-{
-  funcWindowMoveTo(i_param, GravityType_E, 0, 0, i_twt);
-}
-
-//
-void Engine::funcWindowClingToTop(FunctionParam *i_param,
-                                 TargetWindowType i_twt)
-{
-  funcWindowMoveTo(i_param, GravityType_N, 0, 0, i_twt);
-}
-
-//
-void Engine::funcWindowClingToBottom(FunctionParam *i_param,
-                                    TargetWindowType i_twt)
-{
-  funcWindowMoveTo(i_param, GravityType_S, 0, 0, i_twt);
-}
-
-// close window
-void Engine::funcWindowClose(FunctionParam *i_param, TargetWindowType i_twt)
-{
-  HWND hwnd;
-  if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt))
-    return;
-  PostMessage(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0);
-}
-
-// toggle top-most flag of the window
-void Engine::funcWindowToggleTopMost(FunctionParam *i_param)
-{
-  HWND hwnd;
-  if (!getSuitableWindow(i_param, &hwnd))
-    return;
-  SetWindowPos(
-    hwnd,
-    (GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST) ?
-    HWND_NOTOPMOST : HWND_TOPMOST,
-    0, 0, 0, 0,
-    SWP_ASYNCWINDOWPOS | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOSIZE);
-}
-
-// identify the window
-void Engine::funcWindowIdentify(FunctionParam *i_param)
-{
-  if (!i_param->m_isPressed)
-    return;
-
-  _TCHAR className[GANA_MAX_ATOM_LENGTH];
-  bool ok = false;
-  if (GetClassName(i_param->m_hwnd, className, NUMBER_OF(className)))
-  {
-    if (_tcsicmp(className, _T("ConsoleWindowClass")) == 0)
-    {
-      _TCHAR titleName[1024];
-      if (GetWindowText(i_param->m_hwnd, titleName, NUMBER_OF(titleName)) == 0)
-       titleName[0] = _T('\0');
-      {
-       Acquire a(&m_log, 1);
-       m_log << _T("HWND:\t") << std::hex
-             << reinterpret_cast<int>(i_param->m_hwnd)
-             << std::dec << std::endl;
-      }
-      Acquire a(&m_log, 0);
-      m_log << _T("CLASS:\t") << className << std::endl;
-      m_log << _T("TITLE:\t") << titleName << std::endl;
-
-      HWND hwnd = getToplevelWindow(i_param->m_hwnd, NULL);
-      RECT rc;
-      GetWindowRect(hwnd, &rc);
-      m_log << _T("Toplevel Window Position/Size: (")
-           << rc.left << _T(", ") << rc.top << _T(") / (")
-           << rcWidth(&rc) << _T("x") << rcHeight(&rc)
-           << _T(")") << std::endl;
-      
-      SystemParametersInfo(SPI_GETWORKAREA, 0, (void *)&rc, FALSE);
-      m_log << _T("Desktop Window Position/Size: (")
-           << rc.left << _T(", ") << rc.top << _T(") / (")
-           << rcWidth(&rc) << _T("x") << rcHeight(&rc)
-           << _T(")") << std::endl;
-
-      m_log << std::endl;
-      ok = true;
-    }
-  }
-  if (!ok)
-  {
-    UINT WM_MAYU_MESSAGE = RegisterWindowMessage(
-               addSessionId(WM_MAYU_MESSAGE_NAME).c_str());
-    CHECK_TRUE( PostMessage(i_param->m_hwnd, WM_MAYU_MESSAGE,
-                           MayuMessage_notifyName, 0) );
-  }
-}
-
-// set alpha blending parameter to the window
-void Engine::funcWindowSetAlpha(FunctionParam *i_param, int i_alpha)
-{
-#if defined(_WINNT)
-  HWND hwnd;
-  if (!getSuitableWindow(i_param, &hwnd))
-    return;
-  
-  if (i_alpha < 0)     // remove all alpha
-  {
-    for (WindowsWithAlpha::iterator i = m_windowsWithAlpha.begin(); 
-        i != m_windowsWithAlpha.end(); ++ i)
-    {
-      SetWindowLong(*i, GWL_EXSTYLE,
-                   GetWindowLong(*i, GWL_EXSTYLE) & ~WS_EX_LAYERED);
-      RedrawWindow(*i, NULL, NULL,
-                  RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);
-    }
-    m_windowsWithAlpha.clear();
-  }
-  else
-  {
-    LONG exStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
-    if (exStyle & WS_EX_LAYERED)       // remove alpha
-    {
-      WindowsWithAlpha::iterator
-       i = std::find(m_windowsWithAlpha.begin(), m_windowsWithAlpha.end(),
-                     hwnd);
-      if (i == m_windowsWithAlpha.end())
-       return; // already layered by the application
-    
-      m_windowsWithAlpha.erase(i);
-    
-      SetWindowLong(hwnd, GWL_EXSTYLE, exStyle & ~WS_EX_LAYERED);
-    }
-    else       // add alpha
-    {
-      SetWindowLong(hwnd, GWL_EXSTYLE, exStyle | WS_EX_LAYERED);
-      i_alpha %= 101;
-      if (!setLayeredWindowAttributes(hwnd, 0,
-                                     (BYTE)(255 * i_alpha / 100), LWA_ALPHA))
-      {
-       Acquire a(&m_log, 0);
-       m_log << _T("error: &WindowSetAlpha(") << i_alpha
-             << _T(") failed for HWND: ") << std::hex
-             << hwnd << std::dec << std::endl;
-       return;
-      }
-      m_windowsWithAlpha.push_front(hwnd);
-    }
-    RedrawWindow(hwnd, NULL, NULL,
-                RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);
-  }
-#endif // _WINNT
-}
-
-
-// redraw the window
-void Engine::funcWindowRedraw(FunctionParam *i_param)
-{
-  HWND hwnd;
-  if (!getSuitableWindow(i_param, &hwnd))
-    return;
-  RedrawWindow(hwnd, NULL, NULL,
-              RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);
-}
-
-// resize window to
-void Engine::funcWindowResizeTo(FunctionParam *i_param, int i_width,
-                               int i_height, TargetWindowType i_twt)
-{
-  HWND hwnd;
-  RECT rc, rcd;
-  if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt, &rc, &rcd))
-    return;
-  
-  if (i_width == 0)
-    i_width = rcWidth(&rc);
-  else if (i_width < 0)
-    i_width += rcWidth(&rcd);
-  
-  if (i_height == 0)
-    i_height = rcHeight(&rc);
-  else if (i_height < 0)
-    i_height += rcHeight(&rcd);
-  
-  asyncResize(hwnd, i_width, i_height);
-}
-
-// move the mouse cursor
-void Engine::funcMouseMove(FunctionParam *i_param, int i_dx, int i_dy)
-{
-  if (!i_param->m_isPressed)
-    return;
-  POINT pt;
-  GetCursorPos(&pt);
-  SetCursorPos(pt.x + i_dx, pt.y + i_dy);
-}
-
-// send a mouse-wheel-message to Windows
-void Engine::funcMouseWheel(FunctionParam *i_param, int i_delta)
-{
-  if (!i_param->m_isPressed)
-    return;
-  mouse_event(MOUSEEVENTF_WHEEL, 0, 0, i_delta, 0);
-}
-
-// convert the contents of the Clipboard to upper case
-void Engine::funcClipboardChangeCase(FunctionParam *i_param,
-                                    BooleanType i_doesConvertToUpperCase)
-{
-  if (!i_param->m_isPressed)
-    return;
-  
-  HGLOBAL hdata;
-  const _TCHAR *text = getTextFromClipboard(&hdata);
-  HGLOBAL hdataNew = NULL;
-  if (text)
-  {
-    int size = static_cast<int>(GlobalSize(hdata));
-    hdataNew = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, size);
-    if (hdataNew)
-    {
-      if (_TCHAR *dataNew = reinterpret_cast<_TCHAR *>(GlobalLock(hdataNew)))
-      {
-       std::memcpy(dataNew, text, size);
-       _TCHAR *dataEnd = dataNew + size;
-       while (dataNew < dataEnd && *dataNew)
-       {
-         _TCHAR c = *dataNew;
-         if (_istlead(c))
-           dataNew += 2;
-         else
-           *dataNew++ =
-             i_doesConvertToUpperCase ? _totupper(c) : _totlower(c);
-       }
-       GlobalUnlock(hdataNew);
-      }
-    }
-  }
-  closeClipboard(hdata, hdataNew);
-}
-
-// convert the contents of the Clipboard to upper case
-void Engine::funcClipboardUpcaseWord(FunctionParam *i_param)
-{
-  funcClipboardChangeCase(i_param, BooleanType_true);
-}
-
-// convert the contents of the Clipboard to lower case
-void Engine::funcClipboardDowncaseWord(FunctionParam *i_param)
-{
-  funcClipboardChangeCase(i_param, BooleanType_false);
-}
-
-// set the contents of the Clipboard to the string
-void Engine::funcClipboardCopy(FunctionParam *i_param, const StrExprArg &i_text)
-{
-  if (!i_param->m_isPressed)
-    return;
-  if (!OpenClipboard(NULL))
-    return;
-  
-  HGLOBAL hdataNew =
-    GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,
-               (i_text.eval().size() + 1) * sizeof(_TCHAR));
-  if (!hdataNew)
-    return;
-  _TCHAR *dataNew = reinterpret_cast<_TCHAR *>(GlobalLock(hdataNew));
-  _tcscpy(dataNew, i_text.eval().c_str());
-  GlobalUnlock(hdataNew);
-  closeClipboard(NULL, hdataNew);
-}
-
-//
-void Engine::funcEmacsEditKillLinePred(
-  FunctionParam *i_param, const KeySeq *i_keySeq1, const KeySeq *i_keySeq2)
-{
-  m_emacsEditKillLine.m_doForceReset = false;
-  if (!i_param->m_isPressed)
-    return;
-  
-  int r = m_emacsEditKillLine.pred();
-  const KeySeq *keySeq;
-  if (r == 1)
-    keySeq = i_keySeq1;
-  else if (r == 2)
-    keySeq = i_keySeq2;
-  else // r == 0
-    return;
-  ASSERT(keySeq);
-  generateKeySeqEvents(i_param->m_c, keySeq, Part_all);
-}
-
-//
-void Engine::funcEmacsEditKillLineFunc(FunctionParam *i_param)
-{
-  if (!i_param->m_isPressed)
-    return;
-  m_emacsEditKillLine.func();
-  m_emacsEditKillLine.m_doForceReset = false;
-}
-
-// clear log
-void Engine::funcLogClear(FunctionParam *i_param)
-{
-  if (!i_param->m_isPressed)
-    return;
-  PostMessage(getAssociatedWndow(), WM_APP_engineNotify,
-             EngineNotify_clearLog, 0);
-}
-
-// recenter
-void Engine::funcRecenter(FunctionParam *i_param)
-{
-  if (!i_param->m_isPressed)
-    return;
-  if (m_hwndFocus)
-  {
-    UINT WM_MAYU_MESSAGE = RegisterWindowMessage(
-               addSessionId(WM_MAYU_MESSAGE_NAME).c_str());
-    PostMessage(m_hwndFocus, WM_MAYU_MESSAGE, MayuMessage_funcRecenter, 0);
-  }
-}
-
-// set IME open status
-void Engine::funcSetImeStatus(FunctionParam *i_param, ToggleType i_toggle)
-{
-  if (!i_param->m_isPressed)
-    return;
-  if (m_hwndFocus)
-  {
-    UINT WM_MAYU_MESSAGE = RegisterWindowMessage(
-               addSessionId(WM_MAYU_MESSAGE_NAME).c_str());
-    int status = -1;
-    switch (i_toggle)
-    {
-      case ToggleType_toggle:
-       status = -1;
-       break;
-      case ToggleType_off:
-       status = 0;
-       break;
-      case ToggleType_on:
-       status = 1;
-       break;
-    }
-    PostMessage(m_hwndFocus, WM_MAYU_MESSAGE, MayuMessage_funcSetImeStatus, status);
-  }
-}
-
-// set IME open status
-void Engine::funcSetImeString(FunctionParam *i_param, const StrExprArg &i_data)
-{
-#if defined(_WINNT)
-  if (!i_param->m_isPressed)
-    return;
-  if (m_hwndFocus)
-  {
-    UINT WM_MAYU_MESSAGE = RegisterWindowMessage(
-               addSessionId(WM_MAYU_MESSAGE_NAME).c_str());
-    PostMessage(m_hwndFocus, WM_MAYU_MESSAGE, MayuMessage_funcSetImeString, i_data.eval().size() * sizeof(_TCHAR));
-
-    DWORD len = 0;
-    DWORD error;
-    DisconnectNamedPipe(m_hookPipe);
-    ConnectNamedPipe(m_hookPipe, NULL);
-    error = WriteFile(m_hookPipe, i_data.eval().c_str(),
-                     i_data.eval().size() * sizeof(_TCHAR),
-                     &len, NULL);
-
-    //FlushFileBuffers(m_hookPipe);
-  }
-#else
-  Acquire a(&m_log);
-  m_log << _T("supported on only Windows NT/2000/XP") << std::endl;
-#endif
-}
-
-// Direct SSTP Server
-class DirectSSTPServer
-{
-public:
-  tstring m_path;
-  HWND m_hwnd;
-  tstring m_name;
-  tstring m_keroname;
-
-public:
-  DirectSSTPServer()
-    : m_hwnd(NULL)
-  {
-  }
-};
-
-
-class ParseDirectSSTPData
-{
-  typedef boost::match_results<boost::regex::const_iterator> MR;
-
-public:
-  typedef std::map<tstring, DirectSSTPServer> DirectSSTPServers;
-
-private:
-  DirectSSTPServers *m_directSSTPServers;
-  
-public:
-  // constructor
-  ParseDirectSSTPData(DirectSSTPServers *i_directSSTPServers)
-    : m_directSSTPServers(i_directSSTPServers)
-  {
-  }
-  
-  bool operator()(const MR& i_what)
-  {
-#ifdef _UNICODE
-    tstring id(to_wstring(std::string(i_what[1].first, i_what[1].second)));
-    tstring member(to_wstring(std::string(i_what[2].first, i_what[2].second)));
-    tstring value(to_wstring(std::string(i_what[3].first, i_what[3].second)));
-#else
-    tstring id(i_what[1].first, i_what[1].second);
-    tstring member(i_what[2].first, i_what[2].second);
-    tstring value(i_what[3].first, i_what[3].second);
-#endif
-
-    if (member == _T("path"))
-      (*m_directSSTPServers)[id].m_path = value;
-    else if (member == _T("hwnd"))
-      (*m_directSSTPServers)[id].m_hwnd =
-       reinterpret_cast<HWND>(_ttoi(value.c_str()));
-    else if (member == _T("name"))
-      (*m_directSSTPServers)[id].m_name = value;
-    else if (member == _T("keroname"))
-      (*m_directSSTPServers)[id].m_keroname = value;
-    return true; 
-  }
-};
-
-// Direct SSTP
-void Engine::funcDirectSSTP(FunctionParam *i_param,
-                           const tregex &i_name,
-                           const StrExprArg &i_protocol,
-                           const std::list<tstringq> &i_headers)
-{
-  if (!i_param->m_isPressed)
-    return;
-
-  // check Direct SSTP server exist ?
-  if (HANDLE hm = OpenMutex(MUTEX_ALL_ACCESS, FALSE, _T("sakura")))
-    CloseHandle(hm);
-  else
-  {
-    Acquire a(&m_log, 0);
-    m_log << _T(" Error(1): Direct SSTP server does not exist.");
-    return;
-  }
-
-  HANDLE hfm = OpenFileMapping(FILE_MAP_READ, FALSE, _T("Sakura"));
-  if (!hfm)
-  {
-    Acquire a(&m_log, 0);
-    m_log << _T(" Error(2): Direct SSTP server does not provide data.");
-    return;
-  }
-  
-  char *data =
-    reinterpret_cast<char *>(MapViewOfFile(hfm, FILE_MAP_READ, 0, 0, 0));
-  if (!data)
-  {
-    CloseHandle(hfm);
-    Acquire a(&m_log, 0);
-    m_log << _T(" Error(3): Direct SSTP server does not provide data.");
-    return;
-  }
-  
-  long length = *(long *)data;
-  const char *begin = data + 4;
-  const char *end = data + length;
-  boost::regex getSakura("([0-9a-fA-F]{32})\\.([^\x01]+)\x01(.*?)\r\n");
-  
-  ParseDirectSSTPData::DirectSSTPServers servers;
-  boost::regex_iterator<boost::regex::const_iterator>
-    it(begin, end, getSakura), last;
-  for (; it != last; ++it)
-    ((ParseDirectSSTPData)(&servers))(*it);
-
-  // make request
-  tstring request;
-  if (!i_protocol.eval().size())
-    request += _T("NOTIFY SSTP/1.1");
-  else
-    request += i_protocol.eval();
-  request += _T("\r\n");
-
-  bool hasSender = false;
-  for (std::list<tstringq>::const_iterator
-        i = i_headers.begin(); i != i_headers.end(); ++ i)
-  {
-    if (_tcsnicmp(_T("Charset"), i->c_str(), 7) == 0 ||
-       _tcsnicmp(_T("Hwnd"),    i->c_str(), 4) == 0)
-      continue;
-    if (_tcsnicmp(_T("Sender"), i->c_str(), 6) == 0)
-      hasSender = true;
-    request += i->c_str();
-    request += _T("\r\n");
-  }
-
-  if (!hasSender)
-  {
-    request += _T("Sender: ");
-    request += loadString(IDS_mayu);
-    request += _T("\r\n");
-  }
-  
-  _TCHAR buf[100];
-  _sntprintf(buf, NUMBER_OF(buf), _T("HWnd: %d\r\n"),
-            reinterpret_cast<int>(m_hwndAssocWindow));
-  request += buf;
-
-#ifdef _UNICODE
-  request += _T("Charset: UTF-8\r\n");
-#else
-  request += _T("Charset: Shift_JIS\r\n");
-#endif
-  request += _T("\r\n");
-
-#ifdef _UNICODE
-  std::string request_UTF_8 = to_UTF_8(request);
-#endif
-
-  // send request to Direct SSTP Server which matches i_name;
-  for (ParseDirectSSTPData::DirectSSTPServers::iterator
-        i = servers.begin(); i != servers.end(); ++ i)
-  {
-    tsmatch what;
-    if (boost::regex_match(i->second.m_name, what, i_name))
-    {
-      COPYDATASTRUCT cd;
-      cd.dwData = 9801;
-#ifdef _UNICODE
-      cd.cbData = request_UTF_8.size();
-      cd.lpData = (void *)request_UTF_8.c_str();
-#else
-      cd.cbData = request.size();
-      cd.lpData = (void *)request.c_str();
-#endif
-      DWORD result;
-      SendMessageTimeout(i->second.m_hwnd, WM_COPYDATA,
-                        reinterpret_cast<WPARAM>(m_hwndAssocWindow),
-                        reinterpret_cast<LPARAM>(&cd),
-                        SMTO_ABORTIFHUNG | SMTO_BLOCK, 5000, &result);
-    }
-  }
-  
-  UnmapViewOfFile(data);
-  CloseHandle(hfm);
-}
-
-
-namespace shu
-{
-  class PlugIn
-  {
-    enum Type
-    {
-      Type_A,
-      Type_W
-    };
-    
-  private:
-    HMODULE m_dll;
-    FARPROC m_func;
-    Type m_type;
-    tstringq m_funcParam;
-    
-  public:
-    PlugIn() : m_dll(NULL)
-    {
-    }
-    
-    ~PlugIn()
-    {
-      FreeLibrary(m_dll);
-    }
-
-    bool load(const tstringq &i_dllName, const tstringq &i_funcName,
-             const tstringq &i_funcParam, tomsgstream &i_log)
-    {
-      m_dll = LoadLibrary((_T("Plugins\\") + i_dllName).c_str());
-      if (!m_dll)
-      {
-       m_dll = LoadLibrary((_T("Plugin\\") + i_dllName).c_str());
-       if (!m_dll)
-       {
-         m_dll = LoadLibrary(i_dllName.c_str());
-         if (!m_dll)
-         {
-           Acquire a(&i_log);
-           i_log << std::endl;
-           i_log << _T("error: &PlugIn() failed to load ") << i_dllName << std::endl;
-           return false;
-         }
-       }
-      }
-
-      // get function
-#ifdef UNICODE
-#  define to_wstring
-#else
-#  define to_string
-#endif
-      m_type = Type_W;
-      m_func = GetProcAddress(m_dll, to_string(_T("mayu") + i_funcName + _T("W")).c_str());
-      if (!m_func)
-      {
-       m_type = Type_A;
-       m_func
-         = GetProcAddress(m_dll, to_string(_T("mayu") + i_funcName + _T("A")).c_str());
-       if (!m_func)
-       {
-         m_func = GetProcAddress(m_dll, to_string(_T("mayu") + i_funcName).c_str());
-         if (!m_func)
-         {
-           m_func = GetProcAddress(m_dll, to_string(i_funcName).c_str());
-           if (!m_func)
-           {
-             Acquire a(&i_log);
-             i_log << std::endl;
-             i_log << _T("error: &PlugIn() failed to find function: ")
-                   << i_funcName << std::endl;
-             return false;
-           }
-         }
-       }
-      }
-      
-      m_funcParam = i_funcParam;
-      return true;
-    }
-
-    void exec()
-    {
-      ASSERT( m_dll );
-      ASSERT( m_func );
-      
-      typedef void (WINAPI * PLUGIN_FUNCTION_A)(const char *i_arg);
-      typedef void (WINAPI * PLUGIN_FUNCTION_W)(const wchar_t *i_arg);
-      switch (m_type)
-      {
-       case Type_A:
-         reinterpret_cast<PLUGIN_FUNCTION_A>(m_func)(to_string(m_funcParam).c_str());
-         break;
-       case Type_W:
-         reinterpret_cast<PLUGIN_FUNCTION_W>(m_func)(to_wstring(m_funcParam).c_str());
-         break;
-      }
-    }
-#undef to_string
-#undef to_wstring
-  };
-
-  static void plugInThread(void *i_plugin)
-  {
-    PlugIn *plugin = static_cast<PlugIn *>(i_plugin);
-    plugin->exec();
-    delete plugin;
-  }
-}
-
-void Engine::funcPlugIn(FunctionParam *i_param,
-                       const StrExprArg &i_dllName,
-                       const StrExprArg &i_funcName,
-                       const StrExprArg &i_funcParam,
-                       BooleanType i_doesCreateThread)
-{
-  if (!i_param->m_isPressed)
-    return;
-
-  shu::PlugIn *plugin = new shu::PlugIn();
-  if (!plugin->load(i_dllName.eval(), i_funcName.eval(), i_funcParam.eval(), m_log))
-  {
-    delete plugin;
-    return;
-  }
-  if (i_doesCreateThread)
-  {
-    if (_beginthread(shu::plugInThread, 0, plugin) == -1)
-    {
-      delete plugin;
-      Acquire a(&m_log);
-      m_log << std::endl;
-      m_log << _T("error: &PlugIn() failed to create thread.");
-    }
-    return;
-  }
-  else
-    plugin->exec();
-}
-
-
-void Engine::funcMouseHook(FunctionParam *i_param,
-                          MouseHookType i_hookType, int i_hookParam)
-{
-  GetCursorPos(&g_hookData->m_mousePos);
-  g_hookData->m_mouseHookType = i_hookType;
-  g_hookData->m_mouseHookParam = i_hookParam;
-
-  switch (i_hookType)
-  {
-    case MouseHookType_WindowMove:
-    {
-      // For this type, g_hookData->m_mouseHookParam means
-      // target window type to move.
-      HWND target;
-      bool isMDI;
-
-      // i_hooParam < 0 means target window to move is MDI.
-      if (i_hookParam < 0)
-       isMDI = true;
-      else
-       isMDI = false;
-
-      // abs(i_hookParam) == 2: target is window under mouse cursor
-      // otherwise: target is current focus window
-      if (i_hookParam == 2 || i_hookParam == -2)
-       target = WindowFromPoint(g_hookData->m_mousePos);
-      else
-       target = i_param->m_hwnd;
-
-      g_hookData->m_hwndMouseHookTarget =
-       getToplevelWindow(target, &isMDI);
-      break;
-    default:
-      g_hookData->m_hwndMouseHookTarget = NULL;
-      break;
-    }
-  }
-  return;
-}
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// StrExpr
-class StrExpr
-{
-private:
-  tstringq m_symbol;
-protected:
-  static const Engine *s_engine;
-public:
-  StrExpr(const tstringq &i_symbol) : m_symbol(i_symbol) {};
-
-  virtual ~StrExpr() {};
-
-  virtual StrExpr *clone() const
-  {
-    return new StrExpr(*this);
-  }
-
-  virtual tstringq eval() const
-  {
-    return m_symbol;
-  }
-
-  static void setEngine(const Engine *i_engine) { s_engine = i_engine; }
-};
-
-const Engine *StrExpr::s_engine = NULL;
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// StrExprClipboard
-class StrExprClipboard : public StrExpr
-{
-public:
-  StrExprClipboard(const tstringq &i_symbol) : StrExpr(i_symbol) {};
-
-  ~StrExprClipboard() {};
-
-  StrExpr *clone() const
-  {
-    return new StrExprClipboard(*this);
-  }
-
-  tstringq eval() const
-  {
-    HGLOBAL g;
-    const _TCHAR *text = getTextFromClipboard(&g);
-    const tstring value(text == NULL ? _T("") : text);
-    closeClipboard(g);
-    return value;
-  }
-};
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// StrExprWindowClassName
-class StrExprWindowClassName : public StrExpr
-{
-public:
-  StrExprWindowClassName(const tstringq &i_symbol) : StrExpr(i_symbol) {};
-
-  ~StrExprWindowClassName() {};
-
-  StrExpr *clone() const
-  {
-    return new StrExprWindowClassName(*this);
-  }
-
-  tstringq eval() const
-  {
-    return s_engine->getCurrentWindowClassName();
-  }
-};
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// StrExprWindowTitleName
-class StrExprWindowTitleName : public StrExpr
-{
-public:
-  StrExprWindowTitleName(const tstringq &i_symbol) : StrExpr(i_symbol) {};
-
-  ~StrExprWindowTitleName() {};
-
-  StrExpr *clone() const
-  {
-    return new StrExprWindowTitleName(*this);
-  }
-
-  tstringq eval() const
-  {
-    return s_engine->getCurrentWindowTitleName();
-  }
-};
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// StrExprArg
-
-
-// default constructor
-StrExprArg::StrExprArg()
-{
-  m_expr = new StrExpr(_T(""));
-}
-
-
-// copy contructor
-StrExprArg::StrExprArg(const StrExprArg &i_data)
-{
-  m_expr = i_data.m_expr->clone();
-}
-
-
-StrExprArg &StrExprArg::operator=(const StrExprArg &i_data)
-{
-  if (i_data.m_expr == m_expr)
-    return *this;
-
-  delete m_expr;
-  m_expr = i_data.m_expr->clone();
-
-  return *this;
-}
-
-
-// initializer
-StrExprArg::StrExprArg(const tstringq &i_symbol, Type i_type)
-{
-  switch (i_type)
-  {
-    case Literal:
-      m_expr = new StrExpr(i_symbol);
-      break;
-    case Builtin:
-      if (i_symbol == _T("Clipboard"))
-       m_expr = new StrExprClipboard(i_symbol);
-      else if (i_symbol == _T("WindowClassName"))
-       m_expr = new StrExprWindowClassName(i_symbol);
-      else if (i_symbol == _T("WindowTitleName"))
-       m_expr = new StrExprWindowTitleName(i_symbol);
-      break;
-    default:
-      break;
-  }
-}
-
-
-StrExprArg::~StrExprArg()
-{
-  delete m_expr;
-}
-
-
-tstringq StrExprArg::eval() const
-{
-  return m_expr->eval();
-}
-
-void StrExprArg::setEngine(const Engine *i_engine)
-{
-  StrExpr::setEngine(i_engine);
-}
-
-// stream output
-tostream &operator<<(tostream &i_ost, const StrExprArg &i_data)
-{
-  i_ost << i_data.eval();
-  return i_ost;
-}
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// function.cpp\r
+\r
+\r
+#include "engine.h"\r
+#include "hook.h"\r
+#include "mayu.h"\r
+#include "mayurc.h"\r
+#include "misc.h"\r
+#include "registry.h"\r
+#include "vkeytable.h"\r
+#include "windowstool.h"\r
+#include <algorithm>\r
+#include <process.h>\r
+\r
+#define FUNCTION_DATA\r
+#include "functions.h"\r
+#undef FUNCTION_DATA\r
+\r
+\r
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// TypeTable\r
+\r
+\r
+template <class T> class TypeTable\r
+{\r
+public:\r
+       T m_type;\r
+       const _TCHAR *m_name;\r
+};\r
+\r
+\r
+template <class T> static inline\r
+bool getTypeName(tstring *o_name, T i_type,\r
+                                const TypeTable<T> *i_table, size_t i_n)\r
+{\r
+       for (size_t i = 0; i < i_n; ++ i)\r
+               if (i_table[i].m_type == i_type) {\r
+                       *o_name = i_table[i].m_name;\r
+                       return true;\r
+               }\r
+       return false;\r
+}\r
+\r
+template <class T> static inline\r
+bool getTypeValue(T *o_type, const tstringi &i_name,\r
+                                 const TypeTable<T> *i_table, size_t i_n)\r
+{\r
+       for (size_t i = 0; i < i_n; ++ i)\r
+               if (i_table[i].m_name == i_name) {\r
+                       *o_type = i_table[i].m_type;\r
+                       return true;\r
+               }\r
+       return false;\r
+}\r
+\r
+\r
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// VKey\r
+\r
+\r
+// stream output\r
+tostream &operator<<(tostream &i_ost, VKey i_data)\r
+{\r
+       if (i_data & VKey_extended)\r
+               i_ost << _T("E-");\r
+       if (i_data & VKey_released)\r
+               i_ost << _T("U-");\r
+       if (i_data & VKey_pressed)\r
+               i_ost << _T("D-");\r
+\r
+       u_int8 code = i_data & ~(VKey_extended | VKey_released | VKey_pressed);\r
+       const VKeyTable *vkt;\r
+       for (vkt = g_vkeyTable; vkt->m_name; ++ vkt)\r
+               if (vkt->m_code == code)\r
+                       break;\r
+       if (vkt->m_name)\r
+               i_ost << vkt->m_name;\r
+       else\r
+               i_ost << _T("0x") << std::hex << code << std::dec;\r
+       return i_ost;\r
+}\r
+\r
+\r
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// ToWindowType\r
+\r
+\r
+// ToWindowType table\r
+typedef TypeTable<ToWindowType> TypeTable_ToWindowType;\r
+static const TypeTable_ToWindowType g_toWindowTypeTable[] = {\r
+       { ToWindowType_toOverlappedWindow, _T("toOverlappedWindow") },\r
+       { ToWindowType_toMainWindow,       _T("toMainWindow")       },\r
+       { ToWindowType_toItself,           _T("toItself")           },\r
+       { ToWindowType_toParentWindow,     _T("toParentWindow")     },\r
+};\r
+\r
+\r
+// stream output\r
+tostream &operator<<(tostream &i_ost, ToWindowType i_data)\r
+{\r
+       tstring name;\r
+       if (getTypeName(&name, i_data,\r
+                                       g_toWindowTypeTable, NUMBER_OF(g_toWindowTypeTable)))\r
+               i_ost << name;\r
+       else\r
+               i_ost << static_cast<int>(i_data);\r
+       return i_ost;\r
+}\r
+\r
+\r
+// get value of ToWindowType\r
+bool getTypeValue(ToWindowType *o_type, const tstring &i_name)\r
+{\r
+       return getTypeValue(o_type, i_name,\r
+                                               g_toWindowTypeTable, NUMBER_OF(g_toWindowTypeTable));\r
+}\r
+\r
+\r
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// GravityType\r
+\r
+\r
+// GravityType table\r
+typedef TypeTable<GravityType> TypeTable_GravityType;\r
+static const TypeTable_GravityType g_gravityTypeTable[] = {\r
+       { GravityType_C,  _T("C")  },\r
+       { GravityType_N,  _T("N")  },\r
+       { GravityType_E,  _T("E")  },\r
+       { GravityType_W,  _T("W")  },\r
+       { GravityType_S,  _T("S")  },\r
+       { GravityType_NW, _T("NW") },\r
+       { GravityType_NW, _T("WN") },\r
+       { GravityType_NE, _T("NE") },\r
+       { GravityType_NE, _T("EN") },\r
+       { GravityType_SW, _T("SW") },\r
+       { GravityType_SW, _T("WS") },\r
+       { GravityType_SE, _T("SE") },\r
+       { GravityType_SE, _T("ES") },\r
+};\r
+\r
+\r
+// stream output\r
+tostream &operator<<(tostream &i_ost, GravityType i_data)\r
+{\r
+       tstring name;\r
+       if (getTypeName(&name, i_data,\r
+                                       g_gravityTypeTable, NUMBER_OF(g_gravityTypeTable)))\r
+               i_ost << name;\r
+       else\r
+               i_ost << _T("(GravityType internal error)");\r
+       return i_ost;\r
+}\r
+\r
+\r
+// get value of GravityType\r
+bool getTypeValue(GravityType *o_type, const tstring &i_name)\r
+{\r
+       return getTypeValue(o_type, i_name,\r
+                                               g_gravityTypeTable, NUMBER_OF(g_gravityTypeTable));\r
+}\r
+\r
+\r
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// MouseHookType\r
+\r
+\r
+// MouseHookType table\r
+typedef TypeTable<MouseHookType> TypeTable_MouseHookType;\r
+static const TypeTable_MouseHookType g_mouseHookTypeTable[] = {\r
+       { MouseHookType_None,  _T("None")  },\r
+       { MouseHookType_Wheel,  _T("Wheel")  },\r
+       { MouseHookType_WindowMove,  _T("WindowMove")  },\r
+};\r
+\r
+\r
+// stream output\r
+tostream &operator<<(tostream &i_ost, MouseHookType i_data)\r
+{\r
+       tstring name;\r
+       if (getTypeName(&name, i_data,\r
+                                       g_mouseHookTypeTable, NUMBER_OF(g_mouseHookTypeTable)))\r
+               i_ost << name;\r
+       else\r
+               i_ost << _T("(MouseHookType internal error)");\r
+       return i_ost;\r
+}\r
+\r
+\r
+// get value of MouseHookType\r
+bool getTypeValue(MouseHookType *o_type, const tstring &i_name)\r
+{\r
+       return getTypeValue(o_type, i_name, g_mouseHookTypeTable,\r
+                                               NUMBER_OF(g_mouseHookTypeTable));\r
+}\r
+\r
+\r
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// MayuDialogType\r
+\r
+\r
+// ModifierLockType table\r
+typedef TypeTable<MayuDialogType> TypeTable_MayuDialogType;\r
+static const TypeTable_MayuDialogType g_mayuDialogTypeTable[] = {\r
+       { MayuDialogType_investigate, _T("investigate")  },\r
+       { MayuDialogType_log,         _T("log")          },\r
+};\r
+\r
+\r
+// stream output\r
+tostream &operator<<(tostream &i_ost, MayuDialogType i_data)\r
+{\r
+       tstring name;\r
+       if (getTypeName(&name, i_data,\r
+                                       g_mayuDialogTypeTable, NUMBER_OF(g_mayuDialogTypeTable)))\r
+               i_ost << name;\r
+       else\r
+               i_ost << _T("(MayuDialogType internal error)");\r
+       return i_ost;\r
+}\r
+\r
+\r
+// get value of MayuDialogType\r
+bool getTypeValue(MayuDialogType *o_type, const tstring &i_name)\r
+{\r
+       return getTypeValue(o_type, i_name, g_mayuDialogTypeTable,\r
+                                               NUMBER_OF(g_mayuDialogTypeTable));\r
+}\r
+\r
+\r
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// ToggleType\r
+\r
+\r
+// ToggleType table\r
+typedef TypeTable<ToggleType> TypeTable_ToggleType;\r
+static const TypeTable_ToggleType g_toggleType[] = {\r
+       { ToggleType_toggle, _T("toggle") },\r
+       { ToggleType_off, _T("off") },\r
+       { ToggleType_off, _T("false") },\r
+       { ToggleType_off, _T("released") },\r
+       { ToggleType_on,  _T("on")  },\r
+       { ToggleType_on,  _T("true")  },\r
+       { ToggleType_on,  _T("pressed")  },\r
+};\r
+\r
+\r
+// stream output\r
+tostream &operator<<(tostream &i_ost, ToggleType i_data)\r
+{\r
+       tstring name;\r
+       if (getTypeName(&name, i_data, g_toggleType, NUMBER_OF(g_toggleType)))\r
+               i_ost << name;\r
+       else\r
+               i_ost << _T("(ToggleType internal error)");\r
+       return i_ost;\r
+}\r
+\r
+\r
+// get value of ToggleType\r
+bool getTypeValue(ToggleType *o_type, const tstring &i_name)\r
+{\r
+       return getTypeValue(o_type, i_name, g_toggleType,\r
+                                               NUMBER_OF(g_toggleType));\r
+}\r
+\r
+\r
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// ModifierLockType\r
+\r
+\r
+// ModifierLockType table\r
+typedef TypeTable<ModifierLockType> TypeTable_ModifierLockType;\r
+static const TypeTable_ModifierLockType g_modifierLockTypeTable[] = {\r
+       { ModifierLockType_Lock0, _T("lock0") },\r
+       { ModifierLockType_Lock1, _T("lock1") },\r
+       { ModifierLockType_Lock2, _T("lock2") },\r
+       { ModifierLockType_Lock3, _T("lock3") },\r
+       { ModifierLockType_Lock4, _T("lock4") },\r
+       { ModifierLockType_Lock5, _T("lock5") },\r
+       { ModifierLockType_Lock6, _T("lock6") },\r
+       { ModifierLockType_Lock7, _T("lock7") },\r
+       { ModifierLockType_Lock8, _T("lock8") },\r
+       { ModifierLockType_Lock9, _T("lock9") },\r
+};\r
+\r
+\r
+// stream output\r
+tostream &operator<<(tostream &i_ost, ModifierLockType i_data)\r
+{\r
+       tstring name;\r
+       if (getTypeName(&name, i_data,\r
+                                       g_modifierLockTypeTable, NUMBER_OF(g_modifierLockTypeTable)))\r
+               i_ost << name;\r
+       else\r
+               i_ost << _T("(ModifierLockType internal error)");\r
+       return i_ost;\r
+}\r
+\r
+\r
+// get value of ModifierLockType\r
+bool getTypeValue(ModifierLockType *o_type, const tstring &i_name)\r
+{\r
+       return getTypeValue(o_type, i_name, g_modifierLockTypeTable,\r
+                                               NUMBER_OF(g_modifierLockTypeTable));\r
+}\r
+\r
+\r
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// ShowCommandType\r
+\r
+\r
+// ShowCommandType table\r
+typedef TypeTable<ShowCommandType> TypeTable_ShowCommandType;\r
+static const TypeTable_ShowCommandType g_showCommandTypeTable[] = {\r
+       { ShowCommandType_hide,            _T("hide")            },\r
+       { ShowCommandType_maximize,        _T("maximize")        },\r
+       { ShowCommandType_minimize,        _T("minimize")        },\r
+       { ShowCommandType_restore,         _T("restore")         },\r
+       { ShowCommandType_show,            _T("show")            },\r
+       { ShowCommandType_showDefault,     _T("showDefault")     },\r
+       { ShowCommandType_showMaximized,   _T("showMaximized")   },\r
+       { ShowCommandType_showMinimized,   _T("showMinimized")   },\r
+       { ShowCommandType_showMinNoActive, _T("showMinNoActive") },\r
+       { ShowCommandType_showNA,          _T("showNA")          },\r
+       { ShowCommandType_showNoActivate,  _T("showNoActivate")  },\r
+       { ShowCommandType_showNormal,      _T("showNormal")      },\r
+};\r
+\r
+\r
+// stream output\r
+tostream &operator<<(tostream &i_ost, ShowCommandType i_data)\r
+{\r
+       tstring name;\r
+       if (getTypeName(&name, i_data,\r
+                                       g_showCommandTypeTable, NUMBER_OF(g_showCommandTypeTable)))\r
+               i_ost << name;\r
+       else\r
+               i_ost << _T("(ShowCommandType internal error)");\r
+       return i_ost;\r
+}\r
+\r
+\r
+// get value of ShowCommandType\r
+bool getTypeValue(ShowCommandType *o_type, const tstring &i_name)\r
+{\r
+       return getTypeValue(o_type, i_name, g_showCommandTypeTable,\r
+                                               NUMBER_OF(g_showCommandTypeTable));\r
+}\r
+\r
+\r
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// TargetWindowType\r
+\r
+\r
+// ModifierLockType table\r
+typedef TypeTable<TargetWindowType> TypeTable_TargetWindowType;\r
+static const TypeTable_TargetWindowType g_targetWindowType[] = {\r
+       { TargetWindowType_overlapped, _T("overlapped") },\r
+       { TargetWindowType_mdi,        _T("mdi")        },\r
+};\r
+\r
+\r
+// stream output\r
+tostream &operator<<(tostream &i_ost, TargetWindowType i_data)\r
+{\r
+       tstring name;\r
+       if (getTypeName(&name, i_data,\r
+                                       g_targetWindowType, NUMBER_OF(g_targetWindowType)))\r
+               i_ost << name;\r
+       else\r
+               i_ost << _T("(TargetWindowType internal error)");\r
+       return i_ost;\r
+}\r
+\r
+\r
+// get value of TargetWindowType\r
+bool getTypeValue(TargetWindowType *o_type, const tstring &i_name)\r
+{\r
+       return getTypeValue(o_type, i_name, g_targetWindowType,\r
+                                               NUMBER_OF(g_targetWindowType));\r
+}\r
+\r
+\r
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// BooleanType\r
+\r
+\r
+// BooleanType table\r
+typedef TypeTable<BooleanType> TypeTable_BooleanType;\r
+static const TypeTable_BooleanType g_booleanType[] = {\r
+       { BooleanType_false, _T("false") },\r
+       { BooleanType_true,  _T("true")  },\r
+};\r
+\r
+\r
+// stream output\r
+tostream &operator<<(tostream &i_ost, BooleanType i_data)\r
+{\r
+       tstring name;\r
+       if (getTypeName(&name, i_data, g_booleanType, NUMBER_OF(g_booleanType)))\r
+               i_ost << name;\r
+       else\r
+               i_ost << _T("(BooleanType internal error)");\r
+       return i_ost;\r
+}\r
+\r
+\r
+// get value of BooleanType\r
+bool getTypeValue(BooleanType *o_type, const tstring &i_name)\r
+{\r
+       return getTypeValue(o_type, i_name, g_booleanType,\r
+                                               NUMBER_OF(g_booleanType));\r
+}\r
+\r
+\r
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// LogicalOperatorType\r
+\r
+\r
+// LogicalOperatorType table\r
+typedef TypeTable<LogicalOperatorType> TypeTable_LogicalOperatorType;\r
+static const TypeTable_LogicalOperatorType g_logicalOperatorType[] = {\r
+       { LogicalOperatorType_or, _T("||") },\r
+       { LogicalOperatorType_and,  _T("&&")  },\r
+};\r
+\r
+\r
+// stream output\r
+tostream &operator<<(tostream &i_ost, LogicalOperatorType i_data)\r
+{\r
+       tstring name;\r
+       if (getTypeName(&name, i_data, g_logicalOperatorType,\r
+                                       NUMBER_OF(g_logicalOperatorType)))\r
+               i_ost << name;\r
+       else\r
+               i_ost << _T("(LogicalOperatorType internal error)");\r
+       return i_ost;\r
+}\r
+\r
+\r
+// get value of LogicalOperatorType\r
+bool getTypeValue(LogicalOperatorType *o_type, const tstring &i_name)\r
+{\r
+       return getTypeValue(o_type, i_name, g_logicalOperatorType,\r
+                                               NUMBER_OF(g_logicalOperatorType));\r
+}\r
+\r
+\r
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// WindowMonitorFromType\r
+\r
+\r
+// WindowMonitorFromType table\r
+typedef TypeTable<WindowMonitorFromType> TypeTable_WindowMonitorFromType;\r
+static const TypeTable_WindowMonitorFromType g_windowMonitorFromType[] = {\r
+       { WindowMonitorFromType_primary, _T("primary") },\r
+       { WindowMonitorFromType_current, _T("current") },\r
+};\r
+\r
+\r
+// stream output\r
+tostream &operator<<(tostream &i_ost, WindowMonitorFromType i_data)\r
+{\r
+       tstring name;\r
+       if (getTypeName(&name, i_data, g_windowMonitorFromType,\r
+                                       NUMBER_OF(g_windowMonitorFromType)))\r
+               i_ost << name;\r
+       else\r
+               i_ost << _T("(WindowMonitorFromType internal error)");\r
+       return i_ost;\r
+}\r
+\r
+\r
+// get value of WindowMonitorFromType\r
+bool getTypeValue(WindowMonitorFromType *o_type, const tstring &i_name)\r
+{\r
+       return getTypeValue(o_type, i_name, g_windowMonitorFromType,\r
+                                               NUMBER_OF(g_windowMonitorFromType));\r
+}\r
+\r
+\r
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// std::list<tstringq>\r
+\r
+\r
+/// stream output\r
+tostream &operator<<(tostream &i_ost, const std::list<tstringq> &i_data)\r
+{\r
+       for (std::list<tstringq>::const_iterator\r
+                       i = i_data.begin(); i != i_data.end(); ++ i) {\r
+               i_ost << *i << _T(", ");\r
+       }\r
+       return i_ost;\r
+}\r
+\r
+\r
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// FunctionData\r
+\r
+\r
+//\r
+FunctionData::~FunctionData()\r
+{\r
+}\r
+\r
+\r
+// stream output\r
+tostream &operator<<(tostream &i_ost, const FunctionData *i_data)\r
+{\r
+       return i_data->output(i_ost);\r
+}\r
+\r
+\r
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// FunctionCreator\r
+\r
+\r
+///\r
+class FunctionCreator\r
+{\r
+public:\r
+       typedef FunctionData *(*Creator)();             ///\r
+\r
+public:\r
+       const _TCHAR *m_name;                           /// function name\r
+       Creator m_creator;                              /// function data creator\r
+};\r
+\r
+\r
+// create function\r
+FunctionData *createFunctionData(const tstring &i_name)\r
+{\r
+       static\r
+#define FUNCTION_CREATOR\r
+#include "functions.h"\r
+#undef FUNCTION_CREATOR\r
+       ;\r
+\r
+       for (size_t i = 0; i != NUMBER_OF(functionCreators); ++ i)\r
+               if (i_name == functionCreators[i].m_name)\r
+                       return functionCreators[i].m_creator();\r
+       return NULL;\r
+}\r
+\r
+\r
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// misc. functions\r
+\r
+\r
+//\r
+bool getSuitableWindow(FunctionParam *i_param, HWND *o_hwnd)\r
+{\r
+       if (!i_param->m_isPressed)\r
+               return false;\r
+       *o_hwnd = getToplevelWindow(i_param->m_hwnd, NULL);\r
+       if (!*o_hwnd)\r
+               return false;\r
+       return true;\r
+}\r
+\r
+//\r
+bool getSuitableMdiWindow(FunctionParam *i_param, HWND *o_hwnd,\r
+                                                 TargetWindowType *io_twt,\r
+                                                 RECT *o_rcWindow = NULL, RECT *o_rcParent = NULL)\r
+{\r
+       if (!i_param->m_isPressed)\r
+               return false;\r
+       bool isMdi = *io_twt == TargetWindowType_mdi;\r
+       *o_hwnd = getToplevelWindow(i_param->m_hwnd, &isMdi);\r
+       *io_twt = isMdi ? TargetWindowType_mdi : TargetWindowType_overlapped;\r
+       if (!*o_hwnd)\r
+               return false;\r
+       switch (*io_twt) {\r
+       case TargetWindowType_overlapped:\r
+               if (o_rcWindow)\r
+                       GetWindowRect(*o_hwnd, o_rcWindow);\r
+               if (o_rcParent) {\r
+                       HMONITOR hm = monitorFromWindow(i_param->m_hwnd,\r
+                                                                                       MONITOR_DEFAULTTONEAREST);\r
+                       MONITORINFO mi;\r
+                       mi.cbSize = sizeof(mi);\r
+                       getMonitorInfo(hm, &mi);\r
+                       *o_rcParent = mi.rcWork;\r
+               }\r
+               break;\r
+       case TargetWindowType_mdi:\r
+               if (o_rcWindow)\r
+                       getChildWindowRect(*o_hwnd, o_rcWindow);\r
+               if (o_rcParent)\r
+                       GetClientRect(GetParent(*o_hwnd), o_rcParent);\r
+               break;\r
+       }\r
+       return true;\r
+}\r
+\r
+// get clipboard text (you must call closeClopboard())\r
+static const _TCHAR *getTextFromClipboard(HGLOBAL *o_hdata)\r
+{\r
+       *o_hdata = NULL;\r
+\r
+       if (!OpenClipboard(NULL))\r
+               return NULL;\r
+\r
+#ifdef UNICODE\r
+       *o_hdata = GetClipboardData(CF_UNICODETEXT);\r
+#else\r
+       *o_hdata = GetClipboardData(CF_TEXT);\r
+#endif\r
+       if (!*o_hdata)\r
+               return NULL;\r
+\r
+       _TCHAR *data = reinterpret_cast<_TCHAR *>(GlobalLock(*o_hdata));\r
+       if (!data)\r
+               return NULL;\r
+       return data;\r
+}\r
+\r
+// close clipboard that opend by getTextFromClipboard()\r
+static void closeClipboard(HGLOBAL i_hdata, HGLOBAL i_hdataNew = NULL)\r
+{\r
+       if (i_hdata)\r
+               GlobalUnlock(i_hdata);\r
+       if (i_hdataNew) {\r
+               EmptyClipboard();\r
+#ifdef UNICODE\r
+               SetClipboardData(CF_UNICODETEXT, i_hdataNew);\r
+#else\r
+               SetClipboardData(CF_TEXT, i_hdataNew);\r
+#endif\r
+       }\r
+       CloseClipboard();\r
+}\r
+\r
+\r
+// EmacsEditKillLineFunc.\r
+// clear the contents of the clopboard\r
+// at that time, confirm if it is the result of the previous kill-line\r
+void Engine::EmacsEditKillLine::func()\r
+{\r
+       if (!m_buf.empty()) {\r
+               HGLOBAL g;\r
+               const _TCHAR *text = getTextFromClipboard(&g);\r
+               if (text == NULL || m_buf != text)\r
+                       reset();\r
+               closeClipboard(g);\r
+       }\r
+       if (OpenClipboard(NULL)) {\r
+               EmptyClipboard();\r
+               CloseClipboard();\r
+       }\r
+}\r
+\r
+\r
+/** if the text of the clipboard is\r
+@doc\r
+<pre>\r
+1: EDIT Control (at EOL C-K): ""            =&gt; buf + "\r\n", Delete\r
+0: EDIT Control (other  C-K): "(.+)"        =&gt; buf + "\1"\r
+0: IE FORM TEXTAREA (at EOL C-K): "\r\n"    =&gt; buf + "\r\n"\r
+2: IE FORM TEXTAREA (other C-K): "(.+)\r\n" =&gt; buf + "\1", Return Left\r
+^retval\r
+</pre>\r
+*/\r
+HGLOBAL Engine::EmacsEditKillLine::makeNewKillLineBuf(\r
+       const _TCHAR *i_data, int *o_retval)\r
+{\r
+       size_t len = m_buf.size();\r
+       len += _tcslen(i_data) + 3;\r
+\r
+       HGLOBAL hdata = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,\r
+                                                               len * sizeof(_TCHAR));\r
+       if (!hdata)\r
+               return NULL;\r
+       _TCHAR *dataNew = reinterpret_cast<_TCHAR *>(GlobalLock(hdata));\r
+       *dataNew = _T('\0');\r
+       if (!m_buf.empty())\r
+               _tcscpy(dataNew, m_buf.c_str());\r
+\r
+       len = _tcslen(i_data);\r
+       if (3 <= len &&\r
+                       i_data[len - 2] == _T('\r') && i_data[len - 1] == _T('\n')) {\r
+               _tcscat(dataNew, i_data);\r
+               len = _tcslen(dataNew);\r
+               dataNew[len - 2] = _T('\0'); // chomp\r
+               *o_retval = 2;\r
+       } else if (len == 0) {\r
+               _tcscat(dataNew, _T("\r\n"));\r
+               *o_retval = 1;\r
+       } else {\r
+               _tcscat(dataNew, i_data);\r
+               *o_retval = 0;\r
+       }\r
+\r
+       m_buf = dataNew;\r
+\r
+       GlobalUnlock(hdata);\r
+       return hdata;\r
+}\r
+\r
+\r
+// EmacsEditKillLinePred\r
+int Engine::EmacsEditKillLine::pred()\r
+{\r
+       HGLOBAL g;\r
+       const _TCHAR *text = getTextFromClipboard(&g);\r
+       int retval;\r
+       HGLOBAL hdata = makeNewKillLineBuf(text ? text : _T(""), &retval);\r
+       closeClipboard(g, hdata);\r
+       return retval;\r
+}\r
+\r
+\r
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// functions\r
+\r
+\r
+// send a default key to Windows\r
+void Engine::funcDefault(FunctionParam *i_param)\r
+{\r
+       {\r
+               Acquire a(&m_log, 1);\r
+               m_log << std::endl;\r
+               i_param->m_doesNeedEndl = false;\r
+       }\r
+       if (i_param->m_isPressed)\r
+               generateModifierEvents(i_param->m_c.m_mkey.m_modifier);\r
+       generateKeyEvent(i_param->m_c.m_mkey.m_key, i_param->m_isPressed, true);\r
+}\r
+\r
+// use a corresponding key of a parent keymap\r
+void Engine::funcKeymapParent(FunctionParam *i_param)\r
+{\r
+       Current c(i_param->m_c);\r
+       c.m_keymap = c.m_keymap->getParentKeymap();\r
+       if (!c.m_keymap) {\r
+               funcDefault(i_param);\r
+               return;\r
+       }\r
+\r
+       {\r
+               Acquire a(&m_log, 1);\r
+               m_log << _T("(") << c.m_keymap->getName() << _T(")") << std::endl;\r
+       }\r
+       i_param->m_doesNeedEndl = false;\r
+       generateKeyboardEvents(c);\r
+}\r
+\r
+// use a corresponding key of a current window\r
+void Engine::funcKeymapWindow(FunctionParam *i_param)\r
+{\r
+       Current c(i_param->m_c);\r
+       c.m_keymap = m_currentFocusOfThread->m_keymaps.front();\r
+       c.m_i = m_currentFocusOfThread->m_keymaps.begin();\r
+       generateKeyboardEvents(c);\r
+}\r
+\r
+// use a corresponding key of the previous prefixed keymap\r
+void Engine::funcKeymapPrevPrefix(FunctionParam *i_param, int i_previous)\r
+{\r
+       Current c(i_param->m_c);\r
+       if (0 < i_previous && 0 <= m_keymapPrefixHistory.size() - i_previous) {\r
+               int n = i_previous - 1;\r
+               KeymapPtrList::reverse_iterator i = m_keymapPrefixHistory.rbegin();\r
+               while (0 < n && i != m_keymapPrefixHistory.rend())\r
+                       --n, ++i;\r
+               c.m_keymap = *i;\r
+               generateKeyboardEvents(c);\r
+       }\r
+}\r
+\r
+// use a corresponding key of an other window class, or use a default key\r
+void Engine::funcOtherWindowClass(FunctionParam *i_param)\r
+{\r
+       Current c(i_param->m_c);\r
+       ++ c.m_i;\r
+       if (c.m_i == m_currentFocusOfThread->m_keymaps.end()) {\r
+               funcDefault(i_param);\r
+               return;\r
+       }\r
+\r
+       c.m_keymap = *c.m_i;\r
+       {\r
+               Acquire a(&m_log, 1);\r
+               m_log << _T("(") << c.m_keymap->getName() << _T(")") << std::endl;\r
+       }\r
+       i_param->m_doesNeedEndl = false;\r
+       generateKeyboardEvents(c);\r
+}\r
+\r
+// prefix key\r
+void Engine::funcPrefix(FunctionParam *i_param, const Keymap *i_keymap,\r
+                                               BooleanType i_doesIgnoreModifiers)\r
+{\r
+       if (!i_param->m_isPressed)\r
+               return;\r
+\r
+       setCurrentKeymap(i_keymap, true);\r
+\r
+       // generate prefixed event\r
+       generateEvents(i_param->m_c, m_currentKeymap, &Event::prefixed);\r
+\r
+       m_isPrefix = true;\r
+       m_doesEditNextModifier = false;\r
+       m_doesIgnoreModifierForPrefix = !!i_doesIgnoreModifiers;\r
+\r
+       {\r
+               Acquire a(&m_log, 1);\r
+               m_log << _T("(") << i_keymap->getName() << _T(", ")\r
+               << (i_doesIgnoreModifiers ? _T("true") : _T("false")) << _T(")");\r
+       }\r
+}\r
+\r
+// other keymap's key\r
+void Engine::funcKeymap(FunctionParam *i_param, const Keymap *i_keymap)\r
+{\r
+       Current c(i_param->m_c);\r
+       c.m_keymap = i_keymap;\r
+       {\r
+               Acquire a(&m_log, 1);\r
+               m_log << _T("(") << c.m_keymap->getName() << _T(")") << std::endl;\r
+               i_param->m_doesNeedEndl = false;\r
+       }\r
+       generateKeyboardEvents(c);\r
+}\r
+\r
+// sync\r
+void Engine::funcSync(FunctionParam *i_param)\r
+{\r
+       if (i_param->m_isPressed)\r
+               generateModifierEvents(i_param->m_af->m_modifier);\r
+       if (!i_param->m_isPressed || m_currentFocusOfThread->m_isConsole)\r
+               return;\r
+\r
+       Key *sync = m_setting->m_keyboard.getSyncKey();\r
+       if (sync->getScanCodesSize() == 0)\r
+               return;\r
+       const ScanCode *sc = sync->getScanCodes();\r
+\r
+       // set variables exported from mayu.dll\r
+       g_hookData->m_syncKey = sc->m_scan;\r
+       g_hookData->m_syncKeyIsExtended = !!(sc->m_flags & ScanCode::E0E1);\r
+       m_isSynchronizing = true;\r
+       generateKeyEvent(sync, false, false);\r
+\r
+       m_cs.release();\r
+       DWORD r = WaitForSingleObject(m_eSync, 5000);\r
+       if (r == WAIT_TIMEOUT) {\r
+               Acquire a(&m_log, 0);\r
+               m_log << _T(" *FAILED*") << std::endl;\r
+       }\r
+       m_cs.acquire();\r
+       m_isSynchronizing = false;\r
+}\r
+\r
+// toggle lock\r
+void Engine::funcToggle(FunctionParam *i_param, ModifierLockType i_lock,\r
+                                               ToggleType i_toggle)\r
+{\r
+       if (i_param->m_isPressed)                       // ignore PRESS\r
+               return;\r
+\r
+       Modifier::Type mt = static_cast<Modifier::Type>(i_lock);\r
+       switch (i_toggle) {\r
+       case ToggleType_toggle:\r
+               m_currentLock.press(mt, !m_currentLock.isPressed(mt));\r
+               break;\r
+       case ToggleType_off:\r
+               m_currentLock.press(mt, false);\r
+               break;\r
+       case ToggleType_on:\r
+               m_currentLock.press(mt, true);\r
+               break;\r
+       }\r
+}\r
+\r
+// edit next user input key's modifier\r
+void Engine::funcEditNextModifier(FunctionParam *i_param,\r
+                                                                 const Modifier &i_modifier)\r
+{\r
+       if (!i_param->m_isPressed)\r
+               return;\r
+\r
+       m_isPrefix = true;\r
+       m_doesEditNextModifier = true;\r
+       m_doesIgnoreModifierForPrefix = true;\r
+       m_modifierForNextKey = i_modifier;\r
+}\r
+\r
+// variable\r
+void Engine::funcVariable(FunctionParam *i_param, int i_mag, int i_inc)\r
+{\r
+       if (!i_param->m_isPressed)\r
+               return;\r
+       m_variable *= i_mag;\r
+       m_variable += i_inc;\r
+}\r
+\r
+// repeat N times\r
+void Engine::funcRepeat(FunctionParam *i_param, const KeySeq *i_keySeq,\r
+                                               int i_max)\r
+{\r
+       if (i_param->m_isPressed) {\r
+               int end = MIN(m_variable, i_max);\r
+               for (int i = 0; i < end - 1; ++ i)\r
+                       generateKeySeqEvents(i_param->m_c, i_keySeq, Part_all);\r
+               if (0 < end)\r
+                       generateKeySeqEvents(i_param->m_c, i_keySeq, Part_down);\r
+       } else\r
+               generateKeySeqEvents(i_param->m_c, i_keySeq, Part_up);\r
+}\r
+\r
+// undefined (bell)\r
+void Engine::funcUndefined(FunctionParam *i_param)\r
+{\r
+       if (!i_param->m_isPressed)\r
+               return;\r
+       MessageBeep(MB_OK);\r
+}\r
+\r
+// ignore\r
+void Engine::funcIgnore(FunctionParam *)\r
+{\r
+       // do nothing\r
+}\r
+\r
+// post message\r
+void Engine::funcPostMessage(FunctionParam *i_param, ToWindowType i_window,\r
+                                                        UINT i_message, WPARAM i_wParam, LPARAM i_lParam)\r
+{\r
+       if (!i_param->m_isPressed)\r
+               return;\r
+\r
+       int window = static_cast<int>(i_window);\r
+\r
+       HWND hwnd = i_param->m_hwnd;\r
+       if (0 < window) {\r
+               for (int i = 0; i < window; ++ i)\r
+                       hwnd = GetParent(hwnd);\r
+       } else if (window == ToWindowType_toMainWindow) {\r
+               while (true) {\r
+                       HWND p = GetParent(hwnd);\r
+                       if (!p)\r
+                               break;\r
+                       hwnd = p;\r
+               }\r
+       } else if (window == ToWindowType_toOverlappedWindow) {\r
+               while (hwnd) {\r
+#ifdef MAYU64\r
+                       LONG_PTR style = GetWindowLongPtr(hwnd, GWL_STYLE);\r
+#else\r
+                       LONG style = GetWindowLong(hwnd, GWL_STYLE);\r
+#endif\r
+                       if ((style & WS_CHILD) == 0)\r
+                               break;\r
+                       hwnd = GetParent(hwnd);\r
+               }\r
+       }\r
+\r
+       if (hwnd)\r
+               PostMessage(hwnd, i_message, i_wParam, i_lParam);\r
+}\r
+\r
+\r
+// ShellExecute\r
+void Engine::funcShellExecute(FunctionParam *i_param,\r
+                                                         const StrExprArg &/*i_operation*/,\r
+                                                         const StrExprArg &/*i_file*/,\r
+                                                         const StrExprArg &/*i_parameters*/,\r
+                                                         const StrExprArg &/*i_directory*/,\r
+                                                         ShowCommandType /*i_showCommand*/)\r
+{\r
+       if (!i_param->m_isPressed)\r
+               return;\r
+       m_afShellExecute = i_param->m_af;\r
+       PostMessage(m_hwndAssocWindow,\r
+                               WM_APP_engineNotify, EngineNotify_shellExecute, 0);\r
+}\r
+\r
+\r
+// shell execute\r
+void Engine::shellExecute()\r
+{\r
+       Acquire a(&m_cs);\r
+\r
+       FunctionData_ShellExecute *fd =\r
+               reinterpret_cast<FunctionData_ShellExecute *>(\r
+                       m_afShellExecute->m_functionData);\r
+\r
+       int r = (int)ShellExecute(\r
+                               NULL,\r
+                               fd->m_operation.eval().empty() ? _T("open") : fd->m_operation.eval().c_str(),\r
+                               fd->m_file.eval().empty() ? NULL : fd->m_file.eval().c_str(),\r
+                               fd->m_parameters.eval().empty() ? NULL : fd->m_parameters.eval().c_str(),\r
+                               fd->m_directory.eval().empty() ? NULL : fd->m_directory.eval().c_str(),\r
+                               fd->m_showCommand);\r
+       if (32 < r)\r
+               return; // success\r
+\r
+       typedef TypeTable<int> ErrorTable;\r
+       static const ErrorTable errorTable[] = {\r
+               { 0, _T("The operating system is out of memory or resources.") },\r
+               { ERROR_FILE_NOT_FOUND, _T("The specified file was not found.") },\r
+               { ERROR_PATH_NOT_FOUND, _T("The specified path was not found.") },\r
+               { ERROR_BAD_FORMAT, _T("The .exe file is invalid ")\r
+                 _T("(non-Win32R .exe or error in .exe image).") },\r
+               { SE_ERR_ACCESSDENIED,\r
+                 _T("The operating system denied access to the specified file.") },\r
+               { SE_ERR_ASSOCINCOMPLETE,\r
+                 _T("The file name association is incomplete or invalid.") },\r
+               { SE_ERR_DDEBUSY,\r
+                 _T("The DDE transaction could not be completed ")\r
+                 _T("because other DDE transactions were being processed. ") },\r
+               { SE_ERR_DDEFAIL, _T("The DDE transaction failed.") },\r
+               { SE_ERR_DDETIMEOUT, _T("The DDE transaction could not be completed ")\r
+                 _T("because the request timed out.") },\r
+               { SE_ERR_DLLNOTFOUND,\r
+                 _T("The specified dynamic-link library was not found.") },\r
+               { SE_ERR_FNF, _T("The specified file was not found.") },\r
+               { SE_ERR_NOASSOC, _T("There is no application associated ")\r
+                 _T("with the given file name extension.") },\r
+               { SE_ERR_OOM,\r
+                 _T("There was not enough memory to complete the operation.") },\r
+               { SE_ERR_PNF, _T("The specified path was not found.") },\r
+               { SE_ERR_SHARE, _T("A sharing violation occurred.") },\r
+       };\r
+\r
+       tstring errorMessage(_T("Unknown error."));\r
+       getTypeName(&errorMessage, r, errorTable, NUMBER_OF(errorTable));\r
+\r
+       Acquire b(&m_log, 0);\r
+       m_log << _T("error: ") << fd << _T(": ") << errorMessage << std::endl;\r
+}\r
+\r
+\r
+struct EnumWindowsForSetForegroundWindowParam {\r
+       const FunctionData_SetForegroundWindow *m_fd;\r
+       HWND m_hwnd;\r
+\r
+public:\r
+       EnumWindowsForSetForegroundWindowParam(\r
+               const FunctionData_SetForegroundWindow *i_fd)\r
+                       : m_fd(i_fd),\r
+                       m_hwnd(NULL) {\r
+       }\r
+};\r
+\r
+\r
+/// enum windows for SetForegroundWindow\r
+static BOOL CALLBACK enumWindowsForSetForegroundWindow(\r
+       HWND i_hwnd, LPARAM i_lParam)\r
+{\r
+       EnumWindowsForSetForegroundWindowParam &ep =\r
+               *reinterpret_cast<EnumWindowsForSetForegroundWindowParam *>(i_lParam);\r
+\r
+       _TCHAR name[GANA_MAX_ATOM_LENGTH];\r
+       if (!GetClassName(i_hwnd, name, NUMBER_OF(name)))\r
+               return TRUE;\r
+       tsmatch what;\r
+       if (!boost::regex_search(tstring(name), what, ep.m_fd->m_windowClassName))\r
+               if (ep.m_fd->m_logicalOp == LogicalOperatorType_and)\r
+                       return TRUE;                            // match failed\r
+\r
+       if (ep.m_fd->m_logicalOp == LogicalOperatorType_and) {\r
+               if (GetWindowText(i_hwnd, name, NUMBER_OF(name)) == 0)\r
+                       name[0] = _T('\0');\r
+               if (!boost::regex_search(tstring(name), what,\r
+                                                                ep.m_fd->m_windowTitleName))\r
+                       return TRUE;                            // match failed\r
+       }\r
+\r
+       ep.m_hwnd = i_hwnd;\r
+       return FALSE;\r
+}\r
+\r
+\r
+/// SetForegroundWindow\r
+void Engine::funcSetForegroundWindow(FunctionParam *i_param, const tregex &,\r
+                                                                        LogicalOperatorType , const tregex &)\r
+{\r
+       if (!i_param->m_isPressed)\r
+               return;\r
+       EnumWindowsForSetForegroundWindowParam\r
+       ep(static_cast<const FunctionData_SetForegroundWindow *>(\r
+                  i_param->m_af->m_functionData));\r
+       EnumWindows(enumWindowsForSetForegroundWindow,\r
+                               reinterpret_cast<LPARAM>(&ep));\r
+       if (ep.m_hwnd)\r
+               PostMessage(m_hwndAssocWindow,\r
+                                       WM_APP_engineNotify, EngineNotify_setForegroundWindow,\r
+                                       reinterpret_cast<LPARAM>(ep.m_hwnd));\r
+\r
+}\r
+\r
+\r
+// load setting\r
+void Engine::funcLoadSetting(FunctionParam *i_param, const StrExprArg &i_name)\r
+{\r
+       if (!i_param->m_isPressed)\r
+               return;\r
+       if (!i_name.eval().empty()) {\r
+               // set MAYU_REGISTRY_ROOT\.mayuIndex which name is same with i_name\r
+               Registry reg(MAYU_REGISTRY_ROOT);\r
+\r
+               tregex split(_T("^([^;]*);([^;]*);(.*)$"));\r
+               tstringi dot_mayu;\r
+               for (size_t i = 0; i < MAX_MAYU_REGISTRY_ENTRIES; ++ i) {\r
+                       _TCHAR buf[100];\r
+                       _sntprintf(buf, NUMBER_OF(buf), _T(".mayu%d"), i);\r
+                       if (!reg.read(buf, &dot_mayu))\r
+                               break;\r
+\r
+                       tsmatch what;\r
+                       if (boost::regex_match(dot_mayu, what, split) &&\r
+                                       what.str(1) == i_name.eval()) {\r
+                               reg.write(_T(".mayuIndex"), i);\r
+                               goto success;\r
+                       }\r
+               }\r
+\r
+               {\r
+                       Acquire a(&m_log, 0);\r
+                       m_log << _T("unknown setting name: ") << i_name;\r
+               }\r
+               return;\r
+\r
+success:\r
+               ;\r
+       }\r
+       PostMessage(m_hwndAssocWindow,\r
+                               WM_APP_engineNotify, EngineNotify_loadSetting, 0);\r
+}\r
+\r
+// virtual key\r
+void Engine::funcVK(FunctionParam *i_param, VKey i_vkey)\r
+{\r
+       long key = static_cast<long>(i_vkey);\r
+       BYTE vkey = static_cast<BYTE>(i_vkey);\r
+       bool isExtended = !!(key & VKey_extended);\r
+       bool isUp       = !i_param->m_isPressed && !!(key & VKey_released);\r
+       bool isDown     = i_param->m_isPressed && !!(key & VKey_pressed);\r
+\r
+       if (vkey == VK_LBUTTON && isDown)\r
+               mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);\r
+       else if (vkey == VK_LBUTTON && isUp)\r
+               mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);\r
+       else if (vkey == VK_MBUTTON && isDown)\r
+               mouse_event(MOUSEEVENTF_MIDDLEDOWN, 0, 0, 0, 0);\r
+       else if (vkey == VK_MBUTTON && isUp)\r
+               mouse_event(MOUSEEVENTF_MIDDLEUP, 0, 0, 0, 0);\r
+       else if (vkey == VK_RBUTTON && isDown)\r
+               mouse_event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0);\r
+       else if (vkey == VK_RBUTTON && isUp)\r
+               mouse_event(MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0);\r
+       else if (vkey == VK_XBUTTON1 && isDown)\r
+               mouse_event(MOUSEEVENTF_XDOWN, 0, 0, XBUTTON1, 0);\r
+       else if (vkey == VK_XBUTTON1 && isUp)\r
+               mouse_event(MOUSEEVENTF_XUP, 0, 0, XBUTTON1, 0);\r
+       else if (vkey == VK_XBUTTON2 && isDown)\r
+               mouse_event(MOUSEEVENTF_XDOWN, 0, 0, XBUTTON2, 0);\r
+       else if (vkey == VK_XBUTTON2 && isUp)\r
+               mouse_event(MOUSEEVENTF_XUP, 0, 0, XBUTTON2, 0);\r
+       else if (isUp || isDown)\r
+               keybd_event(vkey,\r
+                                       static_cast<BYTE>(MapVirtualKey(vkey, 0)),\r
+                                       (isExtended ? KEYEVENTF_EXTENDEDKEY : 0) |\r
+                                       (i_param->m_isPressed ? 0 : KEYEVENTF_KEYUP), 0);\r
+}\r
+\r
+// wait\r
+void Engine::funcWait(FunctionParam *i_param, int i_milliSecond)\r
+{\r
+       if (!i_param->m_isPressed)\r
+               return;\r
+       if (i_milliSecond < 0 || 5000 < i_milliSecond)  // too long wait\r
+               return;\r
+\r
+       m_isSynchronizing = true;\r
+       m_cs.release();\r
+       Sleep(i_milliSecond);\r
+       m_cs.acquire();\r
+       m_isSynchronizing = false;\r
+}\r
+\r
+// investigate WM_COMMAND, WM_SYSCOMMAND\r
+void Engine::funcInvestigateCommand(FunctionParam *i_param)\r
+{\r
+       if (!i_param->m_isPressed)\r
+               return;\r
+       Acquire a(&m_log, 0);\r
+       g_hookData->m_doesNotifyCommand = !g_hookData->m_doesNotifyCommand;\r
+       if (g_hookData->m_doesNotifyCommand)\r
+               m_log << _T(" begin") << std::endl;\r
+       else\r
+               m_log << _T(" end") << std::endl;\r
+}\r
+\r
+// show mayu dialog box\r
+void Engine::funcMayuDialog(FunctionParam *i_param, MayuDialogType i_dialog,\r
+                                                       ShowCommandType i_showCommand)\r
+{\r
+       if (!i_param->m_isPressed)\r
+               return;\r
+       PostMessage(getAssociatedWndow(), WM_APP_engineNotify, EngineNotify_showDlg,\r
+                               static_cast<LPARAM>(i_dialog) |\r
+                               static_cast<LPARAM>(i_showCommand));\r
+}\r
+\r
+// describe bindings\r
+void Engine::funcDescribeBindings(FunctionParam *i_param)\r
+{\r
+       if (!i_param->m_isPressed)\r
+               return;\r
+       {\r
+               Acquire a(&m_log, 1);\r
+               m_log << std::endl;\r
+       }\r
+       describeBindings();\r
+}\r
+\r
+// show help message\r
+void Engine::funcHelpMessage(FunctionParam *i_param, const StrExprArg &i_title,\r
+                                                        const StrExprArg &i_message)\r
+{\r
+       if (!i_param->m_isPressed)\r
+               return;\r
+\r
+       m_helpTitle = i_title.eval();\r
+       m_helpMessage = i_message.eval();\r
+       bool doesShow = !(i_title.eval().size() == 0 && i_message.eval().size() == 0);\r
+       PostMessage(getAssociatedWndow(), WM_APP_engineNotify,\r
+                               EngineNotify_helpMessage, doesShow);\r
+}\r
+\r
+// show variable\r
+void Engine::funcHelpVariable(FunctionParam *i_param, const StrExprArg &i_title)\r
+{\r
+       if (!i_param->m_isPressed)\r
+               return;\r
+\r
+       _TCHAR buf[20];\r
+       _sntprintf(buf, NUMBER_OF(buf), _T("%d"), m_variable);\r
+\r
+       m_helpTitle = i_title.eval();\r
+       m_helpMessage = buf;\r
+       PostMessage(getAssociatedWndow(), WM_APP_engineNotify,\r
+                               EngineNotify_helpMessage, true);\r
+}\r
+\r
+// raise window\r
+void Engine::funcWindowRaise(FunctionParam *i_param,\r
+                                                        TargetWindowType i_twt)\r
+{\r
+       HWND hwnd;\r
+       if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt))\r
+               return;\r
+       SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0,\r
+                                SWP_ASYNCWINDOWPOS | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOSIZE);\r
+}\r
+\r
+// lower window\r
+void Engine::funcWindowLower(FunctionParam *i_param, TargetWindowType i_twt)\r
+{\r
+       HWND hwnd;\r
+       if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt))\r
+               return;\r
+       SetWindowPos(hwnd, HWND_BOTTOM, 0, 0, 0, 0,\r
+                                SWP_ASYNCWINDOWPOS | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOSIZE);\r
+}\r
+\r
+// minimize window\r
+void Engine::funcWindowMinimize(FunctionParam *i_param, TargetWindowType i_twt)\r
+{\r
+       HWND hwnd;\r
+       if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt))\r
+               return;\r
+       PostMessage(hwnd, WM_SYSCOMMAND,\r
+                               IsIconic(hwnd) ? SC_RESTORE : SC_MINIMIZE, 0);\r
+}\r
+\r
+// maximize window\r
+void Engine::funcWindowMaximize(FunctionParam *i_param, TargetWindowType i_twt)\r
+{\r
+       HWND hwnd;\r
+       if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt))\r
+               return;\r
+       PostMessage(hwnd, WM_SYSCOMMAND,\r
+                               IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, 0);\r
+}\r
+\r
+// maximize horizontally or virtically\r
+void Engine::funcWindowHVMaximize(FunctionParam *i_param,\r
+                                                                 BooleanType i_isHorizontal,\r
+                                                                 TargetWindowType i_twt)\r
+{\r
+       HWND hwnd;\r
+       RECT rc, rcd;\r
+       if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt, &rc, &rcd))\r
+               return;\r
+\r
+       // erase non window\r
+       while (true) {\r
+               WindowPositions::iterator i = m_windowPositions.begin();\r
+               WindowPositions::iterator end = m_windowPositions.end();\r
+               for (; i != end; ++ i)\r
+                       if (!IsWindow((*i).m_hwnd))\r
+                               break;\r
+               if (i == end)\r
+                       break;\r
+               m_windowPositions.erase(i);\r
+       }\r
+\r
+       // find target\r
+       WindowPositions::iterator i = m_windowPositions.begin();\r
+       WindowPositions::iterator end = m_windowPositions.end();\r
+       WindowPositions::iterator target = end;\r
+       for (; i != end; ++ i)\r
+               if ((*i).m_hwnd == hwnd) {\r
+                       target = i;\r
+                       break;\r
+               }\r
+\r
+       if (IsZoomed(hwnd))\r
+               PostMessage(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);\r
+       else {\r
+               WindowPosition::Mode mode = WindowPosition::Mode_normal;\r
+\r
+               if (target != end) {\r
+                       WindowPosition &wp = *target;\r
+                       rc = wp.m_rc;\r
+                       if (wp.m_mode == WindowPosition::Mode_HV)\r
+                               mode = wp.m_mode =\r
+                                                  i_isHorizontal ? WindowPosition::Mode_V : WindowPosition::Mode_H;\r
+                       else if (( i_isHorizontal && wp.m_mode == WindowPosition::Mode_V) ||\r
+                                        (!i_isHorizontal && wp.m_mode == WindowPosition::Mode_H))\r
+                               mode = wp.m_mode = WindowPosition::Mode_HV;\r
+                       else\r
+                               m_windowPositions.erase(target);\r
+               } else {\r
+                       mode = i_isHorizontal ? WindowPosition::Mode_H : WindowPosition::Mode_V;\r
+                       m_windowPositions.push_front(WindowPosition(hwnd, rc, mode));\r
+               }\r
+\r
+               if (static_cast<int>(mode) & static_cast<int>(WindowPosition::Mode_H))\r
+                       rc.left = rcd.left, rc.right = rcd.right;\r
+               if (static_cast<int>(mode) & static_cast<int>(WindowPosition::Mode_V))\r
+                       rc.top = rcd.top, rc.bottom = rcd.bottom;\r
+\r
+               asyncMoveWindow(hwnd, rc.left, rc.top, rcWidth(&rc), rcHeight(&rc));\r
+       }\r
+}\r
+\r
+// maximize window horizontally\r
+void Engine::funcWindowHMaximize(FunctionParam *i_param,\r
+                                                                TargetWindowType i_twt)\r
+{\r
+       funcWindowHVMaximize(i_param, BooleanType_true, i_twt);\r
+}\r
+\r
+// maximize window virtically\r
+void Engine::funcWindowVMaximize(FunctionParam *i_param,\r
+                                                                TargetWindowType i_twt)\r
+{\r
+       funcWindowHVMaximize(i_param, BooleanType_false, i_twt);\r
+}\r
+\r
+// move window\r
+void Engine::funcWindowMove(FunctionParam *i_param, int i_dx, int i_dy,\r
+                                                       TargetWindowType i_twt)\r
+{\r
+       funcWindowMoveTo(i_param, GravityType_C, i_dx, i_dy, i_twt);\r
+}\r
+\r
+// move window to ...\r
+void Engine::funcWindowMoveTo(FunctionParam *i_param,\r
+                                                         GravityType i_gravityType,\r
+                                                         int i_dx, int i_dy, TargetWindowType i_twt)\r
+{\r
+       HWND hwnd;\r
+       RECT rc, rcd;\r
+       if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt, &rc, &rcd))\r
+               return;\r
+\r
+       int x = rc.left + i_dx;\r
+       int y = rc.top + i_dy;\r
+\r
+       if (i_gravityType & GravityType_N)\r
+               y = i_dy + rcd.top;\r
+       if (i_gravityType & GravityType_E)\r
+               x = i_dx + rcd.right - rcWidth(&rc);\r
+       if (i_gravityType & GravityType_W)\r
+               x = i_dx + rcd.left;\r
+       if (i_gravityType & GravityType_S)\r
+               y = i_dy + rcd.bottom - rcHeight(&rc);\r
+       asyncMoveWindow(hwnd, x, y);\r
+}\r
+\r
+\r
+// move window visibly\r
+void Engine::funcWindowMoveVisibly(FunctionParam *i_param,\r
+                                                                  TargetWindowType i_twt)\r
+{\r
+       HWND hwnd;\r
+       RECT rc, rcd;\r
+       if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt, &rc, &rcd))\r
+               return;\r
+\r
+       int x = rc.left;\r
+       int y = rc.top;\r
+       if (rc.left < rcd.left)\r
+               x = rcd.left;\r
+       else if (rcd.right < rc.right)\r
+               x = rcd.right - rcWidth(&rc);\r
+       if (rc.top < rcd.top)\r
+               y = rcd.top;\r
+       else if (rcd.bottom < rc.bottom)\r
+               y = rcd.bottom - rcHeight(&rc);\r
+       asyncMoveWindow(hwnd, x, y);\r
+}\r
+\r
+\r
+struct EnumDisplayMonitorsForWindowMonitorToParam {\r
+       std::vector<HMONITOR> m_monitors;\r
+       std::vector<MONITORINFO> m_monitorinfos;\r
+       int m_primaryMonitorIdx;\r
+       int m_currentMonitorIdx;\r
+\r
+       HMONITOR m_hmon;\r
+\r
+public:\r
+       EnumDisplayMonitorsForWindowMonitorToParam(HMONITOR i_hmon)\r
+                       : m_hmon(i_hmon),\r
+                       m_primaryMonitorIdx(-1), m_currentMonitorIdx(-1) {\r
+       }\r
+};\r
+\r
+static BOOL CALLBACK enumDisplayMonitorsForWindowMonitorTo(\r
+       HMONITOR i_hmon, HDC i_hdc, LPRECT i_rcMonitor, LPARAM i_data)\r
+{\r
+       EnumDisplayMonitorsForWindowMonitorToParam &ep =\r
+               *reinterpret_cast<EnumDisplayMonitorsForWindowMonitorToParam *>(i_data);\r
+\r
+       ep.m_monitors.push_back(i_hmon);\r
+\r
+       MONITORINFO mi;\r
+       mi.cbSize = sizeof(mi);\r
+       getMonitorInfo(i_hmon, &mi);\r
+       ep.m_monitorinfos.push_back(mi);\r
+\r
+       if (mi.dwFlags & MONITORINFOF_PRIMARY)\r
+               ep.m_primaryMonitorIdx = ep.m_monitors.size() - 1;\r
+       if (i_hmon == ep.m_hmon)\r
+               ep.m_currentMonitorIdx = ep.m_monitors.size() - 1;\r
+\r
+       return TRUE;\r
+}\r
+\r
+/// move window to other monitor\r
+void Engine::funcWindowMonitorTo(\r
+       FunctionParam *i_param, WindowMonitorFromType i_fromType, int i_monitor,\r
+       BooleanType i_adjustPos, BooleanType i_adjustSize)\r
+{\r
+       HWND hwnd;\r
+       if (! getSuitableWindow(i_param, &hwnd))\r
+               return;\r
+\r
+       HMONITOR hmonCur;\r
+       hmonCur = monitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);\r
+\r
+       EnumDisplayMonitorsForWindowMonitorToParam ep(hmonCur);\r
+       enumDisplayMonitors(NULL, NULL, enumDisplayMonitorsForWindowMonitorTo,\r
+                                               reinterpret_cast<LPARAM>(&ep));\r
+       if (ep.m_monitors.size() < 1 ||\r
+                       ep.m_primaryMonitorIdx < 0 || ep.m_currentMonitorIdx < 0)\r
+               return;\r
+\r
+       int targetIdx;\r
+       switch (i_fromType) {\r
+       case WindowMonitorFromType_primary:\r
+               targetIdx = (ep.m_primaryMonitorIdx + i_monitor) % ep.m_monitors.size();\r
+               break;\r
+\r
+       case WindowMonitorFromType_current:\r
+               targetIdx = (ep.m_currentMonitorIdx + i_monitor) % ep.m_monitors.size();\r
+               break;\r
+       }\r
+       if (ep.m_currentMonitorIdx == targetIdx)\r
+               return;\r
+\r
+       RECT rcCur, rcTarget, rcWin;\r
+       rcCur = ep.m_monitorinfos[ep.m_currentMonitorIdx].rcWork;\r
+       rcTarget = ep.m_monitorinfos[targetIdx].rcWork;\r
+       GetWindowRect(hwnd, &rcWin);\r
+\r
+       int x = rcTarget.left + (rcWin.left - rcCur.left);\r
+       int y = rcTarget.top + (rcWin.top - rcCur.top);\r
+       int w = rcWidth(&rcWin);\r
+       int h = rcHeight(&rcWin);\r
+\r
+       if (i_adjustPos) {\r
+               if (x + w > rcTarget.right)\r
+                       x = rcTarget.right - w;\r
+               if (x < rcTarget.left)\r
+                       x = rcTarget.left;\r
+               if (w > rcWidth(&rcTarget)) {\r
+                       x = rcTarget.left;\r
+                       w = rcWidth(&rcTarget);\r
+               }\r
+\r
+               if (y + h > rcTarget.bottom)\r
+                       y = rcTarget.bottom - h;\r
+               if (y < rcTarget.top)\r
+                       y = rcTarget.top;\r
+               if (h > rcHeight(&rcTarget)) {\r
+                       y = rcTarget.top;\r
+                       h = rcHeight(&rcTarget);\r
+               }\r
+       }\r
+\r
+       if (i_adjustPos && i_adjustSize) {\r
+               if (IsZoomed(hwnd))\r
+                       PostMessage(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);\r
+               asyncMoveWindow(hwnd, x, y, w, h);\r
+       } else {\r
+               asyncMoveWindow(hwnd, x, y);\r
+       }\r
+}\r
+\r
+/// move window to other monitor\r
+void Engine::funcWindowMonitor(\r
+       FunctionParam *i_param, int i_monitor,\r
+       BooleanType i_adjustPos, BooleanType i_adjustSize)\r
+{\r
+       funcWindowMonitorTo(i_param, WindowMonitorFromType_primary, i_monitor,\r
+                                               i_adjustPos, i_adjustSize);\r
+}\r
+\r
+\r
+//\r
+void Engine::funcWindowClingToLeft(FunctionParam *i_param,\r
+                                                                  TargetWindowType i_twt)\r
+{\r
+       funcWindowMoveTo(i_param, GravityType_W, 0, 0, i_twt);\r
+}\r
+\r
+//\r
+void Engine::funcWindowClingToRight(FunctionParam *i_param,\r
+                                                                       TargetWindowType i_twt)\r
+{\r
+       funcWindowMoveTo(i_param, GravityType_E, 0, 0, i_twt);\r
+}\r
+\r
+//\r
+void Engine::funcWindowClingToTop(FunctionParam *i_param,\r
+                                                                 TargetWindowType i_twt)\r
+{\r
+       funcWindowMoveTo(i_param, GravityType_N, 0, 0, i_twt);\r
+}\r
+\r
+//\r
+void Engine::funcWindowClingToBottom(FunctionParam *i_param,\r
+                                                                        TargetWindowType i_twt)\r
+{\r
+       funcWindowMoveTo(i_param, GravityType_S, 0, 0, i_twt);\r
+}\r
+\r
+// close window\r
+void Engine::funcWindowClose(FunctionParam *i_param, TargetWindowType i_twt)\r
+{\r
+       HWND hwnd;\r
+       if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt))\r
+               return;\r
+       PostMessage(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0);\r
+}\r
+\r
+// toggle top-most flag of the window\r
+void Engine::funcWindowToggleTopMost(FunctionParam *i_param)\r
+{\r
+       HWND hwnd;\r
+       if (!getSuitableWindow(i_param, &hwnd))\r
+               return;\r
+       SetWindowPos(\r
+               hwnd,\r
+#ifdef MAYU64\r
+               (GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST) ?\r
+#else\r
+               (GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST) ?\r
+#endif\r
+               HWND_NOTOPMOST : HWND_TOPMOST,\r
+               0, 0, 0, 0,\r
+               SWP_ASYNCWINDOWPOS | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOSIZE);\r
+}\r
+\r
+// identify the window\r
+void Engine::funcWindowIdentify(FunctionParam *i_param)\r
+{\r
+       if (!i_param->m_isPressed)\r
+               return;\r
+\r
+       _TCHAR className[GANA_MAX_ATOM_LENGTH];\r
+       bool ok = false;\r
+       if (GetClassName(i_param->m_hwnd, className, NUMBER_OF(className))) {\r
+               if (_tcsicmp(className, _T("ConsoleWindowClass")) == 0) {\r
+                       _TCHAR titleName[1024];\r
+                       if (GetWindowText(i_param->m_hwnd, titleName, NUMBER_OF(titleName)) == 0)\r
+                               titleName[0] = _T('\0');\r
+                       {\r
+                               Acquire a(&m_log, 1);\r
+                               m_log << _T("HWND:\t") << std::hex\r
+                               << reinterpret_cast<int>(i_param->m_hwnd)\r
+                               << std::dec << std::endl;\r
+                       }\r
+                       Acquire a(&m_log, 0);\r
+                       m_log << _T("CLASS:\t") << className << std::endl;\r
+                       m_log << _T("TITLE:\t") << titleName << std::endl;\r
+\r
+                       HWND hwnd = getToplevelWindow(i_param->m_hwnd, NULL);\r
+                       RECT rc;\r
+                       GetWindowRect(hwnd, &rc);\r
+                       m_log << _T("Toplevel Window Position/Size: (")\r
+                       << rc.left << _T(", ") << rc.top << _T(") / (")\r
+                       << rcWidth(&rc) << _T("x") << rcHeight(&rc)\r
+                       << _T(")") << std::endl;\r
+\r
+                       SystemParametersInfo(SPI_GETWORKAREA, 0, (void *)&rc, FALSE);\r
+                       m_log << _T("Desktop Window Position/Size: (")\r
+                       << rc.left << _T(", ") << rc.top << _T(") / (")\r
+                       << rcWidth(&rc) << _T("x") << rcHeight(&rc)\r
+                       << _T(")") << std::endl;\r
+\r
+                       m_log << std::endl;\r
+                       ok = true;\r
+               }\r
+       }\r
+       if (!ok) {\r
+               UINT WM_MAYU_MESSAGE = RegisterWindowMessage(\r
+                                                                  addSessionId(WM_MAYU_MESSAGE_NAME).c_str());\r
+               CHECK_TRUE( PostMessage(i_param->m_hwnd, WM_MAYU_MESSAGE,\r
+                                                               MayuMessage_notifyName, 0) );\r
+       }\r
+}\r
+\r
+// set alpha blending parameter to the window\r
+void Engine::funcWindowSetAlpha(FunctionParam *i_param, int i_alpha)\r
+{\r
+       HWND hwnd;\r
+       if (!getSuitableWindow(i_param, &hwnd))\r
+               return;\r
+\r
+       if (i_alpha < 0) {      // remove all alpha\r
+               for (WindowsWithAlpha::iterator i = m_windowsWithAlpha.begin();\r
+                               i != m_windowsWithAlpha.end(); ++ i) {\r
+#ifdef MAYU64\r
+                       SetWindowLongPtr(*i, GWL_EXSTYLE,\r
+                                                        GetWindowLongPtr(*i, GWL_EXSTYLE) & ~WS_EX_LAYERED);\r
+#else\r
+                       SetWindowLong(*i, GWL_EXSTYLE,\r
+                                                 GetWindowLong(*i, GWL_EXSTYLE) & ~WS_EX_LAYERED);\r
+#endif\r
+                       RedrawWindow(*i, NULL, NULL,\r
+                                                RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);\r
+               }\r
+               m_windowsWithAlpha.clear();\r
+       } else {\r
+#ifdef MAYU64\r
+               LONG_PTR exStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE);\r
+#else\r
+               LONG exStyle = GetWindowLong(hwnd, GWL_EXSTYLE);\r
+#endif\r
+               if (exStyle & WS_EX_LAYERED) {  // remove alpha\r
+                       WindowsWithAlpha::iterator\r
+                       i = std::find(m_windowsWithAlpha.begin(), m_windowsWithAlpha.end(),\r
+                                                 hwnd);\r
+                       if (i == m_windowsWithAlpha.end())\r
+                               return; // already layered by the application\r
+\r
+                       m_windowsWithAlpha.erase(i);\r
+\r
+#ifdef MAYU64\r
+                       SetWindowLongPtr(hwnd, GWL_EXSTYLE, exStyle & ~WS_EX_LAYERED);\r
+#else\r
+                       SetWindowLong(hwnd, GWL_EXSTYLE, exStyle & ~WS_EX_LAYERED);\r
+#endif\r
+               } else {        // add alpha\r
+#ifdef MAYU64\r
+                       SetWindowLongPtr(hwnd, GWL_EXSTYLE, exStyle | WS_EX_LAYERED);\r
+#else\r
+                       SetWindowLong(hwnd, GWL_EXSTYLE, exStyle | WS_EX_LAYERED);\r
+#endif\r
+                       i_alpha %= 101;\r
+                       if (!setLayeredWindowAttributes(hwnd, 0,\r
+                                                                                       (BYTE)(255 * i_alpha / 100), LWA_ALPHA)) {\r
+                               Acquire a(&m_log, 0);\r
+                               m_log << _T("error: &WindowSetAlpha(") << i_alpha\r
+                               << _T(") failed for HWND: ") << std::hex\r
+                               << hwnd << std::dec << std::endl;\r
+                               return;\r
+                       }\r
+                       m_windowsWithAlpha.push_front(hwnd);\r
+               }\r
+               RedrawWindow(hwnd, NULL, NULL,\r
+                                        RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);\r
+       }\r
+}\r
+\r
+\r
+// redraw the window\r
+void Engine::funcWindowRedraw(FunctionParam *i_param)\r
+{\r
+       HWND hwnd;\r
+       if (!getSuitableWindow(i_param, &hwnd))\r
+               return;\r
+       RedrawWindow(hwnd, NULL, NULL,\r
+                                RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);\r
+}\r
+\r
+// resize window to\r
+void Engine::funcWindowResizeTo(FunctionParam *i_param, int i_width,\r
+                                                               int i_height, TargetWindowType i_twt)\r
+{\r
+       HWND hwnd;\r
+       RECT rc, rcd;\r
+       if (!getSuitableMdiWindow(i_param, &hwnd, &i_twt, &rc, &rcd))\r
+               return;\r
+\r
+       if (i_width == 0)\r
+               i_width = rcWidth(&rc);\r
+       else if (i_width < 0)\r
+               i_width += rcWidth(&rcd);\r
+\r
+       if (i_height == 0)\r
+               i_height = rcHeight(&rc);\r
+       else if (i_height < 0)\r
+               i_height += rcHeight(&rcd);\r
+\r
+       asyncResize(hwnd, i_width, i_height);\r
+}\r
+\r
+// move the mouse cursor\r
+void Engine::funcMouseMove(FunctionParam *i_param, int i_dx, int i_dy)\r
+{\r
+       if (!i_param->m_isPressed)\r
+               return;\r
+       POINT pt;\r
+       GetCursorPos(&pt);\r
+       SetCursorPos(pt.x + i_dx, pt.y + i_dy);\r
+}\r
+\r
+// send a mouse-wheel-message to Windows\r
+void Engine::funcMouseWheel(FunctionParam *i_param, int i_delta)\r
+{\r
+       if (!i_param->m_isPressed)\r
+               return;\r
+       mouse_event(MOUSEEVENTF_WHEEL, 0, 0, i_delta, 0);\r
+}\r
+\r
+// convert the contents of the Clipboard to upper case\r
+void Engine::funcClipboardChangeCase(FunctionParam *i_param,\r
+                                                                        BooleanType i_doesConvertToUpperCase)\r
+{\r
+       if (!i_param->m_isPressed)\r
+               return;\r
+\r
+       HGLOBAL hdata;\r
+       const _TCHAR *text = getTextFromClipboard(&hdata);\r
+       HGLOBAL hdataNew = NULL;\r
+       if (text) {\r
+               int size = static_cast<int>(GlobalSize(hdata));\r
+               hdataNew = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, size);\r
+               if (hdataNew) {\r
+                       if (_TCHAR *dataNew = reinterpret_cast<_TCHAR *>(GlobalLock(hdataNew))) {\r
+                               std::memcpy(dataNew, text, size);\r
+                               _TCHAR *dataEnd = dataNew + size;\r
+                               while (dataNew < dataEnd && *dataNew) {\r
+                                       _TCHAR c = *dataNew;\r
+                                       if (_istlead(c))\r
+                                               dataNew += 2;\r
+                                       else\r
+                                               *dataNew++ =\r
+                                                       i_doesConvertToUpperCase ? _totupper(c) : _totlower(c);\r
+                               }\r
+                               GlobalUnlock(hdataNew);\r
+                       }\r
+               }\r
+       }\r
+       closeClipboard(hdata, hdataNew);\r
+}\r
+\r
+// convert the contents of the Clipboard to upper case\r
+void Engine::funcClipboardUpcaseWord(FunctionParam *i_param)\r
+{\r
+       funcClipboardChangeCase(i_param, BooleanType_true);\r
+}\r
+\r
+// convert the contents of the Clipboard to lower case\r
+void Engine::funcClipboardDowncaseWord(FunctionParam *i_param)\r
+{\r
+       funcClipboardChangeCase(i_param, BooleanType_false);\r
+}\r
+\r
+// set the contents of the Clipboard to the string\r
+void Engine::funcClipboardCopy(FunctionParam *i_param, const StrExprArg &i_text)\r
+{\r
+       if (!i_param->m_isPressed)\r
+               return;\r
+       if (!OpenClipboard(NULL))\r
+               return;\r
+\r
+       HGLOBAL hdataNew =\r
+               GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,\r
+                                       (i_text.eval().size() + 1) * sizeof(_TCHAR));\r
+       if (!hdataNew)\r
+               return;\r
+       _TCHAR *dataNew = reinterpret_cast<_TCHAR *>(GlobalLock(hdataNew));\r
+       _tcscpy(dataNew, i_text.eval().c_str());\r
+       GlobalUnlock(hdataNew);\r
+       closeClipboard(NULL, hdataNew);\r
+}\r
+\r
+//\r
+void Engine::funcEmacsEditKillLinePred(\r
+       FunctionParam *i_param, const KeySeq *i_keySeq1, const KeySeq *i_keySeq2)\r
+{\r
+       m_emacsEditKillLine.m_doForceReset = false;\r
+       if (!i_param->m_isPressed)\r
+               return;\r
+\r
+       int r = m_emacsEditKillLine.pred();\r
+       const KeySeq *keySeq;\r
+       if (r == 1)\r
+               keySeq = i_keySeq1;\r
+       else if (r == 2)\r
+               keySeq = i_keySeq2;\r
+       else // r == 0\r
+               return;\r
+       ASSERT(keySeq);\r
+       generateKeySeqEvents(i_param->m_c, keySeq, Part_all);\r
+}\r
+\r
+//\r
+void Engine::funcEmacsEditKillLineFunc(FunctionParam *i_param)\r
+{\r
+       if (!i_param->m_isPressed)\r
+               return;\r
+       m_emacsEditKillLine.func();\r
+       m_emacsEditKillLine.m_doForceReset = false;\r
+}\r
+\r
+// clear log\r
+void Engine::funcLogClear(FunctionParam *i_param)\r
+{\r
+       if (!i_param->m_isPressed)\r
+               return;\r
+       PostMessage(getAssociatedWndow(), WM_APP_engineNotify,\r
+                               EngineNotify_clearLog, 0);\r
+}\r
+\r
+// recenter\r
+void Engine::funcRecenter(FunctionParam *i_param)\r
+{\r
+       if (!i_param->m_isPressed)\r
+               return;\r
+       if (m_hwndFocus) {\r
+               UINT WM_MAYU_MESSAGE = RegisterWindowMessage(\r
+                                                                  addSessionId(WM_MAYU_MESSAGE_NAME).c_str());\r
+               PostMessage(m_hwndFocus, WM_MAYU_MESSAGE, MayuMessage_funcRecenter, 0);\r
+       }\r
+}\r
+\r
+// set IME open status\r
+void Engine::funcSetImeStatus(FunctionParam *i_param, ToggleType i_toggle)\r
+{\r
+       if (!i_param->m_isPressed)\r
+               return;\r
+       if (m_hwndFocus) {\r
+               UINT WM_MAYU_MESSAGE = RegisterWindowMessage(\r
+                                                                  addSessionId(WM_MAYU_MESSAGE_NAME).c_str());\r
+               int status = -1;\r
+               switch (i_toggle) {\r
+               case ToggleType_toggle:\r
+                       status = -1;\r
+                       break;\r
+               case ToggleType_off:\r
+                       status = 0;\r
+                       break;\r
+               case ToggleType_on:\r
+                       status = 1;\r
+                       break;\r
+               }\r
+               PostMessage(m_hwndFocus, WM_MAYU_MESSAGE, MayuMessage_funcSetImeStatus, status);\r
+       }\r
+}\r
+\r
+// set IME open status\r
+void Engine::funcSetImeString(FunctionParam *i_param, const StrExprArg &i_data)\r
+{\r
+       if (!i_param->m_isPressed)\r
+               return;\r
+       if (m_hwndFocus) {\r
+               UINT WM_MAYU_MESSAGE = RegisterWindowMessage(\r
+                                                                  addSessionId(WM_MAYU_MESSAGE_NAME).c_str());\r
+               PostMessage(m_hwndFocus, WM_MAYU_MESSAGE, MayuMessage_funcSetImeString, i_data.eval().size() * sizeof(_TCHAR));\r
+\r
+               DWORD len = 0;\r
+               DWORD error;\r
+               DisconnectNamedPipe(m_hookPipe);\r
+               ConnectNamedPipe(m_hookPipe, NULL);\r
+               error = WriteFile(m_hookPipe, i_data.eval().c_str(),\r
+                                                 i_data.eval().size() * sizeof(_TCHAR),\r
+                                                 &len, NULL);\r
+\r
+               //FlushFileBuffers(m_hookPipe);\r
+       }\r
+}\r
+\r
+// Direct SSTP Server\r
+class DirectSSTPServer\r
+{\r
+public:\r
+       tstring m_path;\r
+       HWND m_hwnd;\r
+       tstring m_name;\r
+       tstring m_keroname;\r
+\r
+public:\r
+       DirectSSTPServer()\r
+                       : m_hwnd(NULL) {\r
+       }\r
+};\r
+\r
+\r
+class ParseDirectSSTPData\r
+{\r
+       typedef boost::match_results<boost::regex::const_iterator> MR;\r
+\r
+public:\r
+       typedef std::map<tstring, DirectSSTPServer> DirectSSTPServers;\r
+\r
+private:\r
+       DirectSSTPServers *m_directSSTPServers;\r
+\r
+public:\r
+       // constructor\r
+       ParseDirectSSTPData(DirectSSTPServers *i_directSSTPServers)\r
+                       : m_directSSTPServers(i_directSSTPServers) {\r
+       }\r
+\r
+       bool operator()(const MR& i_what) {\r
+#ifdef _UNICODE\r
+               tstring id(to_wstring(std::string(i_what[1].first, i_what[1].second)));\r
+               tstring member(to_wstring(std::string(i_what[2].first, i_what[2].second)));\r
+               tstring value(to_wstring(std::string(i_what[3].first, i_what[3].second)));\r
+#else\r
+               tstring id(i_what[1].first, i_what[1].second);\r
+               tstring member(i_what[2].first, i_what[2].second);\r
+               tstring value(i_what[3].first, i_what[3].second);\r
+#endif\r
+\r
+               if (member == _T("path"))\r
+                       (*m_directSSTPServers)[id].m_path = value;\r
+               else if (member == _T("hwnd"))\r
+                       (*m_directSSTPServers)[id].m_hwnd =\r
+                               reinterpret_cast<HWND>(_ttoi(value.c_str()));\r
+               else if (member == _T("name"))\r
+                       (*m_directSSTPServers)[id].m_name = value;\r
+               else if (member == _T("keroname"))\r
+                       (*m_directSSTPServers)[id].m_keroname = value;\r
+               return true;\r
+       }\r
+};\r
+\r
+// Direct SSTP\r
+void Engine::funcDirectSSTP(FunctionParam *i_param,\r
+                                                       const tregex &i_name,\r
+                                                       const StrExprArg &i_protocol,\r
+                                                       const std::list<tstringq> &i_headers)\r
+{\r
+       if (!i_param->m_isPressed)\r
+               return;\r
+\r
+       // check Direct SSTP server exist ?\r
+       if (HANDLE hm = OpenMutex(MUTEX_ALL_ACCESS, FALSE, _T("sakura")))\r
+               CloseHandle(hm);\r
+       else {\r
+               Acquire a(&m_log, 0);\r
+               m_log << _T(" Error(1): Direct SSTP server does not exist.");\r
+               return;\r
+       }\r
+\r
+       HANDLE hfm = OpenFileMapping(FILE_MAP_READ, FALSE, _T("Sakura"));\r
+       if (!hfm) {\r
+               Acquire a(&m_log, 0);\r
+               m_log << _T(" Error(2): Direct SSTP server does not provide data.");\r
+               return;\r
+       }\r
+\r
+       char *data =\r
+               reinterpret_cast<char *>(MapViewOfFile(hfm, FILE_MAP_READ, 0, 0, 0));\r
+       if (!data) {\r
+               CloseHandle(hfm);\r
+               Acquire a(&m_log, 0);\r
+               m_log << _T(" Error(3): Direct SSTP server does not provide data.");\r
+               return;\r
+       }\r
+\r
+       long length = *(long *)data;\r
+       const char *begin = data + 4;\r
+       const char *end = data + length;\r
+       boost::regex getSakura("([0-9a-fA-F]{32})\\.([^\x01]+)\x01(.*?)\r\n");\r
+\r
+       ParseDirectSSTPData::DirectSSTPServers servers;\r
+       boost::regex_iterator<boost::regex::const_iterator>\r
+       it(begin, end, getSakura), last;\r
+       for (; it != last; ++it)\r
+               ((ParseDirectSSTPData)(&servers))(*it);\r
+\r
+       // make request\r
+       tstring request;\r
+       if (!i_protocol.eval().size())\r
+               request += _T("NOTIFY SSTP/1.1");\r
+       else\r
+               request += i_protocol.eval();\r
+       request += _T("\r\n");\r
+\r
+       bool hasSender = false;\r
+       for (std::list<tstringq>::const_iterator\r
+                       i = i_headers.begin(); i != i_headers.end(); ++ i) {\r
+               if (_tcsnicmp(_T("Charset"), i->c_str(), 7) == 0 ||\r
+                               _tcsnicmp(_T("Hwnd"),    i->c_str(), 4) == 0)\r
+                       continue;\r
+               if (_tcsnicmp(_T("Sender"), i->c_str(), 6) == 0)\r
+                       hasSender = true;\r
+               request += i->c_str();\r
+               request += _T("\r\n");\r
+       }\r
+\r
+       if (!hasSender) {\r
+               request += _T("Sender: ");\r
+               request += loadString(IDS_mayu);\r
+               request += _T("\r\n");\r
+       }\r
+\r
+       _TCHAR buf[100];\r
+       _sntprintf(buf, NUMBER_OF(buf), _T("HWnd: %d\r\n"),\r
+                          reinterpret_cast<int>(m_hwndAssocWindow));\r
+       request += buf;\r
+\r
+#ifdef _UNICODE\r
+       request += _T("Charset: UTF-8\r\n");\r
+#else\r
+       request += _T("Charset: Shift_JIS\r\n");\r
+#endif\r
+       request += _T("\r\n");\r
+\r
+#ifdef _UNICODE\r
+       std::string request_UTF_8 = to_UTF_8(request);\r
+#endif\r
+\r
+       // send request to Direct SSTP Server which matches i_name;\r
+       for (ParseDirectSSTPData::DirectSSTPServers::iterator\r
+                       i = servers.begin(); i != servers.end(); ++ i) {\r
+               tsmatch what;\r
+               if (boost::regex_match(i->second.m_name, what, i_name)) {\r
+                       COPYDATASTRUCT cd;\r
+                       cd.dwData = 9801;\r
+#ifdef _UNICODE\r
+                       cd.cbData = request_UTF_8.size();\r
+                       cd.lpData = (void *)request_UTF_8.c_str();\r
+#else\r
+                       cd.cbData = request.size();\r
+                       cd.lpData = (void *)request.c_str();\r
+#endif\r
+#ifdef MAYU64\r
+                       DWORD_PTR result;\r
+#else\r
+                       DWORD result;\r
+#endif\r
+                       SendMessageTimeout(i->second.m_hwnd, WM_COPYDATA,\r
+                                                          reinterpret_cast<WPARAM>(m_hwndAssocWindow),\r
+                                                          reinterpret_cast<LPARAM>(&cd),\r
+                                                          SMTO_ABORTIFHUNG | SMTO_BLOCK, 5000, &result);\r
+               }\r
+       }\r
+\r
+       UnmapViewOfFile(data);\r
+       CloseHandle(hfm);\r
+}\r
+\r
+\r
+namespace shu\r
+{\r
+class PlugIn\r
+{\r
+       enum Type {\r
+               Type_A,\r
+               Type_W\r
+       };\r
+\r
+private:\r
+       HMODULE m_dll;\r
+       FARPROC m_func;\r
+       Type m_type;\r
+       tstringq m_funcParam;\r
+\r
+public:\r
+       PlugIn() : m_dll(NULL) {\r
+       }\r
+\r
+       ~PlugIn() {\r
+               FreeLibrary(m_dll);\r
+       }\r
+\r
+       bool load(const tstringq &i_dllName, const tstringq &i_funcName,\r
+                         const tstringq &i_funcParam, tomsgstream &i_log) {\r
+               m_dll = LoadLibrary((_T("Plugins\\") + i_dllName).c_str());\r
+               if (!m_dll) {\r
+                       m_dll = LoadLibrary((_T("Plugin\\") + i_dllName).c_str());\r
+                       if (!m_dll) {\r
+                               m_dll = LoadLibrary(i_dllName.c_str());\r
+                               if (!m_dll) {\r
+                                       Acquire a(&i_log);\r
+                                       i_log << std::endl;\r
+                                       i_log << _T("error: &PlugIn() failed to load ") << i_dllName << std::endl;\r
+                                       return false;\r
+                               }\r
+                       }\r
+               }\r
+\r
+               // get function\r
+#ifdef UNICODE\r
+#  define to_wstring\r
+#else\r
+#  define to_string\r
+#endif\r
+               m_type = Type_W;\r
+               m_func = GetProcAddress(m_dll, to_string(_T("mayu") + i_funcName + _T("W")).c_str());\r
+               if (!m_func) {\r
+                       m_type = Type_A;\r
+                       m_func\r
+                       = GetProcAddress(m_dll, to_string(_T("mayu") + i_funcName + _T("A")).c_str());\r
+                       if (!m_func) {\r
+                               m_func = GetProcAddress(m_dll, to_string(_T("mayu") + i_funcName).c_str());\r
+                               if (!m_func) {\r
+                                       m_func = GetProcAddress(m_dll, to_string(i_funcName).c_str());\r
+                                       if (!m_func) {\r
+                                               Acquire a(&i_log);\r
+                                               i_log << std::endl;\r
+                                               i_log << _T("error: &PlugIn() failed to find function: ")\r
+                                               << i_funcName << std::endl;\r
+                                               return false;\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+\r
+               m_funcParam = i_funcParam;\r
+               return true;\r
+       }\r
+\r
+       void exec() {\r
+               ASSERT( m_dll );\r
+               ASSERT( m_func );\r
+\r
+               typedef void (WINAPI * PLUGIN_FUNCTION_A)(const char *i_arg);\r
+               typedef void (WINAPI * PLUGIN_FUNCTION_W)(const wchar_t *i_arg);\r
+               switch (m_type) {\r
+               case Type_A:\r
+                       reinterpret_cast<PLUGIN_FUNCTION_A>(m_func)(to_string(m_funcParam).c_str());\r
+                       break;\r
+               case Type_W:\r
+                       reinterpret_cast<PLUGIN_FUNCTION_W>(m_func)(to_wstring(m_funcParam).c_str());\r
+                       break;\r
+               }\r
+       }\r
+#undef to_string\r
+#undef to_wstring\r
+};\r
+\r
+static void plugInThread(void *i_plugin)\r
+{\r
+       PlugIn *plugin = static_cast<PlugIn *>(i_plugin);\r
+       plugin->exec();\r
+       delete plugin;\r
+}\r
+}\r
+\r
+void Engine::funcPlugIn(FunctionParam *i_param,\r
+                                               const StrExprArg &i_dllName,\r
+                                               const StrExprArg &i_funcName,\r
+                                               const StrExprArg &i_funcParam,\r
+                                               BooleanType i_doesCreateThread)\r
+{\r
+       if (!i_param->m_isPressed)\r
+               return;\r
+\r
+       shu::PlugIn *plugin = new shu::PlugIn();\r
+       if (!plugin->load(i_dllName.eval(), i_funcName.eval(), i_funcParam.eval(), m_log)) {\r
+               delete plugin;\r
+               return;\r
+       }\r
+       if (i_doesCreateThread) {\r
+               if (_beginthread(shu::plugInThread, 0, plugin) == -1) {\r
+                       delete plugin;\r
+                       Acquire a(&m_log);\r
+                       m_log << std::endl;\r
+                       m_log << _T("error: &PlugIn() failed to create thread.");\r
+               }\r
+               return;\r
+       } else\r
+               plugin->exec();\r
+}\r
+\r
+\r
+void Engine::funcMouseHook(FunctionParam *i_param,\r
+                                                  MouseHookType i_hookType, int i_hookParam)\r
+{\r
+       GetCursorPos(&g_hookData->m_mousePos);\r
+       g_hookData->m_mouseHookType = i_hookType;\r
+       g_hookData->m_mouseHookParam = i_hookParam;\r
+\r
+       switch (i_hookType) {\r
+       case MouseHookType_WindowMove: {\r
+               // For this type, g_hookData->m_mouseHookParam means\r
+               // target window type to move.\r
+               HWND target;\r
+               bool isMDI;\r
+\r
+               // i_hooParam < 0 means target window to move is MDI.\r
+               if (i_hookParam < 0)\r
+                       isMDI = true;\r
+               else\r
+                       isMDI = false;\r
+\r
+               // abs(i_hookParam) == 2: target is window under mouse cursor\r
+               // otherwise: target is current focus window\r
+               if (i_hookParam == 2 || i_hookParam == -2)\r
+                       target = WindowFromPoint(g_hookData->m_mousePos);\r
+               else\r
+                       target = i_param->m_hwnd;\r
+\r
+               g_hookData->m_hwndMouseHookTarget =\r
+                       reinterpret_cast<DWORD>(getToplevelWindow(target, &isMDI));\r
+               break;\r
+               default:\r
+                       g_hookData->m_hwndMouseHookTarget = NULL;\r
+                       break;\r
+               }\r
+       }\r
+       return;\r
+}\r
+\r
+\r
+// cancel prefix\r
+void Engine::funcCancelPrefix(FunctionParam *i_param)\r
+{\r
+       m_isPrefix = false;\r
+}\r
+\r
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// StrExpr\r
+class StrExpr\r
+{\r
+private:\r
+       tstringq m_symbol;\r
+protected:\r
+       static const Engine *s_engine;\r
+public:\r
+       StrExpr(const tstringq &i_symbol) : m_symbol(i_symbol) {};\r
+\r
+       virtual ~StrExpr() {};\r
+\r
+       virtual StrExpr *clone() const {\r
+               return new StrExpr(*this);\r
+       }\r
+\r
+       virtual tstringq eval() const {\r
+               return m_symbol;\r
+       }\r
+\r
+       static void setEngine(const Engine *i_engine) {\r
+               s_engine = i_engine;\r
+       }\r
+};\r
+\r
+const Engine *StrExpr::s_engine = NULL;\r
+\r
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// StrExprClipboard\r
+class StrExprClipboard : public StrExpr\r
+{\r
+public:\r
+       StrExprClipboard(const tstringq &i_symbol) : StrExpr(i_symbol) {};\r
+\r
+       ~StrExprClipboard() {};\r
+\r
+       StrExpr *clone() const {\r
+               return new StrExprClipboard(*this);\r
+       }\r
+\r
+       tstringq eval() const {\r
+               HGLOBAL g;\r
+               const _TCHAR *text = getTextFromClipboard(&g);\r
+               const tstring value(text == NULL ? _T("") : text);\r
+               closeClipboard(g);\r
+               return value;\r
+       }\r
+};\r
+\r
+\r
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// StrExprWindowClassName\r
+class StrExprWindowClassName : public StrExpr\r
+{\r
+public:\r
+       StrExprWindowClassName(const tstringq &i_symbol) : StrExpr(i_symbol) {};\r
+\r
+       ~StrExprWindowClassName() {};\r
+\r
+       StrExpr *clone() const {\r
+               return new StrExprWindowClassName(*this);\r
+       }\r
+\r
+       tstringq eval() const {\r
+               return s_engine->getCurrentWindowClassName();\r
+       }\r
+};\r
+\r
+\r
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// StrExprWindowTitleName\r
+class StrExprWindowTitleName : public StrExpr\r
+{\r
+public:\r
+       StrExprWindowTitleName(const tstringq &i_symbol) : StrExpr(i_symbol) {};\r
+\r
+       ~StrExprWindowTitleName() {};\r
+\r
+       StrExpr *clone() const {\r
+               return new StrExprWindowTitleName(*this);\r
+       }\r
+\r
+       tstringq eval() const {\r
+               return s_engine->getCurrentWindowTitleName();\r
+       }\r
+};\r
+\r
+\r
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// StrExprArg\r
+\r
+\r
+// default constructor\r
+StrExprArg::StrExprArg()\r
+{\r
+       m_expr = new StrExpr(_T(""));\r
+}\r
+\r
+\r
+// copy contructor\r
+StrExprArg::StrExprArg(const StrExprArg &i_data)\r
+{\r
+       m_expr = i_data.m_expr->clone();\r
+}\r
+\r
+\r
+StrExprArg &StrExprArg::operator=(const StrExprArg &i_data)\r
+{\r
+       if (i_data.m_expr == m_expr)\r
+               return *this;\r
+\r
+       delete m_expr;\r
+       m_expr = i_data.m_expr->clone();\r
+\r
+       return *this;\r
+}\r
+\r
+\r
+// initializer\r
+StrExprArg::StrExprArg(const tstringq &i_symbol, Type i_type)\r
+{\r
+       switch (i_type) {\r
+       case Literal:\r
+               m_expr = new StrExpr(i_symbol);\r
+               break;\r
+       case Builtin:\r
+               if (i_symbol == _T("Clipboard"))\r
+                       m_expr = new StrExprClipboard(i_symbol);\r
+               else if (i_symbol == _T("WindowClassName"))\r
+                       m_expr = new StrExprWindowClassName(i_symbol);\r
+               else if (i_symbol == _T("WindowTitleName"))\r
+                       m_expr = new StrExprWindowTitleName(i_symbol);\r
+               break;\r
+       default:\r
+               break;\r
+       }\r
+}\r
+\r
+\r
+StrExprArg::~StrExprArg()\r
+{\r
+       delete m_expr;\r
+}\r
+\r
+\r
+tstringq StrExprArg::eval() const\r
+{\r
+       return m_expr->eval();\r
+}\r
+\r
+void StrExprArg::setEngine(const Engine *i_engine)\r
+{\r
+       StrExpr::setEngine(i_engine);\r
+}\r
+\r
+// stream output\r
+tostream &operator<<(tostream &i_ost, const StrExprArg &i_data)\r
+{\r
+       i_ost << i_data.eval();\r
+       return i_ost;\r
+}\r