1 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\r
7 #include "dlgsetting.h"
\r
8 #include "errormessage.h"
\r
11 #include "registry.h"
\r
12 #include "setting.h"
\r
13 #include "windowstool.h"
\r
14 #include "vkeytable.h"
\r
17 #include <algorithm>
\r
20 #include <sys/stat.h>
\r
25 Key prefixed(_T("prefixed"));
\r
26 Key before_key_down(_T("before-key-down"));
\r
27 Key after_key_up(_T("after-key-up"));
\r
37 // get mayu filename
\r
38 static bool getFilenameFromRegistry(
\r
39 tstringi *o_name, tstringi *o_filename, Setting::Symbols *o_symbols)
\r
41 Registry reg(MAYU_REGISTRY_ROOT);
\r
43 reg.read(_T(".mayuIndex"), &index, 0);
\r
45 _sntprintf(buf, NUMBER_OF(buf), _T(".mayu%d"), index);
\r
48 if (!reg.read(buf, &entry))
\r
51 tregex getFilename(_T("^([^;]*);([^;]*);(.*)$"));
\r
52 tsmatch getFilenameResult;
\r
53 if (!boost::regex_match(entry, getFilenameResult, getFilename))
\r
57 *o_name = getFilenameResult.str(1);
\r
59 *o_filename = getFilenameResult.str(2);
\r
61 tstringi symbols = getFilenameResult.str(3);
\r
62 tregex symbol(_T("-D([^;]*)(.*)$"));
\r
63 tsmatch symbolResult;
\r
64 while (boost::regex_search(symbols, symbolResult, symbol)) {
\r
65 o_symbols->insert(symbolResult.str(1));
\r
66 symbols = symbolResult.str(2);
\r
73 // get home directory path
\r
74 void getHomeDirectories(HomeDirectories *o_pathes)
\r
78 if (getFilenameFromRegistry(NULL, &filename, NULL) &&
\r
79 !filename.empty()) {
\r
80 tregex getPath(_T("^(.*[/\\\\])[^/\\\\]*$"));
\r
81 tsmatch getPathResult;
\r
82 if (boost::regex_match(filename, getPathResult, getPath))
\r
83 o_pathes->push_back(getPathResult.str(1));
\r
86 const _TCHAR *home = _tgetenv(_T("HOME"));
\r
88 o_pathes->push_back(home);
\r
90 const _TCHAR *homedrive = _tgetenv(_T("HOMEDRIVE"));
\r
91 const _TCHAR *homepath = _tgetenv(_T("HOMEPATH"));
\r
92 if (homedrive && homepath)
\r
93 o_pathes->push_back(tstringi(homedrive) + homepath);
\r
95 const _TCHAR *userprofile = _tgetenv(_T("USERPROFILE"));
\r
97 o_pathes->push_back(userprofile);
\r
99 _TCHAR buf[GANA_MAX_PATH];
\r
100 DWORD len = GetCurrentDirectory(NUMBER_OF(buf), buf);
\r
101 if (0 < len && len < NUMBER_OF(buf))
\r
102 o_pathes->push_back(buf);
\r
104 _TCHAR buf[GANA_MAX_PATH];
\r
107 if (GetModuleFileName(GetModuleHandle(NULL), buf, NUMBER_OF(buf)))
\r
108 o_pathes->push_back(pathRemoveFileSpec(buf));
\r
112 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\r
116 // is there no more tokens ?
\r
117 bool SettingLoader::isEOL()
\r
119 return m_ti == m_tokens.end();
\r
124 Token *SettingLoader::getToken()
\r
127 throw ErrorMessage() << _T("too few words.");
\r
128 return &*(m_ti ++);
\r
133 Token *SettingLoader::lookToken()
\r
136 throw ErrorMessage() << _T("too few words.");
\r
142 bool SettingLoader::getOpenParen(bool i_doesThrow, const _TCHAR *i_name)
\r
144 if (!isEOL() && lookToken()->isOpenParen()) {
\r
149 throw ErrorMessage() << _T("there must be `(' after `&")
\r
150 << i_name << _T("'.");
\r
156 bool SettingLoader::getCloseParen(bool i_doesThrow, const _TCHAR *i_name)
\r
158 if (!isEOL() && lookToken()->isCloseParen()) {
\r
163 throw ErrorMessage() << _T("`&") << i_name
\r
164 << _T("': too many arguments.");
\r
170 bool SettingLoader::getComma(bool i_doesThrow, const _TCHAR *i_name)
\r
172 if (!isEOL() && lookToken()->isComma()) {
\r
177 throw ErrorMessage() << _T("`&") << i_name
\r
178 << _T("': comma expected.");
\r
184 void SettingLoader::load_INCLUDE()
\r
186 SettingLoader loader(m_soLog, m_log);
\r
187 loader.m_defaultAssignModifier = m_defaultAssignModifier;
\r
188 loader.m_defaultKeySeqModifier = m_defaultKeySeqModifier;
\r
189 if (!loader.load(m_setting, (*getToken()).getString()))
\r
190 m_isThereAnyError = true;
\r
195 void SettingLoader::load_SCAN_CODES(Key *o_key)
\r
197 for (int j = 0; j < Key::MAX_SCAN_CODES_SIZE && !isEOL(); ++ j) {
\r
201 Token *t = getToken();
\r
202 if (t->isNumber()) {
\r
203 sc.m_scan = (u_char)t->getNumber();
\r
204 o_key->addScanCode(sc);
\r
207 if (*t == _T("E0-")) sc.m_flags |= ScanCode::E0;
\r
208 else if (*t == _T("E1-")) sc.m_flags |= ScanCode::E1;
\r
209 else throw ErrorMessage() << _T("`") << *t
\r
210 << _T("': invalid modifier.");
\r
217 void SettingLoader::load_DEFINE_KEY()
\r
219 Token *t = getToken();
\r
223 if (*t == _T('(')) {
\r
224 key.addName(getToken()->getString());
\r
225 while (t = getToken(), *t != _T(')'))
\r
226 key.addName(t->getString());
\r
227 if (*getToken() != _T("="))
\r
228 throw ErrorMessage() << _T("there must be `=' after `)'.");
\r
230 key.addName(t->getString());
\r
231 while (t = getToken(), *t != _T("="))
\r
232 key.addName(t->getString());
\r
235 load_SCAN_CODES(&key);
\r
236 m_setting->m_keyboard.addKey(key);
\r
240 // <DEFINE_MODIFIER>
\r
241 void SettingLoader::load_DEFINE_MODIFIER()
\r
243 Token *t = getToken();
\r
245 if (*t == _T("shift") ) mt = Modifier::Type_Shift;
\r
246 else if (*t == _T("alt") ||
\r
247 *t == _T("meta") ||
\r
248 *t == _T("menu") ) mt = Modifier::Type_Alt;
\r
249 else if (*t == _T("control") ||
\r
250 *t == _T("ctrl") ) mt = Modifier::Type_Control;
\r
251 else if (*t == _T("windows") ||
\r
252 *t == _T("win") ) mt = Modifier::Type_Windows;
\r
253 else throw ErrorMessage() << _T("`") << *t
\r
254 << _T("': invalid modifier name.");
\r
256 if (*getToken() != _T("="))
\r
257 throw ErrorMessage() << _T("there must be `=' after modifier name.");
\r
262 m_setting->m_keyboard.searchKeyByNonAliasName(t->getString());
\r
264 throw ErrorMessage() << _T("`") << *t << _T("': invalid key name.");
\r
265 m_setting->m_keyboard.addModifier(mt, key);
\r
270 // <DEFINE_SYNC_KEY>
\r
271 void SettingLoader::load_DEFINE_SYNC_KEY()
\r
273 Key *key = m_setting->m_keyboard.getSyncKey();
\r
275 key->addName(_T("sync"));
\r
277 if (*getToken() != _T("="))
\r
278 throw ErrorMessage() << _T("there must be `=' after `sync'.");
\r
280 load_SCAN_CODES(key);
\r
285 void SettingLoader::load_DEFINE_ALIAS()
\r
287 Token *name = getToken();
\r
289 if (*getToken() != _T("="))
\r
290 throw ErrorMessage() << _T("there must be `=' after `alias'.");
\r
292 Token *t = getToken();
\r
293 Key *key = m_setting->m_keyboard.searchKeyByNonAliasName(t->getString());
\r
295 throw ErrorMessage() << _T("`") << *t << _T("': invalid key name.");
\r
296 m_setting->m_keyboard.addAlias(name->getString(), key);
\r
300 // <DEFINE_SUBSTITUTE>
\r
301 void SettingLoader::load_DEFINE_SUBSTITUTE()
\r
303 typedef std::list<ModifiedKey> AssignedKeys;
\r
304 AssignedKeys assignedKeys;
\r
308 load_MODIFIER(Modifier::Type_ASSIGN, m_defaultAssignModifier);
\r
309 mkey.m_key = load_KEY_NAME();
\r
310 assignedKeys.push_back(mkey);
\r
311 } while (!(*lookToken() == _T("=>") || *lookToken() == _T("=")));
\r
314 KeySeq *keySeq = load_KEY_SEQUENCE(_T(""), false, Modifier::Type_ASSIGN);
\r
315 ModifiedKey mkey = keySeq->getFirstModifiedKey();
\r
317 throw ErrorMessage() << _T("no key is specified for substitute.");
\r
319 for (AssignedKeys::iterator i = assignedKeys.begin();
\r
320 i != assignedKeys.end(); ++ i)
\r
321 m_setting->m_keyboard.addSubstitute(*i, mkey);
\r
326 void SettingLoader::load_DEFINE_OPTION()
\r
328 Token *t = getToken();
\r
329 if (*t == _T("KL-")) {
\r
330 if (*getToken() != _T("=")) {
\r
331 throw ErrorMessage() << _T("there must be `=' after `def option KL-'.");
\r
334 load_ARGUMENT(&m_setting->m_correctKanaLockHandling);
\r
336 } else if (*t == _T("delay-of")) {
\r
337 if (*getToken() != _T("!!!")) {
\r
338 throw ErrorMessage()
\r
339 << _T("there must be `!!!' after `def option delay-of'.");
\r
342 if (*getToken() != _T("=")) {
\r
343 throw ErrorMessage()
\r
344 << _T("there must be `=' after `def option delay-of !!!'.");
\r
347 load_ARGUMENT(&m_setting->m_oneShotRepeatableDelay);
\r
349 } else if (*t == _T("sts4mayu")) {
\r
350 if (*getToken() != _T("=")) {
\r
351 throw ErrorMessage()
\r
352 << _T("there must be `=' after `def option sts4mayu'.");
\r
355 load_ARGUMENT(&m_setting->m_sts4mayu);
\r
357 } else if (*t == _T("cts4mayu")) {
\r
358 if (*getToken() != _T("=")) {
\r
359 throw ErrorMessage()
\r
360 << _T("there must be `=' after `def option cts4mayu'.");
\r
363 load_ARGUMENT(&m_setting->m_cts4mayu);
\r
365 } else if (*t == _T("mouse-event")) {
\r
366 if (*getToken() != _T("=")) {
\r
367 throw ErrorMessage()
\r
368 << _T("there must be `=' after `def option mouse-event'.");
\r
371 load_ARGUMENT(&m_setting->m_mouseEvent);
\r
373 } else if (*t == _T("drag-threshold")) {
\r
374 if (*getToken() != _T("=")) {
\r
375 throw ErrorMessage()
\r
376 << _T("there must be `=' after `def option drag-threshold'.");
\r
379 load_ARGUMENT(&m_setting->m_dragThreshold);
\r
382 throw ErrorMessage() << _T("syntax error `def option ") << *t << _T("'.");
\r
388 // <KEYBOARD_DEFINITION>
\r
389 void SettingLoader::load_KEYBOARD_DEFINITION()
\r
391 Token *t = getToken();
\r
394 if (*t == _T("key")) load_DEFINE_KEY();
\r
396 // <DEFINE_MODIFIER>
\r
397 else if (*t == _T("mod")) load_DEFINE_MODIFIER();
\r
399 // <DEFINE_SYNC_KEY>
\r
400 else if (*t == _T("sync")) load_DEFINE_SYNC_KEY();
\r
403 else if (*t == _T("alias")) load_DEFINE_ALIAS();
\r
405 // <DEFINE_SUBSTITUTE>
\r
406 else if (*t == _T("subst")) load_DEFINE_SUBSTITUTE();
\r
409 else if (*t == _T("option")) load_DEFINE_OPTION();
\r
412 else throw ErrorMessage() << _T("syntax error `") << *t << _T("'.");
\r
417 Modifier SettingLoader::load_MODIFIER(
\r
418 Modifier::Type i_mode, Modifier i_modifier, Modifier::Type *o_mode)
\r
421 *o_mode = Modifier::Type_begin;
\r
423 Modifier isModifierSpecified;
\r
424 enum { PRESS, RELEASE, DONTCARE } flag = PRESS;
\r
427 for (i = i_mode; i < Modifier::Type_ASSIGN; ++ i) {
\r
428 i_modifier.dontcare(Modifier::Type(i));
\r
429 isModifierSpecified.on(Modifier::Type(i));
\r
438 const static struct {
\r
440 Modifier::Type m_mt;
\r
442 // <BASIC_MODIFIER>
\r
443 { _T("S-"), Modifier::Type_Shift },
\r
444 { _T("A-"), Modifier::Type_Alt },
\r
445 { _T("M-"), Modifier::Type_Alt },
\r
446 { _T("C-"), Modifier::Type_Control },
\r
447 { _T("W-"), Modifier::Type_Windows },
\r
448 // <KEYSEQ_MODIFIER>
\r
449 { _T("U-"), Modifier::Type_Up },
\r
450 { _T("D-"), Modifier::Type_Down },
\r
451 // <ASSIGN_MODIFIER>
\r
452 { _T("R-"), Modifier::Type_Repeat },
\r
453 { _T("IL-"), Modifier::Type_ImeLock },
\r
454 { _T("IC-"), Modifier::Type_ImeComp },
\r
455 { _T("I-"), Modifier::Type_ImeComp },
\r
456 { _T("NL-"), Modifier::Type_NumLock },
\r
457 { _T("CL-"), Modifier::Type_CapsLock },
\r
458 { _T("SL-"), Modifier::Type_ScrollLock },
\r
459 { _T("KL-"), Modifier::Type_KanaLock },
\r
460 { _T("MAX-"), Modifier::Type_Maximized },
\r
461 { _T("MIN-"), Modifier::Type_Minimized },
\r
462 { _T("MMAX-"), Modifier::Type_MdiMaximized },
\r
463 { _T("MMIN-"), Modifier::Type_MdiMinimized },
\r
464 { _T("T-"), Modifier::Type_Touchpad },
\r
465 { _T("TS-"), Modifier::Type_TouchpadSticky },
\r
466 { _T("M0-"), Modifier::Type_Mod0 },
\r
467 { _T("M1-"), Modifier::Type_Mod1 },
\r
468 { _T("M2-"), Modifier::Type_Mod2 },
\r
469 { _T("M3-"), Modifier::Type_Mod3 },
\r
470 { _T("M4-"), Modifier::Type_Mod4 },
\r
471 { _T("M5-"), Modifier::Type_Mod5 },
\r
472 { _T("M6-"), Modifier::Type_Mod6 },
\r
473 { _T("M7-"), Modifier::Type_Mod7 },
\r
474 { _T("M8-"), Modifier::Type_Mod8 },
\r
475 { _T("M9-"), Modifier::Type_Mod9 },
\r
476 { _T("L0-"), Modifier::Type_Lock0 },
\r
477 { _T("L1-"), Modifier::Type_Lock1 },
\r
478 { _T("L2-"), Modifier::Type_Lock2 },
\r
479 { _T("L3-"), Modifier::Type_Lock3 },
\r
480 { _T("L4-"), Modifier::Type_Lock4 },
\r
481 { _T("L5-"), Modifier::Type_Lock5 },
\r
482 { _T("L6-"), Modifier::Type_Lock6 },
\r
483 { _T("L7-"), Modifier::Type_Lock7 },
\r
484 { _T("L8-"), Modifier::Type_Lock8 },
\r
485 { _T("L9-"), Modifier::Type_Lock9 },
\r
488 for (int i = 0; i < NUMBER_OF(map); ++ i)
\r
489 if (*t == map[i].m_s) {
\r
491 Modifier::Type mt = map[i].m_mt;
\r
492 if (static_cast<int>(i_mode) <= static_cast<int>(mt))
\r
493 throw ErrorMessage() << _T("`") << *t
\r
494 << _T("': invalid modifier at this context.");
\r
497 i_modifier.press(mt);
\r
500 i_modifier.release(mt);
\r
503 i_modifier.dontcare(mt);
\r
506 isModifierSpecified.on(mt);
\r
509 if (o_mode && *o_mode < mt) {
\r
510 if (mt < Modifier::Type_BASIC)
\r
511 *o_mode = Modifier::Type_BASIC;
\r
512 else if (mt < Modifier::Type_KEYSEQ)
\r
513 *o_mode = Modifier::Type_KEYSEQ;
\r
514 else if (mt < Modifier::Type_ASSIGN)
\r
515 *o_mode = Modifier::Type_ASSIGN;
\r
517 goto continue_loop;
\r
520 if (*t == _T("*")) {
\r
526 if (*t == _T("~")) {
\r
535 for (i = Modifier::Type_begin; i != Modifier::Type_end; ++ i)
\r
536 if (!isModifierSpecified.isOn(Modifier::Type(i)))
\r
541 i_modifier.release(Modifier::Type(i));
\r
544 i_modifier.dontcare(Modifier::Type(i));
\r
549 bool isDontcareUp = i_modifier.isDontcare(Modifier::Type_Up);
\r
550 bool isDontcareDown = i_modifier.isDontcare(Modifier::Type_Down);
\r
551 bool isOnUp = i_modifier.isOn(Modifier::Type_Up);
\r
552 bool isOnDown = i_modifier.isOn(Modifier::Type_Down);
\r
553 if (isDontcareUp && isDontcareDown)
\r
555 else if (isDontcareUp)
\r
556 i_modifier.on(Modifier::Type_Up, !isOnDown);
\r
557 else if (isDontcareDown)
\r
558 i_modifier.on(Modifier::Type_Down, !isOnUp);
\r
559 else if (isOnUp == isOnDown) {
\r
560 i_modifier.dontcare(Modifier::Type_Up);
\r
561 i_modifier.dontcare(Modifier::Type_Down);
\r
565 if (!isModifierSpecified.isOn(Modifier::Type_Repeat))
\r
566 i_modifier.dontcare(Modifier::Type_Repeat);
\r
572 Key *SettingLoader::load_KEY_NAME()
\r
574 Token *t = getToken();
\r
575 Key *key = m_setting->m_keyboard.searchKey(t->getString());
\r
577 throw ErrorMessage() << _T("`") << *t << _T("': invalid key name.");
\r
582 // <KEYMAP_DEFINITION>
\r
583 void SettingLoader::load_KEYMAP_DEFINITION(const Token *i_which)
\r
585 Keymap::Type type = Keymap::Type_keymap;
\r
586 Token *name = getToken(); // <KEYMAP_NAME>
\r
587 tstringi windowClassName;
\r
588 tstringi windowTitleName;
\r
589 KeySeq *keySeq = NULL;
\r
590 Keymap *parentKeymap = NULL;
\r
591 bool isKeymap2 = false;
\r
592 bool doesLoadDefaultKeySeq = false;
\r
595 Token *t = lookToken();
\r
596 if (*i_which == _T("window")) { // <WINDOW>
\r
597 if (t->isOpenParen())
\r
598 // "(" <WINDOW_CLASS_NAME> "&&" <WINDOW_TITLE_NAME> ")"
\r
599 // "(" <WINDOW_CLASS_NAME> "||" <WINDOW_TITLE_NAME> ")"
\r
602 windowClassName = getToken()->getRegexp();
\r
604 if (*t == _T("&&"))
\r
605 type = Keymap::Type_windowAnd;
\r
606 else if (*t == _T("||"))
\r
607 type = Keymap::Type_windowOr;
\r
609 throw ErrorMessage() << _T("`") << *t << _T("': unknown operator.");
\r
610 windowTitleName = getToken()->getRegexp();
\r
611 if (!getToken()->isCloseParen())
\r
612 throw ErrorMessage() << _T("there must be `)'.");
\r
613 } else if (t->isRegexp()) { // <WINDOW_CLASS_NAME>
\r
615 type = Keymap::Type_windowAnd;
\r
616 windowClassName = t->getRegexp();
\r
618 } else if (*i_which == _T("keymap"))
\r
620 else if (*i_which == _T("keymap2"))
\r
626 doesLoadDefaultKeySeq = true;
\r
629 m_currentKeymap = m_setting->m_keymaps.add(
\r
630 Keymap(type, name->getString(), windowClassName, windowTitleName,
\r
633 if (doesLoadDefaultKeySeq) {
\r
634 Token *t = lookToken();
\r
636 if (*t == _T(":")) {
\r
639 parentKeymap = m_setting->m_keymaps.searchByName(t->getString());
\r
641 throw ErrorMessage() << _T("`") << *t
\r
642 << _T("': unknown keymap name.");
\r
646 if (!(*t == _T("=>") || *t == _T("=")))
\r
647 throw ErrorMessage() << _T("`") << *t << _T("': syntax error.");
\r
648 keySeq = SettingLoader::load_KEY_SEQUENCE();
\r
651 if (keySeq == NULL) {
\r
653 if (type == Keymap::Type_keymap && !isKeymap2)
\r
654 fd = createFunctionData(_T("KeymapParent"));
\r
655 else if (type == Keymap::Type_keymap && !isKeymap2)
\r
656 fd = createFunctionData(_T("Undefined"));
\r
657 else // (type == Keymap::Type_windowAnd || type == Keymap::Type_windowOr)
\r
658 fd = createFunctionData(_T("KeymapParent"));
\r
660 keySeq = m_setting->m_keySeqs.add(
\r
661 KeySeq(name->getString()).add(ActionFunction(fd)));
\r
664 m_currentKeymap->setIfNotYet(keySeq, parentKeymap);
\r
668 // <ARGUMENT>
\r
669 void SettingLoader::load_ARGUMENT(bool *o_arg)
\r
671 *o_arg = !(*getToken() == _T("false"));
\r
675 // <ARGUMENT>
\r
676 void SettingLoader::load_ARGUMENT(int *o_arg)
\r
678 *o_arg = getToken()->getNumber();
\r
682 // <ARGUMENT>
\r
683 void SettingLoader::load_ARGUMENT(unsigned int *o_arg)
\r
685 *o_arg = getToken()->getNumber();
\r
689 // <ARGUMENT>
\r
690 void SettingLoader::load_ARGUMENT(long *o_arg)
\r
692 *o_arg = getToken()->getNumber();
\r
696 // <ARGUMENT>
\r
697 void SettingLoader::load_ARGUMENT(unsigned __int64 *o_arg)
\r
699 *o_arg = getToken()->getNumber();
\r
703 // <ARGUMENT>
\r
704 void SettingLoader::load_ARGUMENT(__int64 *o_arg)
\r
706 *o_arg = getToken()->getNumber();
\r
710 // <ARGUMENT>
\r
711 void SettingLoader::load_ARGUMENT(tstringq *o_arg)
\r
713 *o_arg = getToken()->getString();
\r
717 // <ARGUMENT>
\r
718 void SettingLoader::load_ARGUMENT(std::list<tstringq> *o_arg)
\r
721 if (!lookToken()->isString())
\r
723 o_arg->push_back(getToken()->getString());
\r
725 if (!lookToken()->isComma())
\r
732 // <ARGUMENT>
\r
733 void SettingLoader::load_ARGUMENT(tregex *o_arg)
\r
735 *o_arg = getToken()->getRegexp();
\r
739 // <ARGUMENT_VK>
\r
740 void SettingLoader::load_ARGUMENT(VKey *o_arg)
\r
742 Token *t = getToken();
\r
745 if (t->isNumber()) {
\r
746 vkey |= static_cast<BYTE>(t->getNumber());
\r
748 } else if (*t == _T("E-")) vkey |= VKey_extended;
\r
749 else if (*t == _T("U-")) vkey |= VKey_released;
\r
750 else if (*t == _T("D-")) vkey |= VKey_pressed;
\r
752 const VKeyTable *vkt;
\r
753 for (vkt = g_vkeyTable; vkt->m_name; ++ vkt)
\r
754 if (*t == vkt->m_name)
\r
757 throw ErrorMessage() << _T("`") << *t
\r
758 << _T("': unknown virtual key name.");
\r
759 vkey |= vkt->m_code;
\r
764 if (!(vkey & VKey_released) && !(vkey & VKey_pressed))
\r
765 vkey |= VKey_released | VKey_pressed;
\r
766 *o_arg = static_cast<VKey>(vkey);
\r
770 // <ARGUMENT_WINDOW>
\r
771 void SettingLoader::load_ARGUMENT(ToWindowType *o_arg)
\r
773 Token *t = getToken();
\r
774 if (t->isNumber()) {
\r
775 if (ToWindowType_toBegin <= t->getNumber()) {
\r
776 *o_arg = static_cast<ToWindowType>(t->getNumber());
\r
779 } else if (getTypeValue(o_arg, t->getString()))
\r
781 throw ErrorMessage() << _T("`") << *t << _T("': invalid target window.");
\r
785 // <ARGUMENT>
\r
786 void SettingLoader::load_ARGUMENT(GravityType *o_arg)
\r
788 Token *t = getToken();
\r
789 if (getTypeValue(o_arg, t->getString()))
\r
791 throw ErrorMessage() << _T("`") << *t << _T("': unknown gravity symbol.");
\r
795 // <ARGUMENT>
\r
796 void SettingLoader::load_ARGUMENT(MouseHookType *o_arg)
\r
798 Token *t = getToken();
\r
799 if (getTypeValue(o_arg, t->getString()))
\r
801 throw ErrorMessage() << _T("`") << *t << _T("': unknown MouseHookType symbol.");
\r
805 // <ARGUMENT>
\r
806 void SettingLoader::load_ARGUMENT(MayuDialogType *o_arg)
\r
808 Token *t = getToken();
\r
809 if (getTypeValue(o_arg, t->getString()))
\r
811 throw ErrorMessage() << _T("`") << *t << _T("': unknown dialog box.");
\r
815 // <ARGUMENT_LOCK>
\r
816 void SettingLoader::load_ARGUMENT(ModifierLockType *o_arg)
\r
818 Token *t = getToken();
\r
819 if (getTypeValue(o_arg, t->getString()))
\r
821 throw ErrorMessage() << _T("`") << *t << _T("': unknown lock name.");
\r
825 // <ARGUMENT_LOCK>
\r
826 void SettingLoader::load_ARGUMENT(ToggleType *o_arg)
\r
828 Token *t = getToken();
\r
829 if (getTypeValue(o_arg, t->getString()))
\r
831 throw ErrorMessage() << _T("`") << *t << _T("': unknown toggle name.");
\r
835 // <ARGUMENT_SHOW_WINDOW>
\r
836 void SettingLoader::load_ARGUMENT(ShowCommandType *o_arg)
\r
838 Token *t = getToken();
\r
839 if (getTypeValue(o_arg, t->getString()))
\r
841 throw ErrorMessage() << _T("`") << *t << _T("': unknown show command.");
\r
845 // <ARGUMENT_TARGET_WINDOW>
\r
846 void SettingLoader::load_ARGUMENT(TargetWindowType *o_arg)
\r
848 Token *t = getToken();
\r
849 if (getTypeValue(o_arg, t->getString()))
\r
851 throw ErrorMessage() << _T("`") << *t
\r
852 << _T("': unknown target window type.");
\r
857 void SettingLoader::load_ARGUMENT(BooleanType *o_arg)
\r
859 Token *t = getToken();
\r
860 if (getTypeValue(o_arg, t->getString()))
\r
862 throw ErrorMessage() << _T("`") << *t << _T("': must be true or false.");
\r
866 // <ARGUMENT>
\r
867 void SettingLoader::load_ARGUMENT(LogicalOperatorType *o_arg)
\r
869 Token *t = getToken();
\r
870 if (getTypeValue(o_arg, t->getString()))
\r
872 throw ErrorMessage() << _T("`") << *t << _T("': must be 'or' or 'and'.");
\r
876 // <ARGUMENT>
\r
877 void SettingLoader::load_ARGUMENT(Modifier *o_arg)
\r
880 for (int i = Modifier::Type_begin; i != Modifier::Type_end; ++ i)
\r
881 modifier.dontcare(static_cast<Modifier::Type>(i));
\r
882 *o_arg = load_MODIFIER(Modifier::Type_ASSIGN, modifier);
\r
886 // <ARGUMENT>
\r
887 void SettingLoader::load_ARGUMENT(const Keymap **o_arg)
\r
889 Token *t = getToken();
\r
890 const Keymap *&keymap = *o_arg;
\r
891 keymap = m_setting->m_keymaps.searchByName(t->getString());
\r
893 throw ErrorMessage() << _T("`") << *t << _T("': unknown keymap name.");
\r
897 // <ARGUMENT>
\r
898 void SettingLoader::load_ARGUMENT(const KeySeq **o_arg)
\r
900 Token *t = getToken();
\r
901 const KeySeq *&keySeq = *o_arg;
\r
902 if (t->isOpenParen()) {
\r
903 keySeq = load_KEY_SEQUENCE(_T(""), true);
\r
904 getToken(); // close paren
\r
905 } else if (*t == _T("$")) {
\r
907 keySeq = m_setting->m_keySeqs.searchByName(t->getString());
\r
909 throw ErrorMessage() << _T("`$") << *t << _T("': unknown keyseq name.");
\r
911 throw ErrorMessage() << _T("`") << *t << _T("': it is not keyseq.");
\r
915 // <ARGUMENT>
\r
916 void SettingLoader::load_ARGUMENT(StrExprArg *o_arg)
\r
918 Token *t = getToken();
\r
919 StrExprArg::Type type = StrExprArg::Literal;
\r
920 if (*t == _T("$") && t->isQuoted() == false
\r
921 && lookToken()->getType() == Token::Type_string) {
\r
922 type = StrExprArg::Builtin;
\r
925 *o_arg = StrExprArg(t->getString(), type);
\r
929 // <ARGUMENT>
\r
930 void SettingLoader::load_ARGUMENT(WindowMonitorFromType *o_arg)
\r
932 Token *t = getToken();
\r
933 if (getTypeValue(o_arg, t->getString()))
\r
935 throw ErrorMessage() << _T("`") << *t
\r
936 << _T("': unknown monitor from type.");
\r
941 KeySeq *SettingLoader::load_KEY_SEQUENCE(
\r
942 const tstringi &i_name, bool i_isInParen, Modifier::Type i_mode)
\r
944 KeySeq keySeq(i_name);
\r
946 Modifier::Type mode;
\r
947 Modifier modifier = load_MODIFIER(i_mode, m_defaultKeySeqModifier, &mode);
\r
948 keySeq.setMode(mode);
\r
949 Token *t = lookToken();
\r
950 if (t->isCloseParen() && i_isInParen)
\r
952 else if (t->isOpenParen()) {
\r
953 getToken(); // open paren
\r
954 KeySeq *ks = load_KEY_SEQUENCE(_T(""), true, i_mode);
\r
955 getToken(); // close paren
\r
956 keySeq.add(ActionKeySeq(ks));
\r
957 } else if (*t == _T("$")) { // <KEYSEQ_NAME>
\r
960 KeySeq *ks = m_setting->m_keySeqs.searchByName(t->getString());
\r
962 throw ErrorMessage() << _T("`$") << *t
\r
963 << _T("': unknown keyseq name.");
\r
964 if (!ks->isCorrectMode(i_mode))
\r
965 throw ErrorMessage()
\r
967 << _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.");
\r
968 keySeq.setMode(ks->getMode());
\r
969 keySeq.add(ActionKeySeq(ks));
\r
970 } else if (*t == _T("&")) { // <FUNCTION_NAME>
\r
975 ActionFunction af(createFunctionData(t->getString()), modifier);
\r
976 if (af.m_functionData == NULL)
\r
977 throw ErrorMessage() << _T("`&") << *t
\r
978 << _T("': unknown function name.");
\r
979 af.m_functionData->load(this);
\r
981 } else { // <KEYSEQ_MODIFIED_KEY_NAME>
\r
983 mkey.m_modifier = modifier;
\r
984 mkey.m_key = load_KEY_NAME();
\r
985 keySeq.add(ActionKey(mkey));
\r
988 return m_setting->m_keySeqs.add(keySeq);
\r
993 void SettingLoader::load_KEY_ASSIGN()
\r
995 typedef std::list<ModifiedKey> AssignedKeys;
\r
996 AssignedKeys assignedKeys;
\r
1000 load_MODIFIER(Modifier::Type_ASSIGN, m_defaultAssignModifier);
\r
1001 if (*lookToken() == _T("=")) {
\r
1003 m_defaultKeySeqModifier = load_MODIFIER(Modifier::Type_KEYSEQ,
\r
1004 m_defaultKeySeqModifier);
\r
1005 m_defaultAssignModifier = mkey.m_modifier;
\r
1010 mkey.m_key = load_KEY_NAME();
\r
1011 assignedKeys.push_back(mkey);
\r
1012 if (*lookToken() == _T("=>") || *lookToken() == _T("="))
\r
1015 load_MODIFIER(Modifier::Type_ASSIGN, m_defaultAssignModifier);
\r
1019 ASSERT(m_currentKeymap);
\r
1020 KeySeq *keySeq = load_KEY_SEQUENCE();
\r
1021 for (AssignedKeys::iterator i = assignedKeys.begin();
\r
1022 i != assignedKeys.end(); ++ i)
\r
1023 m_currentKeymap->addAssignment(*i, keySeq);
\r
1028 void SettingLoader::load_EVENT_ASSIGN()
\r
1030 std::list<ModifiedKey> assignedKeys;
\r
1033 mkey.m_modifier.dontcare(); //set all modifiers to dontcare
\r
1035 Token *t = getToken();
\r
1037 for (e = Event::events; *e; ++ e)
\r
1038 if (*t == (*e)->getName()) {
\r
1043 throw ErrorMessage() << _T("`") << *t << _T("': invalid event name.");
\r
1046 if (!(*t == _T("=>") || *t == _T("=")))
\r
1047 throw ErrorMessage() << _T("`=' is expected.");
\r
1049 ASSERT(m_currentKeymap);
\r
1050 KeySeq *keySeq = load_KEY_SEQUENCE();
\r
1051 m_currentKeymap->addAssignment(mkey, keySeq);
\r
1055 // <MODIFIER_ASSIGNMENT>
\r
1056 void SettingLoader::load_MODIFIER_ASSIGNMENT()
\r
1058 // <MODIFIER_NAME>
\r
1059 Token *t = getToken();
\r
1060 Modifier::Type mt;
\r
1063 Keymap::AssignMode am = Keymap::AM_notModifier;
\r
1064 if (*t == _T("!") ) am = Keymap::AM_true, t = getToken();
\r
1065 else if (*t == _T("!!") ) am = Keymap::AM_oneShot, t = getToken();
\r
1066 else if (*t == _T("!!!")) am = Keymap::AM_oneShotRepeatable, t = getToken();
\r
1068 if (*t == _T("shift")) mt = Modifier::Type_Shift;
\r
1069 else if (*t == _T("alt") ||
\r
1070 *t == _T("meta") ||
\r
1071 *t == _T("menu") ) mt = Modifier::Type_Alt;
\r
1072 else if (*t == _T("control") ||
\r
1073 *t == _T("ctrl") ) mt = Modifier::Type_Control;
\r
1074 else if (*t == _T("windows") ||
\r
1075 *t == _T("win") ) mt = Modifier::Type_Windows;
\r
1076 else if (*t == _T("mod0") ) mt = Modifier::Type_Mod0;
\r
1077 else if (*t == _T("mod1") ) mt = Modifier::Type_Mod1;
\r
1078 else if (*t == _T("mod2") ) mt = Modifier::Type_Mod2;
\r
1079 else if (*t == _T("mod3") ) mt = Modifier::Type_Mod3;
\r
1080 else if (*t == _T("mod4") ) mt = Modifier::Type_Mod4;
\r
1081 else if (*t == _T("mod5") ) mt = Modifier::Type_Mod5;
\r
1082 else if (*t == _T("mod6") ) mt = Modifier::Type_Mod6;
\r
1083 else if (*t == _T("mod7") ) mt = Modifier::Type_Mod7;
\r
1084 else if (*t == _T("mod8") ) mt = Modifier::Type_Mod8;
\r
1085 else if (*t == _T("mod9") ) mt = Modifier::Type_Mod9;
\r
1086 else throw ErrorMessage() << _T("`") << *t
\r
1087 << _T("': invalid modifier name.");
\r
1089 if (am == Keymap::AM_notModifier)
\r
1092 m_currentKeymap->addModifier(mt, Keymap::AO_overwrite, am, NULL);
\r
1100 Keymap::AssignOperator ao;
\r
1101 if (*t == _T("=") ) ao = Keymap::AO_new;
\r
1102 else if (*t == _T("+=")) ao = Keymap::AO_add;
\r
1103 else if (*t == _T("-=")) ao = Keymap::AO_sub;
\r
1104 else throw ErrorMessage() << _T("`") << *t << _T("': is unknown operator.");
\r
1106 // <ASSIGN_MODE>? <KEY_NAME>
\r
1107 while (!isEOL()) {
\r
1110 Keymap::AssignMode am = Keymap::AM_normal;
\r
1111 if (*t == _T("!") ) am = Keymap::AM_true, t = getToken();
\r
1112 else if (*t == _T("!!") ) am = Keymap::AM_oneShot, t = getToken();
\r
1113 else if (*t == _T("!!!")) am = Keymap::AM_oneShotRepeatable, t = getToken();
\r
1116 Key *key = m_setting->m_keyboard.searchKey(t->getString());
\r
1118 throw ErrorMessage() << _T("`") << *t << _T("': invalid key name.");
\r
1120 // we can ignore warning C4701
\r
1121 m_currentKeymap->addModifier(mt, ao, am, key);
\r
1122 if (ao == Keymap::AO_new)
\r
1123 ao = Keymap::AO_add;
\r
1128 // <KEYSEQ_DEFINITION>
\r
1129 void SettingLoader::load_KEYSEQ_DEFINITION()
\r
1131 if (*getToken() != _T("$"))
\r
1132 throw ErrorMessage() << _T("there must be `$' after `keyseq'");
\r
1133 Token *name = getToken();
\r
1134 if (*getToken() != _T("="))
\r
1135 throw ErrorMessage() << _T("there must be `=' after keyseq naem");
\r
1136 load_KEY_SEQUENCE(name->getString(), false, Modifier::Type_ASSIGN);
\r
1141 void SettingLoader::load_DEFINE()
\r
1143 m_setting->m_symbols.insert(getToken()->getString());
\r
1148 void SettingLoader::load_IF()
\r
1150 if (!getToken()->isOpenParen())
\r
1151 throw ErrorMessage() << _T("there must be `(' after `if'.");
\r
1152 Token *t = getToken(); // <SYMBOL> or !
\r
1154 if (*t == _T("!")) {
\r
1156 t = getToken(); // <SYMBOL>
\r
1159 bool doesSymbolExist = (m_setting->m_symbols.find(t->getString())
\r
1160 != m_setting->m_symbols.end());
\r
1161 bool doesRead = ((doesSymbolExist && !not) ||
\r
1162 (!doesSymbolExist && not));
\r
1163 if (0 < m_canReadStack.size())
\r
1164 doesRead = doesRead && m_canReadStack.back();
\r
1166 if (!getToken()->isCloseParen())
\r
1167 throw ErrorMessage() << _T("there must be `)'.");
\r
1169 m_canReadStack.push_back(doesRead);
\r
1171 size_t len = m_canReadStack.size();
\r
1173 if (len < m_canReadStack.size()) {
\r
1174 bool r = m_canReadStack.back();
\r
1175 m_canReadStack.pop_back();
\r
1176 m_canReadStack[len - 1] = r && doesRead;
\r
1177 } else if (len == m_canReadStack.size())
\r
1178 m_canReadStack.pop_back();
\r
1185 // <ELSE> <ELSEIF>
\r
1186 void SettingLoader::load_ELSE(bool i_isElseIf, const tstringi &i_token)
\r
1188 bool doesRead = !load_ENDIF(i_token);
\r
1189 if (0 < m_canReadStack.size())
\r
1190 doesRead = doesRead && m_canReadStack.back();
\r
1191 m_canReadStack.push_back(doesRead);
\r
1193 size_t len = m_canReadStack.size();
\r
1198 if (len < m_canReadStack.size()) {
\r
1199 bool r = m_canReadStack.back();
\r
1200 m_canReadStack.pop_back();
\r
1201 m_canReadStack[len - 1] = doesRead && r;
\r
1202 } else if (len == m_canReadStack.size())
\r
1203 m_canReadStack.pop_back();
\r
1211 bool SettingLoader::load_ENDIF(const tstringi &i_token)
\r
1213 if (m_canReadStack.size() == 0)
\r
1214 throw ErrorMessage() << _T("unbalanced `") << i_token << _T("'");
\r
1215 bool r = m_canReadStack.back();
\r
1216 m_canReadStack.pop_back();
\r
1222 void SettingLoader::load_LINE()
\r
1224 Token *i_token = getToken();
\r
1227 if (*i_token == _T("if") ||
\r
1228 *i_token == _T("and")) load_IF();
\r
1229 else if (*i_token == _T("else")) load_ELSE(false, i_token->getString());
\r
1230 else if (*i_token == _T("elseif") ||
\r
1231 *i_token == _T("elsif") ||
\r
1232 *i_token == _T("elif") ||
\r
1233 *i_token == _T("or")) load_ELSE(true, i_token->getString());
\r
1234 else if (*i_token == _T("endif")) load_ENDIF(_T("endif"));
\r
1235 else if (0 < m_canReadStack.size() && !m_canReadStack.back()) {
\r
1238 } else if (*i_token == _T("define")) load_DEFINE();
\r
1240 else if (*i_token == _T("include")) load_INCLUDE();
\r
1241 // <KEYBOARD_DEFINITION>
\r
1242 else if (*i_token == _T("def")) load_KEYBOARD_DEFINITION();
\r
1243 // <KEYMAP_DEFINITION>
\r
1244 else if (*i_token == _T("keymap") ||
\r
1245 *i_token == _T("keymap2") ||
\r
1246 *i_token == _T("window")) load_KEYMAP_DEFINITION(i_token);
\r
1248 else if (*i_token == _T("key")) load_KEY_ASSIGN();
\r
1250 else if (*i_token == _T("event")) load_EVENT_ASSIGN();
\r
1251 // <MODIFIER_ASSIGNMENT>
\r
1252 else if (*i_token == _T("mod")) load_MODIFIER_ASSIGNMENT();
\r
1253 // <KEYSEQ_DEFINITION>
\r
1254 else if (*i_token == _T("keyseq")) load_KEYSEQ_DEFINITION();
\r
1256 throw ErrorMessage() << _T("syntax error `") << *i_token << _T("'.");
\r
1260 // prefix sort predicate used in load(const string &)
\r
1261 static bool prefixSortPred(const tstringi &i_a, const tstringi &i_b)
\r
1263 return i_b.size() < i_a.size();
\r
1268 _UNICODE: read file (UTF-16 LE/BE, UTF-8, locale specific multibyte encoding)
\r
1271 bool readFile(tstring *o_data, const tstringi &i_filename)
\r
1273 // get size of file
\r
1275 // bcc's _wstat cannot obtain file size
\r
1276 struct _stat sbuf;
\r
1277 if (_tstat(i_filename.c_str(), &sbuf) < 0 || sbuf.st_size == 0)
\r
1280 // so, we use _wstati64 for bcc
\r
1281 struct stati64_t sbuf;
\r
1282 if (_tstati64(i_filename.c_str(), &sbuf) < 0 || sbuf.st_size == 0)
\r
1284 // following check is needed to cast sbuf.st_size to size_t safely
\r
1285 // this cast occurs because of above workaround for bcc
\r
1286 if (sbuf.st_size > UINT_MAX)
\r
1291 FILE *fp = _tfopen(i_filename.c_str(), _T("rb"));
\r
1296 Array<BYTE> buf(static_cast<size_t>(sbuf.st_size) + 1);
\r
1297 if (fread(buf.get(), static_cast<size_t>(sbuf.st_size), 1, fp) != 1) {
\r
1301 buf.get()[sbuf.st_size] = 0; // mbstowcs() requires null
\r
1302 // terminated string
\r
1306 if (buf.get()[0] == 0xffU && buf.get()[1] == 0xfeU &&
\r
1307 sbuf.st_size % 2 == 0)
\r
1308 // UTF-16 Little Endien
\r
1310 size_t size = static_cast<size_t>(sbuf.st_size) / 2;
\r
1311 o_data->resize(size);
\r
1312 BYTE *p = buf.get();
\r
1313 for (size_t i = 0; i < size; ++ i) {
\r
1314 wchar_t c = static_cast<wchar_t>(*p ++);
\r
1315 c |= static_cast<wchar_t>(*p ++) << 8;
\r
1323 if (buf.get()[0] == 0xfeU && buf.get()[1] == 0xffU &&
\r
1324 sbuf.st_size % 2 == 0)
\r
1325 // UTF-16 Big Endien
\r
1327 size_t size = static_cast<size_t>(sbuf.st_size) / 2;
\r
1328 o_data->resize(size);
\r
1329 BYTE *p = buf.get();
\r
1330 for (size_t i = 0; i < size; ++ i) {
\r
1331 wchar_t c = static_cast<wchar_t>(*p ++) << 8;
\r
1332 c |= static_cast<wchar_t>(*p ++);
\r
1339 // try multibyte charset
\r
1340 size_t wsize = mbstowcs(NULL, reinterpret_cast<char *>(buf.get()), 0);
\r
1341 if (wsize != size_t(-1)) {
\r
1342 Array<wchar_t> wbuf(wsize);
\r
1343 mbstowcs(wbuf.get(), reinterpret_cast<char *>(buf.get()), wsize);
\r
1344 o_data->assign(wbuf.get(), wbuf.get() + wsize);
\r
1351 Array<wchar_t> wbuf(static_cast<size_t>(sbuf.st_size));
\r
1352 BYTE *f = buf.get();
\r
1353 BYTE *end = buf.get() + sbuf.st_size;
\r
1354 wchar_t *d = wbuf.get();
\r
1355 enum { STATE_1, STATE_2of2, STATE_2of3, STATE_3of3 } state = STATE_1;
\r
1357 while (f != end) {
\r
1360 if (!(*f & 0x80)) // 0xxxxxxx: 00-7F
\r
1361 *d++ = static_cast<wchar_t>(*f++);
\r
1362 else if ((*f & 0xe0) == 0xc0) { // 110xxxxx 10xxxxxx: 0080-07FF
\r
1363 *d = ((static_cast<wchar_t>(*f++) & 0x1f) << 6);
\r
1364 state = STATE_2of2;
\r
1365 } else if ((*f & 0xf0) == 0xe0) // 1110xxxx 10xxxxxx 10xxxxxx:
\r
1368 *d = ((static_cast<wchar_t>(*f++) & 0x0f) << 12);
\r
1369 state = STATE_2of3;
\r
1376 if ((*f & 0xc0) != 0x80)
\r
1378 *d++ |= (static_cast<wchar_t>(*f++) & 0x3f);
\r
1383 if ((*f & 0xc0) != 0x80)
\r
1385 *d |= ((static_cast<wchar_t>(*f++) & 0x3f) << 6);
\r
1386 state = STATE_3of3;
\r
1390 o_data->assign(wbuf.get(), d);
\r
1397 #endif // _UNICODE
\r
1400 o_data->resize(static_cast<size_t>(sbuf.st_size));
\r
1401 for (off_t i = 0; i < sbuf.st_size; ++ i)
\r
1402 (*o_data)[i] = buf.get()[i];
\r
1408 // load (called from load(Setting *, const tstringi &) only)
\r
1409 void SettingLoader::load(const tstringi &i_filename)
\r
1411 m_currentFilename = i_filename;
\r
1414 if (!readFile(&data, m_currentFilename)) {
\r
1415 Acquire a(m_soLog);
\r
1416 *m_log << m_currentFilename << _T(" : error: file not found") << std::endl;
\r
1418 *m_log << data << std::endl;
\r
1420 m_isThereAnyError = true;
\r
1425 if (m_prefixesRefCcount == 0) {
\r
1426 static const _TCHAR *prefixes[] = {
\r
1427 _T("="), _T("=>"), _T("&&"), _T("||"), _T(":"), _T("$"), _T("&"),
\r
1428 _T("-="), _T("+="), _T("!!!"), _T("!!"), _T("!"),
\r
1429 _T("E0-"), _T("E1-"), // <SCAN_CODE_EXTENTION>
\r
1430 _T("S-"), _T("A-"), _T("M-"), _T("C-"), // <BASIC_MODIFIER>
\r
1431 _T("W-"), _T("*"), _T("~"),
\r
1432 _T("U-"), _T("D-"), // <KEYSEQ_MODIFIER>
\r
1433 _T("R-"), _T("IL-"), _T("IC-"), _T("I-"), // <ASSIGN_MODIFIER>
\r
1434 _T("NL-"), _T("CL-"), _T("SL-"), _T("KL-"),
\r
1435 _T("MAX-"), _T("MIN-"), _T("MMAX-"), _T("MMIN-"),
\r
1436 _T("T-"), _T("TS-"),
\r
1437 _T("M0-"), _T("M1-"), _T("M2-"), _T("M3-"), _T("M4-"),
\r
1438 _T("M5-"), _T("M6-"), _T("M7-"), _T("M8-"), _T("M9-"),
\r
1439 _T("L0-"), _T("L1-"), _T("L2-"), _T("L3-"), _T("L4-"),
\r
1440 _T("L5-"), _T("L6-"), _T("L7-"), _T("L8-"), _T("L9-"),
\r
1442 m_prefixes = new std::vector<tstringi>;
\r
1443 for (size_t i = 0; i < NUMBER_OF(prefixes); ++ i)
\r
1444 m_prefixes->push_back(prefixes[i]);
\r
1445 std::sort(m_prefixes->begin(), m_prefixes->end(), prefixSortPred);
\r
1447 m_prefixesRefCcount ++;
\r
1450 Parser parser(data.c_str(), data.size());
\r
1451 parser.setPrefixes(m_prefixes);
\r
1455 if (!parser.getLine(&m_tokens))
\r
1457 m_ti = m_tokens.begin();
\r
1458 } catch (ErrorMessage &e) {
\r
1459 if (m_log && m_soLog) {
\r
1460 Acquire a(m_soLog);
\r
1461 *m_log << m_currentFilename << _T("(") << parser.getLineNumber()
\r
1462 << _T(") : error: ") << e << std::endl;
\r
1464 m_isThereAnyError = true;
\r
1471 throw WarningMessage() << _T("back garbage is ignored.");
\r
1472 } catch (WarningMessage &w) {
\r
1473 if (m_log && m_soLog) {
\r
1474 Acquire a(m_soLog);
\r
1475 *m_log << i_filename << _T("(") << parser.getLineNumber()
\r
1476 << _T(") : warning: ") << w << std::endl;
\r
1478 } catch (ErrorMessage &e) {
\r
1479 if (m_log && m_soLog) {
\r
1480 Acquire a(m_soLog);
\r
1481 *m_log << i_filename << _T("(") << parser.getLineNumber()
\r
1482 << _T(") : error: ") << e << std::endl;
\r
1484 m_isThereAnyError = true;
\r
1489 -- m_prefixesRefCcount;
\r
1490 if (m_prefixesRefCcount == 0)
\r
1491 delete m_prefixes;
\r
1493 if (0 < m_canReadStack.size()) {
\r
1494 Acquire a(m_soLog);
\r
1495 *m_log << m_currentFilename << _T("(") << parser.getLineNumber()
\r
1496 << _T(") : error: unbalanced `if'. ")
\r
1497 << _T("you forget `endif', didn'i_token you?")
\r
1499 m_isThereAnyError = true;
\r
1504 // is the filename readable ?
\r
1505 bool SettingLoader::isReadable(const tstringi &i_filename,
\r
1506 int i_debugLevel) const
\r
1508 if (i_filename.empty())
\r
1511 tifstream ist(to_string(i_filename).c_str());
\r
1513 tifstream ist(i_filename.c_str());
\r
1516 if (m_log && m_soLog) {
\r
1517 Acquire a(m_soLog, 0);
\r
1518 *m_log << _T(" loading: ") << i_filename << std::endl;
\r
1522 if (m_log && m_soLog) {
\r
1523 Acquire a(m_soLog, i_debugLevel);
\r
1524 *m_log << _T("not found: ") << i_filename << std::endl;
\r
1531 // get filename from registry
\r
1532 bool SettingLoader::getFilenameFromRegistry(tstringi *o_path) const
\r
1534 // get from registry
\r
1535 Registry reg(MAYU_REGISTRY_ROOT);
\r
1537 reg.read(_T(".mayuIndex"), &index, 0);
\r
1539 snprintf(buf, NUMBER_OF(buf), _T(".mayu%d"), index);
\r
1540 if (!reg.read(buf, o_path))
\r
1543 // parse registry entry
\r
1544 Regexp getFilename(_T("^[^;]*;([^;]*);(.*)$"));
\r
1545 if (!getFilename.doesMatch(*o_path))
\r
1548 tstringi path = getFilename[1];
\r
1549 tstringi options = getFilename[2];
\r
1551 if (!(0 < path.size() && isReadable(path)))
\r
1556 Regexp symbol(_T("-D([^;]*)"));
\r
1557 while (symbol.doesMatch(options)) {
\r
1558 m_setting->symbols.insert(symbol[1]);
\r
1559 options = options.substr(symbol.subBegin(1));
\r
1568 bool SettingLoader::getFilename(const tstringi &i_name, tstringi *o_path,
\r
1569 int i_debugLevel) const
\r
1571 // the default filename is ".mayu"
\r
1572 const tstringi &name = i_name.empty() ? tstringi(_T(".mayu")) : i_name;
\r
1574 bool isFirstTime = true;
\r
1577 // find file from registry
\r
1578 if (i_name.empty()) { // called not from 'include'
\r
1579 Setting::Symbols symbols;
\r
1580 if (getFilenameFromRegistry(NULL, o_path, &symbols)) {
\r
1581 if (o_path->empty())
\r
1582 // find file from home directory
\r
1584 HomeDirectories pathes;
\r
1585 getHomeDirectories(&pathes);
\r
1586 for (HomeDirectories::iterator
\r
1587 i = pathes.begin(); i != pathes.end(); ++ i) {
\r
1588 *o_path = *i + _T("\\") + name;
\r
1589 if (isReadable(*o_path, i_debugLevel))
\r
1594 if (!isReadable(*o_path, i_debugLevel))
\r
1598 for (Setting::Symbols::iterator
\r
1599 i = symbols.begin(); i != symbols.end(); ++ i)
\r
1600 m_setting->m_symbols.insert(*i);
\r
1608 // find file from home directory
\r
1609 HomeDirectories pathes;
\r
1610 getHomeDirectories(&pathes);
\r
1611 for (HomeDirectories::iterator i = pathes.begin(); i != pathes.end(); ++ i) {
\r
1612 *o_path = *i + _T("\\") + name;
\r
1613 if (isReadable(*o_path, i_debugLevel))
\r
1617 if (!i_name.empty())
\r
1618 return false; // called by 'include'
\r
1620 if (!DialogBox(g_hInst, MAKEINTRESOURCE(IDD_DIALOG_setting),
\r
1621 NULL, dlgSetting_dlgProc))
\r
1628 SettingLoader::SettingLoader(SyncObject *i_soLog, tostream *i_log)
\r
1629 : m_setting(NULL),
\r
1630 m_isThereAnyError(false),
\r
1633 m_currentKeymap(NULL)
\r
1635 m_defaultKeySeqModifier =
\r
1636 m_defaultAssignModifier.release(Modifier::Type_ImeComp);
\r
1641 If called by "include", 'filename' describes filename.
\r
1642 Otherwise the 'filename' is empty.
\r
1644 bool SettingLoader::load(Setting *i_setting, const tstringi &i_filename)
\r
1646 m_setting = i_setting;
\r
1647 m_isThereAnyError = false;
\r
1650 if (!getFilename(i_filename, &path)) {
\r
1651 if (i_filename.empty()) {
\r
1652 Acquire a(m_soLog);
\r
1653 getFilename(i_filename, &path, 0); // show filenames
\r
1656 throw ErrorMessage() << _T("`") << i_filename
\r
1657 << _T("': no such file or other error.");
\r
1660 // create global keymap's default keySeq
\r
1661 ActionFunction af(createFunctionData(_T("OtherWindowClass")));
\r
1662 KeySeq *globalDefault = m_setting->m_keySeqs.add(KeySeq(_T("")).add(af));
\r
1664 // add default keymap
\r
1665 m_currentKeymap = m_setting->m_keymaps.add(
\r
1666 Keymap(Keymap::Type_windowOr, _T("Global"), _T(""), _T(""),
\r
1667 globalDefault, NULL));
\r
1670 // add keyboard layout name
\r
1671 if (filename.empty())
\r
1673 char keyboardLayoutName[KL_NAMELENGTH];
\r
1674 if (GetKeyboardLayoutName(keyboardLayoutName))
\r
1676 tstringi kl = tstringi(_T("KeyboardLayout/")) + keyboardLayoutName;
\r
1677 m_setting->symbols.insert(kl);
\r
1678 Acquire a(m_soLog);
\r
1679 *m_log << _T("KeyboardLayout: ") << kl << std::endl;
\r
1688 if (i_filename.empty())
\r
1689 m_setting->m_keymaps.adjustModifier(m_setting->m_keyboard);
\r
1691 return !m_isThereAnyError;
\r
1695 std::vector<tstringi> *SettingLoader::m_prefixes; // m_prefixes terminal symbol
\r
1696 size_t SettingLoader::m_prefixesRefCcount; /* reference count of
\r