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