1 /* vim:set et sts=4: */
8 typedef struct _IBusHangulEngine IBusHangulEngine;
9 typedef struct _IBusHangulEngineClass IBusHangulEngineClass;
11 struct _IBusHangulEngine {
15 HangulInputContext *context;
17 HanjaList* hanja_list;
19 IBusLookupTable *table;
20 IBusProperty *hangul_mode_prop;
21 IBusPropList *prop_list;
24 struct _IBusHangulEngineClass {
25 IBusEngineClass parent;
28 /* functions prototype */
29 static void ibus_hangul_engine_class_init (IBusHangulEngineClass *klass);
30 static void ibus_hangul_engine_init (IBusHangulEngine *hangul);
32 ibus_hangul_engine_constructor (GType type,
33 guint n_construct_params,
34 GObjectConstructParam *construct_params);
35 static void ibus_hangul_engine_destroy (IBusHangulEngine *hangul);
37 ibus_hangul_engine_process_key_event
41 static void ibus_hangul_engine_focus_in (IBusEngine *engine);
42 static void ibus_hangul_engine_focus_out (IBusEngine *engine);
43 static void ibus_hangul_engine_reset (IBusEngine *engine);
44 static void ibus_hangul_engine_enable (IBusEngine *engine);
45 static void ibus_hangul_engine_disable (IBusEngine *engine);
47 static void ibus_engine_set_cursor_location (IBusEngine *engine,
52 static void ibus_hangul_engine_set_capabilities
56 static void ibus_hangul_engine_page_up (IBusEngine *engine);
57 static void ibus_hangul_engine_page_down (IBusEngine *engine);
58 static void ibus_hangul_engine_cursor_up (IBusEngine *engine);
59 static void ibus_hangul_engine_cursor_down (IBusEngine *engine);
60 static void ibus_hangul_engine_property_activate
62 const gchar *prop_name,
65 static void ibus_hangul_engine_property_show
67 const gchar *prop_name);
68 static void ibus_hangul_engine_property_hide
70 const gchar *prop_name);
73 static void ibus_hangul_engine_flush (IBusHangulEngine *hangul);
74 static void ibus_hangul_engine_update_preedit_text
75 (IBusHangulEngine *hangul);
76 static void ibus_config_value_changed (IBusConfig *config,
82 static IBusEngineClass *parent_class = NULL;
83 static HanjaTable *hanja_table = NULL;
84 static IBusConfig *config = NULL;
85 static GString *hangul_keyboard;
88 ibus_hangul_engine_get_type (void)
90 static GType type = 0;
92 static const GTypeInfo type_info = {
93 sizeof (IBusHangulEngineClass),
95 (GBaseFinalizeFunc) NULL,
96 (GClassInitFunc) ibus_hangul_engine_class_init,
99 sizeof (IBusHangulEngine),
101 (GInstanceInitFunc) ibus_hangul_engine_init,
105 type = g_type_register_static (IBUS_TYPE_ENGINE,
115 ibus_hangul_init (IBusBus *bus)
118 GValue value = { 0, };
120 hanja_table = hanja_table_load (NULL);
122 config = ibus_bus_get_config (bus);
124 hangul_keyboard = g_string_new_len ("2", 8);
125 res = ibus_config_get_value (config, "engine/Hangul",
126 "HangulKeyboard", &value);
128 const gchar* str = g_value_get_string (&value);
129 g_string_assign (hangul_keyboard, str);
134 ibus_hangul_exit (void)
136 hanja_table_delete (hanja_table);
139 g_object_unref (config);
142 g_string_free (hangul_keyboard, TRUE);
143 hangul_keyboard = NULL;
147 ibus_hangul_engine_class_init (IBusHangulEngineClass *klass)
149 GObjectClass *object_class = G_OBJECT_CLASS (klass);
150 IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass);
151 IBusEngineClass *engine_class = IBUS_ENGINE_CLASS (klass);
153 parent_class = (IBusEngineClass *) g_type_class_peek_parent (klass);
155 object_class->constructor = ibus_hangul_engine_constructor;
156 ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_hangul_engine_destroy;
158 engine_class->process_key_event = ibus_hangul_engine_process_key_event;
160 engine_class->reset = ibus_hangul_engine_reset;
161 engine_class->enable = ibus_hangul_engine_enable;
162 engine_class->disable = ibus_hangul_engine_disable;
164 engine_class->focus_in = ibus_hangul_engine_focus_in;
165 engine_class->focus_out = ibus_hangul_engine_focus_out;
167 engine_class->page_up = ibus_hangul_engine_page_up;
168 engine_class->page_down = ibus_hangul_engine_page_down;
170 engine_class->cursor_up = ibus_hangul_engine_cursor_up;
171 engine_class->cursor_down = ibus_hangul_engine_cursor_down;
173 engine_class->property_activate = ibus_hangul_engine_property_activate;
177 ibus_hangul_engine_init (IBusHangulEngine *hangul)
183 hangul->context = hangul_ic_new (hangul_keyboard->str);
184 hangul->hanja_list = NULL;
185 hangul->hangul_mode = TRUE;
186 label = ibus_text_new_from_string("Setup");
187 tooltip = ibus_text_new_from_string("Configure hangul engine");
188 prop = ibus_property_new ("setup",
193 TRUE, TRUE, 0, NULL);
194 g_object_unref (label);
195 g_object_unref (tooltip);
197 hangul->prop_list = ibus_prop_list_new ();
198 ibus_prop_list_append (hangul->prop_list, prop);
200 hangul->table = ibus_lookup_table_new (9, 0, TRUE, FALSE);
202 g_signal_connect (config, "value-changed",
203 G_CALLBACK(ibus_config_value_changed), hangul);
207 ibus_hangul_engine_constructor (GType type,
208 guint n_construct_params,
209 GObjectConstructParam *construct_params)
211 IBusHangulEngine *hangul;
213 hangul = (IBusHangulEngine *) G_OBJECT_CLASS (parent_class)->constructor (type,
217 return (GObject *)hangul;
222 ibus_hangul_engine_destroy (IBusHangulEngine *hangul)
224 if (hangul->prop_list) {
225 g_object_unref (hangul->prop_list);
226 hangul->prop_list = NULL;
229 if (hangul->hangul_mode_prop) {
230 g_object_unref (hangul->hangul_mode_prop);
231 hangul->hangul_mode_prop = NULL;
235 g_object_unref (hangul->table);
236 hangul->table = NULL;
239 if (hangul->context) {
240 hangul_ic_delete (hangul->context);
241 hangul->context = NULL;
244 IBUS_OBJECT_CLASS (parent_class)->destroy ((IBusObject *)hangul);
248 ibus_hangul_engine_update_preedit_text (IBusHangulEngine *hangul)
253 str = hangul_ic_get_preedit_string (hangul->context);
255 if (str != NULL && str[0] != 0) {
256 text = ibus_text_new_from_ucs4 (str);
257 ibus_text_append_attribute (text, IBUS_ATTR_TYPE_FOREGROUND, 0x00ffffff, 0, -1);
258 ibus_text_append_attribute (text, IBUS_ATTR_TYPE_BACKGROUND, 0x00000000, 0, -1);
259 ibus_engine_update_preedit_text ((IBusEngine *)hangul,
261 ibus_text_get_length (text),
263 g_object_unref (text);
266 text = ibus_text_new_from_static_string ("");
267 ibus_engine_update_preedit_text ((IBusEngine *)hangul, text, 0, FALSE);
268 g_object_unref (text);
273 ibus_hangul_engine_update_auxiliary_text (IBusHangulEngine *hangul)
279 cursor_pos = ibus_lookup_table_get_cursor_pos (hangul->table);
280 comment = hanja_list_get_nth_comment (hangul->hanja_list, cursor_pos);
282 text = ibus_text_new_from_string (comment);
283 ibus_engine_update_auxiliary_text ((IBusEngine *)hangul, text, TRUE);
284 g_object_unref (text);
288 ibus_hangul_engine_update_lookup_table (IBusHangulEngine *hangul)
290 ibus_engine_update_lookup_table ((IBusEngine *)hangul, hangul->table, TRUE);
294 ibus_hangul_engine_commit_current_candidate (IBusHangulEngine *hangul)
300 hangul_ic_reset (hangul->context);
301 ibus_hangul_engine_update_preedit_text (hangul);
303 cursor_pos = ibus_lookup_table_get_cursor_pos (hangul->table);
304 value = hanja_list_get_nth_value (hangul->hanja_list, cursor_pos);
306 text = ibus_text_new_from_string (value);
307 ibus_engine_commit_text ((IBusEngine *)hangul, text);
308 g_object_unref (text);
312 ibus_hangul_engine_open_lookup_table (IBusHangulEngine *hangul)
317 str = hangul_ic_get_preedit_string (hangul->context);
318 utf8 = g_ucs4_to_utf8 (str, -1, NULL, NULL, NULL);
320 HanjaList* list = hanja_table_match_suffix (hanja_table, utf8);
323 n = hanja_list_get_size (list);
325 ibus_lookup_table_clear (hangul->table);
326 for (i = 0; i < n; i++) {
327 const char* value = hanja_list_get_nth_value (list, i);
328 IBusText* text = ibus_text_new_from_string (value);
329 ibus_lookup_table_append_candidate (hangul->table, text);
330 g_object_unref (text);
333 hanja_list_delete (hangul->hanja_list);
334 hangul->hanja_list = list;
336 ibus_lookup_table_set_cursor_pos (hangul->table, 0);
337 ibus_hangul_engine_update_auxiliary_text (hangul);
338 ibus_hangul_engine_update_lookup_table (hangul);
345 ibus_hangul_engine_close_lookup_table (IBusHangulEngine *hangul)
347 ibus_engine_hide_lookup_table ((IBusEngine *)hangul);
348 ibus_engine_hide_auxiliary_text ((IBusEngine *)hangul);
349 hanja_list_delete (hangul->hanja_list);
350 hangul->hanja_list = NULL;
354 ibus_hangul_engine_toggle_lookup_table (IBusHangulEngine *hangul)
356 if (hangul->hanja_list != NULL) {
357 ibus_hangul_engine_close_lookup_table (hangul);
359 ibus_hangul_engine_open_lookup_table (hangul);
364 ibus_hangul_engine_process_candidate_key_event (IBusHangulEngine *hangul,
368 if (keyval == IBUS_Escape) {
369 ibus_hangul_engine_close_lookup_table (hangul);
370 } else if (keyval == IBUS_Return) {
371 ibus_hangul_engine_commit_current_candidate (hangul);
372 ibus_hangul_engine_close_lookup_table (hangul);
373 } else if (keyval >= IBUS_1 && keyval <= IBUS_9) {
378 page_size = ibus_lookup_table_get_page_size (hangul->table);
379 cursor_pos = ibus_lookup_table_get_cursor_pos (hangul->table);
380 page_no = cursor_pos / page_size;
382 cursor_pos = page_no * page_size + (keyval - IBUS_1);
383 ibus_lookup_table_set_cursor_pos (hangul->table, cursor_pos);
385 ibus_hangul_engine_commit_current_candidate (hangul);
386 ibus_hangul_engine_close_lookup_table (hangul);
387 } else if (keyval == IBUS_Left) {
388 ibus_lookup_table_cursor_up (hangul->table);
389 ibus_hangul_engine_update_lookup_table (hangul);
390 ibus_hangul_engine_update_auxiliary_text (hangul);
391 } else if (keyval == IBUS_Right) {
392 ibus_lookup_table_cursor_down (hangul->table);
393 ibus_hangul_engine_update_lookup_table (hangul);
394 ibus_hangul_engine_update_auxiliary_text (hangul);
395 } else if (keyval == IBUS_Up) {
396 ibus_lookup_table_page_up (hangul->table);
397 ibus_hangul_engine_update_lookup_table (hangul);
398 ibus_hangul_engine_update_auxiliary_text (hangul);
399 } else if (keyval == IBUS_Down) {
400 ibus_lookup_table_page_down (hangul->table);
401 ibus_hangul_engine_update_lookup_table (hangul);
402 ibus_hangul_engine_update_auxiliary_text (hangul);
403 } else if (keyval == IBUS_Page_Up) {
404 ibus_lookup_table_page_up (hangul->table);
405 ibus_hangul_engine_update_lookup_table (hangul);
406 ibus_hangul_engine_update_auxiliary_text (hangul);
407 } else if (keyval == IBUS_Page_Down) {
408 ibus_lookup_table_page_down (hangul->table);
409 ibus_hangul_engine_update_lookup_table (hangul);
410 ibus_hangul_engine_update_auxiliary_text (hangul);
411 } else if (keyval == IBUS_h) {
412 ibus_lookup_table_cursor_up (hangul->table);
413 ibus_hangul_engine_update_lookup_table (hangul);
414 ibus_hangul_engine_update_auxiliary_text (hangul);
415 } else if (keyval == IBUS_l) {
416 ibus_lookup_table_cursor_down (hangul->table);
417 ibus_hangul_engine_update_lookup_table (hangul);
418 ibus_hangul_engine_update_auxiliary_text (hangul);
419 } else if (keyval == IBUS_k) {
420 ibus_lookup_table_page_up (hangul->table);
421 ibus_hangul_engine_update_lookup_table (hangul);
422 ibus_hangul_engine_update_auxiliary_text (hangul);
423 } else if (keyval == IBUS_j) {
424 ibus_lookup_table_page_down (hangul->table);
425 ibus_hangul_engine_update_lookup_table (hangul);
426 ibus_hangul_engine_update_auxiliary_text (hangul);
433 ibus_hangul_engine_process_key_event (IBusEngine *engine,
437 IBusHangulEngine *hangul = (IBusHangulEngine *) engine;
442 if (modifiers & IBUS_RELEASE_MASK)
445 // if we don't ignore shift keys, shift key will make flush the preedit
446 // string. So you cannot input shift+key.
447 // Let's think about these examples:
450 if (keyval == IBUS_Shift_L || keyval == IBUS_Shift_R)
453 if (keyval == IBUS_F9 || keyval == IBUS_Hangul_Hanja) {
454 ibus_hangul_engine_toggle_lookup_table (hangul);
458 if (modifiers & (IBUS_CONTROL_MASK | IBUS_MOD1_MASK))
461 if (hangul->hanja_list != NULL) {
462 return ibus_hangul_engine_process_candidate_key_event (hangul,
466 if (keyval == IBUS_BackSpace) {
467 retval = hangul_ic_backspace (hangul->context);
469 retval = hangul_ic_process (hangul->context, keyval);
472 str = hangul_ic_get_commit_string (hangul->context);
473 if (str != NULL && str[0] != 0) {
474 IBusText *text = ibus_text_new_from_ucs4 (str);
475 ibus_engine_commit_text ((IBusEngine *)hangul, text);
476 g_object_unref (text);
479 ibus_hangul_engine_update_preedit_text (hangul);
482 ibus_hangul_engine_flush (hangul);
488 ibus_hangul_engine_flush (IBusHangulEngine *hangul)
493 str = hangul_ic_flush (hangul->context);
495 if (str == NULL || str[0] == 0)
498 text = ibus_text_new_from_ucs4 (str);
500 ibus_engine_hide_preedit_text ((IBusEngine *) hangul);
501 ibus_engine_commit_text ((IBusEngine *) hangul, text);
503 g_object_unref (text);
507 ibus_hangul_engine_focus_in (IBusEngine *engine)
509 IBusHangulEngine *hangul = (IBusHangulEngine *) engine;
511 ibus_engine_register_properties (engine, hangul->prop_list);
513 if (hangul->hanja_list != NULL) {
514 ibus_hangul_engine_update_lookup_table (hangul);
515 ibus_hangul_engine_update_auxiliary_text (hangul);
518 parent_class->focus_in (engine);
522 ibus_hangul_engine_focus_out (IBusEngine *engine)
524 IBusHangulEngine *hangul = (IBusHangulEngine *) engine;
526 if (hangul->hanja_list == NULL) {
527 ibus_hangul_engine_flush (hangul);
529 ibus_engine_hide_lookup_table (engine);
530 ibus_engine_hide_auxiliary_text (engine);
533 parent_class->focus_out ((IBusEngine *) hangul);
537 ibus_hangul_engine_reset (IBusEngine *engine)
539 IBusHangulEngine *hangul = (IBusHangulEngine *) engine;
541 ibus_hangul_engine_flush (hangul);
542 if (hangul->hanja_list != NULL) {
543 ibus_hangul_engine_close_lookup_table (hangul);
545 parent_class->reset (engine);
549 ibus_hangul_engine_enable (IBusEngine *engine)
551 parent_class->enable (engine);
555 ibus_hangul_engine_disable (IBusEngine *engine)
557 ibus_hangul_engine_focus_out (engine);
558 parent_class->disable (engine);
562 ibus_hangul_engine_page_up (IBusEngine *engine)
564 parent_class->page_up (engine);
568 ibus_hangul_engine_page_down (IBusEngine *engine)
570 parent_class->page_down (engine);
574 ibus_hangul_engine_cursor_up (IBusEngine *engine)
576 IBusHangulEngine *hangul = (IBusHangulEngine *) engine;
578 if (hangul->hanja_list != NULL) {
579 ibus_lookup_table_cursor_up (hangul->table);
580 ibus_hangul_engine_update_lookup_table (hangul);
581 ibus_hangul_engine_update_auxiliary_text (hangul);
584 parent_class->cursor_up (engine);
588 ibus_hangul_engine_cursor_down (IBusEngine *engine)
590 IBusHangulEngine *hangul = (IBusHangulEngine *) engine;
592 if (hangul->hanja_list != NULL) {
593 ibus_lookup_table_cursor_down (hangul->table);
594 ibus_hangul_engine_update_lookup_table (hangul);
595 ibus_hangul_engine_update_auxiliary_text (hangul);
598 parent_class->cursor_down (engine);
602 ibus_hangul_engine_property_activate (IBusEngine *engine,
603 const gchar *prop_name,
606 if (strcmp(prop_name, "setup") == 0) {
607 GError *error = NULL;
608 gchar *argv[2] = { NULL, };
610 const char* libexecdir;
612 libexecdir = g_getenv("LIBEXECDIR");
613 if (libexecdir == NULL)
614 libexecdir = LIBEXECDIR;
616 path = g_build_filename(libexecdir, "ibus-setup-hangul", NULL);
619 g_spawn_async (NULL, argv, NULL, 0, NULL, NULL, NULL, &error);
626 ibus_config_value_changed (IBusConfig *config,
627 const gchar *section,
632 IBusHangulEngine *hangul = (IBusHangulEngine *) user_data;
634 if (strcmp(section, "engine/Hangul") == 0) {
635 if (strcmp(name, "HangulKeyboard") == 0) {
636 const gchar *str = g_value_get_string (value);
637 g_string_assign (hangul_keyboard, str);
638 hangul_ic_select_keyboard (hangul->context, hangul_keyboard->str);