1 // Copyright 2010-2018, Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 //     * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 //     * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 //     * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 
30 // Keymap utils of Mozc interface.
31 
32 #include "session/internal/keymap.h"
33 #include "session/internal/keymap-inl.h"
34 
35 #include <memory>
36 #include <set>
37 #include <sstream>
38 #include <string>
39 #include <vector>
40 
41 #include "base/config_file_stream.h"
42 #include "base/file_stream.h"
43 #include "base/logging.h"
44 #include "base/port.h"
45 #include "base/util.h"
46 #include "composer/key_event_util.h"
47 #include "composer/key_parser.h"
48 #include "config/config_handler.h"
49 #include "protocol/commands.pb.h"
50 #include "protocol/config.pb.h"
51 
52 namespace mozc {
53 namespace keymap {
54 namespace {
55 static const char kMSIMEKeyMapFile[] = "system://ms-ime.tsv";
56 static const char kATOKKeyMapFile[] = "system://atok.tsv";
57 static const char kKotoeriKeyMapFile[] = "system://kotoeri.tsv";
58 static const char kCustomKeyMapFile[] = "user://keymap.tsv";
59 static const char kMobileKeyMapFile[] = "system://mobile.tsv";
60 static const char kChromeOsKeyMapFile[] = "system://chromeos.tsv";
61 }  // namespace
62 
63 #if defined(OS_MACOSX)
64 const bool KeyMapManager::kInputModeXCommandSupported = false;
65 #else
66 const bool KeyMapManager::kInputModeXCommandSupported = true;
67 #endif  // OS_MACOSX
68 
KeyMapManager()69 KeyMapManager::KeyMapManager()
70   : keymap_(config::Config::NONE) {
71   InitCommandData();
72 }
73 
~KeyMapManager()74 KeyMapManager::~KeyMapManager() {}
75 
Reset()76 void KeyMapManager::Reset() {
77   keymap_direct_.Clear();
78   keymap_precomposition_.Clear();
79   keymap_composition_.Clear();
80   keymap_conversion_.Clear();
81   keymap_zero_query_suggestion_.Clear();
82   keymap_suggestion_.Clear();
83   keymap_prediction_.Clear();
84 }
85 
Initialize(const config::Config::SessionKeymap keymap)86 bool KeyMapManager::Initialize(const config::Config::SessionKeymap keymap) {
87   keymap_ = keymap;
88   // Clear the previous keymaps.
89   Reset();
90 
91   const char *keymap_file = GetKeyMapFileName(keymap);
92   if (keymap != config::Config::CUSTOM &&
93       keymap_file != NULL &&
94       LoadFile(keymap_file)) {
95     return true;
96   }
97 
98   const char *default_keymapfile = GetKeyMapFileName(
99       config::ConfigHandler::GetDefaultKeyMap());
100   return LoadFile(default_keymapfile);
101 }
102 
ReloadConfig(const config::Config & config)103 bool KeyMapManager::ReloadConfig(const config::Config &config) {
104   // Clear the previous keymaps.
105   Reset();
106 
107   if (keymap_ != config::Config::CUSTOM) {
108     return true;
109   }
110 
111   const string &custom_keymap_table = config.custom_keymap_table();
112 
113   if (custom_keymap_table.empty()) {
114     LOG(WARNING) << "custom_keymap_table is empty. use default setting";
115     const char *default_keymapfile = GetKeyMapFileName(
116         config::ConfigHandler::GetDefaultKeyMap());
117     return LoadFile(default_keymapfile);
118   }
119 
120 #ifndef NO_LOGGING
121   // make a copy of keymap file just for debugging
122   const char *keymap_file = GetKeyMapFileName(keymap_);
123   const string filename = ConfigFileStream::GetFileName(keymap_file);
124   OutputFileStream ofs(filename.c_str());
125   if (ofs) {
126     ofs << "# This is a copy of keymap table for debugging." << std::endl;
127     ofs << "# Nothing happens when you edit this file manually." << std::endl;
128     ofs << custom_keymap_table;
129   }
130 #endif
131 
132   std::istringstream ifs(custom_keymap_table);
133   return LoadStream(&ifs);
134 }
135 
136 // static
GetKeyMapFileName(const config::Config::SessionKeymap keymap)137 const char *KeyMapManager::GetKeyMapFileName(
138     const config::Config::SessionKeymap keymap) {
139   switch (keymap) {
140     case config::Config::ATOK:
141       return kATOKKeyMapFile;
142     case config::Config::MOBILE:
143       return kMobileKeyMapFile;
144     case config::Config::MSIME:
145       return kMSIMEKeyMapFile;
146     case config::Config::KOTOERI:
147       return kKotoeriKeyMapFile;
148     case config::Config::CHROMEOS:
149       return kChromeOsKeyMapFile;
150     case config::Config::CUSTOM:
151       return kCustomKeyMapFile;
152     case config::Config::NONE:
153     default:
154       // should not appear here.
155       LOG(ERROR) << "Keymap type: " << keymap
156                  << " appeared at key map initialization.";
157       const config::Config::SessionKeymap default_keymap =
158           config::ConfigHandler::GetDefaultKeyMap();
159       DCHECK(default_keymap == config::Config::ATOK ||
160              default_keymap == config::Config::MOBILE ||
161              default_keymap == config::Config::MSIME ||
162              default_keymap == config::Config::KOTOERI ||
163              default_keymap == config::Config::CHROMEOS ||
164              default_keymap == config::Config::CUSTOM);
165       // should never make loop.
166       return GetKeyMapFileName(default_keymap);
167   }
168 }
169 
LoadFile(const char * filename)170 bool KeyMapManager::LoadFile(const char *filename) {
171   std::unique_ptr<std::istream> ifs(ConfigFileStream::LegacyOpen(filename));
172   if (ifs.get() == NULL) {
173     LOG(WARNING) << "cannot load keymap table: " << filename;
174     return false;
175   }
176   return LoadStream(ifs.get());
177 }
178 
LoadStream(std::istream * ifs)179 bool KeyMapManager::LoadStream(std::istream *ifs) {
180   std::vector<string> errors;
181   return LoadStreamWithErrors(ifs, &errors);
182 }
183 
LoadStreamWithErrors(std::istream * ifs,std::vector<string> * errors)184 bool KeyMapManager::LoadStreamWithErrors(std::istream *ifs,
185                                          std::vector<string> *errors) {
186   string line;
187   getline(*ifs, line);  // Skip the first line.
188   while (!ifs->eof()) {
189     getline(*ifs, line);
190     Util::ChopReturns(&line);
191 
192     if (line.empty() || line[0] == '#') {  // Skip empty or comment line.
193       continue;
194     }
195 
196     std::vector<string> rules;
197     Util::SplitStringUsing(line, "\t", &rules);
198     if (rules.size() != 3) {
199       LOG(ERROR) << "Invalid format: " << line;
200       continue;
201     }
202 
203     if (!AddCommand(rules[0], rules[1], rules[2])) {
204       errors->push_back(line);
205       LOG(ERROR) << "Unknown command: " << line;
206     }
207   }
208 
209   commands::KeyEvent key_event;
210   KeyParser::ParseKey("TextInput", &key_event);
211   keymap_precomposition_.AddRule(key_event,
212                                  PrecompositionState::INSERT_CHARACTER);
213   keymap_composition_.AddRule(key_event, CompositionState::INSERT_CHARACTER);
214   keymap_conversion_.AddRule(key_event, ConversionState::INSERT_CHARACTER);
215 
216   key_event.Clear();
217   KeyParser::ParseKey("Shift", &key_event);
218   keymap_composition_.AddRule(key_event, CompositionState::INSERT_CHARACTER);
219   return true;
220 }
221 
AddCommand(const string & state_name,const string & key_event_name,const string & command_name)222 bool KeyMapManager::AddCommand(const string &state_name,
223                                const string &key_event_name,
224                                const string &command_name) {
225 #ifdef NO_LOGGING  // means RELEASE BUILD
226   // On the release build, we do not support the ReportBug
227   // commands.  Note, true is returned as the arguments are
228   // interpreted properly.
229   if (command_name == "ReportBug") {
230     return true;
231   }
232 #endif  // NO_LOGGING
233 
234   commands::KeyEvent key_event;
235   if (!KeyParser::ParseKey(key_event_name, &key_event)) {
236     return false;
237   }
238 
239   if (state_name == "DirectInput" || state_name == "Direct") {
240     DirectInputState::Commands command;
241     if (!ParseCommandDirect(command_name, &command)) {
242       return false;
243     }
244 
245     keymap_direct_.AddRule(key_event, command);
246     return true;
247   }
248 
249   if (state_name == "Precomposition") {
250     PrecompositionState::Commands command;
251     if (!ParseCommandPrecomposition(command_name, &command)) {
252       return false;
253     }
254 
255     keymap_precomposition_.AddRule(key_event, command);
256     return true;
257   }
258 
259   if (state_name == "Composition") {
260     CompositionState::Commands command;
261     if (!ParseCommandComposition(command_name, &command)) {
262       return false;
263     }
264 
265     keymap_composition_.AddRule(key_event, command);
266     return true;
267   }
268 
269   if (state_name == "Conversion") {
270     ConversionState::Commands command;
271     if (!ParseCommandConversion(command_name, &command)) {
272       return false;
273     }
274 
275     keymap_conversion_.AddRule(key_event, command);
276     return true;
277   }
278 
279   if (state_name == "ZeroQuerySuggestion") {
280     PrecompositionState::Commands command;
281     if (!ParseCommandPrecomposition(command_name, &command)) {
282       return false;
283     }
284 
285     keymap_zero_query_suggestion_.AddRule(key_event, command);
286     return true;
287   }
288 
289   if (state_name == "Suggestion") {
290     CompositionState::Commands command;
291     if (!ParseCommandComposition(command_name, &command)) {
292       return false;
293     }
294 
295     keymap_suggestion_.AddRule(key_event, command);
296     return true;
297   }
298 
299   if (state_name == "Prediction") {
300     ConversionState::Commands command;
301     if (!ParseCommandConversion(command_name, &command)) {
302       return false;
303     }
304 
305     keymap_prediction_.AddRule(key_event, command);
306     return true;
307   }
308 
309   return false;
310 }
311 
312 namespace {
GetNameInternal(const std::map<T,string> & reverse_command_map,T command,string * name)313 template<typename T> bool GetNameInternal(
314     const std::map<T, string> &reverse_command_map, T command, string *name) {
315   DCHECK(name);
316   typename std::map<T, string>::const_iterator iter =
317       reverse_command_map.find(command);
318   if (iter == reverse_command_map.end()) {
319     return false;
320   } else {
321     *name = iter->second;
322     return true;
323   }
324 }
325 }  // namespace
326 
GetNameFromCommandDirect(DirectInputState::Commands command,string * name) const327 bool KeyMapManager::GetNameFromCommandDirect(
328     DirectInputState::Commands command, string *name) const {
329   return GetNameInternal<DirectInputState::Commands>(
330       reverse_command_direct_map_, command, name);
331 }
332 
GetNameFromCommandPrecomposition(PrecompositionState::Commands command,string * name) const333 bool KeyMapManager::GetNameFromCommandPrecomposition(
334     PrecompositionState::Commands command, string *name) const {
335   return GetNameInternal<PrecompositionState::Commands>(
336       reverse_command_precomposition_map_, command, name);
337 }
338 
GetNameFromCommandComposition(CompositionState::Commands command,string * name) const339 bool KeyMapManager::GetNameFromCommandComposition(
340     CompositionState::Commands command, string *name) const {
341   return GetNameInternal<CompositionState::Commands>(
342       reverse_command_composition_map_, command, name);
343 }
344 
GetNameFromCommandConversion(ConversionState::Commands command,string * name) const345 bool KeyMapManager::GetNameFromCommandConversion(
346     ConversionState::Commands command, string *name) const {
347   return GetNameInternal<ConversionState::Commands>(
348       reverse_command_conversion_map_, command, name);
349 }
350 
RegisterDirectCommand(const string & command_string,DirectInputState::Commands command)351 void KeyMapManager::RegisterDirectCommand(
352     const string &command_string, DirectInputState::Commands command) {
353   command_direct_map_[command_string] = command;
354   reverse_command_direct_map_[command] = command_string;
355 }
356 
RegisterPrecompositionCommand(const string & command_string,PrecompositionState::Commands command)357 void KeyMapManager::RegisterPrecompositionCommand(
358     const string &command_string, PrecompositionState::Commands command) {
359   command_precomposition_map_[command_string] = command;
360   reverse_command_precomposition_map_[command] = command_string;
361 }
362 
RegisterCompositionCommand(const string & command_string,CompositionState::Commands command)363 void KeyMapManager::RegisterCompositionCommand(
364     const string &command_string, CompositionState::Commands command) {
365   command_composition_map_[command_string] = command;
366   reverse_command_composition_map_[command] = command_string;
367 }
368 
RegisterConversionCommand(const string & command_string,ConversionState::Commands command)369 void KeyMapManager::RegisterConversionCommand(
370     const string &command_string, ConversionState::Commands command) {
371   command_conversion_map_[command_string] = command;
372   reverse_command_conversion_map_[command] = command_string;
373 }
374 
InitCommandData()375 void KeyMapManager::InitCommandData() {
376   RegisterDirectCommand("IMEOn", DirectInputState::IME_ON);
377   if (kInputModeXCommandSupported) {
378     RegisterDirectCommand("InputModeHiragana",
379                           DirectInputState::INPUT_MODE_HIRAGANA);
380     RegisterDirectCommand("InputModeFullKatakana",
381                           DirectInputState::INPUT_MODE_FULL_KATAKANA);
382     RegisterDirectCommand("InputModeHalfKatakana",
383                           DirectInputState::INPUT_MODE_HALF_KATAKANA);
384     RegisterDirectCommand("InputModeFullAlphanumeric",
385                           DirectInputState::INPUT_MODE_FULL_ALPHANUMERIC);
386     RegisterDirectCommand("InputModeHalfAlphanumeric",
387                           DirectInputState::INPUT_MODE_HALF_ALPHANUMERIC);
388   } else {
389     RegisterDirectCommand("InputModeHiragana",
390                           DirectInputState::NONE);
391     RegisterDirectCommand("InputModeFullKatakana",
392                           DirectInputState::NONE);
393     RegisterDirectCommand("InputModeHalfKatakana",
394                           DirectInputState::NONE);
395     RegisterDirectCommand("InputModeFullAlphanumeric",
396                           DirectInputState::NONE);
397     RegisterDirectCommand("InputModeHalfAlphanumeric",
398                           DirectInputState::NONE);
399   }
400   RegisterDirectCommand("Reconvert",
401                         DirectInputState::RECONVERT);
402 
403   // Precomposition
404   RegisterPrecompositionCommand("IMEOff", PrecompositionState::IME_OFF);
405   RegisterPrecompositionCommand("IMEOn", PrecompositionState::IME_ON);
406   RegisterPrecompositionCommand("InsertCharacter",
407                                 PrecompositionState::INSERT_CHARACTER);
408   RegisterPrecompositionCommand("InsertSpace",
409                                 PrecompositionState::INSERT_SPACE);
410   RegisterPrecompositionCommand("InsertAlternateSpace",
411                                 PrecompositionState::INSERT_ALTERNATE_SPACE);
412   RegisterPrecompositionCommand("InsertHalfSpace",
413                                 PrecompositionState::INSERT_HALF_SPACE);
414   RegisterPrecompositionCommand("InsertFullSpace",
415                                 PrecompositionState::INSERT_FULL_SPACE);
416   RegisterPrecompositionCommand("ToggleAlphanumericMode",
417                                 PrecompositionState::TOGGLE_ALPHANUMERIC_MODE);
418   if (kInputModeXCommandSupported) {
419     RegisterPrecompositionCommand("InputModeHiragana",
420                                   PrecompositionState::INPUT_MODE_HIRAGANA);
421     RegisterPrecompositionCommand(
422         "InputModeFullKatakana",
423         PrecompositionState::INPUT_MODE_FULL_KATAKANA);
424     RegisterPrecompositionCommand(
425         "InputModeHalfKatakana",
426         PrecompositionState::INPUT_MODE_HALF_KATAKANA);
427     RegisterPrecompositionCommand(
428         "InputModeFullAlphanumeric",
429         PrecompositionState::INPUT_MODE_FULL_ALPHANUMERIC);
430     RegisterPrecompositionCommand(
431         "InputModeHalfAlphanumeric",
432         PrecompositionState::INPUT_MODE_HALF_ALPHANUMERIC);
433     RegisterPrecompositionCommand(
434         "InputModeSwitchKanaType",
435         PrecompositionState::INPUT_MODE_SWITCH_KANA_TYPE);
436   } else {
437     RegisterPrecompositionCommand("InputModeHiragana",
438                                   PrecompositionState::NONE);
439     RegisterPrecompositionCommand("InputModeFullKatakana",
440                                   PrecompositionState::NONE);
441     RegisterPrecompositionCommand("InputModeHalfKatakana",
442                                   PrecompositionState::NONE);
443     RegisterPrecompositionCommand("InputModeFullAlphanumeric",
444                                   PrecompositionState::NONE);
445     RegisterPrecompositionCommand("InputModeHalfAlphanumeric",
446                                   PrecompositionState::NONE);
447     RegisterPrecompositionCommand("InputModeSwitchKanaType",
448                                   PrecompositionState::NONE);
449   }
450 
451   RegisterPrecompositionCommand("LaunchConfigDialog",
452                                 PrecompositionState::LAUNCH_CONFIG_DIALOG);
453   RegisterPrecompositionCommand("LaunchDictionaryTool",
454                                 PrecompositionState::LAUNCH_DICTIONARY_TOOL);
455   RegisterPrecompositionCommand(
456       "LaunchWordRegisterDialog",
457       PrecompositionState::LAUNCH_WORD_REGISTER_DIALOG);
458 
459   RegisterPrecompositionCommand("Revert", PrecompositionState::REVERT);
460   RegisterPrecompositionCommand("Undo", PrecompositionState::UNDO);
461   RegisterPrecompositionCommand("Reconvert", PrecompositionState::RECONVERT);
462 
463   RegisterPrecompositionCommand("Cancel", PrecompositionState::CANCEL);
464   RegisterPrecompositionCommand("CancelAndIMEOff",
465                                 PrecompositionState::CANCEL_AND_IME_OFF);
466   RegisterPrecompositionCommand("CommitFirstSuggestion",
467                                 PrecompositionState::COMMIT_FIRST_SUGGESTION);
468   RegisterPrecompositionCommand("PredictAndConvert",
469                                 PrecompositionState::PREDICT_AND_CONVERT);
470 
471   // Composition
472   RegisterCompositionCommand("IMEOff", CompositionState::IME_OFF);
473   RegisterCompositionCommand("IMEOn", CompositionState::IME_ON);
474   RegisterCompositionCommand("InsertCharacter",
475                              CompositionState::INSERT_CHARACTER);
476   RegisterCompositionCommand("Delete", CompositionState::DEL);
477   RegisterCompositionCommand("Backspace", CompositionState::BACKSPACE);
478   RegisterCompositionCommand("InsertSpace",
479                              CompositionState::INSERT_SPACE);
480   RegisterCompositionCommand("InsertAlternateSpace",
481                              CompositionState::INSERT_ALTERNATE_SPACE);
482   RegisterCompositionCommand("InsertHalfSpace",
483                              CompositionState::INSERT_HALF_SPACE);
484   RegisterCompositionCommand("InsertFullSpace",
485                              CompositionState::INSERT_FULL_SPACE);
486   RegisterCompositionCommand("Cancel", CompositionState::CANCEL);
487   RegisterCompositionCommand("CancelAndIMEOff",
488                              CompositionState::CANCEL_AND_IME_OFF);
489   RegisterCompositionCommand("Undo", CompositionState::UNDO);
490   RegisterCompositionCommand("MoveCursorLeft",
491                              CompositionState::MOVE_CURSOR_LEFT);
492   RegisterCompositionCommand("MoveCursorRight",
493                              CompositionState::MOVE_CURSOR_RIGHT);
494   RegisterCompositionCommand("MoveCursorToBeginning",
495                              CompositionState::MOVE_CURSOR_TO_BEGINNING);
496   RegisterCompositionCommand("MoveCursorToEnd",
497                              CompositionState::MOVE_MOVE_CURSOR_TO_END);
498   RegisterCompositionCommand("Commit", CompositionState::COMMIT);
499   RegisterCompositionCommand("CommitFirstSuggestion",
500                              CompositionState::COMMIT_FIRST_SUGGESTION);
501   RegisterCompositionCommand("Convert", CompositionState::CONVERT);
502   RegisterCompositionCommand("ConvertWithoutHistory",
503                              CompositionState::CONVERT_WITHOUT_HISTORY);
504   RegisterCompositionCommand("PredictAndConvert",
505                              CompositionState::PREDICT_AND_CONVERT);
506   RegisterCompositionCommand("ConvertToHiragana",
507                              CompositionState::CONVERT_TO_HIRAGANA);
508   RegisterCompositionCommand("ConvertToFullKatakana",
509                              CompositionState::CONVERT_TO_FULL_KATAKANA);
510   RegisterCompositionCommand("ConvertToHalfKatakana",
511                              CompositionState::CONVERT_TO_HALF_KATAKANA);
512   RegisterCompositionCommand("ConvertToHalfWidth",
513                              CompositionState::CONVERT_TO_HALF_WIDTH);
514   RegisterCompositionCommand("ConvertToFullAlphanumeric",
515                              CompositionState::CONVERT_TO_FULL_ALPHANUMERIC);
516   RegisterCompositionCommand("ConvertToHalfAlphanumeric",
517                              CompositionState::CONVERT_TO_HALF_ALPHANUMERIC);
518   RegisterCompositionCommand("SwitchKanaType",
519                              CompositionState::SWITCH_KANA_TYPE);
520   RegisterCompositionCommand("DisplayAsHiragana",
521                              CompositionState::DISPLAY_AS_HIRAGANA);
522   RegisterCompositionCommand("DisplayAsFullKatakana",
523                              CompositionState::DISPLAY_AS_FULL_KATAKANA);
524   RegisterCompositionCommand("DisplayAsHalfKatakana",
525                              CompositionState::DISPLAY_AS_HALF_KATAKANA);
526   RegisterCompositionCommand("DisplayAsHalfWidth",
527                              CompositionState::TRANSLATE_HALF_WIDTH);
528   RegisterCompositionCommand("DisplayAsFullAlphanumeric",
529                              CompositionState::TRANSLATE_FULL_ASCII);
530   RegisterCompositionCommand("DisplayAsHalfAlphanumeric",
531                              CompositionState::TRANSLATE_HALF_ASCII);
532   RegisterCompositionCommand("ToggleAlphanumericMode",
533                              CompositionState::TOGGLE_ALPHANUMERIC_MODE);
534   if (kInputModeXCommandSupported) {
535     RegisterCompositionCommand("InputModeHiragana",
536                                CompositionState::INPUT_MODE_HIRAGANA);
537     RegisterCompositionCommand("InputModeFullKatakana",
538                                CompositionState::INPUT_MODE_FULL_KATAKANA);
539     RegisterCompositionCommand("InputModeHalfKatakana",
540                                CompositionState::INPUT_MODE_HALF_KATAKANA);
541     RegisterCompositionCommand("InputModeFullAlphanumeric",
542                                CompositionState::INPUT_MODE_FULL_ALPHANUMERIC);
543     RegisterCompositionCommand("InputModeHalfAlphanumeric",
544                                CompositionState::INPUT_MODE_HALF_ALPHANUMERIC);
545   } else {
546     RegisterCompositionCommand("InputModeHiragana",
547                              CompositionState::NONE);
548     RegisterCompositionCommand("InputModeFullKatakana",
549                                CompositionState::NONE);
550     RegisterCompositionCommand("InputModeHalfKatakana",
551                                CompositionState::NONE);
552     RegisterCompositionCommand("InputModeFullAlphanumeric",
553                                CompositionState::NONE);
554     RegisterCompositionCommand("InputModeHalfAlphanumeric",
555                                CompositionState::NONE);
556   }
557 
558   // Conversion
559   RegisterConversionCommand("IMEOff", ConversionState::IME_OFF);
560   RegisterConversionCommand("IMEOn", ConversionState::IME_ON);
561   RegisterConversionCommand("InsertCharacter",
562                             ConversionState::INSERT_CHARACTER);
563   RegisterConversionCommand("InsertSpace",
564                             ConversionState::INSERT_SPACE);
565   RegisterConversionCommand("InsertAlternateSpace",
566                             ConversionState::INSERT_ALTERNATE_SPACE);
567   RegisterConversionCommand("InsertHalfSpace",
568                             ConversionState::INSERT_HALF_SPACE);
569   RegisterConversionCommand("InsertFullSpace",
570                             ConversionState::INSERT_FULL_SPACE);
571   RegisterConversionCommand("Cancel", ConversionState::CANCEL);
572   RegisterConversionCommand("CancelAndIMEOff",
573                             ConversionState::CANCEL_AND_IME_OFF);
574   RegisterConversionCommand("Undo", ConversionState::UNDO);
575   RegisterConversionCommand("SegmentFocusLeft",
576                             ConversionState::SEGMENT_FOCUS_LEFT);
577   RegisterConversionCommand("SegmentFocusRight",
578                             ConversionState::SEGMENT_FOCUS_RIGHT);
579   RegisterConversionCommand("SegmentFocusFirst",
580                             ConversionState::SEGMENT_FOCUS_FIRST);
581   RegisterConversionCommand("SegmentFocusLast",
582                             ConversionState::SEGMENT_FOCUS_LAST);
583   RegisterConversionCommand("SegmentWidthExpand",
584                             ConversionState::SEGMENT_WIDTH_EXPAND);
585   RegisterConversionCommand("SegmentWidthShrink",
586                             ConversionState::SEGMENT_WIDTH_SHRINK);
587   RegisterConversionCommand("ConvertNext", ConversionState::CONVERT_NEXT);
588   RegisterConversionCommand("ConvertPrev", ConversionState::CONVERT_PREV);
589   RegisterConversionCommand("ConvertNextPage",
590                             ConversionState::CONVERT_NEXT_PAGE);
591   RegisterConversionCommand("ConvertPrevPage",
592                             ConversionState::CONVERT_PREV_PAGE);
593   RegisterConversionCommand("PredictAndConvert",
594                             ConversionState::PREDICT_AND_CONVERT);
595   RegisterConversionCommand("Commit", ConversionState::COMMIT);
596   RegisterConversionCommand("CommitOnlyFirstSegment",
597                             ConversionState::COMMIT_SEGMENT);
598   RegisterConversionCommand("ConvertToHiragana",
599                             ConversionState::CONVERT_TO_HIRAGANA);
600   RegisterConversionCommand("ConvertToFullKatakana",
601                             ConversionState::CONVERT_TO_FULL_KATAKANA);
602   RegisterConversionCommand("ConvertToHalfKatakana",
603                             ConversionState::CONVERT_TO_HALF_KATAKANA);
604   RegisterConversionCommand("ConvertToHalfWidth",
605                             ConversionState::CONVERT_TO_HALF_WIDTH);
606   RegisterConversionCommand("ConvertToFullAlphanumeric",
607                             ConversionState::CONVERT_TO_FULL_ALPHANUMERIC);
608   RegisterConversionCommand("ConvertToHalfAlphanumeric",
609                             ConversionState::CONVERT_TO_HALF_ALPHANUMERIC);
610   RegisterConversionCommand("SwitchKanaType",
611                             ConversionState::SWITCH_KANA_TYPE);
612   RegisterConversionCommand("ToggleAlphanumericMode",
613                             ConversionState::TOGGLE_ALPHANUMERIC_MODE);
614   RegisterConversionCommand("DisplayAsHiragana",
615                             ConversionState::DISPLAY_AS_HIRAGANA);
616   RegisterConversionCommand("DisplayAsFullKatakana",
617                             ConversionState::DISPLAY_AS_FULL_KATAKANA);
618   RegisterConversionCommand("DisplayAsHalfKatakana",
619                             ConversionState::DISPLAY_AS_HALF_KATAKANA);
620   RegisterConversionCommand("DisplayAsHalfWidth",
621                             ConversionState::TRANSLATE_HALF_WIDTH);
622   RegisterConversionCommand("DisplayAsFullAlphanumeric",
623                             ConversionState::TRANSLATE_FULL_ASCII);
624   RegisterConversionCommand("DisplayAsHalfAlphanumeric",
625                             ConversionState::TRANSLATE_HALF_ASCII);
626   RegisterConversionCommand("DeleteSelectedCandidate",
627                             ConversionState::DELETE_SELECTED_CANDIDATE);
628   if (kInputModeXCommandSupported) {
629     RegisterConversionCommand("InputModeHiragana",
630                               ConversionState::INPUT_MODE_HIRAGANA);
631     RegisterConversionCommand("InputModeFullKatakana",
632                               ConversionState::INPUT_MODE_FULL_KATAKANA);
633     RegisterConversionCommand("InputModeHalfKatakana",
634                               ConversionState::INPUT_MODE_HALF_KATAKANA);
635     RegisterConversionCommand("InputModeFullAlphanumeric",
636                               ConversionState::INPUT_MODE_FULL_ALPHANUMERIC);
637     RegisterConversionCommand("InputModeHalfAlphanumeric",
638                               ConversionState::INPUT_MODE_HALF_ALPHANUMERIC);
639   } else {
640     RegisterConversionCommand("InputModeHiragana",
641                               ConversionState::NONE);
642     RegisterConversionCommand("InputModeFullKatakana",
643                               ConversionState::NONE);
644     RegisterConversionCommand("InputModeHalfKatakana",
645                               ConversionState::NONE);
646     RegisterConversionCommand("InputModeFullAlphanumeric",
647                               ConversionState::NONE);
648     RegisterConversionCommand("InputModeHalfAlphanumeric",
649                               ConversionState::NONE);
650   }
651 #ifndef NO_LOGGING  // means NOT RELEASE build
652   RegisterConversionCommand("ReportBug", ConversionState::REPORT_BUG);
653 #endif  // NO_LOGGING
654 }
655 
GetCommandDirect(const commands::KeyEvent & key_event,DirectInputState::Commands * command) const656 bool KeyMapManager::GetCommandDirect(
657     const commands::KeyEvent &key_event,
658     DirectInputState::Commands *command) const {
659   return keymap_direct_.GetCommand(key_event, command);
660 }
661 
GetCommandPrecomposition(const commands::KeyEvent & key_event,PrecompositionState::Commands * command) const662 bool KeyMapManager::GetCommandPrecomposition(
663     const commands::KeyEvent &key_event,
664     PrecompositionState::Commands *command) const {
665   return keymap_precomposition_.GetCommand(key_event, command);
666 }
667 
GetCommandComposition(const commands::KeyEvent & key_event,CompositionState::Commands * command) const668 bool KeyMapManager::GetCommandComposition(
669     const commands::KeyEvent &key_event,
670     CompositionState::Commands *command) const {
671   return keymap_composition_.GetCommand(key_event, command);
672 }
673 
GetCommandZeroQuerySuggestion(const commands::KeyEvent & key_event,PrecompositionState::Commands * command) const674 bool KeyMapManager::GetCommandZeroQuerySuggestion(
675     const commands::KeyEvent &key_event,
676     PrecompositionState::Commands *command) const {
677   // try zero query suggestion rule first
678   if (keymap_zero_query_suggestion_.GetCommand(key_event, command)) {
679     return true;
680   }
681   // use precomposition rule
682   return keymap_precomposition_.GetCommand(key_event, command);
683 }
684 
GetCommandSuggestion(const commands::KeyEvent & key_event,CompositionState::Commands * command) const685 bool KeyMapManager::GetCommandSuggestion(
686     const commands::KeyEvent &key_event,
687     CompositionState::Commands *command) const {
688   // try suggestion rule first
689   if (keymap_suggestion_.GetCommand(key_event, command)) {
690     return true;
691   }
692   // use composition rule
693   return keymap_composition_.GetCommand(key_event, command);
694 }
695 
GetCommandConversion(const commands::KeyEvent & key_event,ConversionState::Commands * command) const696 bool KeyMapManager::GetCommandConversion(
697     const commands::KeyEvent &key_event,
698     ConversionState::Commands *command) const {
699   return keymap_conversion_.GetCommand(key_event, command);
700 }
701 
GetCommandPrediction(const commands::KeyEvent & key_event,ConversionState::Commands * command) const702 bool KeyMapManager::GetCommandPrediction(
703     const commands::KeyEvent &key_event,
704     ConversionState::Commands *command) const {
705   // try prediction rule first
706   if (keymap_prediction_.GetCommand(key_event, command)) {
707     return true;
708   }
709   // use conversion rule
710   return keymap_conversion_.GetCommand(key_event, command);
711 }
712 
ParseCommandDirect(const string & command_string,DirectInputState::Commands * command) const713 bool KeyMapManager::ParseCommandDirect(
714     const string &command_string,
715     DirectInputState::Commands *command) const {
716   if (command_direct_map_.count(command_string) == 0) {
717     return false;
718   }
719   *command = command_direct_map_.find(command_string)->second;
720   return true;
721 }
722 
723 // This should be in KeyMap instead of KeyMapManager.
ParseCommandPrecomposition(const string & command_string,PrecompositionState::Commands * command) const724 bool KeyMapManager::ParseCommandPrecomposition(
725     const string &command_string,
726     PrecompositionState::Commands *command) const {
727   if (command_precomposition_map_.count(command_string) == 0) {
728     return false;
729   }
730   *command = command_precomposition_map_.find(command_string)->second;
731   return true;
732 }
733 
734 
ParseCommandComposition(const string & command_string,CompositionState::Commands * command) const735 bool KeyMapManager::ParseCommandComposition(
736     const string &command_string,
737     CompositionState::Commands *command) const {
738   if (command_composition_map_.count(command_string) == 0) {
739     return false;
740   }
741   *command = command_composition_map_.find(command_string)->second;
742   return true;
743 }
744 
ParseCommandConversion(const string & command_string,ConversionState::Commands * command) const745 bool KeyMapManager::ParseCommandConversion(
746     const string &command_string,
747     ConversionState::Commands *command) const {
748   if (command_conversion_map_.count(command_string) == 0) {
749     return false;
750   }
751   *command = command_conversion_map_.find(command_string)->second;
752   return true;
753 }
754 
GetAvailableCommandNameDirect(std::set<string> * command_names) const755 void KeyMapManager::GetAvailableCommandNameDirect(
756     std::set<string> *command_names) const {
757   DCHECK(command_names);
758   for (std::map<string, DirectInputState::Commands>::const_iterator iter
759            = command_direct_map_.begin();
760        iter != command_direct_map_.end(); ++iter) {
761     command_names->insert(iter->first);
762   }
763 }
764 
GetAvailableCommandNamePrecomposition(std::set<string> * command_names) const765 void KeyMapManager::GetAvailableCommandNamePrecomposition(
766     std::set<string> *command_names) const {
767   DCHECK(command_names);
768   for (std::map<string, PrecompositionState::Commands>::const_iterator iter
769            = command_precomposition_map_.begin();
770        iter != command_precomposition_map_.end(); ++iter) {
771     command_names->insert(iter->first);
772   }
773 }
774 
GetAvailableCommandNameComposition(std::set<string> * command_names) const775 void KeyMapManager::GetAvailableCommandNameComposition(
776     std::set<string> *command_names) const {
777   DCHECK(command_names);
778   for (std::map<string, CompositionState::Commands>::const_iterator iter
779            = command_composition_map_.begin();
780        iter != command_composition_map_.end(); ++iter) {
781     command_names->insert(iter->first);
782   }
783 }
784 
GetAvailableCommandNameConversion(std::set<string> * command_names) const785 void KeyMapManager::GetAvailableCommandNameConversion(
786     std::set<string> *command_names) const {
787   DCHECK(command_names);
788   for (std::map<string, ConversionState::Commands>::const_iterator iter
789            = command_conversion_map_.begin();
790        iter != command_conversion_map_.end(); ++iter) {
791     command_names->insert(iter->first);
792   }
793 }
794 
GetAvailableCommandNameZeroQuerySuggestion(std::set<string> * command_names) const795 void KeyMapManager::GetAvailableCommandNameZeroQuerySuggestion(
796     std::set<string> *command_names) const {
797   GetAvailableCommandNamePrecomposition(command_names);
798 }
799 
GetAvailableCommandNameSuggestion(std::set<string> * command_names) const800 void KeyMapManager::GetAvailableCommandNameSuggestion(
801     std::set<string> *command_names) const {
802   GetAvailableCommandNameComposition(command_names);
803 }
804 
GetAvailableCommandNamePrediction(std::set<string> * command_names) const805 void KeyMapManager::GetAvailableCommandNamePrediction(
806     std::set<string> *command_names) const {
807   GetAvailableCommandNameConversion(command_names);
808 }
809 
810 }  // namespace keymap
811 }  // namespace mozc
812