OSDN Git Service

post WM_NULL to attached threads on yamy exit to unmap mayu{32,64}.dll
[yamy/yamy.git] / setting.cpp
1 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
2 // setting.cpp\r
3 \r
4 \r
5 #include "misc.h"\r
6 \r
7 #include "dlgsetting.h"\r
8 #include "errormessage.h"\r
9 #include "mayu.h"\r
10 #include "mayurc.h"\r
11 #include "registry.h"\r
12 #include "setting.h"\r
13 #include "windowstool.h"\r
14 #include "vkeytable.h"\r
15 #include "array.h"\r
16 \r
17 #include <algorithm>\r
18 #include <fstream>\r
19 #include <iomanip>\r
20 #include <sys/stat.h>\r
21 \r
22 \r
23 namespace Event\r
24 {\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
28 Key *events[] = {\r
29         &prefixed,\r
30         &before_key_down,\r
31         &after_key_up,\r
32         NULL,\r
33 };\r
34 }\r
35 \r
36 \r
37 // get mayu filename\r
38 static bool getFilenameFromRegistry(\r
39         tstringi *o_name, tstringi *o_filename, Setting::Symbols *o_symbols)\r
40 {\r
41         Registry reg(MAYU_REGISTRY_ROOT);\r
42         int index;\r
43         reg.read(_T(".mayuIndex"), &index, 0);\r
44         _TCHAR buf[100];\r
45         _sntprintf(buf, NUMBER_OF(buf), _T(".mayu%d"), index);\r
46 \r
47         tstringi entry;\r
48         if (!reg.read(buf, &entry))\r
49                 return false;\r
50 \r
51         tregex getFilename(_T("^([^;]*);([^;]*);(.*)$"));\r
52         tsmatch getFilenameResult;\r
53         if (!boost::regex_match(entry, getFilenameResult, getFilename))\r
54                 return false;\r
55 \r
56         if (o_name)\r
57                 *o_name = getFilenameResult.str(1);\r
58         if (o_filename)\r
59                 *o_filename = getFilenameResult.str(2);\r
60         if (o_symbols) {\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
67                 }\r
68         }\r
69         return true;\r
70 }\r
71 \r
72 \r
73 // get home directory path\r
74 void getHomeDirectories(HomeDirectories *o_pathes)\r
75 {\r
76         tstringi filename;\r
77 #ifndef USE_INI\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
84         }\r
85 \r
86         const _TCHAR *home = _tgetenv(_T("HOME"));\r
87         if (home)\r
88                 o_pathes->push_back(home);\r
89 \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
94 \r
95         const _TCHAR *userprofile = _tgetenv(_T("USERPROFILE"));\r
96         if (userprofile)\r
97                 o_pathes->push_back(userprofile);\r
98 \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
103 #else //USE_INI\r
104         _TCHAR buf[GANA_MAX_PATH];\r
105 #endif //USE_INI\r
106 \r
107         if (GetModuleFileName(GetModuleHandle(NULL), buf, NUMBER_OF(buf)))\r
108                 o_pathes->push_back(pathRemoveFileSpec(buf));\r
109 }\r
110 \r
111 \r
112 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
113 // SettingLoader\r
114 \r
115 \r
116 // is there no more tokens ?\r
117 bool SettingLoader::isEOL()\r
118 {\r
119         return m_ti == m_tokens.end();\r
120 }\r
121 \r
122 \r
123 // get next token\r
124 Token *SettingLoader::getToken()\r
125 {\r
126         if (isEOL())\r
127                 throw ErrorMessage() << _T("too few words.");\r
128         return &*(m_ti ++);\r
129 }\r
130 \r
131 \r
132 // look next token\r
133 Token *SettingLoader::lookToken()\r
134 {\r
135         if (isEOL())\r
136                 throw ErrorMessage() << _T("too few words.");\r
137         return &*m_ti;\r
138 }\r
139 \r
140 \r
141 // argument "("\r
142 bool SettingLoader::getOpenParen(bool i_doesThrow, const _TCHAR *i_name)\r
143 {\r
144         if (!isEOL() && lookToken()->isOpenParen()) {\r
145                 getToken();\r
146                 return true;\r
147         }\r
148         if (i_doesThrow)\r
149                 throw ErrorMessage() << _T("there must be `(' after `&")\r
150                 << i_name << _T("'.");\r
151         return false;\r
152 }\r
153 \r
154 \r
155 // argument ")"\r
156 bool SettingLoader::getCloseParen(bool i_doesThrow, const _TCHAR *i_name)\r
157 {\r
158         if (!isEOL() && lookToken()->isCloseParen()) {\r
159                 getToken();\r
160                 return true;\r
161         }\r
162         if (i_doesThrow)\r
163                 throw ErrorMessage() << _T("`&")  << i_name\r
164                 << _T("': too many arguments.");\r
165         return false;\r
166 }\r
167 \r
168 \r
169 // argument ","\r
170 bool SettingLoader::getComma(bool i_doesThrow, const _TCHAR *i_name)\r
171 {\r
172         if (!isEOL() && lookToken()->isComma()) {\r
173                 getToken();\r
174                 return true;\r
175         }\r
176         if (i_doesThrow)\r
177                 throw ErrorMessage() << _T("`&")  << i_name\r
178                 << _T("': comma expected.");\r
179         return false;\r
180 }\r
181 \r
182 \r
183 // <INCLUDE>\r
184 void SettingLoader::load_INCLUDE()\r
185 {\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
191 }\r
192 \r
193 \r
194 // <SCAN_CODES>\r
195 void SettingLoader::load_SCAN_CODES(Key *o_key)\r
196 {\r
197         for (int j = 0; j < Key::MAX_SCAN_CODES_SIZE && !isEOL(); ++ j) {\r
198                 ScanCode sc;\r
199                 sc.m_flags = 0;\r
200                 while (true) {\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
205                                 break;\r
206                         }\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
211                 }\r
212         }\r
213 }\r
214 \r
215 \r
216 // <DEFINE_KEY>\r
217 void SettingLoader::load_DEFINE_KEY()\r
218 {\r
219         Token *t = getToken();\r
220         Key key;\r
221 \r
222         // <KEY_NAMES>\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
229         } else {\r
230                 key.addName(t->getString());\r
231                 while (t = getToken(), *t != _T("="))\r
232                         key.addName(t->getString());\r
233         }\r
234 \r
235         load_SCAN_CODES(&key);\r
236         m_setting->m_keyboard.addKey(key);\r
237 }\r
238 \r
239 \r
240 // <DEFINE_MODIFIER>\r
241 void SettingLoader::load_DEFINE_MODIFIER()\r
242 {\r
243         Token *t = getToken();\r
244         Modifier::Type mt;\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
255 \r
256         if (*getToken() != _T("="))\r
257                 throw ErrorMessage() << _T("there must be `=' after modifier name.");\r
258 \r
259         while (!isEOL()) {\r
260                 t = getToken();\r
261                 Key *key =\r
262                         m_setting->m_keyboard.searchKeyByNonAliasName(t->getString());\r
263                 if (!key)\r
264                         throw ErrorMessage() << _T("`") << *t << _T("': invalid key name.");\r
265                 m_setting->m_keyboard.addModifier(mt, key);\r
266         }\r
267 }\r
268 \r
269 \r
270 // <DEFINE_SYNC_KEY>\r
271 void SettingLoader::load_DEFINE_SYNC_KEY()\r
272 {\r
273         Key *key = m_setting->m_keyboard.getSyncKey();\r
274         key->initialize();\r
275         key->addName(_T("sync"));\r
276 \r
277         if (*getToken() != _T("="))\r
278                 throw ErrorMessage() << _T("there must be `=' after `sync'.");\r
279 \r
280         load_SCAN_CODES(key);\r
281 }\r
282 \r
283 \r
284 // <DEFINE_ALIAS>\r
285 void SettingLoader::load_DEFINE_ALIAS()\r
286 {\r
287         Token *name = getToken();\r
288 \r
289         if (*getToken() != _T("="))\r
290                 throw ErrorMessage() << _T("there must be `=' after `alias'.");\r
291 \r
292         Token *t = getToken();\r
293         Key *key = m_setting->m_keyboard.searchKeyByNonAliasName(t->getString());\r
294         if (!key)\r
295                 throw ErrorMessage() << _T("`") << *t << _T("': invalid key name.");\r
296         m_setting->m_keyboard.addAlias(name->getString(), key);\r
297 }\r
298 \r
299 \r
300 // <DEFINE_SUBSTITUTE>\r
301 void SettingLoader::load_DEFINE_SUBSTITUTE()\r
302 {\r
303         typedef std::list<ModifiedKey> AssignedKeys;\r
304         AssignedKeys assignedKeys;\r
305         do {\r
306                 ModifiedKey mkey;\r
307                 mkey.m_modifier =\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
312         getToken();\r
313 \r
314         KeySeq *keySeq = load_KEY_SEQUENCE(_T(""), false, Modifier::Type_ASSIGN);\r
315         ModifiedKey mkey = keySeq->getFirstModifiedKey();\r
316         if (!mkey.m_key)\r
317                 throw ErrorMessage() << _T("no key is specified for substitute.");\r
318 \r
319         for (AssignedKeys::iterator i = assignedKeys.begin();\r
320                         i != assignedKeys.end(); ++ i)\r
321                 m_setting->m_keyboard.addSubstitute(*i, mkey);\r
322 }\r
323 \r
324 \r
325 // <DEFINE_OPTION>\r
326 void SettingLoader::load_DEFINE_OPTION()\r
327 {\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
332                 }\r
333 \r
334                 load_ARGUMENT(&m_setting->m_correctKanaLockHandling);\r
335 \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
340                 }\r
341 \r
342                 if (*getToken() != _T("=")) {\r
343                         throw ErrorMessage()\r
344                         << _T("there must be `=' after `def option delay-of !!!'.");\r
345                 }\r
346 \r
347                 load_ARGUMENT(&m_setting->m_oneShotRepeatableDelay);\r
348 \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
353                 }\r
354 \r
355                 load_ARGUMENT(&m_setting->m_sts4mayu);\r
356 \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
361                 }\r
362 \r
363                 load_ARGUMENT(&m_setting->m_cts4mayu);\r
364 \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
369                 }\r
370 \r
371                 load_ARGUMENT(&m_setting->m_mouseEvent);\r
372 \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
377                 }\r
378 \r
379                 load_ARGUMENT(&m_setting->m_dragThreshold);\r
380 \r
381         } else {\r
382                 throw ErrorMessage() << _T("syntax error `def option ") << *t << _T("'.");\r
383         }\r
384 }\r
385 \r
386 \r
387 \r
388 // <KEYBOARD_DEFINITION>\r
389 void SettingLoader::load_KEYBOARD_DEFINITION()\r
390 {\r
391         Token *t = getToken();\r
392 \r
393         // <DEFINE_KEY>\r
394         if (*t == _T("key")) load_DEFINE_KEY();\r
395 \r
396         // <DEFINE_MODIFIER>\r
397         else if (*t == _T("mod")) load_DEFINE_MODIFIER();\r
398 \r
399         // <DEFINE_SYNC_KEY>\r
400         else if (*t == _T("sync")) load_DEFINE_SYNC_KEY();\r
401 \r
402         // <DEFINE_ALIAS>\r
403         else if (*t == _T("alias")) load_DEFINE_ALIAS();\r
404 \r
405         // <DEFINE_SUBSTITUTE>\r
406         else if (*t == _T("subst")) load_DEFINE_SUBSTITUTE();\r
407 \r
408         // <DEFINE_OPTION>\r
409         else if (*t == _T("option")) load_DEFINE_OPTION();\r
410 \r
411         //\r
412         else throw ErrorMessage() << _T("syntax error `") << *t << _T("'.");\r
413 }\r
414 \r
415 \r
416 // <..._MODIFIER>\r
417 Modifier SettingLoader::load_MODIFIER(\r
418         Modifier::Type i_mode, Modifier i_modifier, Modifier::Type *o_mode)\r
419 {\r
420         if (o_mode)\r
421                 *o_mode = Modifier::Type_begin;\r
422 \r
423         Modifier isModifierSpecified;\r
424         enum { PRESS, RELEASE, DONTCARE } flag = PRESS;\r
425 \r
426         int i;\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
430         }\r
431 \r
432         Token *t = NULL;\r
433 \r
434 continue_loop:\r
435         while (!isEOL()) {\r
436                 t = lookToken();\r
437 \r
438                 const static struct {\r
439                         const _TCHAR *m_s;\r
440                         Modifier::Type m_mt;\r
441                 } map[] = {\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
486                 };\r
487 \r
488                 for (int i = 0; i < NUMBER_OF(map); ++ i)\r
489                         if (*t == map[i].m_s) {\r
490                                 getToken();\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
495                                 switch (flag) {\r
496                                 case PRESS:\r
497                                         i_modifier.press(mt);\r
498                                         break;\r
499                                 case RELEASE:\r
500                                         i_modifier.release(mt);\r
501                                         break;\r
502                                 case DONTCARE:\r
503                                         i_modifier.dontcare(mt);\r
504                                         break;\r
505                                 }\r
506                                 isModifierSpecified.on(mt);\r
507                                 flag = PRESS;\r
508 \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
516                                 }\r
517                                 goto continue_loop;\r
518                         }\r
519 \r
520                 if (*t == _T("*")) {\r
521                         getToken();\r
522                         flag = DONTCARE;\r
523                         continue;\r
524                 }\r
525 \r
526                 if (*t == _T("~")) {\r
527                         getToken();\r
528                         flag = RELEASE;\r
529                         continue;\r
530                 }\r
531 \r
532                 break;\r
533         }\r
534 \r
535         for (i = Modifier::Type_begin; i != Modifier::Type_end; ++ i)\r
536                 if (!isModifierSpecified.isOn(Modifier::Type(i)))\r
537                         switch (flag) {\r
538                         case PRESS:\r
539                                 break;\r
540                         case RELEASE:\r
541                                 i_modifier.release(Modifier::Type(i));\r
542                                 break;\r
543                         case DONTCARE:\r
544                                 i_modifier.dontcare(Modifier::Type(i));\r
545                                 break;\r
546                         }\r
547 \r
548         // fix up and down\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
554                 ;\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
562         }\r
563 \r
564         // fix repeat\r
565         if (!isModifierSpecified.isOn(Modifier::Type_Repeat))\r
566                 i_modifier.dontcare(Modifier::Type_Repeat);\r
567         return i_modifier;\r
568 }\r
569 \r
570 \r
571 // <KEY_NAME>\r
572 Key *SettingLoader::load_KEY_NAME()\r
573 {\r
574         Token *t = getToken();\r
575         Key *key = m_setting->m_keyboard.searchKey(t->getString());\r
576         if (!key)\r
577                 throw ErrorMessage() << _T("`") << *t << _T("': invalid key name.");\r
578         return key;\r
579 }\r
580 \r
581 \r
582 // <KEYMAP_DEFINITION>\r
583 void SettingLoader::load_KEYMAP_DEFINITION(const Token *i_which)\r
584 {\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
593 \r
594         if (!isEOL()) {\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
600                         {\r
601                                 getToken();\r
602                                 windowClassName = getToken()->getRegexp();\r
603                                 t = getToken();\r
604                                 if (*t == _T("&&"))\r
605                                         type = Keymap::Type_windowAnd;\r
606                                 else if (*t == _T("||"))\r
607                                         type = Keymap::Type_windowOr;\r
608                                 else\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
614                                 getToken();\r
615                                 type = Keymap::Type_windowAnd;\r
616                                 windowClassName = t->getRegexp();\r
617                         }\r
618                 } else if (*i_which == _T("keymap"))\r
619                         ;\r
620                 else if (*i_which == _T("keymap2"))\r
621                         isKeymap2 = true;\r
622                 else\r
623                         ASSERT(false);\r
624 \r
625                 if (!isEOL())\r
626                         doesLoadDefaultKeySeq = true;\r
627         }\r
628 \r
629         m_currentKeymap = m_setting->m_keymaps.add(\r
630                                                   Keymap(type, name->getString(), windowClassName, windowTitleName,\r
631                                                                  NULL, NULL));\r
632 \r
633         if (doesLoadDefaultKeySeq) {\r
634                 Token *t = lookToken();\r
635                 // <KEYMAP_PARENT>\r
636                 if (*t == _T(":")) {\r
637                         getToken();\r
638                         t = getToken();\r
639                         parentKeymap = m_setting->m_keymaps.searchByName(t->getString());\r
640                         if (!parentKeymap)\r
641                                 throw ErrorMessage() << _T("`") << *t\r
642                                 << _T("': unknown keymap name.");\r
643                 }\r
644                 if (!isEOL()) {\r
645                         t = getToken();\r
646                         if (!(*t == _T("=>") || *t == _T("=")))\r
647                                 throw ErrorMessage() << _T("`") << *t << _T("': syntax error.");\r
648                         keySeq = SettingLoader::load_KEY_SEQUENCE();\r
649                 }\r
650         }\r
651         if (keySeq == NULL) {\r
652                 FunctionData *fd;\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
659                 ASSERT( fd );\r
660                 keySeq = m_setting->m_keySeqs.add(\r
661                                          KeySeq(name->getString()).add(ActionFunction(fd)));\r
662         }\r
663 \r
664         m_currentKeymap->setIfNotYet(keySeq, parentKeymap);\r
665 }\r
666 \r
667 \r
668 // &lt;ARGUMENT&gt;\r
669 void SettingLoader::load_ARGUMENT(bool *o_arg)\r
670 {\r
671         *o_arg = !(*getToken() == _T("false"));\r
672 }\r
673 \r
674 \r
675 // &lt;ARGUMENT&gt;\r
676 void SettingLoader::load_ARGUMENT(int *o_arg)\r
677 {\r
678         *o_arg = getToken()->getNumber();\r
679 }\r
680 \r
681 \r
682 // &lt;ARGUMENT&gt;\r
683 void SettingLoader::load_ARGUMENT(unsigned int *o_arg)\r
684 {\r
685         *o_arg = getToken()->getNumber();\r
686 }\r
687 \r
688 \r
689 // &lt;ARGUMENT&gt;\r
690 void SettingLoader::load_ARGUMENT(long *o_arg)\r
691 {\r
692         *o_arg = getToken()->getNumber();\r
693 }\r
694 \r
695 \r
696 // &lt;ARGUMENT&gt;\r
697 void SettingLoader::load_ARGUMENT(unsigned __int64 *o_arg)\r
698 {\r
699         *o_arg = getToken()->getNumber();\r
700 }\r
701 \r
702 \r
703 // &lt;ARGUMENT&gt;\r
704 void SettingLoader::load_ARGUMENT(__int64 *o_arg)\r
705 {\r
706         *o_arg = getToken()->getNumber();\r
707 }\r
708 \r
709 \r
710 // &lt;ARGUMENT&gt;\r
711 void SettingLoader::load_ARGUMENT(tstringq *o_arg)\r
712 {\r
713         *o_arg = getToken()->getString();\r
714 }\r
715 \r
716 \r
717 // &lt;ARGUMENT&gt;\r
718 void SettingLoader::load_ARGUMENT(std::list<tstringq> *o_arg)\r
719 {\r
720         while (true) {\r
721                 if (!lookToken()->isString())\r
722                         return;\r
723                 o_arg->push_back(getToken()->getString());\r
724 \r
725                 if (!lookToken()->isComma())\r
726                         return;\r
727                 getToken();\r
728         }\r
729 }\r
730 \r
731 \r
732 // &lt;ARGUMENT&gt;\r
733 void SettingLoader::load_ARGUMENT(tregex *o_arg)\r
734 {\r
735         *o_arg = getToken()->getRegexp();\r
736 }\r
737 \r
738 \r
739 // &lt;ARGUMENT_VK&gt;\r
740 void SettingLoader::load_ARGUMENT(VKey *o_arg)\r
741 {\r
742         Token *t = getToken();\r
743         int vkey = 0;\r
744         while (true) {\r
745                 if (t->isNumber()) {\r
746                         vkey |= static_cast<BYTE>(t->getNumber());\r
747                         break;\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
751                 else {\r
752                         const VKeyTable *vkt;\r
753                         for (vkt = g_vkeyTable; vkt->m_name; ++ vkt)\r
754                                 if (*t == vkt->m_name)\r
755                                         break;\r
756                         if (!vkt->m_name)\r
757                                 throw ErrorMessage() << _T("`") << *t\r
758                                 << _T("': unknown virtual key name.");\r
759                         vkey |= vkt->m_code;\r
760                         break;\r
761                 }\r
762                 t = getToken();\r
763         }\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
767 }\r
768 \r
769 \r
770 // &lt;ARGUMENT_WINDOW&gt;\r
771 void SettingLoader::load_ARGUMENT(ToWindowType *o_arg)\r
772 {\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
777                         return;\r
778                 }\r
779         } else if (getTypeValue(o_arg, t->getString()))\r
780                 return;\r
781         throw ErrorMessage() << _T("`") << *t << _T("': invalid target window.");\r
782 }\r
783 \r
784 \r
785 // &lt;ARGUMENT&gt;\r
786 void SettingLoader::load_ARGUMENT(GravityType *o_arg)\r
787 {\r
788         Token *t = getToken();\r
789         if (getTypeValue(o_arg, t->getString()))\r
790                 return;\r
791         throw ErrorMessage() << _T("`") << *t << _T("': unknown gravity symbol.");\r
792 }\r
793 \r
794 \r
795 // &lt;ARGUMENT&gt;\r
796 void SettingLoader::load_ARGUMENT(MouseHookType *o_arg)\r
797 {\r
798         Token *t = getToken();\r
799         if (getTypeValue(o_arg, t->getString()))\r
800                 return;\r
801         throw ErrorMessage() << _T("`") << *t << _T("': unknown MouseHookType symbol.");\r
802 }\r
803 \r
804 \r
805 // &lt;ARGUMENT&gt;\r
806 void SettingLoader::load_ARGUMENT(MayuDialogType *o_arg)\r
807 {\r
808         Token *t = getToken();\r
809         if (getTypeValue(o_arg, t->getString()))\r
810                 return;\r
811         throw ErrorMessage() << _T("`") << *t << _T("': unknown dialog box.");\r
812 }\r
813 \r
814 \r
815 // &lt;ARGUMENT_LOCK&gt;\r
816 void SettingLoader::load_ARGUMENT(ModifierLockType *o_arg)\r
817 {\r
818         Token *t = getToken();\r
819         if (getTypeValue(o_arg, t->getString()))\r
820                 return;\r
821         throw ErrorMessage() << _T("`") << *t << _T("': unknown lock name.");\r
822 }\r
823 \r
824 \r
825 // &lt;ARGUMENT_LOCK&gt;\r
826 void SettingLoader::load_ARGUMENT(ToggleType *o_arg)\r
827 {\r
828         Token *t = getToken();\r
829         if (getTypeValue(o_arg, t->getString()))\r
830                 return;\r
831         throw ErrorMessage() << _T("`") << *t << _T("': unknown toggle name.");\r
832 }\r
833 \r
834 \r
835 // &lt;ARGUMENT_SHOW_WINDOW&gt;\r
836 void SettingLoader::load_ARGUMENT(ShowCommandType *o_arg)\r
837 {\r
838         Token *t = getToken();\r
839         if (getTypeValue(o_arg, t->getString()))\r
840                 return;\r
841         throw ErrorMessage() << _T("`") << *t << _T("': unknown show command.");\r
842 }\r
843 \r
844 \r
845 // &lt;ARGUMENT_TARGET_WINDOW&gt;\r
846 void SettingLoader::load_ARGUMENT(TargetWindowType *o_arg)\r
847 {\r
848         Token *t = getToken();\r
849         if (getTypeValue(o_arg, t->getString()))\r
850                 return;\r
851         throw ErrorMessage() << _T("`") << *t\r
852         << _T("': unknown target window type.");\r
853 }\r
854 \r
855 \r
856 // &lt;bool&gt;\r
857 void SettingLoader::load_ARGUMENT(BooleanType *o_arg)\r
858 {\r
859         Token *t = getToken();\r
860         if (getTypeValue(o_arg, t->getString()))\r
861                 return;\r
862         throw ErrorMessage() << _T("`") << *t << _T("': must be true or false.");\r
863 }\r
864 \r
865 \r
866 // &lt;ARGUMENT&gt;\r
867 void SettingLoader::load_ARGUMENT(LogicalOperatorType *o_arg)\r
868 {\r
869         Token *t = getToken();\r
870         if (getTypeValue(o_arg, t->getString()))\r
871                 return;\r
872         throw ErrorMessage() << _T("`") << *t << _T("': must be 'or' or 'and'.");\r
873 }\r
874 \r
875 \r
876 // &lt;ARGUMENT&gt;\r
877 void SettingLoader::load_ARGUMENT(Modifier *o_arg)\r
878 {\r
879         Modifier modifier;\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
883 }\r
884 \r
885 \r
886 // &lt;ARGUMENT&gt;\r
887 void SettingLoader::load_ARGUMENT(const Keymap **o_arg)\r
888 {\r
889         Token *t = getToken();\r
890         const Keymap *&keymap = *o_arg;\r
891         keymap = m_setting->m_keymaps.searchByName(t->getString());\r
892         if (!keymap)\r
893                 throw ErrorMessage() << _T("`") << *t << _T("': unknown keymap name.");\r
894 }\r
895 \r
896 \r
897 // &lt;ARGUMENT&gt;\r
898 void SettingLoader::load_ARGUMENT(const KeySeq **o_arg)\r
899 {\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
906                 t = getToken();\r
907                 keySeq = m_setting->m_keySeqs.searchByName(t->getString());\r
908                 if (!keySeq)\r
909                         throw ErrorMessage() << _T("`$") << *t << _T("': unknown keyseq name.");\r
910         } else\r
911                 throw ErrorMessage() << _T("`") << *t << _T("': it is not keyseq.");\r
912 }\r
913 \r
914 \r
915 // &lt;ARGUMENT&gt;\r
916 void SettingLoader::load_ARGUMENT(StrExprArg *o_arg)\r
917 {\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
923                 t = getToken();\r
924         }\r
925         *o_arg = StrExprArg(t->getString(), type);\r
926 }\r
927 \r
928 \r
929 // &lt;ARGUMENT&gt;\r
930 void SettingLoader::load_ARGUMENT(WindowMonitorFromType *o_arg)\r
931 {\r
932         Token *t = getToken();\r
933         if (getTypeValue(o_arg, t->getString()))\r
934                 return;\r
935         throw ErrorMessage() << _T("`") << *t\r
936         << _T("': unknown monitor from type.");\r
937 }\r
938 \r
939 \r
940 // <KEY_SEQUENCE>\r
941 KeySeq *SettingLoader::load_KEY_SEQUENCE(\r
942         const tstringi &i_name, bool i_isInParen, Modifier::Type i_mode)\r
943 {\r
944         KeySeq keySeq(i_name);\r
945         while (!isEOL()) {\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
951                         break;\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
958                         getToken();\r
959                         t = getToken();\r
960                         KeySeq *ks = m_setting->m_keySeqs.searchByName(t->getString());\r
961                         if (ks == NULL)\r
962                                 throw ErrorMessage() << _T("`$") << *t\r
963                                 << _T("': unknown keyseq name.");\r
964                         if (!ks->isCorrectMode(i_mode))\r
965                                 throw ErrorMessage()\r
966                                 << _T("`$") << *t\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
971                         getToken();\r
972                         t = getToken();\r
973 \r
974                         // search function\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
980                         keySeq.add(af);\r
981                 } else { // <KEYSEQ_MODIFIED_KEY_NAME>\r
982                         ModifiedKey mkey;\r
983                         mkey.m_modifier = modifier;\r
984                         mkey.m_key = load_KEY_NAME();\r
985                         keySeq.add(ActionKey(mkey));\r
986                 }\r
987         }\r
988         return m_setting->m_keySeqs.add(keySeq);\r
989 }\r
990 \r
991 \r
992 // <KEY_ASSIGN>\r
993 void SettingLoader::load_KEY_ASSIGN()\r
994 {\r
995         typedef std::list<ModifiedKey> AssignedKeys;\r
996         AssignedKeys assignedKeys;\r
997 \r
998         ModifiedKey mkey;\r
999         mkey.m_modifier =\r
1000                 load_MODIFIER(Modifier::Type_ASSIGN, m_defaultAssignModifier);\r
1001         if (*lookToken() == _T("=")) {\r
1002                 getToken();\r
1003                 m_defaultKeySeqModifier = load_MODIFIER(Modifier::Type_KEYSEQ,\r
1004                                                                                                 m_defaultKeySeqModifier);\r
1005                 m_defaultAssignModifier = mkey.m_modifier;\r
1006                 return;\r
1007         }\r
1008 \r
1009         while (true) {\r
1010                 mkey.m_key = load_KEY_NAME();\r
1011                 assignedKeys.push_back(mkey);\r
1012                 if (*lookToken() == _T("=>") || *lookToken() == _T("="))\r
1013                         break;\r
1014                 mkey.m_modifier =\r
1015                         load_MODIFIER(Modifier::Type_ASSIGN, m_defaultAssignModifier);\r
1016         }\r
1017         getToken();\r
1018 \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
1024 }\r
1025 \r
1026 \r
1027 // <EVENT_ASSIGN>\r
1028 void SettingLoader::load_EVENT_ASSIGN()\r
1029 {\r
1030         std::list<ModifiedKey> assignedKeys;\r
1031 \r
1032         ModifiedKey mkey;\r
1033         mkey.m_modifier.dontcare();                     //set all modifiers to dontcare\r
1034 \r
1035         Token *t = getToken();\r
1036         Key **e;\r
1037         for (e = Event::events; *e; ++ e)\r
1038                 if (*t == (*e)->getName()) {\r
1039                         mkey.m_key = *e;\r
1040                         break;\r
1041                 }\r
1042         if (!*e)\r
1043                 throw ErrorMessage() << _T("`") << *t << _T("': invalid event name.");\r
1044 \r
1045         t = getToken();\r
1046         if (!(*t == _T("=>") || *t == _T("=")))\r
1047                 throw ErrorMessage() << _T("`=' is expected.");\r
1048 \r
1049         ASSERT(m_currentKeymap);\r
1050         KeySeq *keySeq = load_KEY_SEQUENCE();\r
1051         m_currentKeymap->addAssignment(mkey, keySeq);\r
1052 }\r
1053 \r
1054 \r
1055 // <MODIFIER_ASSIGNMENT>\r
1056 void SettingLoader::load_MODIFIER_ASSIGNMENT()\r
1057 {\r
1058         // <MODIFIER_NAME>\r
1059         Token *t = getToken();\r
1060         Modifier::Type mt;\r
1061 \r
1062         while (true) {\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
1067 \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
1088 \r
1089                 if (am == Keymap::AM_notModifier)\r
1090                         break;\r
1091 \r
1092                 m_currentKeymap->addModifier(mt, Keymap::AO_overwrite, am, NULL);\r
1093                 if (isEOL())\r
1094                         return;\r
1095                 t = getToken();\r
1096         }\r
1097 \r
1098         // <ASSIGN_OP>\r
1099         t = getToken();\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
1105 \r
1106         // <ASSIGN_MODE>? <KEY_NAME>\r
1107         while (!isEOL()) {\r
1108                 // <ASSIGN_MODE>?\r
1109                 t = getToken();\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
1114 \r
1115                 // <KEY_NAME>\r
1116                 Key *key = m_setting->m_keyboard.searchKey(t->getString());\r
1117                 if (!key)\r
1118                         throw ErrorMessage() << _T("`") << *t << _T("': invalid key name.");\r
1119 \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
1124         }\r
1125 }\r
1126 \r
1127 \r
1128 // <KEYSEQ_DEFINITION>\r
1129 void SettingLoader::load_KEYSEQ_DEFINITION()\r
1130 {\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
1137 }\r
1138 \r
1139 \r
1140 // <DEFINE>\r
1141 void SettingLoader::load_DEFINE()\r
1142 {\r
1143         m_setting->m_symbols.insert(getToken()->getString());\r
1144 }\r
1145 \r
1146 \r
1147 // <IF>\r
1148 void SettingLoader::load_IF()\r
1149 {\r
1150         if (!getToken()->isOpenParen())\r
1151                 throw ErrorMessage() << _T("there must be `(' after `if'.");\r
1152         Token *t = getToken(); // <SYMBOL> or !\r
1153         bool not = false;\r
1154         if (*t == _T("!")) {\r
1155                 not = true;\r
1156                 t = getToken(); // <SYMBOL>\r
1157         }\r
1158 \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
1165 \r
1166         if (!getToken()->isCloseParen())\r
1167                 throw ErrorMessage() << _T("there must be `)'.");\r
1168 \r
1169         m_canReadStack.push_back(doesRead);\r
1170         if (!isEOL()) {\r
1171                 size_t len = m_canReadStack.size();\r
1172                 load_LINE();\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
1179                 else\r
1180                         ; // `end' found\r
1181         }\r
1182 }\r
1183 \r
1184 \r
1185 // <ELSE> <ELSEIF>\r
1186 void SettingLoader::load_ELSE(bool i_isElseIf, const tstringi &i_token)\r
1187 {\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
1192         if (!isEOL()) {\r
1193                 size_t len = m_canReadStack.size();\r
1194                 if (i_isElseIf)\r
1195                         load_IF();\r
1196                 else\r
1197                         load_LINE();\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
1204                 else\r
1205                         ; // `end' found\r
1206         }\r
1207 }\r
1208 \r
1209 \r
1210 // <ENDIF>\r
1211 bool SettingLoader::load_ENDIF(const tstringi &i_token)\r
1212 {\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
1217         return r;\r
1218 }\r
1219 \r
1220 \r
1221 // <LINE>\r
1222 void SettingLoader::load_LINE()\r
1223 {\r
1224         Token *i_token = getToken();\r
1225 \r
1226         // <COND_SYMBOL>\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
1236                 while (!isEOL())\r
1237                         getToken();\r
1238         } else if (*i_token == _T("define")) load_DEFINE();\r
1239         // <INCLUDE>\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
1247         // <KEY_ASSIGN>\r
1248         else if (*i_token == _T("key")) load_KEY_ASSIGN();\r
1249         // <EVENT_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
1255         else\r
1256                 throw ErrorMessage() << _T("syntax error `") << *i_token << _T("'.");\r
1257 }\r
1258 \r
1259 \r
1260 // prefix sort predicate used in load(const string &)\r
1261 static bool prefixSortPred(const tstringi &i_a, const tstringi &i_b)\r
1262 {\r
1263         return i_b.size() < i_a.size();\r
1264 }\r
1265 \r
1266 \r
1267 /*\r
1268   _UNICODE: read file (UTF-16 LE/BE, UTF-8, locale specific multibyte encoding)\r
1269   _MBCS: read file\r
1270 */\r
1271 bool readFile(tstring *o_data, const tstringi &i_filename)\r
1272 {\r
1273         // get size of file\r
1274 #if 0\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
1278                 return false;\r
1279 #else\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
1283                 return false;\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
1287                 return false;\r
1288 #endif\r
1289 \r
1290         // open\r
1291         FILE *fp = _tfopen(i_filename.c_str(), _T("rb"));\r
1292         if (!fp)\r
1293                 return false;\r
1294 \r
1295         // read file\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
1298                 fclose(fp);\r
1299                 return false;\r
1300         }\r
1301         buf.get()[sbuf.st_size] = 0;                    // mbstowcs() requires null\r
1302         // terminated string\r
1303 \r
1304 #ifdef _UNICODE\r
1305         //\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
1309         {\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
1316                         (*o_data)[i] = c;\r
1317                 }\r
1318                 fclose(fp);\r
1319                 return true;\r
1320         }\r
1321 \r
1322         //\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
1326         {\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
1333                         (*o_data)[i] = c;\r
1334                 }\r
1335                 fclose(fp);\r
1336                 return true;\r
1337         }\r
1338 \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
1345                 fclose(fp);\r
1346                 return true;\r
1347         }\r
1348 \r
1349         // try UTF-8\r
1350         {\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
1356 \r
1357                 while (f != end) {\r
1358                         switch (state) {\r
1359                         case STATE_1:\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
1366                                         // 0800 - FFFF\r
1367                                 {\r
1368                                         *d = ((static_cast<wchar_t>(*f++) & 0x0f) << 12);\r
1369                                         state = STATE_2of3;\r
1370                                 } else\r
1371                                         goto not_UTF_8;\r
1372                                 break;\r
1373 \r
1374                         case STATE_2of2:\r
1375                         case STATE_3of3:\r
1376                                 if ((*f & 0xc0) != 0x80)\r
1377                                         goto not_UTF_8;\r
1378                                 *d++ |= (static_cast<wchar_t>(*f++) & 0x3f);\r
1379                                 state = STATE_1;\r
1380                                 break;\r
1381 \r
1382                         case STATE_2of3:\r
1383                                 if ((*f & 0xc0) != 0x80)\r
1384                                         goto not_UTF_8;\r
1385                                 *d |= ((static_cast<wchar_t>(*f++) & 0x3f) << 6);\r
1386                                 state = STATE_3of3;\r
1387                                 break;\r
1388                         }\r
1389                 }\r
1390                 o_data->assign(wbuf.get(), d);\r
1391                 fclose(fp);\r
1392                 return true;\r
1393 \r
1394 not_UTF_8:\r
1395                 ;\r
1396         }\r
1397 #endif // _UNICODE\r
1398 \r
1399         // assume ascii\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
1403         fclose(fp);\r
1404         return true;\r
1405 }\r
1406 \r
1407 \r
1408 // load (called from load(Setting *, const tstringi &) only)\r
1409 void SettingLoader::load(const tstringi &i_filename)\r
1410 {\r
1411         m_currentFilename = i_filename;\r
1412 \r
1413         tstring data;\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
1417 #if 1\r
1418                 *m_log << data << std::endl;\r
1419 #endif\r
1420                 m_isThereAnyError = true;\r
1421                 return;\r
1422         }\r
1423 \r
1424         // prefix\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
1441                 };\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
1446         }\r
1447         m_prefixesRefCcount ++;\r
1448 \r
1449         // create parser\r
1450         Parser parser(data.c_str(), data.size());\r
1451         parser.setPrefixes(m_prefixes);\r
1452 \r
1453         while (true) {\r
1454                 try {\r
1455                         if (!parser.getLine(&m_tokens))\r
1456                                 break;\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
1463                         }\r
1464                         m_isThereAnyError = true;\r
1465                         continue;\r
1466                 }\r
1467 \r
1468                 try {\r
1469                         load_LINE();\r
1470                         if (!isEOL())\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
1477                         }\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
1483                         }\r
1484                         m_isThereAnyError = true;\r
1485                 }\r
1486         }\r
1487 \r
1488         // m_prefixes\r
1489         -- m_prefixesRefCcount;\r
1490         if (m_prefixesRefCcount == 0)\r
1491                 delete m_prefixes;\r
1492 \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
1498                 << std::endl;\r
1499                 m_isThereAnyError = true;\r
1500         }\r
1501 }\r
1502 \r
1503 \r
1504 // is the filename readable ?\r
1505 bool SettingLoader::isReadable(const tstringi &i_filename,\r
1506                                                            int i_debugLevel) const\r
1507 {\r
1508         if (i_filename.empty())\r
1509                 return false;\r
1510 #ifdef UNICODE\r
1511         tifstream ist(to_string(i_filename).c_str());\r
1512 #else\r
1513         tifstream ist(i_filename.c_str());\r
1514 #endif\r
1515         if (ist.good()) {\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
1519                 }\r
1520                 return true;\r
1521         } else {\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
1525                 }\r
1526                 return false;\r
1527         }\r
1528 }\r
1529 \r
1530 #if 0\r
1531 // get filename from registry\r
1532 bool SettingLoader::getFilenameFromRegistry(tstringi *o_path) const\r
1533 {\r
1534         // get from registry\r
1535         Registry reg(MAYU_REGISTRY_ROOT);\r
1536         int index;\r
1537         reg.read(_T(".mayuIndex"), &index, 0);\r
1538         char buf[100];\r
1539         snprintf(buf, NUMBER_OF(buf), _T(".mayu%d"), index);\r
1540         if (!reg.read(buf, o_path))\r
1541                 return false;\r
1542 \r
1543         // parse registry entry\r
1544         Regexp getFilename(_T("^[^;]*;([^;]*);(.*)$"));\r
1545         if (!getFilename.doesMatch(*o_path))\r
1546                 return false;\r
1547 \r
1548         tstringi path = getFilename[1];\r
1549         tstringi options = getFilename[2];\r
1550 \r
1551         if (!(0 < path.size() && isReadable(path)))\r
1552                 return false;\r
1553         *o_path = path;\r
1554 \r
1555         // set symbols\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
1560         }\r
1561 \r
1562         return true;\r
1563 }\r
1564 #endif\r
1565 \r
1566 \r
1567 // get filename\r
1568 bool SettingLoader::getFilename(const tstringi &i_name, tstringi *o_path,\r
1569                                                                 int i_debugLevel) const\r
1570 {\r
1571         // the default filename is ".mayu"\r
1572         const tstringi &name = i_name.empty() ? tstringi(_T(".mayu")) : i_name;\r
1573 \r
1574         bool isFirstTime = true;\r
1575 \r
1576         while (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
1583                                 {\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
1590                                                         goto add_symbols;\r
1591                                         }\r
1592                                         return false;\r
1593                                 } else {\r
1594                                         if (!isReadable(*o_path, i_debugLevel))\r
1595                                                 return false;\r
1596                                 }\r
1597 add_symbols:\r
1598                                 for (Setting::Symbols::iterator\r
1599                                                 i = symbols.begin(); i != symbols.end(); ++ i)\r
1600                                         m_setting->m_symbols.insert(*i);\r
1601                                 return true;\r
1602                         }\r
1603                 }\r
1604 \r
1605                 if (!isFirstTime)\r
1606                         return false;\r
1607 \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
1614                                 return true;\r
1615                 }\r
1616 \r
1617                 if (!i_name.empty())\r
1618                         return false;                           // called by 'include'\r
1619 \r
1620                 if (!DialogBox(g_hInst, MAKEINTRESOURCE(IDD_DIALOG_setting),\r
1621                                            NULL, dlgSetting_dlgProc))\r
1622                         return false;\r
1623         }\r
1624 }\r
1625 \r
1626 \r
1627 // constructor\r
1628 SettingLoader::SettingLoader(SyncObject *i_soLog, tostream *i_log)\r
1629                 : m_setting(NULL),\r
1630                 m_isThereAnyError(false),\r
1631                 m_soLog(i_soLog),\r
1632                 m_log(i_log),\r
1633                 m_currentKeymap(NULL)\r
1634 {\r
1635         m_defaultKeySeqModifier =\r
1636                 m_defaultAssignModifier.release(Modifier::Type_ImeComp);\r
1637 }\r
1638 \r
1639 \r
1640 /* load m_setting\r
1641    If called by "include", 'filename' describes filename.\r
1642    Otherwise the 'filename' is empty.\r
1643  */\r
1644 bool SettingLoader::load(Setting *i_setting, const tstringi &i_filename)\r
1645 {\r
1646         m_setting = i_setting;\r
1647         m_isThereAnyError = false;\r
1648 \r
1649         tstringi path;\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
1654                         return false;\r
1655                 } else\r
1656                         throw ErrorMessage() << _T("`") << i_filename\r
1657                         << _T("': no such file or other error.");\r
1658         }\r
1659 \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
1663 \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
1668 \r
1669         /*\r
1670         // add keyboard layout name\r
1671         if (filename.empty())\r
1672         {\r
1673           char keyboardLayoutName[KL_NAMELENGTH];\r
1674           if (GetKeyboardLayoutName(keyboardLayoutName))\r
1675           {\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
1680           }\r
1681         }\r
1682         */\r
1683 \r
1684         // load\r
1685         load(path);\r
1686 \r
1687         // finalize\r
1688         if (i_filename.empty())\r
1689                 m_setting->m_keymaps.adjustModifier(m_setting->m_keyboard);\r
1690 \r
1691         return !m_isThereAnyError;\r
1692 }\r
1693 \r
1694 \r
1695 std::vector<tstringi> *SettingLoader::m_prefixes; // m_prefixes terminal symbol\r
1696 size_t SettingLoader::m_prefixesRefCcount;      /* reference count of\r
1697                                                    m_prefixes */\r