1 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7 #include "dlgsetting.h"
8 #include "errormessage.h"
13 #include "windowstool.h"
14 #include "vkeytable.h"
25 Key prefixed(_T("prefixed"));
26 Key before_key_down(_T("before-key-down"));
27 Key after_key_up(_T("after-key-up"));
39 static bool getFilenameFromRegistry(
40 tstringi *o_name, tstringi *o_filename, Setting::Symbols *o_symbols)
42 Registry reg(MAYU_REGISTRY_ROOT);
44 reg.read(_T(".mayuIndex"), &index, 0);
46 _sntprintf(buf, NUMBER_OF(buf), _T(".mayu%d"), index);
49 if (!reg.read(buf, &entry))
52 tregex getFilename(_T("^([^;]*);([^;]*);(.*)$"));
53 tsmatch getFilenameResult;
54 if (!boost::regex_match(entry, getFilenameResult, getFilename))
58 *o_name = getFilenameResult.str(1);
60 *o_filename = getFilenameResult.str(2);
63 tstringi symbols = getFilenameResult.str(3);
64 tregex symbol(_T("-D([^;]*)(.*)$"));
66 while (boost::regex_search(symbols, symbolResult, symbol))
68 o_symbols->insert(symbolResult.str(1));
69 symbols = symbolResult.str(2);
76 // get home directory path
77 void getHomeDirectories(HomeDirectories *o_pathes)
80 if (getFilenameFromRegistry(NULL, &filename, NULL) &&
83 tregex getPath(_T("^(.*[/\\\\])[^/\\\\]*$"));
84 tsmatch getPathResult;
85 if (boost::regex_match(filename, getPathResult, getPath))
86 o_pathes->push_back(getPathResult.str(1));
89 const _TCHAR *home = _tgetenv(_T("HOME"));
91 o_pathes->push_back(home);
93 const _TCHAR *homedrive = _tgetenv(_T("HOMEDRIVE"));
94 const _TCHAR *homepath = _tgetenv(_T("HOMEPATH"));
95 if (homedrive && homepath)
96 o_pathes->push_back(tstringi(homedrive) + homepath);
98 const _TCHAR *userprofile = _tgetenv(_T("USERPROFILE"));
100 o_pathes->push_back(userprofile);
102 _TCHAR buf[GANA_MAX_PATH];
103 DWORD len = GetCurrentDirectory(NUMBER_OF(buf), buf);
104 if (0 < len && len < NUMBER_OF(buf))
105 o_pathes->push_back(buf);
107 if (GetModuleFileName(GetModuleHandle(NULL), buf, NUMBER_OF(buf)))
108 o_pathes->push_back(pathRemoveFileSpec(buf));
112 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
116 // is there no more tokens ?
117 bool SettingLoader::isEOL()
119 return m_ti == m_tokens.end();
124 Token *SettingLoader::getToken()
127 throw ErrorMessage() << _T("too few words.");
133 Token *SettingLoader::lookToken()
136 throw ErrorMessage() << _T("too few words.");
142 bool SettingLoader::getOpenParen(bool i_doesThrow, const _TCHAR *i_name)
144 if (!isEOL() && lookToken()->isOpenParen())
150 throw ErrorMessage() << _T("there must be `(' after `&")
151 << i_name << _T("'.");
157 bool SettingLoader::getCloseParen(bool i_doesThrow, const _TCHAR *i_name)
159 if (!isEOL() && lookToken()->isCloseParen())
165 throw ErrorMessage() << _T("`&") << i_name
166 << _T("': too many arguments.");
172 bool SettingLoader::getComma(bool i_doesThrow, const _TCHAR *i_name)
174 if (!isEOL() && lookToken()->isComma())
180 throw ErrorMessage() << _T("`&") << i_name
181 << _T("': comma expected.");
187 void SettingLoader::load_INCLUDE()
189 SettingLoader loader(m_soLog, m_log);
190 loader.m_defaultAssignModifier = m_defaultAssignModifier;
191 loader.m_defaultKeySeqModifier = m_defaultKeySeqModifier;
192 if (!loader.load(m_setting, (*getToken()).getString()))
193 m_isThereAnyError = true;
198 void SettingLoader::load_SCAN_CODES(Key *o_key)
200 for (int j = 0; j < Key::MAX_SCAN_CODES_SIZE && !isEOL(); ++ j)
206 Token *t = getToken();
209 sc.m_scan = (u_char)t->getNumber();
210 o_key->addScanCode(sc);
213 if (*t == _T("E0-")) sc.m_flags |= ScanCode::E0;
214 else if (*t == _T("E1-")) sc.m_flags |= ScanCode::E1;
215 else throw ErrorMessage() << _T("`") << *t
216 << _T("': invalid modifier.");
223 void SettingLoader::load_DEFINE_KEY()
225 Token *t = getToken();
231 key.addName(getToken()->getString());
232 while (t = getToken(), *t != _T(')'))
233 key.addName(t->getString());
234 if (*getToken() != _T("="))
235 throw ErrorMessage() << _T("there must be `=' after `)'.");
239 key.addName(t->getString());
240 while (t = getToken(), *t != _T("="))
241 key.addName(t->getString());
244 load_SCAN_CODES(&key);
245 m_setting->m_keyboard.addKey(key);
250 void SettingLoader::load_DEFINE_MODIFIER()
252 Token *t = getToken();
254 if (*t == _T("shift") ) mt = Modifier::Type_Shift;
255 else if (*t == _T("alt") ||
257 *t == _T("menu") ) mt = Modifier::Type_Alt;
258 else if (*t == _T("control") ||
259 *t == _T("ctrl") ) mt = Modifier::Type_Control;
260 else if (*t == _T("windows") ||
261 *t == _T("win") ) mt = Modifier::Type_Windows;
262 else throw ErrorMessage() << _T("`") << *t
263 << _T("': invalid modifier name.");
265 if (*getToken() != _T("="))
266 throw ErrorMessage() << _T("there must be `=' after modifier name.");
272 m_setting->m_keyboard.searchKeyByNonAliasName(t->getString());
274 throw ErrorMessage() << _T("`") << *t << _T("': invalid key name.");
275 m_setting->m_keyboard.addModifier(mt, key);
281 void SettingLoader::load_DEFINE_SYNC_KEY()
283 Key *key = m_setting->m_keyboard.getSyncKey();
285 key->addName(_T("sync"));
287 if (*getToken() != _T("="))
288 throw ErrorMessage() << _T("there must be `=' after `sync'.");
290 load_SCAN_CODES(key);
295 void SettingLoader::load_DEFINE_ALIAS()
297 Token *name = getToken();
299 if (*getToken() != _T("="))
300 throw ErrorMessage() << _T("there must be `=' after `alias'.");
302 Token *t = getToken();
303 Key *key = m_setting->m_keyboard.searchKeyByNonAliasName(t->getString());
305 throw ErrorMessage() << _T("`") << *t << _T("': invalid key name.");
306 m_setting->m_keyboard.addAlias(name->getString(), key);
310 // <DEFINE_SUBSTITUTE>
311 void SettingLoader::load_DEFINE_SUBSTITUTE()
313 typedef std::list<ModifiedKey> AssignedKeys;
314 AssignedKeys assignedKeys;
319 load_MODIFIER(Modifier::Type_ASSIGN, m_defaultAssignModifier);
320 mkey.m_key = load_KEY_NAME();
321 assignedKeys.push_back(mkey);
322 } while (!(*lookToken() == _T("=>") || *lookToken() == _T("=")));
325 KeySeq *keySeq = load_KEY_SEQUENCE(_T(""), false, Modifier::Type_ASSIGN);
326 ModifiedKey mkey = keySeq->getFirstModifiedKey();
328 throw ErrorMessage() << _T("no key is specified for substitute.");
330 for (AssignedKeys::iterator i = assignedKeys.begin();
331 i != assignedKeys.end(); ++ i)
332 m_setting->m_keyboard.addSubstitute(*i, mkey);
337 void SettingLoader::load_DEFINE_OPTION()
339 Token *t = getToken();
340 if (*t == _T("KL-")) {
341 if (*getToken() != _T("=")) {
342 throw ErrorMessage() << _T("there must be `=' after `def option KL-'.");
345 load_ARGUMENT(&m_setting->m_correctKanaLockHandling);
347 } else if (*t == _T("delay-of")) {
348 if (*getToken() != _T("!!!")) {
350 << _T("there must be `!!!' after `def option delay-of'.");
353 if (*getToken() != _T("=")) {
355 << _T("there must be `=' after `def option delay-of !!!'.");
358 load_ARGUMENT(&m_setting->m_oneShotRepeatableDelay);
360 } else if (*t == _T("sts4mayu")) {
361 if (*getToken() != _T("=")) {
363 << _T("there must be `=' after `def option sts4mayu'.");
366 load_ARGUMENT(&m_setting->m_sts4mayu);
368 } else if (*t == _T("cts4mayu")) {
369 if (*getToken() != _T("=")) {
371 << _T("there must be `=' after `def option cts4mayu'.");
374 load_ARGUMENT(&m_setting->m_cts4mayu);
377 throw ErrorMessage() << _T("syntax error `def option ") << *t << _T("'.");
383 // <KEYBOARD_DEFINITION>
384 void SettingLoader::load_KEYBOARD_DEFINITION()
386 Token *t = getToken();
389 if (*t == _T("key")) load_DEFINE_KEY();
392 else if (*t == _T("mod")) load_DEFINE_MODIFIER();
395 else if (*t == _T("sync")) load_DEFINE_SYNC_KEY();
398 else if (*t == _T("alias")) load_DEFINE_ALIAS();
400 // <DEFINE_SUBSTITUTE>
401 else if (*t == _T("subst")) load_DEFINE_SUBSTITUTE();
404 else if (*t == _T("option")) load_DEFINE_OPTION();
407 else throw ErrorMessage() << _T("syntax error `") << *t << _T("'.");
412 Modifier SettingLoader::load_MODIFIER(
413 Modifier::Type i_mode, Modifier i_modifier, Modifier::Type *o_mode)
416 *o_mode = Modifier::Type_begin;
418 Modifier isModifierSpecified;
419 enum { PRESS, RELEASE, DONTCARE } flag = PRESS;
422 for (i = i_mode; i < Modifier::Type_ASSIGN; ++ i)
424 i_modifier.dontcare(Modifier::Type(i));
425 isModifierSpecified.on(Modifier::Type(i));
435 const static struct { const _TCHAR *m_s; Modifier::Type m_mt; } map[] =
438 { _T("S-"), Modifier::Type_Shift },
439 { _T("A-"), Modifier::Type_Alt },
440 { _T("M-"), Modifier::Type_Alt },
441 { _T("C-"), Modifier::Type_Control },
442 { _T("W-"), Modifier::Type_Windows },
444 { _T("U-"), Modifier::Type_Up },
445 { _T("D-"), Modifier::Type_Down },
447 { _T("R-"), Modifier::Type_Repeat },
448 { _T("IL-"), Modifier::Type_ImeLock },
449 { _T("IC-"), Modifier::Type_ImeComp },
450 { _T("I-"), Modifier::Type_ImeComp },
451 { _T("NL-"), Modifier::Type_NumLock },
452 { _T("CL-"), Modifier::Type_CapsLock },
453 { _T("SL-"), Modifier::Type_ScrollLock },
454 { _T("KL-"), Modifier::Type_KanaLock },
455 { _T("MAX-"), Modifier::Type_Maximized },
456 { _T("MIN-"), Modifier::Type_Minimized },
457 { _T("MMAX-"), Modifier::Type_MdiMaximized },
458 { _T("MMIN-"), Modifier::Type_MdiMinimized },
459 { _T("T-"), Modifier::Type_Touchpad },
460 { _T("TS-"), Modifier::Type_TouchpadSticky },
461 { _T("M0-"), Modifier::Type_Mod0 },
462 { _T("M1-"), Modifier::Type_Mod1 },
463 { _T("M2-"), Modifier::Type_Mod2 },
464 { _T("M3-"), Modifier::Type_Mod3 },
465 { _T("M4-"), Modifier::Type_Mod4 },
466 { _T("M5-"), Modifier::Type_Mod5 },
467 { _T("M6-"), Modifier::Type_Mod6 },
468 { _T("M7-"), Modifier::Type_Mod7 },
469 { _T("M8-"), Modifier::Type_Mod8 },
470 { _T("M9-"), Modifier::Type_Mod9 },
471 { _T("L0-"), Modifier::Type_Lock0 },
472 { _T("L1-"), Modifier::Type_Lock1 },
473 { _T("L2-"), Modifier::Type_Lock2 },
474 { _T("L3-"), Modifier::Type_Lock3 },
475 { _T("L4-"), Modifier::Type_Lock4 },
476 { _T("L5-"), Modifier::Type_Lock5 },
477 { _T("L6-"), Modifier::Type_Lock6 },
478 { _T("L7-"), Modifier::Type_Lock7 },
479 { _T("L8-"), Modifier::Type_Lock8 },
480 { _T("L9-"), Modifier::Type_Lock9 },
483 for (int i = 0; i < NUMBER_OF(map); ++ i)
484 if (*t == map[i].m_s)
487 Modifier::Type mt = map[i].m_mt;
488 if (static_cast<int>(i_mode) <= static_cast<int>(mt))
489 throw ErrorMessage() << _T("`") << *t
490 << _T("': invalid modifier at this context.");
493 case PRESS: i_modifier.press(mt); break;
494 case RELEASE: i_modifier.release(mt); break;
495 case DONTCARE: i_modifier.dontcare(mt); break;
497 isModifierSpecified.on(mt);
500 if (o_mode && *o_mode < mt)
502 if (mt < Modifier::Type_BASIC)
503 *o_mode = Modifier::Type_BASIC;
504 else if (mt < Modifier::Type_KEYSEQ)
505 *o_mode = Modifier::Type_KEYSEQ;
506 else if (mt < Modifier::Type_ASSIGN)
507 *o_mode = Modifier::Type_ASSIGN;
529 for (i = Modifier::Type_begin; i != Modifier::Type_end; ++ i)
530 if (!isModifierSpecified.isOn(Modifier::Type(i)))
534 case RELEASE: i_modifier.release(Modifier::Type(i)); break;
535 case DONTCARE: i_modifier.dontcare(Modifier::Type(i)); break;
539 bool isDontcareUp = i_modifier.isDontcare(Modifier::Type_Up);
540 bool isDontcareDown = i_modifier.isDontcare(Modifier::Type_Down);
541 bool isOnUp = i_modifier.isOn(Modifier::Type_Up);
542 bool isOnDown = i_modifier.isOn(Modifier::Type_Down);
543 if (isDontcareUp && isDontcareDown)
545 else if (isDontcareUp)
546 i_modifier.on(Modifier::Type_Up, !isOnDown);
547 else if (isDontcareDown)
548 i_modifier.on(Modifier::Type_Down, !isOnUp);
549 else if (isOnUp == isOnDown)
551 i_modifier.dontcare(Modifier::Type_Up);
552 i_modifier.dontcare(Modifier::Type_Down);
556 if (!isModifierSpecified.isOn(Modifier::Type_Repeat))
557 i_modifier.dontcare(Modifier::Type_Repeat);
563 Key *SettingLoader::load_KEY_NAME()
565 Token *t = getToken();
566 Key *key = m_setting->m_keyboard.searchKey(t->getString());
568 throw ErrorMessage() << _T("`") << *t << _T("': invalid key name.");
573 // <KEYMAP_DEFINITION>
574 void SettingLoader::load_KEYMAP_DEFINITION(const Token *i_which)
576 Keymap::Type type = Keymap::Type_keymap;
577 Token *name = getToken(); // <KEYMAP_NAME>
578 tstringi windowClassName;
579 tstringi windowTitleName;
580 KeySeq *keySeq = NULL;
581 Keymap *parentKeymap = NULL;
582 bool isKeymap2 = false;
583 bool doesLoadDefaultKeySeq = false;
587 Token *t = lookToken();
588 if (*i_which == _T("window")) // <WINDOW>
590 if (t->isOpenParen())
591 // "(" <WINDOW_CLASS_NAME> "&&" <WINDOW_TITLE_NAME> ")"
592 // "(" <WINDOW_CLASS_NAME> "||" <WINDOW_TITLE_NAME> ")"
595 windowClassName = getToken()->getRegexp();
598 type = Keymap::Type_windowAnd;
599 else if (*t == _T("||"))
600 type = Keymap::Type_windowOr;
602 throw ErrorMessage() << _T("`") << *t << _T("': unknown operator.");
603 windowTitleName = getToken()->getRegexp();
604 if (!getToken()->isCloseParen())
605 throw ErrorMessage() << _T("there must be `)'.");
607 else if (t->isRegexp()) // <WINDOW_CLASS_NAME>
610 type = Keymap::Type_windowAnd;
611 windowClassName = t->getRegexp();
614 else if (*i_which == _T("keymap"))
616 else if (*i_which == _T("keymap2"))
622 doesLoadDefaultKeySeq = true;
625 m_currentKeymap = m_setting->m_keymaps.add(
626 Keymap(type, name->getString(), windowClassName, windowTitleName,
629 if (doesLoadDefaultKeySeq)
631 Token *t = lookToken();
637 parentKeymap = m_setting->m_keymaps.searchByName(t->getString());
639 throw ErrorMessage() << _T("`") << *t
640 << _T("': unknown keymap name.");
645 if (!(*t == _T("=>") || *t == _T("=")))
646 throw ErrorMessage() << _T("`") << *t << _T("': syntax error.");
647 keySeq = SettingLoader::load_KEY_SEQUENCE();
653 if (type == Keymap::Type_keymap && !isKeymap2)
654 fd = createFunctionData(_T("KeymapParent"));
655 else if (type == Keymap::Type_keymap && !isKeymap2)
656 fd = createFunctionData(_T("Undefined"));
657 else // (type == Keymap::Type_windowAnd || type == Keymap::Type_windowOr)
658 fd = createFunctionData(_T("KeymapParent"));
660 keySeq = m_setting->m_keySeqs.add(
661 KeySeq(name->getString()).add(ActionFunction(fd)));
664 m_currentKeymap->setIfNotYet(keySeq, parentKeymap);
669 void SettingLoader::load_ARGUMENT(bool *o_arg)
671 *o_arg = !(*getToken() == _T("false"));
676 void SettingLoader::load_ARGUMENT(int *o_arg)
678 *o_arg = getToken()->getNumber();
683 void SettingLoader::load_ARGUMENT(unsigned int *o_arg)
685 *o_arg = getToken()->getNumber();
690 void SettingLoader::load_ARGUMENT(long *o_arg)
692 *o_arg = getToken()->getNumber();
697 void SettingLoader::load_ARGUMENT(tstringq *o_arg)
699 *o_arg = getToken()->getString();
704 void SettingLoader::load_ARGUMENT(std::list<tstringq> *o_arg)
708 if (!lookToken()->isString())
710 o_arg->push_back(getToken()->getString());
712 if (!lookToken()->isComma())
720 void SettingLoader::load_ARGUMENT(tregex *o_arg)
722 *o_arg = getToken()->getRegexp();
726 // <ARGUMENT_VK>
727 void SettingLoader::load_ARGUMENT(VKey *o_arg)
729 Token *t = getToken();
733 if (t->isNumber()) { vkey |= static_cast<BYTE>(t->getNumber()); break; }
734 else if (*t == _T("E-")) vkey |= VKey_extended;
735 else if (*t == _T("U-")) vkey |= VKey_released;
736 else if (*t == _T("D-")) vkey |= VKey_pressed;
739 const VKeyTable *vkt;
740 for (vkt = g_vkeyTable; vkt->m_name; ++ vkt)
741 if (*t == vkt->m_name)
744 throw ErrorMessage() << _T("`") << *t
745 << _T("': unknown virtual key name.");
751 if (!(vkey & VKey_released) && !(vkey & VKey_pressed))
752 vkey |= VKey_released | VKey_pressed;
753 *o_arg = static_cast<VKey>(vkey);
757 // <ARGUMENT_WINDOW>
758 void SettingLoader::load_ARGUMENT(ToWindowType *o_arg)
760 Token *t = getToken();
763 if (ToWindowType_toBegin <= t->getNumber())
765 *o_arg = static_cast<ToWindowType>(t->getNumber());
769 else if (getTypeValue(o_arg, t->getString()))
771 throw ErrorMessage() << _T("`") << *t << _T("': invalid target window.");
776 void SettingLoader::load_ARGUMENT(GravityType *o_arg)
778 Token *t = getToken();
779 if (getTypeValue(o_arg, t->getString()))
781 throw ErrorMessage() << _T("`") << *t << _T("': unknown gravity symbol.");
786 void SettingLoader::load_ARGUMENT(MouseHookType *o_arg)
788 Token *t = getToken();
789 if (getTypeValue(o_arg, t->getString()))
791 throw ErrorMessage() << _T("`") << *t << _T("': unknown MouseHookType symbol.");
796 void SettingLoader::load_ARGUMENT(MayuDialogType *o_arg)
798 Token *t = getToken();
799 if (getTypeValue(o_arg, t->getString()))
801 throw ErrorMessage() << _T("`") << *t << _T("': unknown dialog box.");
805 // <ARGUMENT_LOCK>
806 void SettingLoader::load_ARGUMENT(ModifierLockType *o_arg)
808 Token *t = getToken();
809 if (getTypeValue(o_arg, t->getString()))
811 throw ErrorMessage() << _T("`") << *t << _T("': unknown lock name.");
815 // <ARGUMENT_LOCK>
816 void SettingLoader::load_ARGUMENT(ToggleType *o_arg)
818 Token *t = getToken();
819 if (getTypeValue(o_arg, t->getString()))
821 throw ErrorMessage() << _T("`") << *t << _T("': unknown toggle name.");
825 // <ARGUMENT_SHOW_WINDOW>
826 void SettingLoader::load_ARGUMENT(ShowCommandType *o_arg)
828 Token *t = getToken();
829 if (getTypeValue(o_arg, t->getString()))
831 throw ErrorMessage() << _T("`") << *t << _T("': unknown show command.");
835 // <ARGUMENT_TARGET_WINDOW>
836 void SettingLoader::load_ARGUMENT(TargetWindowType *o_arg)
838 Token *t = getToken();
839 if (getTypeValue(o_arg, t->getString()))
841 throw ErrorMessage() << _T("`") << *t
842 << _T("': unknown target window type.");
847 void SettingLoader::load_ARGUMENT(BooleanType *o_arg)
849 Token *t = getToken();
850 if (getTypeValue(o_arg, t->getString()))
852 throw ErrorMessage() << _T("`") << *t << _T("': must be true or false.");
857 void SettingLoader::load_ARGUMENT(LogicalOperatorType *o_arg)
859 Token *t = getToken();
860 if (getTypeValue(o_arg, t->getString()))
862 throw ErrorMessage() << _T("`") << *t << _T("': must be 'or' or 'and'.");
867 void SettingLoader::load_ARGUMENT(Modifier *o_arg)
870 for (int i = Modifier::Type_begin; i != Modifier::Type_end; ++ i)
871 modifier.dontcare(static_cast<Modifier::Type>(i));
872 *o_arg = load_MODIFIER(Modifier::Type_ASSIGN, modifier);
877 void SettingLoader::load_ARGUMENT(const Keymap **o_arg)
879 Token *t = getToken();
880 const Keymap *&keymap = *o_arg;
881 keymap = m_setting->m_keymaps.searchByName(t->getString());
883 throw ErrorMessage() << _T("`") << *t << _T("': unknown keymap name.");
888 void SettingLoader::load_ARGUMENT(const KeySeq **o_arg)
890 Token *t = getToken();
891 const KeySeq *&keySeq = *o_arg;
892 if (t->isOpenParen())
894 keySeq = load_KEY_SEQUENCE(_T(""), true);
895 getToken(); // close paren
897 else if (*t == _T("$"))
900 keySeq = m_setting->m_keySeqs.searchByName(t->getString());
902 throw ErrorMessage() << _T("`$") << *t << _T("': unknown keyseq name.");
905 throw ErrorMessage() << _T("`") << *t << _T("': it is not keyseq.");
910 void SettingLoader::load_ARGUMENT(StrExprArg *o_arg)
912 Token *t = getToken();
913 StrExprArg::Type type = StrExprArg::Literal;
914 if (*t == _T("$") && t->isQuoted() == false
915 && lookToken()->getType() == Token::Type_string)
917 type = StrExprArg::Builtin;
920 *o_arg = StrExprArg(t->getString(), type);
925 void SettingLoader::load_ARGUMENT(WindowMonitorFromType *o_arg)
927 Token *t = getToken();
928 if (getTypeValue(o_arg, t->getString()))
930 throw ErrorMessage() << _T("`") << *t
931 << _T("': unknown monitor from type.");
936 KeySeq *SettingLoader::load_KEY_SEQUENCE(
937 const tstringi &i_name, bool i_isInParen, Modifier::Type i_mode)
939 KeySeq keySeq(i_name);
943 Modifier modifier = load_MODIFIER(i_mode, m_defaultKeySeqModifier, &mode);
944 keySeq.setMode(mode);
945 Token *t = lookToken();
946 if (t->isCloseParen() && i_isInParen)
948 else if (t->isOpenParen())
950 getToken(); // open paren
951 KeySeq *ks = load_KEY_SEQUENCE(_T(""), true, i_mode);
952 getToken(); // close paren
953 keySeq.add(ActionKeySeq(ks));
955 else if (*t == _T("$")) // <KEYSEQ_NAME>
959 KeySeq *ks = m_setting->m_keySeqs.searchByName(t->getString());
961 throw ErrorMessage() << _T("`$") << *t
962 << _T("': unknown keyseq name.");
963 if (!ks->isCorrectMode(i_mode))
966 << _T("': Some of R-, IL-, IC-, NL-, CL-, SL-, KL-, MAX-, MIN-, MMAX-, MMIN-, T-, TS-, M0...M9- and L0...L9- are used in the keyseq. They are prohibited in this context.");
967 keySeq.setMode(ks->getMode());
968 keySeq.add(ActionKeySeq(ks));
970 else if (*t == _T("&")) // <FUNCTION_NAME>
976 ActionFunction af(createFunctionData(t->getString()), modifier);
977 if (af.m_functionData == NULL)
978 throw ErrorMessage() << _T("`&") << *t
979 << _T("': unknown function name.");
980 af.m_functionData->load(this);
983 else // <KEYSEQ_MODIFIED_KEY_NAME>
986 mkey.m_modifier = modifier;
987 mkey.m_key = load_KEY_NAME();
988 keySeq.add(ActionKey(mkey));
991 return m_setting->m_keySeqs.add(keySeq);
996 void SettingLoader::load_KEY_ASSIGN()
998 typedef std::list<ModifiedKey> AssignedKeys;
999 AssignedKeys assignedKeys;
1003 load_MODIFIER(Modifier::Type_ASSIGN, m_defaultAssignModifier);
1004 if (*lookToken() == _T("="))
1007 m_defaultKeySeqModifier = load_MODIFIER(Modifier::Type_KEYSEQ,
1008 m_defaultKeySeqModifier);
1009 m_defaultAssignModifier = mkey.m_modifier;
1015 mkey.m_key = load_KEY_NAME();
1016 assignedKeys.push_back(mkey);
1017 if (*lookToken() == _T("=>") || *lookToken() == _T("="))
1020 load_MODIFIER(Modifier::Type_ASSIGN, m_defaultAssignModifier);
1024 ASSERT(m_currentKeymap);
1025 KeySeq *keySeq = load_KEY_SEQUENCE();
1026 for (AssignedKeys::iterator i = assignedKeys.begin();
1027 i != assignedKeys.end(); ++ i)
1028 m_currentKeymap->addAssignment(*i, keySeq);
1033 void SettingLoader::load_EVENT_ASSIGN()
1035 std::list<ModifiedKey> assignedKeys;
1038 mkey.m_modifier.dontcare(); //set all modifiers to dontcare
1040 Token *t = getToken();
1042 for (e = Event::events; *e; ++ e)
1043 if (*t == (*e)->getName())
1049 throw ErrorMessage() << _T("`") << *t << _T("': invalid event name.");
1052 if (!(*t == _T("=>") || *t == _T("=")))
1053 throw ErrorMessage() << _T("`=' is expected.");
1055 ASSERT(m_currentKeymap);
1056 KeySeq *keySeq = load_KEY_SEQUENCE();
1057 m_currentKeymap->addAssignment(mkey, keySeq);
1061 // <MODIFIER_ASSIGNMENT>
1062 void SettingLoader::load_MODIFIER_ASSIGNMENT()
1065 Token *t = getToken();
1070 Keymap::AssignMode am = Keymap::AM_notModifier;
1071 if (*t == _T("!") ) am = Keymap::AM_true, t = getToken();
1072 else if (*t == _T("!!") ) am = Keymap::AM_oneShot, t = getToken();
1073 else if (*t == _T("!!!")) am = Keymap::AM_oneShotRepeatable, t = getToken();
1075 if (*t == _T("shift")) mt = Modifier::Type_Shift;
1076 else if (*t == _T("alt") ||
1078 *t == _T("menu") ) mt = Modifier::Type_Alt;
1079 else if (*t == _T("control") ||
1080 *t == _T("ctrl") ) mt = Modifier::Type_Control;
1081 else if (*t == _T("windows") ||
1082 *t == _T("win") ) mt = Modifier::Type_Windows;
1083 else if (*t == _T("mod0") ) mt = Modifier::Type_Mod0;
1084 else if (*t == _T("mod1") ) mt = Modifier::Type_Mod1;
1085 else if (*t == _T("mod2") ) mt = Modifier::Type_Mod2;
1086 else if (*t == _T("mod3") ) mt = Modifier::Type_Mod3;
1087 else if (*t == _T("mod4") ) mt = Modifier::Type_Mod4;
1088 else if (*t == _T("mod5") ) mt = Modifier::Type_Mod5;
1089 else if (*t == _T("mod6") ) mt = Modifier::Type_Mod6;
1090 else if (*t == _T("mod7") ) mt = Modifier::Type_Mod7;
1091 else if (*t == _T("mod8") ) mt = Modifier::Type_Mod8;
1092 else if (*t == _T("mod9") ) mt = Modifier::Type_Mod9;
1093 else throw ErrorMessage() << _T("`") << *t
1094 << _T("': invalid modifier name.");
1096 if (am == Keymap::AM_notModifier)
1099 m_currentKeymap->addModifier(mt, Keymap::AO_overwrite, am, NULL);
1107 Keymap::AssignOperator ao;
1108 if (*t == _T("=") ) ao = Keymap::AO_new;
1109 else if (*t == _T("+=")) ao = Keymap::AO_add;
1110 else if (*t == _T("-=")) ao = Keymap::AO_sub;
1111 else throw ErrorMessage() << _T("`") << *t << _T("': is unknown operator.");
1113 // <ASSIGN_MODE>? <KEY_NAME>
1118 Keymap::AssignMode am = Keymap::AM_normal;
1119 if (*t == _T("!") ) am = Keymap::AM_true, t = getToken();
1120 else if (*t == _T("!!") ) am = Keymap::AM_oneShot, t = getToken();
1121 else if (*t == _T("!!!")) am = Keymap::AM_oneShotRepeatable, t = getToken();
1124 Key *key = m_setting->m_keyboard.searchKey(t->getString());
1126 throw ErrorMessage() << _T("`") << *t << _T("': invalid key name.");
1128 // we can ignore warning C4701
1129 m_currentKeymap->addModifier(mt, ao, am, key);
1130 if (ao == Keymap::AO_new)
1131 ao = Keymap::AO_add;
1136 // <KEYSEQ_DEFINITION>
1137 void SettingLoader::load_KEYSEQ_DEFINITION()
1139 if (*getToken() != _T("$"))
1140 throw ErrorMessage() << _T("there must be `$' after `keyseq'");
1141 Token *name = getToken();
1142 if (*getToken() != _T("="))
1143 throw ErrorMessage() << _T("there must be `=' after keyseq naem");
1144 load_KEY_SEQUENCE(name->getString(), false, Modifier::Type_ASSIGN);
1149 void SettingLoader::load_DEFINE()
1151 m_setting->m_symbols.insert(getToken()->getString());
1156 void SettingLoader::load_IF()
1158 if (!getToken()->isOpenParen())
1159 throw ErrorMessage() << _T("there must be `(' after `if'.");
1160 Token *t = getToken(); // <SYMBOL> or !
1165 t = getToken(); // <SYMBOL>
1168 bool doesSymbolExist = (m_setting->m_symbols.find(t->getString())
1169 != m_setting->m_symbols.end());
1170 bool doesRead = ((doesSymbolExist && !not) ||
1171 (!doesSymbolExist && not));
1172 if (0 < m_canReadStack.size())
1173 doesRead = doesRead && m_canReadStack.back();
1175 if (!getToken()->isCloseParen())
1176 throw ErrorMessage() << _T("there must be `)'.");
1178 m_canReadStack.push_back(doesRead);
1181 size_t len = m_canReadStack.size();
1183 if (len < m_canReadStack.size())
1185 bool r = m_canReadStack.back();
1186 m_canReadStack.pop_back();
1187 m_canReadStack[len - 1] = r && doesRead;
1189 else if (len == m_canReadStack.size())
1190 m_canReadStack.pop_back();
1198 void SettingLoader::load_ELSE(bool i_isElseIf, const tstringi &i_token)
1200 bool doesRead = !load_ENDIF(i_token);
1201 if (0 < m_canReadStack.size())
1202 doesRead = doesRead && m_canReadStack.back();
1203 m_canReadStack.push_back(doesRead);
1206 size_t len = m_canReadStack.size();
1211 if (len < m_canReadStack.size())
1213 bool r = m_canReadStack.back();
1214 m_canReadStack.pop_back();
1215 m_canReadStack[len - 1] = doesRead && r;
1217 else if (len == m_canReadStack.size())
1218 m_canReadStack.pop_back();
1226 bool SettingLoader::load_ENDIF(const tstringi &i_token)
1228 if (m_canReadStack.size() == 0)
1229 throw ErrorMessage() << _T("unbalanced `") << i_token << _T("'");
1230 bool r = m_canReadStack.back();
1231 m_canReadStack.pop_back();
1237 void SettingLoader::load_LINE()
1239 Token *i_token = getToken();
1242 if (*i_token == _T("if") ||
1243 *i_token == _T("and")) load_IF();
1244 else if (*i_token == _T("else")) load_ELSE(false, i_token->getString());
1245 else if (*i_token == _T("elseif") ||
1246 *i_token == _T("elsif") ||
1247 *i_token == _T("elif") ||
1248 *i_token == _T("or")) load_ELSE(true, i_token->getString());
1249 else if (*i_token == _T("endif")) load_ENDIF(_T("endif"));
1250 else if (0 < m_canReadStack.size() && !m_canReadStack.back())
1255 else if (*i_token == _T("define")) load_DEFINE();
1257 else if (*i_token == _T("include")) load_INCLUDE();
1258 // <KEYBOARD_DEFINITION>
1259 else if (*i_token == _T("def")) load_KEYBOARD_DEFINITION();
1260 // <KEYMAP_DEFINITION>
1261 else if (*i_token == _T("keymap") ||
1262 *i_token == _T("keymap2") ||
1263 *i_token == _T("window")) load_KEYMAP_DEFINITION(i_token);
1265 else if (*i_token == _T("key")) load_KEY_ASSIGN();
1267 else if (*i_token == _T("event")) load_EVENT_ASSIGN();
1268 // <MODIFIER_ASSIGNMENT>
1269 else if (*i_token == _T("mod")) load_MODIFIER_ASSIGNMENT();
1270 // <KEYSEQ_DEFINITION>
1271 else if (*i_token == _T("keyseq")) load_KEYSEQ_DEFINITION();
1273 throw ErrorMessage() << _T("syntax error `") << *i_token << _T("'.");
1277 // prefix sort predicate used in load(const string &)
1278 static bool prefixSortPred(const tstringi &i_a, const tstringi &i_b)
1280 return i_b.size() < i_a.size();
1285 _UNICODE: read file (UTF-16 LE/BE, UTF-8, locale specific multibyte encoding)
1288 bool readFile(tstring *o_data, const tstringi &i_filename)
1292 // bcc's _wstat cannot obtain file size
1294 if (_tstat(i_filename.c_str(), &sbuf) < 0 || sbuf.st_size == 0)
1297 // so, we use _wstati64 for bcc
1298 struct stati64_t sbuf;
1299 if (_tstati64(i_filename.c_str(), &sbuf) < 0 || sbuf.st_size == 0)
1301 // following check is needed to cast sbuf.st_size to size_t safely
1302 // this cast occurs because of above workaround for bcc
1303 if (sbuf.st_size > UINT_MAX)
1308 FILE *fp = _tfopen(i_filename.c_str(), _T("rb"));
1313 Array<BYTE> buf(static_cast<size_t>(sbuf.st_size) + 1);
1314 if (fread(buf.get(), static_cast<size_t>(sbuf.st_size), 1, fp) != 1)
1319 buf.get()[sbuf.st_size] = 0; // mbstowcs() requires null
1320 // terminated string
1324 if (buf.get()[0] == 0xffU && buf.get()[1] == 0xfeU &&
1325 sbuf.st_size % 2 == 0)
1326 // UTF-16 Little Endien
1328 size_t size = static_cast<size_t>(sbuf.st_size) / 2;
1329 o_data->resize(size);
1330 BYTE *p = buf.get();
1331 for (size_t i = 0; i < size; ++ i)
1333 wchar_t c = static_cast<wchar_t>(*p ++);
1334 c |= static_cast<wchar_t>(*p ++) << 8;
1342 if (buf.get()[0] == 0xfeU && buf.get()[1] == 0xffU &&
1343 sbuf.st_size % 2 == 0)
1344 // UTF-16 Big Endien
1346 size_t size = static_cast<size_t>(sbuf.st_size) / 2;
1347 o_data->resize(size);
1348 BYTE *p = buf.get();
1349 for (size_t i = 0; i < size; ++ i)
1351 wchar_t c = static_cast<wchar_t>(*p ++) << 8;
1352 c |= static_cast<wchar_t>(*p ++);
1359 // try multibyte charset
1360 size_t wsize = mbstowcs(NULL, reinterpret_cast<char *>(buf.get()), 0);
1361 if (wsize != size_t(-1))
1363 Array<wchar_t> wbuf(wsize);
1364 mbstowcs(wbuf.get(), reinterpret_cast<char *>(buf.get()), wsize);
1365 o_data->assign(wbuf.get(), wbuf.get() + wsize);
1372 Array<wchar_t> wbuf(static_cast<size_t>(sbuf.st_size));
1373 BYTE *f = buf.get();
1374 BYTE *end = buf.get() + sbuf.st_size;
1375 wchar_t *d = wbuf.get();
1376 enum { STATE_1, STATE_2of2, STATE_2of3, STATE_3of3 } state = STATE_1;
1383 if (!(*f & 0x80)) // 0xxxxxxx: 00-7F
1384 *d++ = static_cast<wchar_t>(*f++);
1385 else if ((*f & 0xe0) == 0xc0) // 110xxxxx 10xxxxxx: 0080-07FF
1387 *d = ((static_cast<wchar_t>(*f++) & 0x1f) << 6);
1390 else if ((*f & 0xf0) == 0xe0) // 1110xxxx 10xxxxxx 10xxxxxx:
1393 *d = ((static_cast<wchar_t>(*f++) & 0x0f) << 12);
1402 if ((*f & 0xc0) != 0x80)
1404 *d++ |= (static_cast<wchar_t>(*f++) & 0x3f);
1409 if ((*f & 0xc0) != 0x80)
1411 *d |= ((static_cast<wchar_t>(*f++) & 0x3f) << 6);
1416 o_data->assign(wbuf.get(), d);
1425 o_data->resize(static_cast<size_t>(sbuf.st_size));
1426 for (off_t i = 0; i < sbuf.st_size; ++ i)
1427 (*o_data)[i] = buf.get()[i];
1433 // load (called from load(Setting *, const tstringi &) only)
1434 void SettingLoader::load(const tstringi &i_filename)
1436 m_currentFilename = i_filename;
1439 if (!readFile(&data, m_currentFilename))
1442 *m_log << m_currentFilename << _T(" : error: file not found") << std::endl;
1444 *m_log << data << std::endl;
1446 m_isThereAnyError = true;
1451 if (m_prefixesRefCcount == 0)
1453 static const _TCHAR *prefixes[] =
1455 _T("="), _T("=>"), _T("&&"), _T("||"), _T(":"), _T("$"), _T("&"),
1456 _T("-="), _T("+="), _T("!!!"), _T("!!"), _T("!"),
1457 _T("E0-"), _T("E1-"), // <SCAN_CODE_EXTENTION>
1458 _T("S-"), _T("A-"), _T("M-"), _T("C-"), // <BASIC_MODIFIER>
1459 _T("W-"), _T("*"), _T("~"),
1460 _T("U-"), _T("D-"), // <KEYSEQ_MODIFIER>
1461 _T("R-"), _T("IL-"), _T("IC-"), _T("I-"), // <ASSIGN_MODIFIER>
1462 _T("NL-"), _T("CL-"), _T("SL-"), _T("KL-"),
1463 _T("MAX-"), _T("MIN-"), _T("MMAX-"), _T("MMIN-"),
1464 _T("T-"), _T("TS-"),
1465 _T("M0-"), _T("M1-"), _T("M2-"), _T("M3-"), _T("M4-"),
1466 _T("M5-"), _T("M6-"), _T("M7-"), _T("M8-"), _T("M9-"),
1467 _T("L0-"), _T("L1-"), _T("L2-"), _T("L3-"), _T("L4-"),
1468 _T("L5-"), _T("L6-"), _T("L7-"), _T("L8-"), _T("L9-"),
1470 m_prefixes = new std::vector<tstringi>;
1471 for (size_t i = 0; i < NUMBER_OF(prefixes); ++ i)
1472 m_prefixes->push_back(prefixes[i]);
1473 std::sort(m_prefixes->begin(), m_prefixes->end(), prefixSortPred);
1475 m_prefixesRefCcount ++;
1478 Parser parser(data.c_str(), data.size());
1479 parser.setPrefixes(m_prefixes);
1485 if (!parser.getLine(&m_tokens))
1487 m_ti = m_tokens.begin();
1489 catch (ErrorMessage &e)
1491 if (m_log && m_soLog)
1494 *m_log << m_currentFilename << _T("(") << parser.getLineNumber()
1495 << _T(") : error: ") << e << std::endl;
1497 m_isThereAnyError = true;
1505 throw WarningMessage() << _T("back garbage is ignored.");
1507 catch (WarningMessage &w)
1509 if (m_log && m_soLog)
1512 *m_log << i_filename << _T("(") << parser.getLineNumber()
1513 << _T(") : warning: ") << w << std::endl;
1516 catch (ErrorMessage &e)
1518 if (m_log && m_soLog)
1521 *m_log << i_filename << _T("(") << parser.getLineNumber()
1522 << _T(") : error: ") << e << std::endl;
1524 m_isThereAnyError = true;
1529 -- m_prefixesRefCcount;
1530 if (m_prefixesRefCcount == 0)
1533 if (0 < m_canReadStack.size())
1536 *m_log << m_currentFilename << _T("(") << parser.getLineNumber()
1537 << _T(") : error: unbalanced `if'. ")
1538 << _T("you forget `endif', didn'i_token you?")
1540 m_isThereAnyError = true;
1545 // is the filename readable ?
1546 bool SettingLoader::isReadable(const tstringi &i_filename,
1547 int i_debugLevel) const
1549 if (i_filename.empty())
1552 tifstream ist(to_string(i_filename).c_str());
1554 tifstream ist(i_filename.c_str());
1558 if (m_log && m_soLog)
1560 Acquire a(m_soLog, 0);
1561 *m_log << _T(" loading: ") << i_filename << std::endl;
1567 if (m_log && m_soLog)
1569 Acquire a(m_soLog, i_debugLevel);
1570 *m_log << _T("not found: ") << i_filename << std::endl;
1577 // get filename from registry
1578 bool SettingLoader::getFilenameFromRegistry(tstringi *o_path) const
1580 // get from registry
1581 Registry reg(MAYU_REGISTRY_ROOT);
1583 reg.read(_T(".mayuIndex"), &index, 0);
1585 snprintf(buf, NUMBER_OF(buf), _T(".mayu%d"), index);
1586 if (!reg.read(buf, o_path))
1589 // parse registry entry
1590 Regexp getFilename(_T("^[^;]*;([^;]*);(.*)$"));
1591 if (!getFilename.doesMatch(*o_path))
1594 tstringi path = getFilename[1];
1595 tstringi options = getFilename[2];
1597 if (!(0 < path.size() && isReadable(path)))
1602 Regexp symbol(_T("-D([^;]*)"));
1603 while (symbol.doesMatch(options))
1605 m_setting->symbols.insert(symbol[1]);
1606 options = options.substr(symbol.subBegin(1));
1615 bool SettingLoader::getFilename(const tstringi &i_name, tstringi *o_path,
1616 int i_debugLevel) const
1618 // the default filename is ".mayu"
1619 const tstringi &name = i_name.empty() ? tstringi(_T(".mayu")) : i_name;
1621 bool isFirstTime = true;
1625 // find file from registry
1626 if (i_name.empty()) // called not from 'include'
1628 Setting::Symbols symbols;
1629 if (getFilenameFromRegistry(NULL, o_path, &symbols))
1631 if (o_path->empty())
1632 // find file from home directory
1634 HomeDirectories pathes;
1635 getHomeDirectories(&pathes);
1636 for (HomeDirectories::iterator
1637 i = pathes.begin(); i != pathes.end(); ++ i)
1639 *o_path = *i + _T("\\") + name;
1640 if (isReadable(*o_path, i_debugLevel))
1647 if (!isReadable(*o_path, i_debugLevel))
1651 for (Setting::Symbols::iterator
1652 i = symbols.begin(); i != symbols.end(); ++ i)
1653 m_setting->m_symbols.insert(*i);
1661 // find file from home directory
1662 HomeDirectories pathes;
1663 getHomeDirectories(&pathes);
1664 for (HomeDirectories::iterator i = pathes.begin(); i != pathes.end(); ++ i)
1666 *o_path = *i + _T("\\") + name;
1667 if (isReadable(*o_path, i_debugLevel))
1671 if (!i_name.empty())
1672 return false; // called by 'include'
1674 if (!DialogBox(g_hInst, MAKEINTRESOURCE(IDD_DIALOG_setting),
1675 NULL, dlgSetting_dlgProc))
1682 SettingLoader::SettingLoader(SyncObject *i_soLog, tostream *i_log)
1684 m_isThereAnyError(false),
1687 m_currentKeymap(NULL)
1689 m_defaultKeySeqModifier =
1690 m_defaultAssignModifier.release(Modifier::Type_ImeComp);
1695 If called by "include", 'filename' describes filename.
1696 Otherwise the 'filename' is empty.
1698 bool SettingLoader::load(Setting *i_setting, const tstringi &i_filename)
1700 m_setting = i_setting;
1701 m_isThereAnyError = false;
1704 if (!getFilename(i_filename, &path))
1706 if (i_filename.empty())
1709 getFilename(i_filename, &path, 0); // show filenames
1713 throw ErrorMessage() << _T("`") << i_filename
1714 << _T("': no such file or other error.");
1717 // create global keymap's default keySeq
1718 ActionFunction af(createFunctionData(_T("OtherWindowClass")));
1719 KeySeq *globalDefault = m_setting->m_keySeqs.add(KeySeq(_T("")).add(af));
1721 // add default keymap
1722 m_currentKeymap = m_setting->m_keymaps.add(
1723 Keymap(Keymap::Type_windowOr, _T("Global"), _T(""), _T(""),
1724 globalDefault, NULL));
1727 // add keyboard layout name
1728 if (filename.empty())
1730 char keyboardLayoutName[KL_NAMELENGTH];
1731 if (GetKeyboardLayoutName(keyboardLayoutName))
1733 tstringi kl = tstringi(_T("KeyboardLayout/")) + keyboardLayoutName;
1734 m_setting->symbols.insert(kl);
1736 *m_log << _T("KeyboardLayout: ") << kl << std::endl;
1745 if (i_filename.empty())
1746 m_setting->m_keymaps.adjustModifier(m_setting->m_keyboard);
1748 return !m_isThereAnyError;
1752 std::vector<tstringi> *SettingLoader::m_prefixes; // m_prefixes terminal symbol
1753 size_t SettingLoader::m_prefixesRefCcount; /* reference count of