1 /* vim:set et sts=4: */
16 typedef struct _IBusHangulEngine IBusHangulEngine;
17 typedef struct _IBusHangulEngineClass IBusHangulEngineClass;
19 typedef struct _HanjaKeyList HanjaKeyList;
21 struct _IBusHangulEngine {
25 HangulInputContext *context;
29 HanjaList* hanja_list;
31 IBusLookupTable *table;
33 IBusProperty *prop_hanja_mode;
34 IBusPropList *prop_list;
37 struct _IBusHangulEngineClass {
38 IBusEngineClass parent;
46 struct _HanjaKeyList {
51 /* functions prototype */
52 static void ibus_hangul_engine_class_init
53 (IBusHangulEngineClass *klass);
54 static void ibus_hangul_engine_init (IBusHangulEngine *hangul);
56 ibus_hangul_engine_constructor
58 guint n_construct_params,
59 GObjectConstructParam *construct_params);
60 static void ibus_hangul_engine_destroy (IBusHangulEngine *hangul);
62 ibus_hangul_engine_process_key_event
67 static void ibus_hangul_engine_focus_in (IBusEngine *engine);
68 static void ibus_hangul_engine_focus_out (IBusEngine *engine);
69 static void ibus_hangul_engine_reset (IBusEngine *engine);
70 static void ibus_hangul_engine_enable (IBusEngine *engine);
71 static void ibus_hangul_engine_disable (IBusEngine *engine);
73 static void ibus_engine_set_cursor_location (IBusEngine *engine,
78 static void ibus_hangul_engine_set_capabilities
82 static void ibus_hangul_engine_page_up (IBusEngine *engine);
83 static void ibus_hangul_engine_page_down (IBusEngine *engine);
84 static void ibus_hangul_engine_cursor_up (IBusEngine *engine);
85 static void ibus_hangul_engine_cursor_down (IBusEngine *engine);
86 static void ibus_hangul_engine_property_activate
88 const gchar *prop_name,
91 static void ibus_hangul_engine_property_show
93 const gchar *prop_name);
94 static void ibus_hangul_engine_property_hide
96 const gchar *prop_name);
99 static void ibus_hangul_engine_candidate_clicked
105 static void ibus_hangul_engine_flush (IBusHangulEngine *hangul);
106 static void ibus_hangul_engine_update_preedit_text
107 (IBusHangulEngine *hangul);
109 static void ibus_hangul_engine_update_lookup_table
110 (IBusHangulEngine *hangul);
111 static void ibus_config_value_changed (IBusConfig *config,
112 const gchar *section,
117 static void lookup_table_set_visible (IBusLookupTable *table,
119 static gboolean lookup_table_is_visible
120 (IBusLookupTable *table);
122 static gboolean key_event_list_match (GArray *list,
126 static void hanja_key_list_init (HanjaKeyList *list);
127 static void hanja_key_list_fini (HanjaKeyList *list);
128 static void hanja_key_list_set_from_string(HanjaKeyList *list,
130 static void hanja_key_list_append (HanjaKeyList *list,
133 static gboolean hanja_key_list_match (HanjaKeyList *list,
136 static gboolean hanja_key_list_has_modifier (HanjaKeyList *list,
139 static IBusEngineClass *parent_class = NULL;
140 static HanjaTable *hanja_table = NULL;
141 static HanjaTable *symbol_table = NULL;
142 static IBusConfig *config = NULL;
143 static GString *hangul_keyboard = NULL;
144 static HanjaKeyList hanja_keys;
145 static int lookup_table_orientation = 0;
148 ibus_hangul_engine_get_type (void)
150 static GType type = 0;
152 static const GTypeInfo type_info = {
153 sizeof (IBusHangulEngineClass),
154 (GBaseInitFunc) NULL,
155 (GBaseFinalizeFunc) NULL,
156 (GClassInitFunc) ibus_hangul_engine_class_init,
159 sizeof (IBusHangulEngine),
161 (GInstanceInitFunc) ibus_hangul_engine_init,
165 type = g_type_register_static (IBUS_TYPE_ENGINE,
175 ibus_hangul_init (IBusBus *bus)
178 GValue value = { 0, };
180 hanja_table = hanja_table_load (NULL);
182 symbol_table = hanja_table_load (IBUSHANGUL_DATADIR "/data/symbol.txt");
184 config = ibus_bus_get_config (bus);
186 g_object_ref_sink (config);
188 hangul_keyboard = g_string_new_len ("2", 8);
189 res = ibus_config_get_value (config, "engine/Hangul",
190 "HangulKeyboard", &value);
192 const gchar* str = g_value_get_string (&value);
193 g_string_assign (hangul_keyboard, str);
194 g_value_unset(&value);
197 hanja_key_list_init(&hanja_keys);
199 res = ibus_config_get_value (config, "engine/Hangul",
200 "HanjaKeys", &value);
202 const gchar* str = g_value_get_string (&value);
203 hanja_key_list_set_from_string(&hanja_keys, str);
204 g_value_unset(&value);
206 hanja_key_list_append(&hanja_keys, IBUS_Hangul_Hanja, 0);
207 hanja_key_list_append(&hanja_keys, IBUS_F9, 0);
212 ibus_hangul_exit (void)
214 hanja_key_list_fini(&hanja_keys);
216 hanja_table_delete (hanja_table);
219 hanja_table_delete (symbol_table);
222 g_object_unref (config);
225 g_string_free (hangul_keyboard, TRUE);
226 hangul_keyboard = NULL;
230 ibus_hangul_engine_class_init (IBusHangulEngineClass *klass)
232 GObjectClass *object_class = G_OBJECT_CLASS (klass);
233 IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass);
234 IBusEngineClass *engine_class = IBUS_ENGINE_CLASS (klass);
236 parent_class = (IBusEngineClass *) g_type_class_peek_parent (klass);
238 object_class->constructor = ibus_hangul_engine_constructor;
239 ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_hangul_engine_destroy;
241 engine_class->process_key_event = ibus_hangul_engine_process_key_event;
243 engine_class->reset = ibus_hangul_engine_reset;
244 engine_class->enable = ibus_hangul_engine_enable;
245 engine_class->disable = ibus_hangul_engine_disable;
247 engine_class->focus_in = ibus_hangul_engine_focus_in;
248 engine_class->focus_out = ibus_hangul_engine_focus_out;
250 engine_class->page_up = ibus_hangul_engine_page_up;
251 engine_class->page_down = ibus_hangul_engine_page_down;
253 engine_class->cursor_up = ibus_hangul_engine_cursor_up;
254 engine_class->cursor_down = ibus_hangul_engine_cursor_down;
256 engine_class->property_activate = ibus_hangul_engine_property_activate;
258 engine_class->candidate_clicked = ibus_hangul_engine_candidate_clicked;
262 ibus_hangul_engine_init (IBusHangulEngine *hangul)
268 hangul->context = hangul_ic_new (hangul_keyboard->str);
269 hangul->preedit = ustring_new();
270 hangul->hanja_list = NULL;
271 hangul->hangul_mode = TRUE;
272 hangul->hanja_mode = FALSE;
274 hangul->prop_list = ibus_prop_list_new ();
275 g_object_ref_sink (hangul->prop_list);
277 label = ibus_text_new_from_string (_("Hanja lock"));
278 tooltip = ibus_text_new_from_string (_("Enable/Disable Hanja mode"));
279 prop = ibus_property_new ("hanja_mode",
284 TRUE, TRUE, PROP_STATE_UNCHECKED, NULL);
285 g_object_ref_sink (prop);
286 ibus_prop_list_append (hangul->prop_list, prop);
287 hangul->prop_hanja_mode = prop;
289 label = ibus_text_new_from_string (_("Setup"));
290 tooltip = ibus_text_new_from_string (_("Configure hangul engine"));
291 prop = ibus_property_new ("setup",
296 TRUE, TRUE, PROP_STATE_UNCHECKED, NULL);
297 ibus_prop_list_append (hangul->prop_list, prop);
299 hangul->table = ibus_lookup_table_new (9, 0, TRUE, FALSE);
300 g_object_ref_sink (hangul->table);
302 g_signal_connect (config, "value-changed",
303 G_CALLBACK(ibus_config_value_changed), hangul);
307 ibus_hangul_engine_constructor (GType type,
308 guint n_construct_params,
309 GObjectConstructParam *construct_params)
311 IBusHangulEngine *hangul;
313 hangul = (IBusHangulEngine *) G_OBJECT_CLASS (parent_class)->constructor (type,
317 return (GObject *)hangul;
322 ibus_hangul_engine_destroy (IBusHangulEngine *hangul)
324 if (hangul->prop_hanja_mode) {
325 g_object_unref (hangul->prop_hanja_mode);
326 hangul->prop_hanja_mode = NULL;
329 if (hangul->prop_list) {
330 g_object_unref (hangul->prop_list);
331 hangul->prop_list = NULL;
335 g_object_unref (hangul->table);
336 hangul->table = NULL;
339 if (hangul->context) {
340 hangul_ic_delete (hangul->context);
341 hangul->context = NULL;
344 IBUS_OBJECT_CLASS (parent_class)->destroy ((IBusObject *)hangul);
348 ibus_hangul_engine_update_preedit_text (IBusHangulEngine *hangul)
350 const ucschar *hic_preedit;
355 // ibus-hangul's preedit string is made up of ibus context's
356 // internal preedit string and libhangul's preedit string.
357 // libhangul only supports one syllable preedit string.
358 // In order to make longer preedit string, ibus-hangul maintains
359 // internal preedit string.
360 hic_preedit = hangul_ic_get_preedit_string (hangul->context);
362 preedit = ustring_dup (hangul->preedit);
363 preedit_len = ustring_length(preedit);
364 ustring_append_ucs4 (preedit, hic_preedit, -1);
366 if (ustring_length(preedit) > 0) {
367 IBusPreeditFocusMode preedit_option = IBUS_ENGINE_PREEDIT_COMMIT;
369 if (hangul->hanja_list != NULL)
370 preedit_option = IBUS_ENGINE_PREEDIT_CLEAR;
372 text = ibus_text_new_from_ucs4 ((gunichar*)preedit->data);
373 // ibus-hangul's internal preedit string
374 ibus_text_append_attribute (text, IBUS_ATTR_TYPE_UNDERLINE,
375 IBUS_ATTR_UNDERLINE_SINGLE, 0, preedit_len);
376 // Preedit string from libhangul context.
377 // This is currently composing syllable.
378 ibus_text_append_attribute (text, IBUS_ATTR_TYPE_FOREGROUND,
379 0x00ffffff, preedit_len, -1);
380 ibus_text_append_attribute (text, IBUS_ATTR_TYPE_BACKGROUND,
381 0x00000000, preedit_len, -1);
382 ibus_engine_update_preedit_text_with_mode ((IBusEngine *)hangul,
384 ibus_text_get_length (text),
388 text = ibus_text_new_from_static_string ("");
389 ibus_engine_update_preedit_text ((IBusEngine *)hangul, text, 0, FALSE);
392 ustring_delete(preedit);
396 ibus_hangul_engine_update_lookup_table_ui (IBusHangulEngine *hangul)
403 cursor_pos = ibus_lookup_table_get_cursor_pos (hangul->table);
404 comment = hanja_list_get_nth_comment (hangul->hanja_list, cursor_pos);
406 text = ibus_text_new_from_string (comment);
407 ibus_engine_update_auxiliary_text ((IBusEngine *)hangul, text, TRUE);
409 // update lookup table
410 ibus_engine_update_lookup_table ((IBusEngine *)hangul, hangul->table, TRUE);
414 ibus_hangul_engine_commit_current_candidate (IBusHangulEngine *hangul)
425 cursor_pos = ibus_lookup_table_get_cursor_pos (hangul->table);
426 key = hanja_list_get_nth_key (hangul->hanja_list, cursor_pos);
427 value = hanja_list_get_nth_value (hangul->hanja_list, cursor_pos);
429 key_len = g_utf8_strlen(key, -1);
430 preedit_len = ustring_length(hangul->preedit);
432 len = MIN(key_len, preedit_len);
433 ustring_erase (hangul->preedit, 0, len);
434 if (key_len > preedit_len)
435 hangul_ic_reset (hangul->context);
437 ibus_hangul_engine_update_preedit_text (hangul);
439 text = ibus_text_new_from_string (value);
440 ibus_engine_commit_text ((IBusEngine *)hangul, text);
444 ibus_hangul_engine_update_hanja_list (IBusHangulEngine *hangul)
447 const ucschar* hic_preedit;
450 if (hangul->hanja_list != NULL) {
451 hanja_list_delete (hangul->hanja_list);
452 hangul->hanja_list = NULL;
455 hic_preedit = hangul_ic_get_preedit_string (hangul->context);
457 preedit = ustring_dup (hangul->preedit);
458 ustring_append_ucs4 (preedit, hic_preedit, -1);
459 if (ustring_length(preedit) > 0) {
460 utf8 = ustring_to_utf8 (preedit, -1);
462 if (symbol_table != NULL)
463 hangul->hanja_list = hanja_table_match_prefix (symbol_table, utf8);
464 if (hangul->hanja_list == NULL)
465 hangul->hanja_list = hanja_table_match_prefix (hanja_table, utf8);
470 ustring_delete (preedit);
475 ibus_hangul_engine_apply_hanja_list (IBusHangulEngine *hangul)
477 HanjaList* list = hangul->hanja_list;
480 n = hanja_list_get_size (list);
482 ibus_lookup_table_clear (hangul->table);
483 for (i = 0; i < n; i++) {
484 const char* value = hanja_list_get_nth_value (list, i);
485 IBusText* text = ibus_text_new_from_string (value);
486 ibus_lookup_table_append_candidate (hangul->table, text);
489 ibus_lookup_table_set_cursor_pos (hangul->table, 0);
490 ibus_hangul_engine_update_lookup_table_ui (hangul);
491 lookup_table_set_visible (hangul->table, TRUE);
496 ibus_hangul_engine_hide_lookup_table (IBusHangulEngine *hangul)
499 is_visible = lookup_table_is_visible (hangul->table);
501 // Sending hide lookup table message when the lookup table
502 // is not visible results wrong behavior. So I have to check
503 // whether the table is visible or not before to hide.
505 ibus_engine_hide_lookup_table ((IBusEngine *)hangul);
506 ibus_engine_hide_auxiliary_text ((IBusEngine *)hangul);
507 lookup_table_set_visible (hangul->table, FALSE);
510 if (hangul->hanja_list != NULL) {
511 hanja_list_delete (hangul->hanja_list);
512 hangul->hanja_list = NULL;
517 ibus_hangul_engine_update_lookup_table (IBusHangulEngine *hangul)
519 ibus_hangul_engine_update_hanja_list (hangul);
521 if (hangul->hanja_list != NULL) {
522 // We should redraw preedit text with IBUS_ENGINE_PREEDIT_CLEAR option
523 // here to prevent committing it on focus out event incidentally.
524 ibus_hangul_engine_update_preedit_text (hangul);
525 ibus_hangul_engine_apply_hanja_list (hangul);
527 ibus_hangul_engine_hide_lookup_table (hangul);
532 ibus_hangul_engine_process_candidate_key_event (IBusHangulEngine *hangul,
536 if (keyval == IBUS_Escape) {
537 ibus_hangul_engine_hide_lookup_table (hangul);
538 // When the lookup table is poped up, preedit string is
539 // updated with IBUS_ENGINE_PREEDIT_CLEAR option.
540 // So, when focus is out, the preedit text will not be committed.
541 // To prevent this problem, we have to update preedit text here
542 // with IBUS_ENGINE_PREEDIT_COMMIT option.
543 ibus_hangul_engine_update_preedit_text (hangul);
545 } else if (keyval == IBUS_Return) {
546 ibus_hangul_engine_commit_current_candidate (hangul);
548 if (hangul->hanja_mode) {
549 ibus_hangul_engine_update_lookup_table (hangul);
551 ibus_hangul_engine_hide_lookup_table (hangul);
554 } else if (keyval >= IBUS_1 && keyval <= IBUS_9) {
559 page_size = ibus_lookup_table_get_page_size (hangul->table);
560 cursor_pos = ibus_lookup_table_get_cursor_pos (hangul->table);
561 page_no = cursor_pos / page_size;
563 cursor_pos = page_no * page_size + (keyval - IBUS_1);
564 ibus_lookup_table_set_cursor_pos (hangul->table, cursor_pos);
566 ibus_hangul_engine_commit_current_candidate (hangul);
568 if (hangul->hanja_mode) {
569 ibus_hangul_engine_update_lookup_table (hangul);
571 ibus_hangul_engine_hide_lookup_table (hangul);
574 } else if (keyval == IBUS_Page_Up) {
575 ibus_lookup_table_page_up (hangul->table);
576 ibus_hangul_engine_update_lookup_table_ui (hangul);
578 } else if (keyval == IBUS_Page_Down) {
579 ibus_lookup_table_page_down (hangul->table);
580 ibus_hangul_engine_update_lookup_table_ui (hangul);
583 if (lookup_table_orientation == 0) {
585 if (keyval == IBUS_Left) {
586 ibus_lookup_table_cursor_up (hangul->table);
587 ibus_hangul_engine_update_lookup_table_ui (hangul);
589 } else if (keyval == IBUS_Right) {
590 ibus_lookup_table_cursor_down (hangul->table);
591 ibus_hangul_engine_update_lookup_table_ui (hangul);
593 } else if (keyval == IBUS_Up) {
594 ibus_lookup_table_page_up (hangul->table);
595 ibus_hangul_engine_update_lookup_table_ui (hangul);
597 } else if (keyval == IBUS_Down) {
598 ibus_lookup_table_page_down (hangul->table);
599 ibus_hangul_engine_update_lookup_table_ui (hangul);
604 if (keyval == IBUS_Left) {
605 ibus_lookup_table_page_up (hangul->table);
606 ibus_hangul_engine_update_lookup_table_ui (hangul);
608 } else if (keyval == IBUS_Right) {
609 ibus_lookup_table_page_down (hangul->table);
610 ibus_hangul_engine_update_lookup_table_ui (hangul);
612 } else if (keyval == IBUS_Up) {
613 ibus_lookup_table_cursor_up (hangul->table);
614 ibus_hangul_engine_update_lookup_table_ui (hangul);
616 } else if (keyval == IBUS_Down) {
617 ibus_lookup_table_cursor_down (hangul->table);
618 ibus_hangul_engine_update_lookup_table_ui (hangul);
624 if (!hangul->hanja_mode) {
625 if (lookup_table_orientation == 0) {
627 if (keyval == IBUS_h) {
628 ibus_lookup_table_cursor_up (hangul->table);
629 ibus_hangul_engine_update_lookup_table_ui (hangul);
631 } else if (keyval == IBUS_l) {
632 ibus_lookup_table_cursor_down (hangul->table);
633 ibus_hangul_engine_update_lookup_table_ui (hangul);
635 } else if (keyval == IBUS_k) {
636 ibus_lookup_table_page_up (hangul->table);
637 ibus_hangul_engine_update_lookup_table_ui (hangul);
639 } else if (keyval == IBUS_j) {
640 ibus_lookup_table_page_down (hangul->table);
641 ibus_hangul_engine_update_lookup_table_ui (hangul);
646 if (keyval == IBUS_h) {
647 ibus_lookup_table_page_up (hangul->table);
648 ibus_hangul_engine_update_lookup_table_ui (hangul);
650 } else if (keyval == IBUS_l) {
651 ibus_lookup_table_page_down (hangul->table);
652 ibus_hangul_engine_update_lookup_table_ui (hangul);
654 } else if (keyval == IBUS_k) {
655 ibus_lookup_table_cursor_up (hangul->table);
656 ibus_hangul_engine_update_lookup_table_ui (hangul);
658 } else if (keyval == IBUS_j) {
659 ibus_lookup_table_cursor_down (hangul->table);
660 ibus_hangul_engine_update_lookup_table_ui (hangul);
670 ibus_hangul_engine_process_key_event (IBusEngine *engine,
675 IBusHangulEngine *hangul = (IBusHangulEngine *) engine;
681 if (modifiers & IBUS_RELEASE_MASK)
684 // if we don't ignore shift keys, shift key will make flush the preedit
685 // string. So you cannot input shift+key.
686 // Let's think about these examples:
689 if (keyval == IBUS_Shift_L || keyval == IBUS_Shift_R)
692 // If hanja key has any modifiers, we ignore that modifier keyval,
693 // or we cannot make the hanja key work.
694 // Because when we get the modifier key alone, we commit the
695 // current preedit string. So after that, even if we get the
696 // right hanja key event, we don't have preedit string to be changed
698 // See this bug: http://code.google.com/p/ibus/issues/detail?id=1036
699 if (hanja_key_list_has_modifier(&hanja_keys, keyval))
702 if (hanja_key_list_match(&hanja_keys, keyval, modifiers)) {
703 if (hangul->hanja_list == NULL) {
704 ibus_hangul_engine_update_lookup_table (hangul);
706 ibus_hangul_engine_hide_lookup_table (hangul);
711 if (hangul->hanja_list != NULL) {
712 retval = ibus_hangul_engine_process_candidate_key_event (hangul,
714 if (hangul->hanja_mode) {
722 // if we've got a key event with modifiers, commit current
723 // preedit string and ignore this key event.
724 // So, if you want to add some key event handler, put it
726 // Omit shift, capslock, numlock and xkb modifiers.
727 mask = IBUS_MODIFIER_MASK &
728 ~(IBUS_SHIFT_MASK | IBUS_LOCK_MASK | IBUS_MOD2_MASK);
729 if (modifiers & mask) {
730 ibus_hangul_engine_flush (hangul);
734 if (keyval == IBUS_BackSpace) {
735 retval = hangul_ic_backspace (hangul->context);
738 if (modifiers & IBUS_LOCK_MASK) {
739 if (keyval >= 'A' && keyval <= 'z') {
741 keyval = tolower(keyval);
743 keyval = toupper(keyval);
746 retval = hangul_ic_process (hangul->context, keyval);
749 str = hangul_ic_get_commit_string (hangul->context);
750 if (hangul->hanja_mode) {
751 const ucschar* hic_preedit;
753 hic_preedit = hangul_ic_get_preedit_string (hangul->context);
754 if (hic_preedit != NULL && hic_preedit[0] != 0) {
755 ustring_append_ucs4 (hangul->preedit, str, -1);
758 const ucschar* preedit;
760 ustring_append_ucs4 (hangul->preedit, str, -1);
761 if (ustring_length (hangul->preedit) > 0) {
762 preedit = ustring_begin (hangul->preedit);
763 text = ibus_text_new_from_ucs4 ((gunichar*)preedit);
764 ibus_engine_commit_text (engine, text);
766 ustring_clear (hangul->preedit);
769 if (str != NULL && str[0] != 0) {
770 IBusText *text = ibus_text_new_from_ucs4 (str);
771 ibus_engine_commit_text (engine, text);
775 ibus_hangul_engine_update_preedit_text (hangul);
777 if (hangul->hanja_mode) {
778 ibus_hangul_engine_update_lookup_table (hangul);
782 ibus_hangul_engine_flush (hangul);
788 ibus_hangul_engine_flush (IBusHangulEngine *hangul)
793 ibus_hangul_engine_hide_lookup_table (hangul);
795 str = hangul_ic_flush (hangul->context);
797 ustring_append_ucs4 (hangul->preedit, str, -1);
799 if (ustring_length (hangul->preedit) != 0) {
800 str = ustring_begin (hangul->preedit);
801 text = ibus_text_new_from_ucs4 (str);
803 ibus_engine_commit_text ((IBusEngine *) hangul, text);
805 ustring_clear(hangul->preedit);
808 ibus_hangul_engine_update_preedit_text (hangul);
812 ibus_hangul_engine_focus_in (IBusEngine *engine)
814 IBusHangulEngine *hangul = (IBusHangulEngine *) engine;
816 if (hangul->hanja_mode) {
817 hangul->prop_hanja_mode->state = PROP_STATE_CHECKED;
819 hangul->prop_hanja_mode->state = PROP_STATE_UNCHECKED;
822 ibus_engine_register_properties (engine, hangul->prop_list);
824 ibus_hangul_engine_update_preedit_text (hangul);
826 if (hangul->hanja_list != NULL) {
827 ibus_hangul_engine_update_lookup_table_ui (hangul);
830 parent_class->focus_in (engine);
834 ibus_hangul_engine_focus_out (IBusEngine *engine)
836 IBusHangulEngine *hangul = (IBusHangulEngine *) engine;
838 if (hangul->hanja_list == NULL) {
840 // ibus_engine_update_preedit_text_with_mode() function which makes
841 // the preedit string committed automatically when the focus is out.
842 // So we don't need to commit the preedit here.
843 hangul_ic_reset (hangul->context);
845 ibus_engine_hide_lookup_table (engine);
846 ibus_engine_hide_auxiliary_text (engine);
849 parent_class->focus_out ((IBusEngine *) hangul);
853 ibus_hangul_engine_reset (IBusEngine *engine)
855 IBusHangulEngine *hangul = (IBusHangulEngine *) engine;
857 ibus_hangul_engine_flush (hangul);
858 parent_class->reset (engine);
862 ibus_hangul_engine_enable (IBusEngine *engine)
864 parent_class->enable (engine);
868 ibus_hangul_engine_disable (IBusEngine *engine)
870 ibus_hangul_engine_focus_out (engine);
871 parent_class->disable (engine);
875 ibus_hangul_engine_page_up (IBusEngine *engine)
877 parent_class->page_up (engine);
881 ibus_hangul_engine_page_down (IBusEngine *engine)
883 parent_class->page_down (engine);
887 ibus_hangul_engine_cursor_up (IBusEngine *engine)
889 IBusHangulEngine *hangul = (IBusHangulEngine *) engine;
891 if (hangul->hanja_list != NULL) {
892 ibus_lookup_table_cursor_up (hangul->table);
893 ibus_hangul_engine_update_lookup_table_ui (hangul);
896 parent_class->cursor_up (engine);
900 ibus_hangul_engine_cursor_down (IBusEngine *engine)
902 IBusHangulEngine *hangul = (IBusHangulEngine *) engine;
904 if (hangul->hanja_list != NULL) {
905 ibus_lookup_table_cursor_down (hangul->table);
906 ibus_hangul_engine_update_lookup_table_ui (hangul);
909 parent_class->cursor_down (engine);
913 ibus_hangul_engine_property_activate (IBusEngine *engine,
914 const gchar *prop_name,
917 if (strcmp(prop_name, "setup") == 0) {
918 GError *error = NULL;
919 gchar *argv[2] = { NULL, };
921 const char* libexecdir;
923 libexecdir = g_getenv("LIBEXECDIR");
924 if (libexecdir == NULL)
925 libexecdir = LIBEXECDIR;
927 path = g_build_filename(libexecdir, "ibus-setup-hangul", NULL);
930 g_spawn_async (NULL, argv, NULL, 0, NULL, NULL, NULL, &error);
933 } else if (strcmp(prop_name, "hanja_mode") == 0) {
934 IBusHangulEngine *hangul = (IBusHangulEngine *) engine;
936 hangul->hanja_mode = !hangul->hanja_mode;
937 if (hangul->hanja_mode) {
938 hangul->prop_hanja_mode->state = PROP_STATE_CHECKED;
940 hangul->prop_hanja_mode->state = PROP_STATE_UNCHECKED;
943 ibus_engine_update_property (engine, hangul->prop_hanja_mode);
944 ibus_hangul_engine_flush (hangul);
949 ibus_config_value_changed (IBusConfig *config,
950 const gchar *section,
955 IBusHangulEngine *hangul = (IBusHangulEngine *) user_data;
957 if (strcmp(section, "engine/Hangul") == 0) {
958 if (strcmp(name, "HangulKeyboard") == 0) {
959 const gchar *str = g_value_get_string (value);
960 g_string_assign (hangul_keyboard, str);
961 hangul_ic_select_keyboard (hangul->context, hangul_keyboard->str);
962 } else if (strcmp(name, "HanjaKeys") == 0) {
963 const gchar* str = g_value_get_string (value);
964 hanja_key_list_set_from_string(&hanja_keys, str);
966 } else if (strcmp(section, "panel") == 0) {
967 if (strcmp(name, "lookup_table_orientation") == 0) {
968 lookup_table_orientation = g_value_get_int (value);
974 lookup_table_set_visible (IBusLookupTable *table, gboolean flag)
976 g_object_set_data (G_OBJECT(table), "visible", GUINT_TO_POINTER(flag));
980 lookup_table_is_visible (IBusLookupTable *table)
982 gpointer res = g_object_get_data (G_OBJECT(table), "visible");
983 return GPOINTER_TO_UINT(res);
987 key_event_list_append(GArray* list, guint keyval, guint modifiers)
989 struct KeyEvent ev = { keyval, modifiers};
990 g_array_append_val(list, ev);
994 key_event_list_match(GArray* list, guint keyval, guint modifiers)
999 /* ignore capslock and numlock */
1000 mask = IBUS_SHIFT_MASK |
1008 for (i = 0; i < list->len; ++i) {
1009 struct KeyEvent* ev = &g_array_index(list, struct KeyEvent, i);
1010 if (ev->keyval == keyval && ev->modifiers == modifiers) {
1019 ibus_hangul_engine_candidate_clicked (IBusEngine *engine,
1024 IBusHangulEngine *hangul = (IBusHangulEngine *) engine;
1028 if (hangul->table == NULL)
1031 ibus_lookup_table_set_cursor_pos (hangul->table, index);
1032 ibus_hangul_engine_commit_current_candidate (hangul);
1034 if (hangul->hanja_mode) {
1035 ibus_hangul_engine_update_lookup_table (hangul);
1037 ibus_hangul_engine_hide_lookup_table (hangul);
1042 hanja_key_list_init(HanjaKeyList* list)
1044 list->all_modifiers = 0;
1045 list->keys = g_array_sized_new(FALSE, TRUE, sizeof(struct KeyEvent), 4);
1049 hanja_key_list_fini(HanjaKeyList* list)
1051 g_array_free(list->keys, TRUE);
1055 hanja_key_list_append_from_string(HanjaKeyList *list, const char* str)
1058 guint modifiers = 0;
1061 res = ibus_key_event_from_string(str, &keyval, &modifiers);
1063 hanja_key_list_append(list, keyval, modifiers);
1068 hanja_key_list_append(HanjaKeyList *list, guint keyval, guint modifiers)
1070 list->all_modifiers |= modifiers;
1071 key_event_list_append(list->keys, keyval, modifiers);
1075 hanja_key_list_set_from_string(HanjaKeyList *list, const char* str)
1077 gchar** items = g_strsplit(str, ",", 0);
1079 list->all_modifiers = 0;
1080 g_array_set_size(list->keys, 0);
1082 if (items != NULL) {
1084 for (i = 0; items[i] != NULL; ++i) {
1085 hanja_key_list_append_from_string(list, items[i]);
1092 hanja_key_list_match(HanjaKeyList* list, guint keyval, guint modifiers)
1094 return key_event_list_match(list->keys, keyval, modifiers);
1098 hanja_key_list_has_modifier(HanjaKeyList* list, guint keyval)
1100 if (list->all_modifiers & IBUS_CONTROL_MASK) {
1101 if (keyval == IBUS_Control_L || keyval == IBUS_Control_R)
1105 if (list->all_modifiers & IBUS_MOD1_MASK) {
1106 if (keyval == IBUS_Alt_L || keyval == IBUS_Alt_R)
1110 if (list->all_modifiers & IBUS_SUPER_MASK) {
1111 if (keyval == IBUS_Super_L || keyval == IBUS_Super_R)
1115 if (list->all_modifiers & IBUS_HYPER_MASK) {
1116 if (keyval == IBUS_Hyper_L || keyval == IBUS_Hyper_R)
1120 if (list->all_modifiers & IBUS_META_MASK) {
1121 if (keyval == IBUS_Meta_L || keyval == IBUS_Meta_R)