1 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
2 /*
3 * nimf-anthy.c
4 * This file is part of Nimf.
5 *
6 * Copyright (C) 2016-2019 Hodong Kim <cogniti@gmail.com>
7 *
8 * Nimf is free software: you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published
10 * by the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * Nimf is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 * See the GNU Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include <nimf.h>
23 #include <anthy/anthy.h>
24 #include <glib/gi18n.h>
25
26 #define NIMF_TYPE_ANTHY (nimf_anthy_get_type ())
27 #define NIMF_ANTHY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NIMF_TYPE_ANTHY, NimfAnthy))
28 #define NIMF_ANTHY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NIMF_TYPE_ANTHY, NimfAnthyClass))
29 #define NIMF_IS_ANTHY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NIMF_TYPE_ANTHY))
30 #define NIMF_IS_ANTHY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NIMF_TYPE_ANTHY))
31 #define NIMF_ANTHY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NIMF_TYPE_ANTHY, NimfAnthyClass))
32
33 #define NIMF_ANTHY_BUFFER_SIZE 256
34
35 typedef struct _NimfAnthy NimfAnthy;
36 typedef struct _NimfAnthyClass NimfAnthyClass;
37
38 struct _NimfAnthy
39 {
40 NimfEngine parent_instance;
41
42 NimfCandidatable *candidatable;
43 GString *preedit;
44 gint preedit_offset; /* in bytes */
45 gint preedit_dx; /* in bytes */
46 NimfPreeditState preedit_state;
47 NimfPreeditAttr **preedit_attrs;
48 gchar *id;
49 GSettings *settings;
50 NimfKey **hiragana_keys;
51 NimfKey **katakana_keys;
52 gchar *method;
53 gboolean method_changed;
54 gint n_input_mode;
55
56 anthy_context_t context;
57 gint current_segment;
58 gchar buffer[NIMF_ANTHY_BUFFER_SIZE];
59 gint current_page;
60 gint n_pages;
61 gint *selections;
62 };
63
64 struct _NimfAnthyClass
65 {
66 /*< private >*/
67 NimfEngineClass parent_class;
68 };
69
70 typedef enum
71 {
72 COMMON,
73 EXPLICIT
74 } NInputMode;
75
76 static gint nimf_anthy_ref_count = 0;
77 static GHashTable *nimf_anthy_romaji = NULL;;
78
79 typedef struct
80 {
81 gchar *key;
82 gchar *value;
83 } RomajiMap;
84
85 static const RomajiMap romaji_map[] = {
86 {"a", "あ"},
87 {"b", ""}, /* dummy */
88 {"ba", "ば"},
89 {"be", "べ"},
90 {"bi", "び"},
91 {"bo", "ぼ"},
92 {"bu", "ぶ"},
93 {"by", ""}, /* dummy */
94 {"bya", "びゃ"},
95 {"bye", "びぇ"},
96 {"byi", "びぃ"},
97 {"byo", "びょ"},
98 {"byu", "びゅ"},
99 {"c", ""}, /* dummy */
100 {"ca", "か"},
101 {"ce", "せ"},
102 {"ch", ""}, /* dummy */
103 {"cha", "ちゃ"},
104 {"che", "ちぇ"},
105 {"chi", "ち"},
106 {"cho", "ちょ"},
107 {"chu", "ちゅ"},
108 {"ci", "し"},
109 {"co", "こ"},
110 {"cu", "く"},
111 {"cy", ""}, /* dummy */
112 {"cya", "ちゃ"},
113 {"cye", "ちぇ"},
114 {"cyi", "ちぃ"},
115 {"cyo", "ちょ"},
116 {"cyu", "ちゅ"},
117 {"d", ""}, /* dummy */
118 {"da", "だ"},
119 {"de", "で"},
120 {"dh", ""}, /* dummy */
121 {"dha", "でゃ"},
122 {"dhe", "でぇ"},
123 {"dhi", "でぃ"},
124 {"dho", "でょ"},
125 {"dhu", "でゅ"},
126 {"di", "ぢ"},
127 {"do", "ど"},
128 {"du", "づ"},
129 {"dw", ""}, /* dummy */
130 {"dwa", "どぁ"},
131 {"dwe", "どぇ"},
132 {"dwi", "どぃ"},
133 {"dwo", "どぉ"},
134 {"dwu", "どぅ"},
135 {"dy", ""}, /* dummy */
136 {"dya", "ぢゃ"},
137 {"dye", "ぢぇ"},
138 {"dyi", "ぢぃ"},
139 {"dyo", "ぢょ"},
140 {"dyu", "ぢゅ"},
141 {"e", "え"},
142 {"f", ""}, /* dummy */
143 {"fa", "ふぁ"},
144 {"fe", "ふぇ"},
145 {"fi", "ふぃ"},
146 {"fo", "ふぉ"},
147 {"fu", "ふ"},
148 {"fw", ""}, /* dummy */
149 {"fwa", "ふぁ"},
150 {"fwe", "ふぇ"},
151 {"fwi", "ふぃ"},
152 {"fwo", "ふぉ"},
153 {"fwu", "ふぅ"},
154 {"fy", ""}, /* dummy */
155 {"fya", "ふゃ"},
156 {"fye", "ふぇ"},
157 {"fyi", "ふぃ"},
158 {"fyo", "ふょ"},
159 {"fyu", "ふゅ"},
160 {"g", ""}, /* dummy */
161 {"ga", "が"},
162 {"ge", "げ"},
163 {"gi", "ぎ"},
164 {"go", "ご"},
165 {"gu", "ぐ"},
166 {"gw", ""}, /* dummy */
167 {"gwa", "ぐぁ"},
168 {"gwe", "ぐえ"},
169 {"gwi", "ぐぃ"},
170 {"gwo", "ぐぉ"},
171 {"gwu", "ぐぅ"},
172 {"gy", ""}, /* dummy */
173 {"gya", "ぎゃ"},
174 {"gye", "ぎぇ"},
175 {"gyi", "ぎぃ"},
176 {"gyo", "ぎょ"},
177 {"gyu", "ぎゅ"},
178 {"h", ""}, /* dummy */
179 {"ha", "は"},
180 {"he", "へ"},
181 {"hi", "ひ"},
182 {"ho", "ほ"},
183 {"hu", "ふ"},
184 {"hy", ""}, /* dummy */
185 {"hya", "ひゃ"},
186 {"hye", "ひぇ"},
187 {"hyi", "ひぃ"},
188 {"hyo", "ひょ"},
189 {"hyu", "ひゅ"},
190 {"i", "い"},
191 {"j", ""}, /* dummy */
192 {"ja", "じゃ"},
193 {"je", "じぇ"},
194 {"ji", "じ"},
195 {"jo", "じょ"},
196 {"ju", "じゅ"},
197 {"jy", ""}, /* dummy */
198 {"jya", "じゃ"},
199 {"jye", "じぇ"},
200 {"jyi", "じぃ"},
201 {"jyo", "じょ"},
202 {"jyu", "じゅ"},
203 {"k", ""}, /* dummy */
204 {"ka", "か"},
205 {"ke", "け"},
206 {"ki", "き"},
207 {"ko", "こ"},
208 {"ku", "く"},
209 {"kw", ""}, /* dummy */
210 {"kwa", "くぁ"},
211 {"ky", ""}, /* dummy */
212 {"kya", "きゃ"},
213 {"kye", "きぇ"},
214 {"kyi", "きぃ"},
215 {"kyo", "きょ"},
216 {"kyu", "きゅ"},
217 {"l", ""}, /* dummy */
218 {"la", "ぁ"},
219 {"le", "ぇ"},
220 {"li", "ぃ"},
221 {"lk", ""}, /* dummy */
222 {"lka", "ヵ"},
223 {"lke", "ヶ"},
224 {"lo", "ぉ"},
225 {"lt", ""}, /* dummy */
226 {"lts", ""}, /* dummy */
227 {"ltsu", "っ"},
228 {"ltu", "っ"},
229 {"lu", "ぅ"},
230 {"lw", ""}, /* dummy */
231 {"lwa", "ゎ"},
232 {"ly", ""}, /* dummy */
233 {"lya", "ゃ"},
234 {"lye", "ぇ"},
235 {"lyi", "ぃ"},
236 {"lyo", "ょ"},
237 {"lyu", "ゅ"},
238 {"m", ""}, /* dummy */
239 {"ma", "ま"},
240 {"me", "め"},
241 {"mi", "み"},
242 {"mo", "も"},
243 {"mu", "む"},
244 {"my", ""}, /* dummy */
245 {"mya", "みゃ"},
246 {"mye", "みぇ"},
247 {"myi", "みぃ"},
248 {"myo", "みょ"},
249 {"myu", "みゅ"},
250 {"n", ""}, /* dummy */
251 {"na", "な"},
252 {"ne", "ね"},
253 {"ni", "に"},
254 {"nn", "ん"},
255 {"no", "の"},
256 {"nu", "ぬ"},
257 {"ny", ""}, /* dummy */
258 {"nya", "にゃ"},
259 {"nye", "にぇ"},
260 {"nyi", "にぃ"},
261 {"nyo", "にょ"},
262 {"nyu", "にゅ"},
263 {"o", "お"},
264 {"p", ""}, /* dummy */
265 {"pa", "ぱ"},
266 {"pe", "ぺ"},
267 {"pi", "ぴ"},
268 {"po", "ぽ"},
269 {"pu", "ぷ"},
270 {"py", ""}, /* dummy */
271 {"pya", "ぴゃ"},
272 {"pye", "ぴぇ"},
273 {"pyi", "ぴぃ"},
274 {"pyo", "ぴょ"},
275 {"pyu", "ぴゅ"},
276 {"q", ""}, /* dummy */
277 {"qa", "くぁ"},
278 {"qe", "くぇ"},
279 {"qi", "くぃ"},
280 {"qo", "くぉ"},
281 {"qu", "く"},
282 {"qw", ""}, /* dummy */
283 {"qwa", "くぁ"},
284 {"qwe", "くぇ"},
285 {"qwi", "くぃ"},
286 {"qwo", "くぉ"},
287 {"qwu", "くぅ"},
288 {"qy", ""}, /* dummy */
289 {"qya", "くゃ"},
290 {"qye", "くぇ"},
291 {"qyi", "くぃ"},
292 {"qyo", "くょ"},
293 {"qyu", "くゅ"},
294 {"r", ""}, /* dummy */
295 {"ra", "ら"},
296 {"re", "れ"},
297 {"ri", "り"},
298 {"ro", "ろ"},
299 {"ru", "る"},
300 {"ry", ""}, /* dummy */
301 {"rya", "りゃ"},
302 {"rye", "りぇ"},
303 {"ryi", "りぃ"},
304 {"ryo", "りょ"},
305 {"ryu", "りゅ"},
306 {"s", ""}, /* dummy */
307 {"sa", "さ"},
308 {"se", "せ"},
309 {"sh", ""}, /* dummy */
310 {"sha", "しゃ"},
311 {"she", "しぇ"},
312 {"shi", "し"},
313 {"sho", "しょ"},
314 {"shu", "しゅ"},
315 {"si", "し"},
316 {"so", "そ"},
317 {"su", "す"},
318 {"sw", ""}, /* dummy */
319 {"swa", "すぁ"},
320 {"swe", "すぇ"},
321 {"swi", "すぃ"},
322 {"swo", "すぉ"},
323 {"swu", "すぅ"},
324 {"sy", ""}, /* dummy */
325 {"sya", "しゃ"},
326 {"sye", "しぇ"},
327 {"syi", "しぃ"},
328 {"syo", "しょ"},
329 {"syu", "しゅ"},
330 {"t", ""}, /* dummy */
331 {"ta", "た"},
332 {"te", "て"},
333 {"th", ""}, /* dummy */
334 {"tha", "てゃ"},
335 {"the", "てぇ"},
336 {"thi", "てぃ"},
337 {"tho", "てょ"},
338 {"thu", "てゅ"},
339 {"ti", "ち"},
340 {"to", "と"},
341 {"ts", ""}, /* dummy */
342 {"tsa", "つぁ"},
343 {"tse", "つぇ"},
344 {"tsi", "つぃ"},
345 {"tso", "つぉ"},
346 {"tsu", "つ"},
347 {"tu", "つ"},
348 {"tw", ""}, /* dummy */
349 {"twa", "とぁ"},
350 {"twe", "とぇ"},
351 {"twi", "とぃ"},
352 {"two", "とぉ"},
353 {"twu", "とぅ"},
354 {"ty", ""}, /* dummy */
355 {"tya", "ちゃ"},
356 {"tye", "ちぇ"},
357 {"tyi", "ちぃ"},
358 {"tyo", "ちょ"},
359 {"tyu", "ちゅ"},
360 {"u", "う"},
361 {"v", ""}, /* dummy */
362 {"va", "ヴぁ"},
363 {"ve", "ヴぇ"},
364 {"vi", "ヴぃ"},
365 {"vo", "ヴぉ"},
366 {"vu", "ヴ"},
367 {"vy", ""}, /* dummy */
368 {"vya", "ヴゃ"},
369 {"vye", "ヴぇ"},
370 {"vyi", "ヴぃ"},
371 {"vyo", "ヴょ"},
372 {"vyu", "ヴゅ"},
373 {"w", ""}, /* dummy */
374 {"wa", "わ"},
375 {"we", "うぇ"},
376 {"wh", ""}, /* dummy */
377 {"wha", "うぁ"},
378 {"whe", "うぇ"},
379 {"whi", "うぃ"},
380 {"who", "うぉ"},
381 {"whu", "う"},
382 {"wi", "うぃ"},
383 {"wo", "を"},
384 {"wu", "う"},
385 {"wy", ""}, /* dummy */
386 {"wye", "ゑ"},
387 {"wyi", "ゐ"},
388 {"x", ""}, /* dummy */
389 {"xa", "ぁ"},
390 {"xe", "ぇ"},
391 {"xi", "ぃ"},
392 {"xk", ""}, /* dummy */
393 {"xka", "ヵ"},
394 {"xke", "ヶ"},
395 {"xn", "ん"},
396 {"xo", "ぉ"},
397 {"xt", ""}, /* dummy */
398 {"xts", ""}, /* dummy */
399 {"xtsu", "っ"},
400 {"xtu", "っ"},
401 {"xu", "ぅ"},
402 {"xw", ""}, /* dummy */
403 {"xwa", "ゎ"},
404 {"xy", ""}, /* dummy */
405 {"xya", "ゃ"},
406 {"xye", "ぇ"},
407 {"xyi", "ぃ"},
408 {"xyo", "ょ"},
409 {"xyu", "ゅ"},
410 {"y", ""}, /* dummy */
411 {"ya", "や"},
412 {"ye", "いぇ"},
413 {"yi", "い"},
414 {"yo", "よ"},
415 {"yu", "ゆ"},
416 {"z", ""}, /* dummy */
417 {"za", "ざ"},
418 {"ze", "ぜ"},
419 {"zi", "じ"},
420 {"zo", "ぞ"},
421 {"zu", "ず"},
422 {"zy", ""}, /* dummy */
423 {"zya", "じゃ"},
424 {"zye", "じぇ"},
425 {"zyi", "じぃ"},
426 {"zyo", "じょ"},
427 {"zyu", "じゅ"},
428 {",", "、"},
429 {".", "。"},
430 {"-", "ー"}
431 };
432
433 G_DEFINE_DYNAMIC_TYPE (NimfAnthy, nimf_anthy, NIMF_TYPE_ENGINE);
434
435 static void
nimf_anthy_update_preedit_state(NimfEngine * engine,NimfServiceIC * target,const gchar * new_preedit,gint cursor_pos)436 nimf_anthy_update_preedit_state (NimfEngine *engine,
437 NimfServiceIC *target,
438 const gchar *new_preedit,
439 gint cursor_pos)
440 {
441 g_debug (G_STRLOC ": %s", G_STRFUNC);
442
443 NimfAnthy *anthy = NIMF_ANTHY (engine);
444
445 if (anthy->preedit_state == NIMF_PREEDIT_STATE_END &&
446 anthy->preedit->len > 0)
447 {
448 anthy->preedit_state = NIMF_PREEDIT_STATE_START;
449 nimf_engine_emit_preedit_start (engine, target);
450 }
451
452 nimf_engine_emit_preedit_changed (engine, target, new_preedit,
453 anthy->preedit_attrs, cursor_pos);
454
455 if (!nimf_service_ic_get_use_preedit (target))
456 nimf_candidatable_set_auxiliary_text (anthy->candidatable,
457 anthy->preedit->str,
458 g_utf8_strlen (anthy->preedit->str,
459 anthy->preedit_offset + anthy->preedit_dx));
460
461 if (anthy->preedit_state == NIMF_PREEDIT_STATE_START &&
462 anthy->preedit->len == 0)
463 {
464 anthy->preedit_state = NIMF_PREEDIT_STATE_END;
465 nimf_engine_emit_preedit_end (engine, target);
466 }
467 }
468
469 static void
nimf_anthy_emit_commit(NimfEngine * engine,NimfServiceIC * target)470 nimf_anthy_emit_commit (NimfEngine *engine,
471 NimfServiceIC *target)
472 {
473 g_debug (G_STRLOC ": %s", G_STRFUNC);
474
475 NimfAnthy *anthy = NIMF_ANTHY (engine);
476 struct anthy_conv_stat conv_stat;
477 gint i;
478
479 anthy_get_stat (anthy->context, &conv_stat);
480
481 for (i = 0; i < conv_stat.nr_segment; i++)
482 anthy_commit_segment (anthy->context, i, anthy->selections[i]);
483
484 if (anthy->preedit->len > 0)
485 {
486 nimf_engine_emit_commit (engine, target, anthy->preedit->str);
487 g_string_assign (anthy->preedit, "");
488 anthy->preedit_offset = 0;
489 anthy->preedit_dx = 0;
490 anthy->preedit_attrs[0]->start_index = 0;
491 anthy->preedit_attrs[0]->end_index = 0;
492 anthy->preedit_attrs[1]->start_index = 0;
493 anthy->preedit_attrs[1]->end_index = 0;
494 nimf_anthy_update_preedit_state (engine, target, "", 0);
495 }
496 }
497
498 void
nimf_anthy_reset(NimfEngine * engine,NimfServiceIC * target)499 nimf_anthy_reset (NimfEngine *engine,
500 NimfServiceIC *target)
501 {
502 g_debug (G_STRLOC ": %s", G_STRFUNC);
503
504 NimfAnthy *anthy = NIMF_ANTHY (engine);
505 struct anthy_conv_stat conv_stat;
506
507 anthy_get_stat (anthy->context, &conv_stat);
508 nimf_candidatable_hide (anthy->candidatable);
509 nimf_anthy_emit_commit (engine, target);
510 memset (anthy->selections, 0, conv_stat.nr_segment * sizeof (gint));
511 anthy_reset_context (anthy->context);
512 }
513
514 void
nimf_anthy_focus_in(NimfEngine * engine,NimfServiceIC * target)515 nimf_anthy_focus_in (NimfEngine *engine,
516 NimfServiceIC *target)
517 {
518 g_debug (G_STRLOC ": %s", G_STRFUNC);
519 }
520
521 void
nimf_anthy_focus_out(NimfEngine * engine,NimfServiceIC * target)522 nimf_anthy_focus_out (NimfEngine *engine,
523 NimfServiceIC *target)
524 {
525 g_debug (G_STRLOC ": %s", G_STRFUNC);
526
527 nimf_candidatable_hide (NIMF_ANTHY (engine)->candidatable);
528 nimf_anthy_reset (engine, target);
529 }
530
531 static gint
nimf_anthy_get_current_page(NimfEngine * engine)532 nimf_anthy_get_current_page (NimfEngine *engine)
533 {
534 g_debug (G_STRLOC ": %s", G_STRFUNC);
535
536 return NIMF_ANTHY (engine)->current_page;
537 }
538
539 static void
nimf_anthy_convert_preedit_text(NimfEngine * engine,NimfServiceIC * target)540 nimf_anthy_convert_preedit_text (NimfEngine *engine,
541 NimfServiceIC *target)
542 {
543 g_debug (G_STRLOC ": %s", G_STRFUNC);
544
545 NimfAnthy *anthy = NIMF_ANTHY (engine);
546 struct anthy_conv_stat conv_stat;
547 gint i;
548 gint offset = 0;
549 gint end_pos = 0;
550 gint len = 0;
551 gint current_segment_len = 0;
552
553 g_string_assign (anthy->preedit, "");
554 anthy_get_stat (anthy->context, &conv_stat);
555
556 for (i = 0; i < conv_stat.nr_segment; i++)
557 {
558 anthy_get_segment (anthy->context, i, anthy->selections[i], anthy->buffer, NIMF_ANTHY_BUFFER_SIZE);
559 len = g_utf8_strlen (anthy->buffer, -1);
560 end_pos += len;
561
562 if (i < anthy->current_segment)
563 offset += len;
564
565 if (i == anthy->current_segment)
566 current_segment_len = len;
567
568 g_string_append (anthy->preedit, anthy->buffer);
569 }
570
571 anthy->preedit_attrs[0]->start_index = 0;
572 anthy->preedit_attrs[0]->end_index = end_pos;
573 anthy->preedit_attrs[1]->start_index = offset;
574 anthy->preedit_attrs[1]->end_index = offset + current_segment_len;
575 nimf_anthy_update_preedit_state (engine, target, anthy->preedit->str,
576 g_utf8_strlen (anthy->preedit->str, -1));
577
578 anthy->preedit_offset = anthy->preedit->len;
579 anthy->preedit_dx = 0;
580 }
581
582 static void
nimf_anthy_update_preedit_text(NimfEngine * engine,NimfServiceIC * target)583 nimf_anthy_update_preedit_text (NimfEngine *engine,
584 NimfServiceIC *target)
585 {
586 g_debug (G_STRLOC ": %s", G_STRFUNC);
587
588 NimfAnthy *anthy = NIMF_ANTHY (engine);
589
590 anthy->preedit_attrs[0]->start_index = 0;
591 anthy->preedit_attrs[0]->end_index = g_utf8_strlen (anthy->preedit->str, -1);
592 anthy->preedit_attrs[1]->start_index = 0;
593 anthy->preedit_attrs[1]->end_index = 0;
594 nimf_anthy_update_preedit_state (engine, target, anthy->preedit->str,
595 g_utf8_strlen (anthy->preedit->str,
596 anthy->preedit_offset + anthy->preedit_dx));
597 }
598
599 static void
nimf_anthy_update_page(NimfEngine * engine,NimfServiceIC * target)600 nimf_anthy_update_page (NimfEngine *engine,
601 NimfServiceIC *target)
602 {
603 g_debug (G_STRLOC ": %s", G_STRFUNC);
604
605 NimfAnthy *anthy = NIMF_ANTHY (engine);
606 struct anthy_conv_stat conv_stat;
607 struct anthy_segment_stat segment_stat;
608 gint i;
609
610 anthy_get_stat (anthy->context, &conv_stat);
611 anthy_get_segment_stat (anthy->context, anthy->current_segment, &segment_stat);
612
613 anthy->n_pages = (segment_stat.nr_candidate + 9) / 10;
614 nimf_candidatable_clear (anthy->candidatable, target);
615
616 for (i = (anthy->current_page - 1) * 10;
617 i < MIN (anthy->current_page * 10, segment_stat.nr_candidate);
618 i++)
619 {
620 anthy_get_segment (anthy->context, anthy->current_segment, i,
621 anthy->buffer, NIMF_ANTHY_BUFFER_SIZE);
622 nimf_candidatable_append (anthy->candidatable, anthy->buffer, NULL);
623 }
624
625 nimf_candidatable_select_item_by_index_in_page
626 (anthy->candidatable, anthy->selections[anthy->current_segment]);
627 nimf_candidatable_set_page_values (anthy->candidatable, target,
628 anthy->current_page, anthy->n_pages, 10);
629 }
630
631 static void
on_candidate_clicked(NimfEngine * engine,NimfServiceIC * target,gchar * text,gint index)632 on_candidate_clicked (NimfEngine *engine,
633 NimfServiceIC *target,
634 gchar *text,
635 gint index)
636 {
637 g_debug (G_STRLOC ": %s", G_STRFUNC);
638
639 NimfAnthy *anthy = NIMF_ANTHY (engine);
640
641 anthy->selections[anthy->current_segment] = (anthy->current_page -1) * 10 + index;
642 nimf_anthy_convert_preedit_text (engine, target);
643 }
644
645 static void
nimf_anthy_page_end(NimfEngine * engine,NimfServiceIC * target)646 nimf_anthy_page_end (NimfEngine *engine, NimfServiceIC *target)
647 {
648 g_debug (G_STRLOC ": %s", G_STRFUNC);
649
650 NimfAnthy *anthy = NIMF_ANTHY (engine);
651
652 if (anthy->current_page == anthy->n_pages)
653 {
654 nimf_candidatable_select_last_item_in_page (anthy->candidatable);
655 return;
656 }
657
658 anthy->current_page = anthy->n_pages;
659 nimf_anthy_update_page (engine, target);
660 nimf_candidatable_select_last_item_in_page (anthy->candidatable);
661 }
662
663 static gboolean
nimf_anthy_page_up(NimfEngine * engine,NimfServiceIC * target)664 nimf_anthy_page_up (NimfEngine *engine, NimfServiceIC *target)
665 {
666 g_debug (G_STRLOC ": %s", G_STRFUNC);
667
668 NimfAnthy *anthy = NIMF_ANTHY (engine);
669
670 if (anthy->current_page <= 1)
671 {
672 nimf_anthy_page_end (engine, target);
673 return FALSE;
674 }
675
676 anthy->current_page--;
677 nimf_anthy_update_page (engine, target);
678 nimf_candidatable_select_last_item_in_page (anthy->candidatable);
679
680 return TRUE;
681 }
682
683 static void
nimf_anthy_page_home(NimfEngine * engine,NimfServiceIC * target)684 nimf_anthy_page_home (NimfEngine *engine, NimfServiceIC *target)
685 {
686 g_debug (G_STRLOC ": %s", G_STRFUNC);
687
688 NimfAnthy *anthy = NIMF_ANTHY (engine);
689
690 if (anthy->current_page <= 1)
691 {
692 nimf_candidatable_select_first_item_in_page (anthy->candidatable);
693 return;
694 }
695
696 anthy->current_page = 1;
697 nimf_anthy_update_page (engine, target);
698 nimf_candidatable_select_first_item_in_page (anthy->candidatable);
699 }
700
701 static gboolean
nimf_anthy_page_down(NimfEngine * engine,NimfServiceIC * target)702 nimf_anthy_page_down (NimfEngine *engine, NimfServiceIC *target)
703 {
704 g_debug (G_STRLOC ": %s", G_STRFUNC);
705
706 NimfAnthy *anthy = NIMF_ANTHY (engine);
707
708 if (anthy->current_page == anthy->n_pages)
709 {
710 nimf_anthy_page_home (engine, target);
711 return FALSE;
712 }
713
714 anthy->current_page++;
715 nimf_anthy_update_page (engine, target);
716 nimf_candidatable_select_first_item_in_page (anthy->candidatable);
717
718 return TRUE;
719 }
720
721 static void
on_candidate_scrolled(NimfEngine * engine,NimfServiceIC * target,gdouble value)722 on_candidate_scrolled (NimfEngine *engine,
723 NimfServiceIC *target,
724 gdouble value)
725 {
726 g_debug (G_STRLOC ": %s", G_STRFUNC);
727
728 NimfAnthy *anthy = NIMF_ANTHY (engine);
729
730 if ((gint) value == nimf_anthy_get_current_page (engine))
731 return;
732
733 while (anthy->n_pages > 1)
734 {
735 gint d = (gint) value - nimf_anthy_get_current_page (engine);
736
737 if (d > 0)
738 nimf_anthy_page_down (engine, target);
739 else if (d < 0)
740 nimf_anthy_page_up (engine, target);
741 else if (d == 0)
742 break;
743 }
744 }
745
746 static void
nimf_anthy_update_candidate(NimfEngine * engine,NimfServiceIC * target)747 nimf_anthy_update_candidate (NimfEngine *engine,
748 NimfServiceIC *target)
749 {
750 g_debug (G_STRLOC ": %s", G_STRFUNC);
751
752 NimfAnthy *anthy = NIMF_ANTHY (engine);
753 struct anthy_conv_stat conv_stat;
754
755 anthy_get_stat (anthy->context, &conv_stat);
756
757 if (conv_stat.nr_segment > 0)
758 {
759 anthy->current_page = 1;
760 nimf_anthy_update_page (engine, target);
761 }
762 else
763 {
764 if (anthy->n_pages > 0)
765 {
766 nimf_candidatable_hide (anthy->candidatable);
767 nimf_candidatable_clear (anthy->candidatable, target);
768 anthy->n_pages = 0;
769 anthy->current_page = 0;
770 }
771 }
772 }
773
774 static gboolean
nimf_anthy_filter_event_romaji(NimfEngine * engine,NimfServiceIC * target,NimfEvent * event)775 nimf_anthy_filter_event_romaji (NimfEngine *engine,
776 NimfServiceIC *target,
777 NimfEvent *event)
778 {
779 g_debug (G_STRLOC ": %s", G_STRFUNC);
780
781 NimfAnthy *anthy = NIMF_ANTHY (engine);
782 const gchar *str;
783
784 g_string_insert_c (anthy->preedit, anthy->preedit_offset + anthy->preedit_dx, event->key.keyval);
785 anthy->preedit_dx++;
786
787 while (TRUE)
788 {
789 gchar *key;
790
791 key = g_strndup (anthy->preedit->str + anthy->preedit_offset,
792 anthy->preedit_dx);
793 str = g_hash_table_lookup (nimf_anthy_romaji, key);
794
795 g_free (key);
796
797 if (str)
798 {
799 if (str[0] != 0)
800 {
801 g_string_erase (anthy->preedit, anthy->preedit_offset,
802 anthy->preedit_dx);
803 g_string_insert (anthy->preedit, anthy->preedit_offset, str);
804 anthy->preedit_offset += strlen (str);
805 anthy->preedit_dx = 0;
806 }
807
808 break;
809 }
810 else
811 {
812 if (anthy->preedit_dx > 1)
813 {
814 char a = anthy->preedit->str[anthy->preedit_offset + anthy->preedit_dx - 2];
815 char b = anthy->preedit->str[anthy->preedit_offset + anthy->preedit_dx - 1];
816
817 if (a != 'n' && a == b)
818 {
819 g_string_erase (anthy->preedit, anthy->preedit_offset + anthy->preedit_dx - 2, 1);
820 g_string_insert (anthy->preedit, anthy->preedit_offset + anthy->preedit_dx - 2, "っ");
821 anthy->preedit_offset += strlen ("っ") - 1;
822 }
823 else if (anthy->n_input_mode == COMMON && a == 'n' &&
824 !(b == 'a' || b == 'e' || b == 'i' || b == 'o' || b == 'u' || b == 'n'))
825 {
826 g_string_erase (anthy->preedit, anthy->preedit_offset + anthy->preedit_dx - 2, 1);
827 g_string_insert (anthy->preedit, anthy->preedit_offset + anthy->preedit_dx - 2, "ん");
828 anthy->preedit_offset += strlen ("ん") - 1;
829 }
830
831 anthy->preedit_offset += anthy->preedit_dx - 1;
832 anthy->preedit_dx = 1;
833 }
834 else
835 {
836 break;
837 }
838 }
839 }
840
841 return TRUE;
842 }
843
844 static void
nimf_anthy_preedit_insert(NimfAnthy * anthy,const gchar * val)845 nimf_anthy_preedit_insert (NimfAnthy *anthy,
846 const gchar *val)
847 {
848 g_debug (G_STRLOC ": %s", G_STRFUNC);
849
850 g_string_insert (anthy->preedit, anthy->preedit_offset, val);
851 anthy->preedit_offset += strlen (val);
852 }
853
854 static gboolean
nimf_anthy_preedit_offset_has_suffix(NimfAnthy * anthy,const gchar * suffix)855 nimf_anthy_preedit_offset_has_suffix (NimfAnthy *anthy, const gchar *suffix)
856 {
857 g_debug (G_STRLOC ": %s", G_STRFUNC);
858
859 gint len = strlen (suffix);
860
861 return !!g_strstr_len (anthy->preedit->str + anthy->preedit_offset - len,
862 len, suffix);
863 }
864
865 static gboolean
nimf_anthy_filter_event_pc104(NimfEngine * engine,NimfServiceIC * target,NimfEvent * event)866 nimf_anthy_filter_event_pc104 (NimfEngine *engine,
867 NimfServiceIC *target,
868 NimfEvent *event)
869 {
870 g_debug (G_STRLOC ": %s", G_STRFUNC);
871
872 NimfAnthy *anthy = NIMF_ANTHY (engine);
873
874 gboolean is_shift = event->key.state & NIMF_SHIFT_MASK;
875
876 switch (event->key.hardware_keycode)
877 {
878 case 49: nimf_anthy_preedit_insert (anthy, "ろ"); break;
879 case 10: nimf_anthy_preedit_insert (anthy, "ぬ"); break;
880 case 11: nimf_anthy_preedit_insert (anthy, "ふ"); break;
881 case 12:
882 if (is_shift) nimf_anthy_preedit_insert (anthy, "ぁ");
883 else nimf_anthy_preedit_insert (anthy, "あ");
884 break;
885 case 13:
886 if (is_shift) nimf_anthy_preedit_insert (anthy, "ぅ");
887 else nimf_anthy_preedit_insert (anthy, "う");
888 break;
889 case 14:
890 if (is_shift) nimf_anthy_preedit_insert (anthy, "ぇ");
891 else nimf_anthy_preedit_insert (anthy, "え");
892 break;
893 case 15:
894 if (is_shift) nimf_anthy_preedit_insert (anthy, "ぉ");
895 else nimf_anthy_preedit_insert (anthy, "お");
896 break;
897 case 16:
898 if (is_shift) nimf_anthy_preedit_insert (anthy, "ゃ");
899 else nimf_anthy_preedit_insert (anthy, "や");
900 break;
901 case 17:
902 if (is_shift) nimf_anthy_preedit_insert (anthy, "ゅ");
903 else nimf_anthy_preedit_insert (anthy, "ゆ");
904 break;
905 case 18:
906 if (is_shift) nimf_anthy_preedit_insert (anthy, "ょ");
907 else nimf_anthy_preedit_insert (anthy, "よ");
908 break;
909 case 19:
910 if (is_shift) nimf_anthy_preedit_insert (anthy, "を");
911 else nimf_anthy_preedit_insert (anthy, "わ");
912 break;
913 case 20:
914 if (is_shift) nimf_anthy_preedit_insert (anthy, "ー");
915 else nimf_anthy_preedit_insert (anthy, "ほ");
916 break;
917 case 21: nimf_anthy_preedit_insert (anthy, "へ"); break;
918 case 24: nimf_anthy_preedit_insert (anthy, "た"); break;
919 case 25: nimf_anthy_preedit_insert (anthy, "て"); break;
920 case 26:
921 if (is_shift) nimf_anthy_preedit_insert (anthy, "ぃ");
922 else nimf_anthy_preedit_insert (anthy, "い");
923 break;
924 case 27: nimf_anthy_preedit_insert (anthy, "す"); break;
925 case 28: nimf_anthy_preedit_insert (anthy, "か"); break;
926 case 29: nimf_anthy_preedit_insert (anthy, "ん"); break;
927 case 30: nimf_anthy_preedit_insert (anthy, "な"); break;
928 case 31: nimf_anthy_preedit_insert (anthy, "に"); break;
929 case 32: nimf_anthy_preedit_insert (anthy, "ら"); break;
930 case 33: nimf_anthy_preedit_insert (anthy, "せ"); break;
931 case 34:
932 if (is_shift)
933 {
934 nimf_anthy_preedit_insert (anthy, "「");
935 }
936 else
937 {
938 if (anthy->preedit->len == 0)
939 break;
940
941 if (nimf_anthy_preedit_offset_has_suffix (anthy, "か"))
942 g_string_overwrite (anthy->preedit,
943 anthy->preedit_offset - strlen ("か"), "が");
944 else if (nimf_anthy_preedit_offset_has_suffix (anthy, "き"))
945 g_string_overwrite (anthy->preedit,
946 anthy->preedit_offset - strlen ("き"), "ぎ");
947 else if (nimf_anthy_preedit_offset_has_suffix (anthy, "く"))
948 g_string_overwrite (anthy->preedit,
949 anthy->preedit_offset - strlen ("く"), "ぐ");
950 else if (nimf_anthy_preedit_offset_has_suffix (anthy, "け"))
951 g_string_overwrite (anthy->preedit,
952 anthy->preedit_offset - strlen ("け"), "げ");
953 else if (nimf_anthy_preedit_offset_has_suffix (anthy, "こ"))
954 g_string_overwrite (anthy->preedit,
955 anthy->preedit_offset - strlen ("こ"), "ご");
956 else if (nimf_anthy_preedit_offset_has_suffix (anthy, "さ"))
957 g_string_overwrite (anthy->preedit,
958 anthy->preedit_offset - strlen ("さ"), "ざ");
959 else if (nimf_anthy_preedit_offset_has_suffix (anthy, "し"))
960 g_string_overwrite (anthy->preedit,
961 anthy->preedit_offset - strlen ("し"), "じ");
962 else if (nimf_anthy_preedit_offset_has_suffix (anthy, "す"))
963 g_string_overwrite (anthy->preedit,
964 anthy->preedit_offset - strlen ("す"), "ず");
965 else if (nimf_anthy_preedit_offset_has_suffix (anthy, "せ"))
966 g_string_overwrite (anthy->preedit,
967 anthy->preedit_offset - strlen ("せ"), "ぜ");
968 else if (nimf_anthy_preedit_offset_has_suffix (anthy, "そ"))
969 g_string_overwrite (anthy->preedit,
970 anthy->preedit_offset - strlen ("そ"), "ぞ");
971 else if (nimf_anthy_preedit_offset_has_suffix (anthy, "た"))
972 g_string_overwrite (anthy->preedit,
973 anthy->preedit_offset - strlen ("た"), "だ");
974 else if (nimf_anthy_preedit_offset_has_suffix (anthy, "ち"))
975 g_string_overwrite (anthy->preedit,
976 anthy->preedit_offset - strlen ("ち"), "ぢ");
977 else if (nimf_anthy_preedit_offset_has_suffix (anthy, "つ"))
978 g_string_overwrite (anthy->preedit,
979 anthy->preedit_offset - strlen ("つ"), "づ");
980 else if (nimf_anthy_preedit_offset_has_suffix (anthy, "て"))
981 g_string_overwrite (anthy->preedit,
982 anthy->preedit_offset - strlen ("て"), "で");
983 else if (nimf_anthy_preedit_offset_has_suffix (anthy, "と"))
984 g_string_overwrite (anthy->preedit,
985 anthy->preedit_offset - strlen ("と"), "ど");
986 else if (nimf_anthy_preedit_offset_has_suffix (anthy, "は"))
987 g_string_overwrite (anthy->preedit,
988 anthy->preedit_offset - strlen ("は"), "ば");
989 else if (nimf_anthy_preedit_offset_has_suffix (anthy, "ひ"))
990 g_string_overwrite (anthy->preedit,
991 anthy->preedit_offset - strlen ("ひ"), "び");
992 else if (nimf_anthy_preedit_offset_has_suffix (anthy, "ふ"))
993 g_string_overwrite (anthy->preedit,
994 anthy->preedit_offset - strlen ("ふ"), "ぶ");
995 else if (nimf_anthy_preedit_offset_has_suffix (anthy, "へ"))
996 g_string_overwrite (anthy->preedit,
997 anthy->preedit_offset - strlen ("へ"), "べ");
998 else if (nimf_anthy_preedit_offset_has_suffix (anthy, "ほ"))
999 g_string_overwrite (anthy->preedit,
1000 anthy->preedit_offset - strlen ("ほ"), "ぼ");
1001 }
1002 break;
1003 case 35:
1004 if (is_shift)
1005 {
1006 nimf_anthy_preedit_insert (anthy, "」");
1007 }
1008 else
1009 {
1010 if (anthy->preedit->len == 0)
1011 break;
1012
1013 if (nimf_anthy_preedit_offset_has_suffix (anthy, "は"))
1014 g_string_overwrite (anthy->preedit,
1015 anthy->preedit_offset - strlen ("は"), "ぱ");
1016 else if (nimf_anthy_preedit_offset_has_suffix (anthy, "ひ"))
1017 g_string_overwrite (anthy->preedit,
1018 anthy->preedit_offset - strlen ("ひ"), "ぴ");
1019 else if (nimf_anthy_preedit_offset_has_suffix (anthy, "ふ"))
1020 g_string_overwrite (anthy->preedit,
1021 anthy->preedit_offset - strlen ("ふ"), "ぷ");
1022 else if (nimf_anthy_preedit_offset_has_suffix (anthy, "へ"))
1023 g_string_overwrite (anthy->preedit,
1024 anthy->preedit_offset - strlen ("へ"), "ぺ");
1025 else if (nimf_anthy_preedit_offset_has_suffix (anthy, "ほ"))
1026 g_string_overwrite (anthy->preedit,
1027 anthy->preedit_offset - strlen ("ほ"), "ぽ");
1028 }
1029 break;
1030 case 51: nimf_anthy_preedit_insert (anthy, "む"); break;
1031 case 38: nimf_anthy_preedit_insert (anthy, "ち"); break;
1032 case 39: nimf_anthy_preedit_insert (anthy, "と"); break;
1033 case 40: nimf_anthy_preedit_insert (anthy, "し"); break;
1034 case 41: nimf_anthy_preedit_insert (anthy, "は"); break;
1035 case 42: nimf_anthy_preedit_insert (anthy, "き"); break;
1036 case 43: nimf_anthy_preedit_insert (anthy, "く"); break;
1037 case 44: nimf_anthy_preedit_insert (anthy, "ま"); break;
1038 case 45: nimf_anthy_preedit_insert (anthy, "の"); break;
1039 case 46: nimf_anthy_preedit_insert (anthy, "り"); break;
1040 case 47: nimf_anthy_preedit_insert (anthy, "れ"); break;
1041 case 48: nimf_anthy_preedit_insert (anthy, "け"); break;
1042 case 52:
1043 if (is_shift) nimf_anthy_preedit_insert (anthy, "っ");
1044 else nimf_anthy_preedit_insert (anthy, "つ");
1045 break;
1046 case 53: nimf_anthy_preedit_insert (anthy, "さ"); break;
1047 case 54: nimf_anthy_preedit_insert (anthy, "そ"); break;
1048 case 55: nimf_anthy_preedit_insert (anthy, "ひ"); break;
1049 case 56: nimf_anthy_preedit_insert (anthy, "こ"); break;
1050 case 57: nimf_anthy_preedit_insert (anthy, "み"); break;
1051 case 58: nimf_anthy_preedit_insert (anthy, "も"); break;
1052 case 59:
1053 if (is_shift) nimf_anthy_preedit_insert (anthy, "、");
1054 else nimf_anthy_preedit_insert (anthy, "ね");
1055 break;
1056 case 60:
1057 if (is_shift) nimf_anthy_preedit_insert (anthy, "。");
1058 else nimf_anthy_preedit_insert (anthy, "る");
1059 break;
1060 case 61:
1061 if (is_shift) nimf_anthy_preedit_insert (anthy, "・");
1062 else nimf_anthy_preedit_insert (anthy, "め");
1063 break;
1064 default:
1065 return FALSE;
1066 }
1067
1068 return TRUE;
1069 }
1070
1071 static gchar *
nimf_anthy_convert_to(NimfAnthy * anthy,int candidate_type)1072 nimf_anthy_convert_to (NimfAnthy *anthy, int candidate_type)
1073 {
1074 g_debug (G_STRLOC ": %s", G_STRFUNC);
1075
1076 struct anthy_conv_stat conv_stat;
1077 GString *string;
1078 gint i;
1079
1080 anthy_set_string (anthy->context, anthy->preedit->str);
1081 anthy_get_stat (anthy->context, &conv_stat);
1082 string = g_string_new ("");
1083 memset (anthy->buffer, 0, NIMF_ANTHY_BUFFER_SIZE);
1084
1085 for (i = 0; i < conv_stat.nr_segment; i++)
1086 {
1087 anthy_get_segment (anthy->context, i, candidate_type,
1088 anthy->buffer, NIMF_ANTHY_BUFFER_SIZE);
1089 g_string_append (string, anthy->buffer);
1090 }
1091
1092 anthy->preedit_offset = anthy->preedit->len;
1093 anthy->preedit_dx = 0;
1094
1095 return g_string_free (string, FALSE);
1096 }
1097
1098 static void
nimf_anthy_replace_last_n(NimfAnthy * anthy)1099 nimf_anthy_replace_last_n (NimfAnthy *anthy)
1100 {
1101 g_debug (G_STRLOC ": %s", G_STRFUNC);
1102
1103 if (g_str_has_suffix (anthy->preedit->str, "n"))
1104 {
1105 g_string_erase (anthy->preedit, anthy->preedit->len - 1, 1);
1106 g_string_append (anthy->preedit, "ん");
1107 }
1108 }
1109
1110 static gboolean
nimf_anthy_filter_event(NimfEngine * engine,NimfServiceIC * target,NimfEvent * event)1111 nimf_anthy_filter_event (NimfEngine *engine,
1112 NimfServiceIC *target,
1113 NimfEvent *event)
1114 {
1115 g_debug (G_STRLOC ": %s", G_STRFUNC);
1116
1117 NimfAnthy *anthy = NIMF_ANTHY (engine);
1118 gboolean retval;
1119
1120 if (event->key.type == NIMF_EVENT_KEY_RELEASE)
1121 return FALSE;
1122
1123 if (anthy->method_changed)
1124 {
1125 nimf_anthy_reset (engine, target);
1126 anthy->method_changed = FALSE;
1127 }
1128
1129 if (nimf_candidatable_is_visible (anthy->candidatable))
1130 {
1131 switch (event->key.keyval)
1132 {
1133 case NIMF_KEY_Return:
1134 case NIMF_KEY_KP_Enter:
1135 nimf_candidatable_hide (anthy->candidatable);
1136 nimf_anthy_emit_commit (engine, target);
1137 return TRUE;
1138 case NIMF_KEY_Up:
1139 case NIMF_KEY_KP_Up:
1140 {
1141 nimf_candidatable_select_previous_item (anthy->candidatable);
1142 gint index = nimf_candidatable_get_selected_index (anthy->candidatable);
1143
1144 if (G_LIKELY (index >= 0))
1145 on_candidate_clicked (engine, target, NULL, index);
1146 }
1147 return TRUE;
1148 case NIMF_KEY_Down:
1149 case NIMF_KEY_KP_Down:
1150 case NIMF_KEY_space:
1151 {
1152 nimf_candidatable_select_next_item (anthy->candidatable);
1153 gint index = nimf_candidatable_get_selected_index (anthy->candidatable);
1154
1155 if (G_LIKELY (index >= 0))
1156 on_candidate_clicked (engine, target, NULL, index);
1157 }
1158 return TRUE;
1159 case NIMF_KEY_Left:
1160 case NIMF_KEY_KP_Left:
1161 if (anthy->current_segment > 0)
1162 {
1163 anthy->current_segment--;
1164 }
1165 else
1166 {
1167 struct anthy_conv_stat conv_stat;
1168
1169 anthy_get_stat (anthy->context, &conv_stat);
1170 anthy->current_segment = conv_stat.nr_segment - 1;
1171 }
1172
1173 nimf_anthy_convert_preedit_text (engine, target);
1174 nimf_anthy_update_candidate (engine, target);
1175 return TRUE;
1176 case NIMF_KEY_Right:
1177 case NIMF_KEY_KP_Right:
1178 {
1179 struct anthy_conv_stat conv_stat;
1180
1181 anthy_get_stat (anthy->context, &conv_stat);
1182
1183 if (anthy->current_segment < conv_stat.nr_segment - 1)
1184 anthy->current_segment++;
1185 else
1186 anthy->current_segment = 0;
1187 }
1188
1189 nimf_anthy_convert_preedit_text (engine, target);
1190 nimf_anthy_update_candidate (engine, target);
1191 return TRUE;
1192 case NIMF_KEY_Page_Up:
1193 case NIMF_KEY_KP_Page_Up:
1194 nimf_anthy_page_up (engine, target);
1195 return TRUE;
1196 case NIMF_KEY_Page_Down:
1197 case NIMF_KEY_KP_Page_Down:
1198 nimf_anthy_page_down (engine, target);
1199 return TRUE;
1200 case NIMF_KEY_Home:
1201 nimf_anthy_page_home (engine, target);
1202 return TRUE;
1203 case NIMF_KEY_End:
1204 nimf_anthy_page_end (engine, target);
1205 return TRUE;
1206 case NIMF_KEY_0:
1207 case NIMF_KEY_1:
1208 case NIMF_KEY_2:
1209 case NIMF_KEY_3:
1210 case NIMF_KEY_4:
1211 case NIMF_KEY_5:
1212 case NIMF_KEY_6:
1213 case NIMF_KEY_7:
1214 case NIMF_KEY_8:
1215 case NIMF_KEY_9:
1216 case NIMF_KEY_KP_0:
1217 case NIMF_KEY_KP_1:
1218 case NIMF_KEY_KP_2:
1219 case NIMF_KEY_KP_3:
1220 case NIMF_KEY_KP_4:
1221 case NIMF_KEY_KP_5:
1222 case NIMF_KEY_KP_6:
1223 case NIMF_KEY_KP_7:
1224 case NIMF_KEY_KP_8:
1225 case NIMF_KEY_KP_9:
1226 {
1227 if (g_strcmp0 (anthy->method,"romaji"))
1228 break;
1229
1230 if (anthy->current_page < 1)
1231 break;
1232
1233 struct anthy_segment_stat segment_stat;
1234 gint i, n;
1235
1236 if (event->key.keyval >= NIMF_KEY_0 &&
1237 event->key.keyval <= NIMF_KEY_9)
1238 n = (event->key.keyval - NIMF_KEY_0 + 9) % 10;
1239 else if (event->key.keyval >= NIMF_KEY_KP_0 &&
1240 event->key.keyval <= NIMF_KEY_KP_9)
1241 n = (event->key.keyval - NIMF_KEY_KP_0 + 9) % 10;
1242 else
1243 break;
1244
1245 i = (anthy->current_page - 1) * 10 + n;
1246
1247 anthy_get_segment_stat (anthy->context, anthy->current_segment, &segment_stat);
1248
1249 if (i < MIN (anthy->current_page * 10, segment_stat.nr_candidate))
1250 {
1251 on_candidate_clicked (engine, target, NULL, n);
1252 nimf_anthy_update_candidate (engine, target);
1253 }
1254 }
1255 return TRUE;
1256 case NIMF_KEY_Escape:
1257 nimf_candidatable_hide (anthy->candidatable);
1258 nimf_anthy_update_preedit_text (engine, target);
1259 return TRUE;
1260 default:
1261 nimf_candidatable_hide (anthy->candidatable);
1262 nimf_anthy_update_preedit_text (engine, target);
1263 break;
1264 }
1265 }
1266
1267 if (anthy->preedit->len > 0)
1268 {
1269 if (G_UNLIKELY (nimf_event_matches (event, (const NimfKey **) anthy->hiragana_keys)))
1270 {
1271 gchar *converted;
1272
1273 converted = nimf_anthy_convert_to (anthy, NTH_HIRAGANA_CANDIDATE);
1274
1275 g_string_assign (anthy->preedit, converted);
1276 nimf_anthy_update_preedit_state (engine, target, anthy->preedit->str,
1277 g_utf8_strlen (anthy->preedit->str, -1));
1278 g_free (converted);
1279
1280 return TRUE;
1281 }
1282 else if (G_UNLIKELY (nimf_event_matches (event, (const NimfKey **) anthy->katakana_keys)))
1283 {
1284 gchar *converted;
1285
1286 converted = nimf_anthy_convert_to (anthy, NTH_KATAKANA_CANDIDATE);
1287
1288 g_string_assign (anthy->preedit, converted);
1289 nimf_anthy_update_preedit_state (engine, target, anthy->preedit->str,
1290 g_utf8_strlen (anthy->preedit->str, -1));
1291 g_free (converted);
1292
1293 return TRUE;
1294 }
1295 }
1296
1297 if ((event->key.state & NIMF_MODIFIER_MASK) == NIMF_CONTROL_MASK ||
1298 (event->key.state & NIMF_MODIFIER_MASK) == (NIMF_CONTROL_MASK | NIMF_MOD2_MASK))
1299 return FALSE;
1300
1301 if (event->key.keyval == NIMF_KEY_space)
1302 {
1303 if (anthy->preedit->len == 0)
1304 {
1305 nimf_candidatable_hide (anthy->candidatable);
1306 return FALSE;
1307 }
1308
1309 anthy->current_segment = 0;
1310 struct anthy_conv_stat conv_stat;
1311
1312 if (anthy->n_input_mode == COMMON)
1313 nimf_anthy_replace_last_n (anthy);
1314
1315 anthy_set_string (anthy->context, anthy->preedit->str);
1316 anthy_get_stat (anthy->context, &conv_stat);
1317 anthy->current_segment = conv_stat.nr_segment - 1;
1318 anthy->selections = g_realloc_n (anthy->selections, conv_stat.nr_segment,
1319 sizeof (gint));
1320 memset (anthy->selections, 0, conv_stat.nr_segment * sizeof (gint));
1321
1322 nimf_anthy_convert_preedit_text (engine, target);
1323
1324 if (!nimf_candidatable_is_visible (anthy->candidatable))
1325 nimf_candidatable_show (anthy->candidatable, target,
1326 !nimf_service_ic_get_use_preedit (target));
1327
1328 anthy->current_segment = 0;
1329 nimf_anthy_convert_preedit_text (engine, target);
1330 nimf_anthy_update_candidate (engine, target);
1331
1332 return TRUE;
1333 }
1334
1335 if (event->key.keyval == NIMF_KEY_Return)
1336 {
1337 if (anthy->preedit->len > 0)
1338 {
1339 if (anthy->n_input_mode == COMMON)
1340 nimf_anthy_replace_last_n (anthy);
1341
1342 nimf_anthy_reset (engine, target);
1343 retval = TRUE;
1344 }
1345
1346 retval = FALSE;
1347 }
1348 else if (event->key.keyval == NIMF_KEY_BackSpace)
1349 {
1350 if (anthy->preedit_offset + anthy->preedit_dx > 0)
1351 {
1352 if (anthy->preedit_dx > 0)
1353 {
1354 g_string_erase (anthy->preedit, anthy->preedit_offset + anthy->preedit_dx - 1, 1);
1355 anthy->preedit_dx--;
1356 }
1357 else if (anthy->preedit_offset > 0)
1358 {
1359 const gchar *prev;
1360
1361 prev = g_utf8_prev_char (anthy->preedit->str + anthy->preedit_offset);
1362 g_string_erase (anthy->preedit, prev - anthy->preedit->str,
1363 anthy->preedit->str + anthy->preedit_offset - prev);
1364 anthy->preedit_offset = prev - anthy->preedit->str;
1365 }
1366
1367 retval = TRUE;
1368 }
1369 else
1370 {
1371 retval = FALSE;
1372 }
1373 }
1374 else if (event->key.keyval == NIMF_KEY_Delete ||
1375 event->key.keyval == NIMF_KEY_KP_Delete)
1376 {
1377 if (anthy->preedit_offset + anthy->preedit_dx < anthy->preedit->len)
1378 {
1379 const gchar *next;
1380 gint len;
1381
1382 next = g_utf8_next_char (anthy->preedit->str + anthy->preedit_offset + anthy->preedit_dx);
1383 len = next - (anthy->preedit->str + anthy->preedit_offset + anthy->preedit_dx);
1384
1385 g_string_erase (anthy->preedit, anthy->preedit_offset + anthy->preedit_dx, len);
1386
1387 retval = TRUE;
1388 }
1389 else
1390 {
1391 retval = FALSE;
1392 }
1393 }
1394 else if (event->key.keyval == NIMF_KEY_Left ||
1395 event->key.keyval == NIMF_KEY_KP_Left)
1396 {
1397 if (anthy->preedit_dx > 0)
1398 {
1399 anthy->preedit_offset += anthy->preedit_dx - 1;
1400 anthy->preedit_dx = 0;
1401
1402 retval = TRUE;
1403 }
1404 else if (anthy->preedit_offset > 0)
1405 {
1406 const gchar *prev;
1407
1408 prev = g_utf8_prev_char (anthy->preedit->str + anthy->preedit_offset);
1409 anthy->preedit_offset = prev - anthy->preedit->str;
1410
1411 retval = TRUE;
1412 }
1413 else
1414 {
1415 retval = FALSE;
1416 }
1417 }
1418 else if (event->key.keyval == NIMF_KEY_Right ||
1419 event->key.keyval == NIMF_KEY_KP_Right)
1420 {
1421 const gchar *next;
1422
1423 if (anthy->preedit_offset + anthy->preedit_dx < anthy->preedit->len)
1424 {
1425 next = g_utf8_next_char (anthy->preedit->str + anthy->preedit_offset + anthy->preedit_dx);
1426 anthy->preedit_offset = next - anthy->preedit->str;
1427 anthy->preedit_dx = 0;
1428
1429 retval = TRUE;
1430 }
1431 else
1432 {
1433 retval = FALSE;
1434 }
1435 }
1436 else if (event->key.keyval > 127)
1437 retval = FALSE;
1438 else if (g_strcmp0 (anthy->method, "romaji") == 0)
1439 retval = nimf_anthy_filter_event_romaji (engine, target, event);
1440 else
1441 retval = nimf_anthy_filter_event_pc104 (engine, target, event);
1442
1443 if (retval == FALSE)
1444 return FALSE;
1445
1446 nimf_anthy_update_preedit_text (engine, target);
1447
1448 return TRUE;
1449 }
1450
1451 static void
on_changed_keys(GSettings * settings,gchar * key,NimfAnthy * anthy)1452 on_changed_keys (GSettings *settings,
1453 gchar *key,
1454 NimfAnthy *anthy)
1455 {
1456 g_debug (G_STRLOC ": %s", G_STRFUNC);
1457
1458 gchar **keys = g_settings_get_strv (settings, key);
1459
1460 if (g_strcmp0 (key, "hiragana-keys") == 0)
1461 {
1462 nimf_key_freev (anthy->hiragana_keys);
1463 anthy->hiragana_keys = nimf_key_newv ((const gchar **) keys);
1464 }
1465 else if (g_strcmp0 (key, "katakana-keys") == 0)
1466 {
1467 nimf_key_freev (anthy->katakana_keys);
1468 anthy->katakana_keys = nimf_key_newv ((const gchar **) keys);
1469 }
1470
1471 g_strfreev (keys);
1472 }
1473
1474 static void
on_changed_method(GSettings * settings,gchar * key,NimfAnthy * anthy)1475 on_changed_method (GSettings *settings,
1476 gchar *key,
1477 NimfAnthy *anthy)
1478 {
1479 g_debug (G_STRLOC ": %s", G_STRFUNC);
1480
1481 g_free (anthy->method);
1482 anthy->method = g_settings_get_string (settings, key);
1483 anthy->method_changed = TRUE;
1484 }
1485
1486 static gint
nimf_anthy_get_n_input_mode(NimfAnthy * anthy)1487 nimf_anthy_get_n_input_mode (NimfAnthy *anthy)
1488 {
1489 g_debug (G_STRLOC ": %s", G_STRFUNC);
1490
1491 gchar *mode;
1492 gint retval;
1493
1494 mode = g_settings_get_string (anthy->settings, "get-n-input-mode-list");
1495
1496 if (g_strcmp0 (mode, "common") == 0)
1497 retval = COMMON;
1498 else
1499 retval = EXPLICIT;
1500
1501 g_free (mode);
1502
1503 return retval;
1504 }
1505
1506 static void
on_changed_n_input_mode(GSettings * settings,gchar * key,NimfAnthy * anthy)1507 on_changed_n_input_mode (GSettings *settings,
1508 gchar *key,
1509 NimfAnthy *anthy)
1510 {
1511 g_debug (G_STRLOC ": %s", G_STRFUNC);
1512
1513 gchar *mode;
1514
1515 mode = g_settings_get_string (settings, key);
1516
1517 if (g_strcmp0 (mode, "common") == 0)
1518 anthy->n_input_mode = COMMON;
1519 else
1520 anthy->n_input_mode = EXPLICIT;
1521
1522 g_free (mode);
1523 }
1524
1525 static void
nimf_anthy_init(NimfAnthy * anthy)1526 nimf_anthy_init (NimfAnthy *anthy)
1527 {
1528 g_debug (G_STRLOC ": %s", G_STRFUNC);
1529
1530 gchar **hiragana_keys;
1531 gchar **katakana_keys;
1532
1533 anthy->id = g_strdup ("nimf-anthy");
1534 anthy->preedit = g_string_new ("");
1535 anthy->preedit_attrs = g_malloc0_n (3, sizeof (NimfPreeditAttr *));
1536 anthy->preedit_attrs[0] = nimf_preedit_attr_new (NIMF_PREEDIT_ATTR_UNDERLINE, 0, 0);
1537 anthy->preedit_attrs[1] = nimf_preedit_attr_new (NIMF_PREEDIT_ATTR_HIGHLIGHT, 0, 0);
1538 anthy->preedit_attrs[2] = NULL;
1539 anthy->selections = g_malloc0_n (16, sizeof (gint));
1540
1541 if (nimf_anthy_romaji)
1542 {
1543 g_hash_table_ref (nimf_anthy_romaji);
1544 }
1545 else
1546 {
1547 nimf_anthy_romaji = g_hash_table_new (g_str_hash, g_str_equal);
1548
1549 gint i;
1550 for (i = 0; i < G_N_ELEMENTS (romaji_map); i++)
1551 g_hash_table_insert (nimf_anthy_romaji, romaji_map[i].key,
1552 romaji_map[i].value);
1553 }
1554
1555 if (anthy_init () < 0)
1556 g_error (G_STRLOC ": %s: anthy is not initialized", G_STRFUNC);
1557
1558 /* FIXME */
1559 /* anthy_set_personality () */
1560 anthy->context = anthy_create_context ();
1561 nimf_anthy_ref_count++;
1562 anthy_context_set_encoding (anthy->context, ANTHY_UTF8_ENCODING);
1563
1564 anthy->settings = g_settings_new ("org.nimf.engines.nimf-anthy");
1565 anthy->method = g_settings_get_string (anthy->settings, "get-method-infos");
1566 anthy->n_input_mode = nimf_anthy_get_n_input_mode (anthy);
1567 hiragana_keys = g_settings_get_strv (anthy->settings, "hiragana-keys");
1568 katakana_keys = g_settings_get_strv (anthy->settings, "katakana-keys");
1569 anthy->hiragana_keys = nimf_key_newv ((const gchar **) hiragana_keys);
1570 anthy->katakana_keys = nimf_key_newv ((const gchar **) katakana_keys);
1571
1572 g_strfreev (hiragana_keys);
1573 g_strfreev (katakana_keys);
1574
1575 g_signal_connect (anthy->settings, "changed::hiragana-keys",
1576 G_CALLBACK (on_changed_keys), anthy);
1577 g_signal_connect (anthy->settings, "changed::katakana-keys",
1578 G_CALLBACK (on_changed_keys), anthy);
1579 g_signal_connect (anthy->settings, "changed::get-method-infos",
1580 G_CALLBACK (on_changed_method), anthy);
1581 g_signal_connect (anthy->settings, "changed::get-n-input-mode-list",
1582 G_CALLBACK (on_changed_n_input_mode), anthy);
1583 }
1584
1585 static void
nimf_anthy_finalize(GObject * object)1586 nimf_anthy_finalize (GObject *object)
1587 {
1588 g_debug (G_STRLOC ": %s", G_STRFUNC);
1589
1590 NimfAnthy *anthy = NIMF_ANTHY (object);
1591
1592 nimf_preedit_attr_freev (anthy->preedit_attrs);
1593 g_free (anthy->id);
1594 g_free (anthy->selections);
1595 g_hash_table_unref (nimf_anthy_romaji);
1596 g_string_free (anthy->preedit, TRUE);
1597 nimf_key_freev (anthy->hiragana_keys);
1598 nimf_key_freev (anthy->katakana_keys);
1599 g_free (anthy->method);
1600 g_object_unref (anthy->settings);
1601
1602 if (--nimf_anthy_ref_count == 0)
1603 {
1604 nimf_anthy_romaji = NULL;
1605 anthy_release_context (anthy->context);
1606 anthy_quit ();
1607 }
1608
1609 G_OBJECT_CLASS (nimf_anthy_parent_class)->finalize (object);
1610 }
1611
1612 const gchar *
nimf_anthy_get_id(NimfEngine * engine)1613 nimf_anthy_get_id (NimfEngine *engine)
1614 {
1615 g_debug (G_STRLOC ": %s", G_STRFUNC);
1616
1617 g_return_val_if_fail (NIMF_IS_ENGINE (engine), NULL);
1618
1619 return NIMF_ANTHY (engine)->id;
1620 }
1621
1622 const gchar *
nimf_anthy_get_icon_name(NimfEngine * engine)1623 nimf_anthy_get_icon_name (NimfEngine *engine)
1624 {
1625 g_debug (G_STRLOC ": %s", G_STRFUNC);
1626
1627 g_return_val_if_fail (NIMF_IS_ENGINE (engine), NULL);
1628
1629 return NIMF_ANTHY (engine)->id;
1630 }
1631
1632 void
nimf_anthy_set_method(NimfEngine * engine,const gchar * method_id)1633 nimf_anthy_set_method (NimfEngine *engine, const gchar *method_id)
1634 {
1635 g_debug (G_STRLOC ": %s", G_STRFUNC);
1636
1637 g_settings_set_string (NIMF_ANTHY (engine)->settings,
1638 "get-method-infos", method_id);
1639 }
1640
1641 static void
nimf_anthy_constructed(GObject * object)1642 nimf_anthy_constructed (GObject *object)
1643 {
1644 g_debug (G_STRLOC ": %s", G_STRFUNC);
1645
1646 NimfAnthy *anthy = NIMF_ANTHY (object);
1647
1648 anthy->candidatable = nimf_engine_get_candidatable (NIMF_ENGINE (anthy));
1649 }
1650
1651 static void
nimf_anthy_class_init(NimfAnthyClass * class)1652 nimf_anthy_class_init (NimfAnthyClass *class)
1653 {
1654 g_debug (G_STRLOC ": %s", G_STRFUNC);
1655
1656 GObjectClass *object_class = G_OBJECT_CLASS (class);
1657 NimfEngineClass *engine_class = NIMF_ENGINE_CLASS (class);
1658
1659 engine_class->filter_event = nimf_anthy_filter_event;
1660 engine_class->reset = nimf_anthy_reset;
1661 engine_class->focus_in = nimf_anthy_focus_in;
1662 engine_class->focus_out = nimf_anthy_focus_out;
1663
1664 engine_class->candidate_page_up = nimf_anthy_page_up;
1665 engine_class->candidate_page_down = nimf_anthy_page_down;
1666 engine_class->candidate_clicked = on_candidate_clicked;
1667 engine_class->candidate_scrolled = on_candidate_scrolled;
1668
1669 engine_class->get_id = nimf_anthy_get_id;
1670 engine_class->get_icon_name = nimf_anthy_get_icon_name;
1671 engine_class->set_method = nimf_anthy_set_method;
1672
1673 object_class->constructed = nimf_anthy_constructed;
1674 object_class->finalize = nimf_anthy_finalize;
1675 }
1676
1677 static void
nimf_anthy_class_finalize(NimfAnthyClass * class)1678 nimf_anthy_class_finalize (NimfAnthyClass *class)
1679 {
1680 g_debug (G_STRLOC ": %s", G_STRFUNC);
1681 }
1682
1683 typedef struct {
1684 const gchar *id;
1685 const gchar *name;
1686 } Method;
1687
1688 static const Method methods[] = {
1689 {"romaji", N_("Romaji")},
1690 {"pc104", N_("English Keyboard (pc104)")}
1691 };
1692
1693 NimfMethodInfo **
nimf_anthy_get_method_infos()1694 nimf_anthy_get_method_infos ()
1695 {
1696 g_debug (G_STRLOC ": %s", G_STRFUNC);
1697
1698 NimfMethodInfo **infos;
1699 gint n_methods = G_N_ELEMENTS (methods);
1700 gint i;
1701
1702 infos = g_malloc (sizeof (NimfMethodInfo *) * n_methods + 1);
1703
1704 for (i = 0; i < n_methods; i++)
1705 {
1706 infos[i] = nimf_method_info_new ();
1707 infos[i]->method_id = g_strdup (methods[i].id);
1708 infos[i]->label = g_strdup (gettext (methods[i].name));
1709 infos[i]->group = NULL;
1710 }
1711
1712 infos[n_methods] = NULL;
1713
1714 return infos;
1715 }
1716
1717 static const Method modes[] = {
1718 {"common", N_("Common practice")},
1719 {"explicit", N_("Explicitly type nn")}
1720 };
1721
1722 NimfMethodInfo **
nimf_anthy_get_n_input_mode_list()1723 nimf_anthy_get_n_input_mode_list ()
1724 {
1725 g_debug (G_STRLOC ": %s", G_STRFUNC);
1726
1727 NimfMethodInfo **infos;
1728 gint n_methods = G_N_ELEMENTS (modes);
1729 gint i;
1730
1731 infos = g_malloc (sizeof (NimfMethodInfo *) * n_methods + 1);
1732
1733 for (i = 0; i < n_methods; i++)
1734 {
1735 infos[i] = nimf_method_info_new ();
1736 infos[i]->method_id = g_strdup (modes[i].id);
1737 infos[i]->label = g_strdup (gettext (modes[i].name));
1738 infos[i]->group = NULL;
1739 }
1740
1741 infos[n_methods] = NULL;
1742
1743 return infos;
1744 }
1745
1746 void
module_register_type(GTypeModule * type_module)1747 module_register_type (GTypeModule *type_module)
1748 {
1749 g_debug (G_STRLOC ": %s", G_STRFUNC);
1750
1751 nimf_anthy_register_type (type_module);
1752 }
1753
1754 GType
module_get_type()1755 module_get_type ()
1756 {
1757 g_debug (G_STRLOC ": %s", G_STRFUNC);
1758
1759 return nimf_anthy_get_type ();
1760 }
1761