1 /*
2 * SPDX-FileCopyrightText: 2005 Takuro Ashie
3 * SPDX-FileCopyrightText: 2012-2017 CSSlayer <wengxt@gmail.com>
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 *
7 */
8
9 #include "key2kana_table.h"
10
11 // fundamental table
12 static Key2KanaTable romaji_table(("DefaultRomajiTable"),
13 fcitx_anthy_romaji_typing_rule);
14 static Key2KanaTable
15 romaji_double_consonant_table(("DefaultRomajiDoubleConsonantTable"),
16 fcitx_anthy_romaji_double_consonant_rule);
17 static Key2KanaTable kana_table(("DefaultKanaTable"),
18 fcitx_anthy_kana_typing_rule);
19 static Key2KanaTable
20 kana_voiced_consonant_table(("DefaultKanaVoicedConsonantTable"),
21 fcitx_anthy_kana_voiced_consonant_rule);
22 static Key2KanaTable nicola_table(("DefaultNICOLATable"),
23 fcitx_anthy_nicola_table);
24
25 // symbols
26 static Key2KanaTable half_symbol_table(("DefaultRomajiHalfSymbolTable"),
27 fcitx_anthy_half_symbol_rule);
28 static Key2KanaTable wide_symbol_table(("DefaultRomajiWideSymbolTable"),
29 fcitx_anthy_wide_symbol_rule);
30
31 // numbers
32 static Key2KanaTable half_number_table(("DefaultRomajiHalfNumberTable"),
33 fcitx_anthy_half_number_rule);
34 static Key2KanaTable wide_number_table(("DefaultRomajiWideNumberTable"),
35 fcitx_anthy_wide_number_rule);
36
37 // period
38 static Key2KanaTable romaji_ja_period_table(("DefaultRomajiJaPeriodTable"),
39 fcitx_anthy_romaji_ja_period_rule);
40 static Key2KanaTable
41 romaji_wide_period_table(("DefaultRomajiWidePeriodTable"),
42 fcitx_anthy_romaji_wide_period_rule);
43 static Key2KanaTable
44 romaji_half_period_table(("DefaultRomajiHalfPeriodTable"),
45 fcitx_anthy_romaji_half_period_rule);
46
47 static Key2KanaTable kana_ja_period_table(("DefaultKanaJaPeriodTable"),
48 fcitx_anthy_kana_ja_period_rule);
49 static Key2KanaTable kana_wide_period_table(("DefaultKanaWidePeriodTable"),
50 fcitx_anthy_kana_wide_period_rule);
51 static Key2KanaTable kana_half_period_table(("DefaultKanaHalfPeriodTable"),
52 fcitx_anthy_kana_half_period_rule);
53
54 // comma
55 static Key2KanaTable romaji_ja_comma_table(("DefaultRomajiJaCommaTable"),
56 fcitx_anthy_romaji_ja_comma_rule);
57 static Key2KanaTable
58 romaji_wide_comma_table(("DefaultRomajiWideCommaTable"),
59 fcitx_anthy_romaji_wide_comma_rule);
60 static Key2KanaTable
61 romaji_half_comma_table(("DefaultRomajiHalfCommaTable"),
62 fcitx_anthy_romaji_half_comma_rule);
63
64 static Key2KanaTable kana_ja_comma_table(("DefaultKanaJaCommaTable"),
65 fcitx_anthy_kana_ja_comma_rule);
66 static Key2KanaTable kana_wide_comma_table(("DefaultKanaWideCommaTable"),
67 fcitx_anthy_kana_wide_comma_rule);
68 static Key2KanaTable kana_half_comma_table(("DefaultKanaHalfCommaTable"),
69 fcitx_anthy_kana_half_comma_rule);
70
71 // bracket
72 static Key2KanaTable
73 romaji_ja_bracket_table(("DefaultRomajiJaBracketTable"),
74 fcitx_anthy_romaji_ja_bracket_rule);
75 static Key2KanaTable
76 romaji_wide_bracket_table(("DefaultRomajiWideBracketTable"),
77 fcitx_anthy_romaji_wide_bracket_rule);
78
79 static Key2KanaTable kana_ja_bracket_table(("DefaultKanaJaBracketTable"),
80 fcitx_anthy_kana_ja_bracket_rule);
81 static Key2KanaTable
82 kana_wide_bracket_table(("DefaultRomajiWideBracketTable"),
83 fcitx_anthy_kana_wide_bracket_rule);
84
85 // slash
86 static Key2KanaTable romaji_ja_slash_table(("DefaultRomajiJaSlashTable"),
87 fcitx_anthy_romaji_ja_slash_rule);
88 static Key2KanaTable
89 romaji_wide_slash_table(("DefaultRomajiWideSlashTable"),
90 fcitx_anthy_romaji_wide_slash_rule);
91
92 static Key2KanaTable kana_ja_slash_table(("DefaultKanaJaSlashTable"),
93 fcitx_anthy_kana_ja_slash_rule);
94 static Key2KanaTable kana_wide_slash_table(("DefaultRomajiWideSlashTable"),
95 fcitx_anthy_kana_wide_slash_rule);
96
Key2KanaRule()97 Key2KanaRule::Key2KanaRule() {}
98
load(std::string sequence,std::vector<std::string> result)99 void Key2KanaRule::load(std::string sequence, std::vector<std::string> result) {
100 sequence_ = std::move(sequence);
101 result_ = std::move(result);
102 }
103
~Key2KanaRule()104 Key2KanaRule::~Key2KanaRule() {}
105
sequence() const106 const std::string &Key2KanaRule::sequence() const { return sequence_; }
107
result(unsigned int idx)108 std::string Key2KanaRule::result(unsigned int idx) {
109 if (idx < result_.size())
110 return result_[idx];
111
112 return std::string();
113 }
114
clear()115 void Key2KanaRule::clear() {
116 sequence_ = std::string();
117 result_.clear();
118 }
119
isEmpty()120 bool Key2KanaRule::isEmpty() {
121 if (!sequence_.empty())
122 return false;
123
124 if (result_.empty())
125 return true;
126
127 for (unsigned int i = 0; i < result_.size(); i++) {
128 if (!result_[i].empty())
129 return false;
130 }
131
132 return true;
133 }
134
Key2KanaTable(std::string name)135 Key2KanaTable::Key2KanaTable(std::string name) : name_(std::move(name)) {}
136
Key2KanaTable(std::string name,ConvRule * table)137 Key2KanaTable::Key2KanaTable(std::string name, ConvRule *table)
138 : name_(std::move(name)) {
139 for (unsigned int i = 0; table[i].string; i++) {
140 appendRule(table[i].string ? table[i].string : "",
141 table[i].result ? table[i].result : "",
142 table[i].cont ? table[i].cont : "");
143 }
144 }
145
Key2KanaTable(std::string name,NicolaRule * table)146 Key2KanaTable::Key2KanaTable(std::string name, NicolaRule *table)
147 : name_(std::move(name)) {
148 for (unsigned int i = 0; table[i].key; i++) {
149 appendRule(table[i].key ? table[i].key : "",
150 table[i].single ? table[i].single : "",
151 table[i].left_shift ? table[i].left_shift : "",
152 table[i].right_shift ? table[i].right_shift : "");
153 }
154 }
155
appendRule(std::string sequence,std::vector<std::string> result)156 void Key2KanaTable::appendRule(std::string sequence,
157 std::vector<std::string> result) {
158 rules_.emplace_back();
159 rules_.back().load(std::move(sequence), std::move(result));
160 }
161
appendRule(std::string sequence,std::string result,std::string cont)162 void Key2KanaTable::appendRule(std::string sequence, std::string result,
163 std::string cont) {
164 std::vector<std::string> list;
165 list.push_back(std::move(result));
166 list.push_back(std::move(cont));
167 appendRule(std::move(sequence), std::move(list));
168 }
169
appendRule(std::string sequence,std::string normal,std::string left_shift,std::string right_shift)170 void Key2KanaTable::appendRule(std::string sequence, std::string normal,
171 std::string left_shift,
172 std::string right_shift) {
173 std::vector<std::string> list;
174 list.push_back(normal);
175 list.push_back(left_shift);
176 list.push_back(right_shift);
177 appendRule(std::move(sequence), std::move(list));
178 }
179
clear()180 void Key2KanaTable::clear() { rules_.clear(); }
181
Key2KanaTableSet()182 Key2KanaTableSet::Key2KanaTableSet()
183 : name_(""), fundamentalTable_(nullptr),
184 voicedConsonantTable_(Key2KanaTable("voiced consonant table")),
185 additionalTable_(nullptr), typingMethod_(TypingMethod::ROMAJI),
186 periodStyle_(PeriodStyle::JAPANESE), commaStyle_(CommaStyle::JAPANESE),
187 bracketStyle_(BracketStyle::JAPANESE), slashStyle_(SlashStyle::JAPANESE),
188 useHalfSymbol_(false), useHalfNumber_(false) {
189 setTypingMethod(typingMethod_);
190 }
191
~Key2KanaTableSet()192 Key2KanaTableSet::~Key2KanaTableSet() {}
193
setTypingMethod(TypingMethod method,Key2KanaTable * fundamental_table)194 void Key2KanaTableSet::setTypingMethod(TypingMethod method,
195 Key2KanaTable *fundamental_table) {
196 typingMethod_ = method;
197 fundamentalTable_ = fundamental_table;
198 resetTables();
199 }
200
setSymbolHalf(bool half)201 void Key2KanaTableSet::setSymbolHalf(bool half) {
202 useHalfSymbol_ = half;
203 resetTables();
204 }
205
setNumberHalf(bool half)206 void Key2KanaTableSet::setNumberHalf(bool half) {
207 useHalfNumber_ = half;
208 resetTables();
209 }
210
setPeriodStyle(PeriodStyle style)211 void Key2KanaTableSet::setPeriodStyle(PeriodStyle style) {
212 periodStyle_ = style;
213 resetTables();
214 }
215
setCommaStyle(CommaStyle style)216 void Key2KanaTableSet::setCommaStyle(CommaStyle style) {
217 commaStyle_ = style;
218 resetTables();
219 }
220
setBracketStyle(BracketStyle style)221 void Key2KanaTableSet::setBracketStyle(BracketStyle style) {
222 bracketStyle_ = style;
223 resetTables();
224 }
225
setSlashStyle(SlashStyle style)226 void Key2KanaTableSet::setSlashStyle(SlashStyle style) {
227 slashStyle_ = style;
228 resetTables();
229 }
230
create_voiced_consonant_table(Key2KanaTable & table,Key2KanaTable & fund_table)231 static void create_voiced_consonant_table(Key2KanaTable &table,
232 Key2KanaTable &fund_table) {
233 table.clear();
234
235 const std::string sonant_mark = std::string("\xE3\x82\x9B");
236 const std::string half_sonant_mark = std::string("\xE3\x82\x9C");
237 std::vector<std::string> sonant_mark_list;
238 std::vector<std::string> half_sonant_mark_list;
239
240 Key2KanaRules::iterator it;
241 Key2KanaRules &rules = fund_table.table();
242 for (it = rules.begin(); it != rules.end(); it++) {
243 std::string result = it->result(0);
244 if (result == sonant_mark)
245 sonant_mark_list.push_back(it->sequence());
246 else if (result == half_sonant_mark)
247 half_sonant_mark_list.push_back(it->sequence());
248 }
249
250 VoicedConsonantRule *templ = fcitx_anthy_voiced_consonant_table;
251
252 for (unsigned int i = 0; templ[i].string; i++) {
253 if (templ[i].voiced && *templ[i].voiced) {
254 std::vector<std::string>::iterator it;
255 for (it = sonant_mark_list.begin(); it != sonant_mark_list.end();
256 it++) {
257 table.appendRule(std::string(templ[i].string) + *it,
258 std::string(templ[i].voiced), std::string());
259 }
260 }
261 if (templ[i].half_voiced && *templ[i].half_voiced) {
262 std::vector<std::string>::iterator it;
263 for (it = half_sonant_mark_list.begin();
264 it != half_sonant_mark_list.end(); it++) {
265 table.appendRule(std::string(templ[i].string) + *it,
266 std::string(templ[i].half_voiced),
267 std::string());
268 }
269 }
270 }
271 }
272
resetTables()273 void Key2KanaTableSet::resetTables() {
274 allTables_.clear();
275
276 bool is_romaji = typingMethod_ == TypingMethod::ROMAJI;
277 bool is_kana = typingMethod_ == TypingMethod::KANA;
278 bool is_nicola = typingMethod_ == TypingMethod::NICOLA;
279
280 // symbols table
281 if (useHalfSymbol_)
282 allTables_.push_back(&half_symbol_table);
283 else
284 allTables_.push_back(&wide_symbol_table);
285
286 // numbers table
287 if (useHalfNumber_)
288 allTables_.push_back(&half_number_table);
289 else
290 allTables_.push_back(&wide_number_table);
291
292 if (is_romaji || is_kana) {
293 switch (periodStyle_) {
294 case PeriodStyle::JAPANESE:
295 if (is_romaji)
296 allTables_.push_back(&romaji_ja_period_table);
297 else
298 allTables_.push_back(&kana_ja_period_table);
299 break;
300 case PeriodStyle::WIDE:
301 if (is_romaji)
302 allTables_.push_back(&romaji_wide_period_table);
303 else
304 allTables_.push_back(&kana_wide_period_table);
305 break;
306 case PeriodStyle::HALF:
307 if (is_romaji)
308 allTables_.push_back(&romaji_half_period_table);
309 else
310 allTables_.push_back(&kana_half_period_table);
311 break;
312 default:
313 break;
314 }
315 }
316
317 if (is_romaji || is_kana) {
318 switch (commaStyle_) {
319 case CommaStyle::JAPANESE:
320 if (is_romaji)
321 allTables_.push_back(&romaji_ja_comma_table);
322 else
323 allTables_.push_back(&kana_ja_comma_table);
324 break;
325 case CommaStyle::WIDE:
326 if (is_romaji)
327 allTables_.push_back(&romaji_wide_comma_table);
328 else
329 allTables_.push_back(&kana_wide_comma_table);
330 break;
331 case CommaStyle::HALF:
332 if (is_romaji)
333 allTables_.push_back(&romaji_half_comma_table);
334 else
335 allTables_.push_back(&kana_half_comma_table);
336 break;
337 default:
338 break;
339 }
340 }
341
342 if (is_romaji || is_kana) {
343 switch (bracketStyle_) {
344 case BracketStyle::JAPANESE:
345 if (is_romaji)
346 allTables_.push_back(&romaji_ja_bracket_table);
347 else
348 allTables_.push_back(&kana_ja_bracket_table);
349 break;
350 case BracketStyle::WIDE:
351 if (is_romaji)
352 allTables_.push_back(&romaji_wide_bracket_table);
353 else
354 allTables_.push_back(&kana_wide_bracket_table);
355 break;
356 default:
357 break;
358 }
359 }
360
361 if (is_romaji || is_kana) {
362 switch (slashStyle_) {
363 case SlashStyle::JAPANESE:
364 if (is_romaji)
365 allTables_.push_back(&romaji_ja_slash_table);
366 else
367 allTables_.push_back(&kana_ja_slash_table);
368 break;
369 case SlashStyle::WIDE:
370 if (is_romaji)
371 allTables_.push_back(&romaji_wide_slash_table);
372 else
373 allTables_.push_back(&kana_wide_slash_table);
374 break;
375 default:
376 break;
377 }
378 }
379
380 if (!fundamentalTable_) {
381 if (is_romaji) {
382 allTables_.push_back(&romaji_double_consonant_table);
383 allTables_.push_back(&romaji_table);
384 } else if (is_kana) {
385 create_voiced_consonant_table(voicedConsonantTable_, kana_table);
386 allTables_.push_back(&voicedConsonantTable_);
387 allTables_.push_back(&kana_table);
388 } else if (is_nicola) {
389 allTables_.push_back(&nicola_table);
390 }
391 } else {
392 if (is_romaji) {
393 allTables_.push_back(&romaji_double_consonant_table);
394 allTables_.push_back(fundamentalTable_);
395 } else if (is_kana) {
396 create_voiced_consonant_table(voicedConsonantTable_,
397 *fundamentalTable_);
398 allTables_.push_back(&voicedConsonantTable_);
399 allTables_.push_back(fundamentalTable_);
400 } else if (is_nicola) {
401 allTables_.push_back(fundamentalTable_);
402 }
403 }
404 }
405