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);
78 static IBusEngineClass *parent_class = NULL;
79 static HanjaTable *hanja_table = NULL;
82 ibus_hangul_engine_get_type (void)
84 static GType type = 0;
86 static const GTypeInfo type_info = {
87 sizeof (IBusHangulEngineClass),
89 (GBaseFinalizeFunc) NULL,
90 (GClassInitFunc) ibus_hangul_engine_class_init,
93 sizeof (IBusHangulEngine),
95 (GInstanceInitFunc) ibus_hangul_engine_init,
99 type = g_type_register_static (IBUS_TYPE_ENGINE,
109 ibus_hangul_init (void)
111 hanja_table = hanja_table_load (NULL);
115 ibus_hangul_exit (void)
117 hanja_table_delete (hanja_table);
121 ibus_hangul_engine_class_init (IBusHangulEngineClass *klass)
123 GObjectClass *object_class = G_OBJECT_CLASS (klass);
124 IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass);
125 IBusEngineClass *engine_class = IBUS_ENGINE_CLASS (klass);
127 parent_class = (IBusEngineClass *) g_type_class_peek_parent (klass);
129 object_class->constructor = ibus_hangul_engine_constructor;
130 ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_hangul_engine_destroy;
132 engine_class->process_key_event = ibus_hangul_engine_process_key_event;
134 engine_class->reset = ibus_hangul_engine_reset;
135 engine_class->enable = ibus_hangul_engine_enable;
136 engine_class->disable = ibus_hangul_engine_disable;
138 engine_class->focus_in = ibus_hangul_engine_focus_in;
139 engine_class->focus_out = ibus_hangul_engine_focus_out;
141 engine_class->page_up = ibus_hangul_engine_page_up;
142 engine_class->page_down = ibus_hangul_engine_page_down;
144 engine_class->cursor_up = ibus_hangul_engine_cursor_up;
145 engine_class->cursor_down = ibus_hangul_engine_cursor_down;
149 ibus_hangul_engine_init (IBusHangulEngine *hangul)
151 hangul->context = hangul_ic_new ("2");
152 hangul->hanja_list = NULL;
153 hangul->hangul_mode = TRUE;
154 hangul->hangul_mode_prop = ibus_property_new ("hangul_mode_prop",
164 hangul->prop_list = ibus_prop_list_new ();
165 ibus_prop_list_append (hangul->prop_list, hangul->hangul_mode_prop);
167 hangul->table = ibus_lookup_table_new (9, 0, TRUE, FALSE);
171 ibus_hangul_engine_constructor (GType type,
172 guint n_construct_params,
173 GObjectConstructParam *construct_params)
175 IBusHangulEngine *hangul;
177 hangul = (IBusHangulEngine *) G_OBJECT_CLASS (parent_class)->constructor (type,
181 return (GObject *)hangul;
186 ibus_hangul_engine_destroy (IBusHangulEngine *hangul)
188 if (hangul->prop_list) {
189 g_object_unref (hangul->prop_list);
190 hangul->prop_list = NULL;
193 if (hangul->hangul_mode_prop) {
194 g_object_unref (hangul->hangul_mode_prop);
195 hangul->hangul_mode_prop = NULL;
199 g_object_unref (hangul->table);
200 hangul->table = NULL;
203 if (hangul->context) {
204 hangul_ic_delete (hangul->context);
205 hangul->context = NULL;
208 IBUS_OBJECT_CLASS (parent_class)->destroy ((IBusObject *)hangul);
212 ibus_hangul_engine_update_preedit_text (IBusHangulEngine *hangul)
217 str = hangul_ic_get_preedit_string (hangul->context);
219 if (str != NULL && str[0] != 0) {
220 text = ibus_text_new_from_ucs4 (str);
221 ibus_text_append_attribute (text, IBUS_ATTR_TYPE_FOREGROUND, 0x00ffffff, 0, -1);
222 ibus_text_append_attribute (text, IBUS_ATTR_TYPE_BACKGROUND, 0x00000000, 0, -1);
223 ibus_engine_update_preedit_text ((IBusEngine *)hangul,
225 ibus_text_get_length (text),
227 g_object_unref (text);
230 text = ibus_text_new_from_static_string ("");
231 ibus_engine_update_preedit_text ((IBusEngine *)hangul, text, 0, FALSE);
232 g_object_unref (text);
237 ibus_hangul_engine_update_auxiliary_text (IBusHangulEngine *hangul)
243 cursor_pos = ibus_lookup_table_get_cursor_pos (hangul->table);
244 comment = hanja_list_get_nth_comment (hangul->hanja_list, cursor_pos);
246 text = ibus_text_new_from_string (comment);
247 ibus_engine_update_auxiliary_text ((IBusEngine *)hangul, text, TRUE);
248 g_object_unref (text);
252 ibus_hangul_engine_update_lookup_table (IBusHangulEngine *hangul)
254 ibus_engine_update_lookup_table ((IBusEngine *)hangul, hangul->table, TRUE);
258 ibus_hangul_engine_commit_current_candidate (IBusHangulEngine *hangul)
264 hangul_ic_reset (hangul->context);
265 ibus_hangul_engine_update_preedit_text (hangul);
267 cursor_pos = ibus_lookup_table_get_cursor_pos (hangul->table);
268 value = hanja_list_get_nth_value (hangul->hanja_list, cursor_pos);
270 text = ibus_text_new_from_string (value);
271 ibus_engine_commit_text ((IBusEngine *)hangul, text);
272 g_object_unref (text);
276 ibus_hangul_engine_open_lookup_table (IBusHangulEngine *hangul)
281 str = hangul_ic_get_preedit_string (hangul->context);
282 utf8 = g_ucs4_to_utf8 (str, -1, NULL, NULL, NULL);
284 HanjaList* list = hanja_table_match_suffix (hanja_table, utf8);
287 n = hanja_list_get_size (list);
289 ibus_lookup_table_clear (hangul->table);
290 for (i = 0; i < n; i++) {
291 const char* value = hanja_list_get_nth_value (list, i);
292 IBusText* text = ibus_text_new_from_string (value);
293 ibus_lookup_table_append_candidate (hangul->table, text);
294 g_object_unref (text);
297 hanja_list_delete (hangul->hanja_list);
298 hangul->hanja_list = list;
300 ibus_lookup_table_set_cursor_pos (hangul->table, 0);
301 ibus_hangul_engine_update_auxiliary_text (hangul);
302 ibus_hangul_engine_update_lookup_table (hangul);
309 ibus_hangul_engine_close_lookup_table (IBusHangulEngine *hangul)
311 ibus_engine_hide_lookup_table ((IBusEngine *)hangul);
312 ibus_engine_hide_auxiliary_text ((IBusEngine *)hangul);
313 hanja_list_delete (hangul->hanja_list);
314 hangul->hanja_list = NULL;
318 ibus_hangul_engine_toggle_lookup_table (IBusHangulEngine *hangul)
320 if (hangul->hanja_list != NULL) {
321 ibus_hangul_engine_close_lookup_table (hangul);
323 ibus_hangul_engine_open_lookup_table (hangul);
328 ibus_hangul_engine_process_candidate_key_event (IBusHangulEngine *hangul,
332 if (keyval == IBUS_Escape) {
333 ibus_hangul_engine_close_lookup_table (hangul);
334 } else if (keyval == IBUS_Return) {
335 ibus_hangul_engine_commit_current_candidate (hangul);
336 ibus_hangul_engine_close_lookup_table (hangul);
337 } else if (keyval >= IBUS_1 && keyval <= IBUS_9) {
342 page_size = ibus_lookup_table_get_page_size (hangul->table);
343 cursor_pos = ibus_lookup_table_get_cursor_pos (hangul->table);
344 page_no = cursor_pos / page_size;
346 cursor_pos = page_no * page_size + (keyval - IBUS_1);
347 ibus_lookup_table_set_cursor_pos (hangul->table, cursor_pos);
349 ibus_hangul_engine_commit_current_candidate (hangul);
350 ibus_hangul_engine_close_lookup_table (hangul);
351 } else if (keyval == IBUS_Left) {
352 ibus_lookup_table_cursor_up (hangul->table);
353 ibus_hangul_engine_update_lookup_table (hangul);
354 ibus_hangul_engine_update_auxiliary_text (hangul);
355 } else if (keyval == IBUS_Right) {
356 ibus_lookup_table_cursor_down (hangul->table);
357 ibus_hangul_engine_update_lookup_table (hangul);
358 ibus_hangul_engine_update_auxiliary_text (hangul);
359 } else if (keyval == IBUS_Up) {
360 ibus_lookup_table_page_up (hangul->table);
361 ibus_hangul_engine_update_lookup_table (hangul);
362 ibus_hangul_engine_update_auxiliary_text (hangul);
363 } else if (keyval == IBUS_Down) {
364 ibus_lookup_table_page_down (hangul->table);
365 ibus_hangul_engine_update_lookup_table (hangul);
366 ibus_hangul_engine_update_auxiliary_text (hangul);
367 } else if (keyval == IBUS_Page_Up) {
368 ibus_lookup_table_page_up (hangul->table);
369 ibus_hangul_engine_update_lookup_table (hangul);
370 ibus_hangul_engine_update_auxiliary_text (hangul);
371 } else if (keyval == IBUS_Page_Down) {
372 ibus_lookup_table_page_down (hangul->table);
373 ibus_hangul_engine_update_lookup_table (hangul);
374 ibus_hangul_engine_update_auxiliary_text (hangul);
375 } else if (keyval == IBUS_h) {
376 ibus_lookup_table_cursor_up (hangul->table);
377 ibus_hangul_engine_update_lookup_table (hangul);
378 ibus_hangul_engine_update_auxiliary_text (hangul);
379 } else if (keyval == IBUS_l) {
380 ibus_lookup_table_cursor_down (hangul->table);
381 ibus_hangul_engine_update_lookup_table (hangul);
382 ibus_hangul_engine_update_auxiliary_text (hangul);
383 } else if (keyval == IBUS_k) {
384 ibus_lookup_table_page_up (hangul->table);
385 ibus_hangul_engine_update_lookup_table (hangul);
386 ibus_hangul_engine_update_auxiliary_text (hangul);
387 } else if (keyval == IBUS_j) {
388 ibus_lookup_table_page_down (hangul->table);
389 ibus_hangul_engine_update_lookup_table (hangul);
390 ibus_hangul_engine_update_auxiliary_text (hangul);
397 ibus_hangul_engine_process_key_event (IBusEngine *engine,
401 IBusHangulEngine *hangul = (IBusHangulEngine *) engine;
406 if (modifiers & IBUS_RELEASE_MASK)
409 // if we don't ignore shift keys, shift key will make flush the preedit
410 // string. So you cannot input shift+key.
411 // Let's think about these examples:
414 if (keyval == IBUS_Shift_L || keyval == IBUS_Shift_R)
417 if (keyval == IBUS_F9 || keyval == IBUS_Hangul_Hanja) {
418 ibus_hangul_engine_toggle_lookup_table (hangul);
422 if (modifiers & (IBUS_CONTROL_MASK | IBUS_MOD1_MASK))
425 if (hangul->hanja_list != NULL) {
426 return ibus_hangul_engine_process_candidate_key_event (hangul,
430 if (keyval == IBUS_BackSpace) {
431 retval = hangul_ic_backspace (hangul->context);
433 retval = hangul_ic_process (hangul->context, keyval);
436 str = hangul_ic_get_commit_string (hangul->context);
437 if (str != NULL && str[0] != 0) {
438 IBusText *text = ibus_text_new_from_ucs4 (str);
439 ibus_engine_commit_text ((IBusEngine *)hangul, text);
440 g_object_unref (text);
443 ibus_hangul_engine_update_preedit_text (hangul);
446 ibus_hangul_engine_flush (hangul);
452 ibus_hangul_engine_flush (IBusHangulEngine *hangul)
457 str = hangul_ic_flush (hangul->context);
459 if (str == NULL || str[0] == 0)
462 text = ibus_text_new_from_ucs4 (str);
464 ibus_engine_hide_preedit_text ((IBusEngine *) hangul);
465 ibus_engine_commit_text ((IBusEngine *) hangul, text);
467 g_object_unref (text);
471 ibus_hangul_engine_toggle_hangul_mode (IBusHangulEngine *hangul)
474 hangul->hangul_mode = ! hangul->hangul_mode;
476 ibus_hangul_engine_flush (hangul);
478 if (hangul->hangul_mode) {
479 text = ibus_text_new_from_static_string ("한");
482 text = ibus_text_new_from_static_string ("A");
485 ibus_property_set_label (hangul->hangul_mode_prop, text);
486 ibus_engine_update_property ((IBusEngine *)hangul, hangul->hangul_mode_prop);
487 g_object_unref (text);
491 ibus_hangul_engine_focus_in (IBusEngine *engine)
493 IBusHangulEngine *hangul = (IBusHangulEngine *) engine;
495 ibus_engine_register_properties (engine, hangul->prop_list);
497 if (hangul->hanja_list != NULL) {
498 ibus_hangul_engine_update_lookup_table (hangul);
499 ibus_hangul_engine_update_auxiliary_text (hangul);
502 parent_class->focus_in (engine);
506 ibus_hangul_engine_focus_out (IBusEngine *engine)
508 IBusHangulEngine *hangul = (IBusHangulEngine *) engine;
510 if (hangul->hanja_list == NULL) {
511 ibus_hangul_engine_flush (hangul);
513 ibus_engine_hide_lookup_table (engine);
514 ibus_engine_hide_auxiliary_text (engine);
517 parent_class->focus_out ((IBusEngine *) hangul);
521 ibus_hangul_engine_reset (IBusEngine *engine)
523 IBusHangulEngine *hangul = (IBusHangulEngine *) engine;
525 ibus_hangul_engine_flush (hangul);
526 if (hangul->hanja_list != NULL) {
527 ibus_hangul_engine_close_lookup_table (hangul);
529 parent_class->reset (engine);
533 ibus_hangul_engine_enable (IBusEngine *engine)
535 parent_class->enable (engine);
539 ibus_hangul_engine_disable (IBusEngine *engine)
541 ibus_hangul_engine_focus_out (engine);
542 parent_class->disable (engine);
546 ibus_hangul_engine_page_up (IBusEngine *engine)
548 parent_class->page_up (engine);
552 ibus_hangul_engine_page_down (IBusEngine *engine)
554 parent_class->page_down (engine);
558 ibus_hangul_engine_cursor_up (IBusEngine *engine)
560 IBusHangulEngine *hangul = (IBusHangulEngine *) engine;
562 if (hangul->hanja_list != NULL) {
563 ibus_lookup_table_cursor_up (hangul->table);
564 ibus_hangul_engine_update_lookup_table (hangul);
565 ibus_hangul_engine_update_auxiliary_text (hangul);
568 parent_class->cursor_up (engine);
572 ibus_hangul_engine_cursor_down (IBusEngine *engine)
574 IBusHangulEngine *hangul = (IBusHangulEngine *) engine;
576 if (hangul->hanja_list != NULL) {
577 ibus_lookup_table_cursor_down (hangul->table);
578 ibus_hangul_engine_update_lookup_table (hangul);
579 ibus_hangul_engine_update_auxiliary_text (hangul);
582 parent_class->cursor_down (engine);