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_toggle_hangul_mode
61 (IBusHangulEngine *hangul);
63 static void ibus_hangul_property_activate (IBusEngine *engine,
64 const gchar *prop_name,
66 static void ibus_hangul_engine_property_show
68 const gchar *prop_name);
69 static void ibus_hangul_engine_property_hide
71 const gchar *prop_name);
74 static void ibus_hangul_engine_flush (IBusHangulEngine *hangul);
75 static void ibus_hangul_engine_update_preedit_text
76 (IBusHangulEngine *hangul);
77 static void ibus_config_value_changed (IBusConfig *config,
83 static IBusEngineClass *parent_class = NULL;
84 static HanjaTable *hanja_table = NULL;
85 static IBusConfig *config = NULL;
86 static GString *hangul_keyboard;
89 ibus_hangul_engine_get_type (void)
91 static GType type = 0;
93 static const GTypeInfo type_info = {
94 sizeof (IBusHangulEngineClass),
96 (GBaseFinalizeFunc) NULL,
97 (GClassInitFunc) ibus_hangul_engine_class_init,
100 sizeof (IBusHangulEngine),
102 (GInstanceInitFunc) ibus_hangul_engine_init,
106 type = g_type_register_static (IBUS_TYPE_ENGINE,
116 ibus_hangul_init (IBusBus *bus)
119 GValue value = { 0, };
121 hanja_table = hanja_table_load (NULL);
123 config = ibus_bus_get_config (bus);
125 hangul_keyboard = g_string_new_len ("2", 8);
126 res = ibus_config_get_value (config, "engine/Hangul",
127 "HangulKeyboard", &value);
129 const gchar* str = g_value_get_string (&value);
130 g_string_assign (hangul_keyboard, str);
135 ibus_hangul_exit (void)
137 hanja_table_delete (hanja_table);
140 g_object_unref (config);
143 g_string_free (hangul_keyboard, TRUE);
144 hangul_keyboard = NULL;
148 ibus_hangul_engine_class_init (IBusHangulEngineClass *klass)
150 GObjectClass *object_class = G_OBJECT_CLASS (klass);
151 IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass);
152 IBusEngineClass *engine_class = IBUS_ENGINE_CLASS (klass);
154 parent_class = (IBusEngineClass *) g_type_class_peek_parent (klass);
156 object_class->constructor = ibus_hangul_engine_constructor;
157 ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_hangul_engine_destroy;
159 engine_class->process_key_event = ibus_hangul_engine_process_key_event;
161 engine_class->reset = ibus_hangul_engine_reset;
162 engine_class->enable = ibus_hangul_engine_enable;
163 engine_class->disable = ibus_hangul_engine_disable;
165 engine_class->focus_in = ibus_hangul_engine_focus_in;
166 engine_class->focus_out = ibus_hangul_engine_focus_out;
168 engine_class->page_up = ibus_hangul_engine_page_up;
169 engine_class->page_down = ibus_hangul_engine_page_down;
171 engine_class->cursor_up = ibus_hangul_engine_cursor_up;
172 engine_class->cursor_down = ibus_hangul_engine_cursor_down;
176 ibus_hangul_engine_init (IBusHangulEngine *hangul)
178 hangul->context = hangul_ic_new (hangul_keyboard->str);
179 hangul->hanja_list = NULL;
180 hangul->hangul_mode = TRUE;
181 hangul->hangul_mode_prop = ibus_property_new ("hangul_mode_prop",
191 hangul->prop_list = ibus_prop_list_new ();
192 ibus_prop_list_append (hangul->prop_list, hangul->hangul_mode_prop);
194 hangul->table = ibus_lookup_table_new (9, 0, TRUE, FALSE);
196 g_signal_connect (config, "value-changed",
197 G_CALLBACK(ibus_config_value_changed), hangul);
201 ibus_hangul_engine_constructor (GType type,
202 guint n_construct_params,
203 GObjectConstructParam *construct_params)
205 IBusHangulEngine *hangul;
207 hangul = (IBusHangulEngine *) G_OBJECT_CLASS (parent_class)->constructor (type,
211 return (GObject *)hangul;
216 ibus_hangul_engine_destroy (IBusHangulEngine *hangul)
218 if (hangul->prop_list) {
219 g_object_unref (hangul->prop_list);
220 hangul->prop_list = NULL;
223 if (hangul->hangul_mode_prop) {
224 g_object_unref (hangul->hangul_mode_prop);
225 hangul->hangul_mode_prop = NULL;
229 g_object_unref (hangul->table);
230 hangul->table = NULL;
233 if (hangul->context) {
234 hangul_ic_delete (hangul->context);
235 hangul->context = NULL;
238 IBUS_OBJECT_CLASS (parent_class)->destroy ((IBusObject *)hangul);
242 ibus_hangul_engine_update_preedit_text (IBusHangulEngine *hangul)
247 str = hangul_ic_get_preedit_string (hangul->context);
249 if (str != NULL && str[0] != 0) {
250 text = ibus_text_new_from_ucs4 (str);
251 ibus_text_append_attribute (text, IBUS_ATTR_TYPE_FOREGROUND, 0x00ffffff, 0, -1);
252 ibus_text_append_attribute (text, IBUS_ATTR_TYPE_BACKGROUND, 0x00000000, 0, -1);
253 ibus_engine_update_preedit_text ((IBusEngine *)hangul,
255 ibus_text_get_length (text),
257 g_object_unref (text);
260 text = ibus_text_new_from_static_string ("");
261 ibus_engine_update_preedit_text ((IBusEngine *)hangul, text, 0, FALSE);
262 g_object_unref (text);
267 ibus_hangul_engine_update_auxiliary_text (IBusHangulEngine *hangul)
273 cursor_pos = ibus_lookup_table_get_cursor_pos (hangul->table);
274 comment = hanja_list_get_nth_comment (hangul->hanja_list, cursor_pos);
276 text = ibus_text_new_from_string (comment);
277 ibus_engine_update_auxiliary_text ((IBusEngine *)hangul, text, TRUE);
278 g_object_unref (text);
282 ibus_hangul_engine_update_lookup_table (IBusHangulEngine *hangul)
284 ibus_engine_update_lookup_table ((IBusEngine *)hangul, hangul->table, TRUE);
288 ibus_hangul_engine_commit_current_candidate (IBusHangulEngine *hangul)
294 hangul_ic_reset (hangul->context);
295 ibus_hangul_engine_update_preedit_text (hangul);
297 cursor_pos = ibus_lookup_table_get_cursor_pos (hangul->table);
298 value = hanja_list_get_nth_value (hangul->hanja_list, cursor_pos);
300 text = ibus_text_new_from_string (value);
301 ibus_engine_commit_text ((IBusEngine *)hangul, text);
302 g_object_unref (text);
306 ibus_hangul_engine_open_lookup_table (IBusHangulEngine *hangul)
311 str = hangul_ic_get_preedit_string (hangul->context);
312 utf8 = g_ucs4_to_utf8 (str, -1, NULL, NULL, NULL);
314 HanjaList* list = hanja_table_match_suffix (hanja_table, utf8);
317 n = hanja_list_get_size (list);
319 ibus_lookup_table_clear (hangul->table);
320 for (i = 0; i < n; i++) {
321 const char* value = hanja_list_get_nth_value (list, i);
322 IBusText* text = ibus_text_new_from_string (value);
323 ibus_lookup_table_append_candidate (hangul->table, text);
324 g_object_unref (text);
327 hanja_list_delete (hangul->hanja_list);
328 hangul->hanja_list = list;
330 ibus_lookup_table_set_cursor_pos (hangul->table, 0);
331 ibus_hangul_engine_update_auxiliary_text (hangul);
332 ibus_hangul_engine_update_lookup_table (hangul);
339 ibus_hangul_engine_close_lookup_table (IBusHangulEngine *hangul)
341 ibus_engine_hide_lookup_table ((IBusEngine *)hangul);
342 ibus_engine_hide_auxiliary_text ((IBusEngine *)hangul);
343 hanja_list_delete (hangul->hanja_list);
344 hangul->hanja_list = NULL;
348 ibus_hangul_engine_toggle_lookup_table (IBusHangulEngine *hangul)
350 if (hangul->hanja_list != NULL) {
351 ibus_hangul_engine_close_lookup_table (hangul);
353 ibus_hangul_engine_open_lookup_table (hangul);
358 ibus_hangul_engine_process_candidate_key_event (IBusHangulEngine *hangul,
362 if (keyval == IBUS_Escape) {
363 ibus_hangul_engine_close_lookup_table (hangul);
364 } else if (keyval == IBUS_Return) {
365 ibus_hangul_engine_commit_current_candidate (hangul);
366 ibus_hangul_engine_close_lookup_table (hangul);
367 } else if (keyval >= IBUS_1 && keyval <= IBUS_9) {
372 page_size = ibus_lookup_table_get_page_size (hangul->table);
373 cursor_pos = ibus_lookup_table_get_cursor_pos (hangul->table);
374 page_no = cursor_pos / page_size;
376 cursor_pos = page_no * page_size + (keyval - IBUS_1);
377 ibus_lookup_table_set_cursor_pos (hangul->table, cursor_pos);
379 ibus_hangul_engine_commit_current_candidate (hangul);
380 ibus_hangul_engine_close_lookup_table (hangul);
381 } else if (keyval == IBUS_Left) {
382 ibus_lookup_table_cursor_up (hangul->table);
383 ibus_hangul_engine_update_lookup_table (hangul);
384 ibus_hangul_engine_update_auxiliary_text (hangul);
385 } else if (keyval == IBUS_Right) {
386 ibus_lookup_table_cursor_down (hangul->table);
387 ibus_hangul_engine_update_lookup_table (hangul);
388 ibus_hangul_engine_update_auxiliary_text (hangul);
389 } else if (keyval == IBUS_Up) {
390 ibus_lookup_table_page_up (hangul->table);
391 ibus_hangul_engine_update_lookup_table (hangul);
392 ibus_hangul_engine_update_auxiliary_text (hangul);
393 } else if (keyval == IBUS_Down) {
394 ibus_lookup_table_page_down (hangul->table);
395 ibus_hangul_engine_update_lookup_table (hangul);
396 ibus_hangul_engine_update_auxiliary_text (hangul);
397 } else if (keyval == IBUS_Page_Up) {
398 ibus_lookup_table_page_up (hangul->table);
399 ibus_hangul_engine_update_lookup_table (hangul);
400 ibus_hangul_engine_update_auxiliary_text (hangul);
401 } else if (keyval == IBUS_Page_Down) {
402 ibus_lookup_table_page_down (hangul->table);
403 ibus_hangul_engine_update_lookup_table (hangul);
404 ibus_hangul_engine_update_auxiliary_text (hangul);
405 } else if (keyval == IBUS_h) {
406 ibus_lookup_table_cursor_up (hangul->table);
407 ibus_hangul_engine_update_lookup_table (hangul);
408 ibus_hangul_engine_update_auxiliary_text (hangul);
409 } else if (keyval == IBUS_l) {
410 ibus_lookup_table_cursor_down (hangul->table);
411 ibus_hangul_engine_update_lookup_table (hangul);
412 ibus_hangul_engine_update_auxiliary_text (hangul);
413 } else if (keyval == IBUS_k) {
414 ibus_lookup_table_page_up (hangul->table);
415 ibus_hangul_engine_update_lookup_table (hangul);
416 ibus_hangul_engine_update_auxiliary_text (hangul);
417 } else if (keyval == IBUS_j) {
418 ibus_lookup_table_page_down (hangul->table);
419 ibus_hangul_engine_update_lookup_table (hangul);
420 ibus_hangul_engine_update_auxiliary_text (hangul);
427 ibus_hangul_engine_process_key_event (IBusEngine *engine,
431 IBusHangulEngine *hangul = (IBusHangulEngine *) engine;
436 if (modifiers & IBUS_RELEASE_MASK)
439 // if we don't ignore shift keys, shift key will make flush the preedit
440 // string. So you cannot input shift+key.
441 // Let's think about these examples:
444 if (keyval == IBUS_Shift_L || keyval == IBUS_Shift_R)
447 if (keyval == IBUS_F9 || keyval == IBUS_Hangul_Hanja) {
448 ibus_hangul_engine_toggle_lookup_table (hangul);
452 if (modifiers & (IBUS_CONTROL_MASK | IBUS_MOD1_MASK))
455 if (hangul->hanja_list != NULL) {
456 return ibus_hangul_engine_process_candidate_key_event (hangul,
460 if (keyval == IBUS_BackSpace) {
461 retval = hangul_ic_backspace (hangul->context);
463 retval = hangul_ic_process (hangul->context, keyval);
466 str = hangul_ic_get_commit_string (hangul->context);
467 if (str != NULL && str[0] != 0) {
468 IBusText *text = ibus_text_new_from_ucs4 (str);
469 ibus_engine_commit_text ((IBusEngine *)hangul, text);
470 g_object_unref (text);
473 ibus_hangul_engine_update_preedit_text (hangul);
476 ibus_hangul_engine_flush (hangul);
482 ibus_hangul_engine_flush (IBusHangulEngine *hangul)
487 str = hangul_ic_flush (hangul->context);
489 if (str == NULL || str[0] == 0)
492 text = ibus_text_new_from_ucs4 (str);
494 ibus_engine_hide_preedit_text ((IBusEngine *) hangul);
495 ibus_engine_commit_text ((IBusEngine *) hangul, text);
497 g_object_unref (text);
501 ibus_hangul_engine_toggle_hangul_mode (IBusHangulEngine *hangul)
504 hangul->hangul_mode = ! hangul->hangul_mode;
506 ibus_hangul_engine_flush (hangul);
508 if (hangul->hangul_mode) {
509 text = ibus_text_new_from_static_string ("한");
512 text = ibus_text_new_from_static_string ("A");
515 ibus_property_set_label (hangul->hangul_mode_prop, text);
516 ibus_engine_update_property ((IBusEngine *)hangul, hangul->hangul_mode_prop);
517 g_object_unref (text);
521 ibus_hangul_engine_focus_in (IBusEngine *engine)
523 IBusHangulEngine *hangul = (IBusHangulEngine *) engine;
525 ibus_engine_register_properties (engine, hangul->prop_list);
527 if (hangul->hanja_list != NULL) {
528 ibus_hangul_engine_update_lookup_table (hangul);
529 ibus_hangul_engine_update_auxiliary_text (hangul);
532 parent_class->focus_in (engine);
536 ibus_hangul_engine_focus_out (IBusEngine *engine)
538 IBusHangulEngine *hangul = (IBusHangulEngine *) engine;
540 if (hangul->hanja_list == NULL) {
541 ibus_hangul_engine_flush (hangul);
543 ibus_engine_hide_lookup_table (engine);
544 ibus_engine_hide_auxiliary_text (engine);
547 parent_class->focus_out ((IBusEngine *) hangul);
551 ibus_hangul_engine_reset (IBusEngine *engine)
553 IBusHangulEngine *hangul = (IBusHangulEngine *) engine;
555 ibus_hangul_engine_flush (hangul);
556 if (hangul->hanja_list != NULL) {
557 ibus_hangul_engine_close_lookup_table (hangul);
559 parent_class->reset (engine);
563 ibus_hangul_engine_enable (IBusEngine *engine)
565 parent_class->enable (engine);
569 ibus_hangul_engine_disable (IBusEngine *engine)
571 ibus_hangul_engine_focus_out (engine);
572 parent_class->disable (engine);
576 ibus_hangul_engine_page_up (IBusEngine *engine)
578 parent_class->page_up (engine);
582 ibus_hangul_engine_page_down (IBusEngine *engine)
584 parent_class->page_down (engine);
588 ibus_hangul_engine_cursor_up (IBusEngine *engine)
590 IBusHangulEngine *hangul = (IBusHangulEngine *) engine;
592 if (hangul->hanja_list != NULL) {
593 ibus_lookup_table_cursor_up (hangul->table);
594 ibus_hangul_engine_update_lookup_table (hangul);
595 ibus_hangul_engine_update_auxiliary_text (hangul);
598 parent_class->cursor_up (engine);
602 ibus_hangul_engine_cursor_down (IBusEngine *engine)
604 IBusHangulEngine *hangul = (IBusHangulEngine *) engine;
606 if (hangul->hanja_list != NULL) {
607 ibus_lookup_table_cursor_down (hangul->table);
608 ibus_hangul_engine_update_lookup_table (hangul);
609 ibus_hangul_engine_update_auxiliary_text (hangul);
612 parent_class->cursor_down (engine);
616 ibus_config_value_changed (IBusConfig *config,
617 const gchar *section,
622 IBusHangulEngine *hangul = (IBusHangulEngine *) user_data;
624 if (strcmp(section, "engine/Hangul") == 0) {
625 if (strcmp(name, "HangulKeyboard") == 0) {
626 const gchar *str = g_value_get_string (value);
627 g_string_assign (hangul_keyboard, str);
628 hangul_ic_select_keyboard (hangul->context, hangul_keyboard->str);