Fix backspace processing:
[platform/upstream/ibus-hangul.git] / src / engine.c
1 /* vim:set et sts=4: */
2
3 #include <ibus.h>
4 #include <hangul.h>
5 #include <string.h>
6 #include "engine.h"
7
8 typedef struct _IBusHangulEngine IBusHangulEngine;
9 typedef struct _IBusHangulEngineClass IBusHangulEngineClass;
10
11 struct _IBusHangulEngine {
12         IBusEngine parent;
13
14     /* members */
15     HangulInputContext *context;
16     gboolean hangul_mode;
17
18     IBusLookupTable *table;
19     IBusProperty    *hangul_mode_prop;
20     IBusPropList    *prop_list;
21 };
22
23 struct _IBusHangulEngineClass {
24         IBusEngineClass parent;
25 };
26
27 /* functions prototype */
28 static void     ibus_hangul_engine_class_init   (IBusHangulEngineClass  *klass);
29 static void     ibus_hangul_engine_init             (IBusHangulEngine           *hangul);
30 static GObject*
31             ibus_hangul_engine_constructor  (GType                   type,
32                                              guint                   n_construct_params,
33                                              GObjectConstructParam  *construct_params);
34 static void     ibus_hangul_engine_destroy              (IBusHangulEngine               *hangul);
35 static gboolean
36                         ibus_hangul_engine_process_key_event
37                                             (IBusEngine             *engine,
38                                              guint                       keyval,
39                                              guint                       modifiers);
40 static void ibus_hangul_engine_focus_in     (IBusEngine             *engine);
41 static void ibus_hangul_engine_focus_out    (IBusEngine             *engine);
42 static void ibus_hangul_engine_reset        (IBusEngine             *engine);
43 static void ibus_hangul_engine_enable       (IBusEngine             *engine);
44 static void ibus_hangul_engine_disable      (IBusEngine             *engine);
45 #if 0
46 static void ibus_engine_set_cursor_location (IBusEngine             *engine,
47                                              gint                    x,
48                                              gint                    y,
49                                              gint                    w,
50                                              gint                    h);
51 static void ibus_hangul_engine_set_capabilities
52                                             (IBusEngine             *engine,
53                                              guint                   caps);
54 #endif
55 static void ibus_hangul_engine_page_up      (IBusEngine             *engine);
56 static void ibus_hangul_engine_page_down    (IBusEngine             *engine);
57 static void ibus_hangul_engine_cursor_up    (IBusEngine             *engine);
58 static void ibus_hangul_engine_cursor_down  (IBusEngine             *engine);
59 static void ibus_hangul_engine_toggle_hangul_mode
60                                             (IBusHangulEngine       *hangul);
61 #if 0
62 static void ibus_hangul_property_activate   (IBusEngine             *engine,
63                                              const gchar            *prop_name,
64                                              gint                    prop_state);
65 static void ibus_hangul_engine_property_show
66                                                                                         (IBusEngine             *engine,
67                                              const gchar            *prop_name);
68 static void ibus_hangul_engine_property_hide
69                                                                                         (IBusEngine             *engine,
70                                              const gchar            *prop_name);
71 #endif
72
73 static void ibus_hangul_engine_flush        (IBusHangulEngine       *hangul);
74 static void ibus_hangul_engine_update_preedit_text
75                                             (IBusHangulEngine       *hangul);
76
77 static IBusEngineClass *parent_class = NULL;
78
79 GType
80 ibus_hangul_engine_get_type (void)
81 {
82         static GType type = 0;
83
84         static const GTypeInfo type_info = {
85                 sizeof (IBusHangulEngineClass),
86                 (GBaseInitFunc)         NULL,
87                 (GBaseFinalizeFunc) NULL,
88                 (GClassInitFunc)        ibus_hangul_engine_class_init,
89                 NULL,
90                 NULL,
91                 sizeof (IBusHangulEngine),
92                 0,
93                 (GInstanceInitFunc)     ibus_hangul_engine_init,
94         };
95
96         if (type == 0) {
97                 type = g_type_register_static (IBUS_TYPE_ENGINE,
98                                                                            "IBusHangulEngine",
99                                                                            &type_info,
100                                                                            (GTypeFlags) 0);
101         }
102
103         return type;
104 }
105
106 static void
107 ibus_hangul_engine_class_init (IBusHangulEngineClass *klass)
108 {
109     GObjectClass *object_class = G_OBJECT_CLASS (klass);
110         IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass);
111         IBusEngineClass *engine_class = IBUS_ENGINE_CLASS (klass);
112
113         parent_class = (IBusEngineClass *) g_type_class_peek_parent (klass);
114
115     object_class->constructor = ibus_hangul_engine_constructor;
116         ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_hangul_engine_destroy;
117
118     engine_class->process_key_event = ibus_hangul_engine_process_key_event;
119
120     engine_class->reset = ibus_hangul_engine_reset;
121     engine_class->enable = ibus_hangul_engine_enable;
122     engine_class->disable = ibus_hangul_engine_disable;
123
124     engine_class->focus_in = ibus_hangul_engine_focus_in;
125     engine_class->focus_out = ibus_hangul_engine_focus_out;
126
127     engine_class->page_up = ibus_hangul_engine_page_up;
128     engine_class->page_down = ibus_hangul_engine_page_down;
129
130     engine_class->cursor_up = ibus_hangul_engine_cursor_up;
131     engine_class->cursor_down = ibus_hangul_engine_cursor_down;
132 }
133
134 static void
135 ibus_hangul_engine_init (IBusHangulEngine *hangul)
136 {
137     hangul->context = hangul_ic_new ("2");
138     hangul->hangul_mode = TRUE;
139     hangul->hangul_mode_prop = ibus_property_new ("hangul_mode_prop",
140                                            PROP_TYPE_NORMAL,
141                                            NULL,
142                                            NULL,
143                                            NULL,
144                                            TRUE,
145                                            FALSE,
146                                            0,
147                                            NULL);
148
149     hangul->prop_list = ibus_prop_list_new ();
150     ibus_prop_list_append (hangul->prop_list,  hangul->hangul_mode_prop);
151
152     hangul->table = ibus_lookup_table_new (9, 0, TRUE, TRUE);
153 }
154
155 static GObject*
156 ibus_hangul_engine_constructor (GType                   type,
157                                 guint                   n_construct_params,
158                                 GObjectConstructParam  *construct_params)
159 {
160     IBusHangulEngine *hangul;
161
162     hangul = (IBusHangulEngine *) G_OBJECT_CLASS (parent_class)->constructor (type,
163                                                        n_construct_params,
164                                                        construct_params);
165
166     return (GObject *)hangul;
167 }
168
169
170 static void
171 ibus_hangul_engine_destroy (IBusHangulEngine *hangul)
172 {
173     if (hangul->prop_list) {
174         g_object_unref (hangul->prop_list);
175         hangul->prop_list = NULL;
176     }
177
178     if (hangul->hangul_mode_prop) {
179         g_object_unref (hangul->hangul_mode_prop);
180         hangul->hangul_mode_prop = NULL;
181     }
182
183     if (hangul->table) {
184         g_object_unref (hangul->table);
185         hangul->table = NULL;
186     }
187
188     if (hangul->context) {
189         hangul_ic_delete (hangul->context);
190         hangul->context = NULL;
191     }
192
193         IBUS_OBJECT_CLASS (parent_class)->destroy ((IBusObject *)hangul);
194 }
195
196 static void
197 ibus_hangul_engine_update_preedit_text (IBusHangulEngine *hangul)
198 {
199     const gunichar *str;
200     IBusText *text;
201
202     str = hangul_ic_get_preedit_string (hangul->context);
203
204     if (str != NULL && str[0] != 0) {
205         text = ibus_text_new_from_ucs4 (str);
206         ibus_text_append_attribute (text, IBUS_ATTR_TYPE_FOREGROUND, 0x00ffffff, 0, -1);
207         ibus_text_append_attribute (text, IBUS_ATTR_TYPE_BACKGROUND, 0x00000000, 0, -1);
208         ibus_engine_update_preedit_text ((IBusEngine *)hangul,
209                                          text,
210                                          ibus_text_get_length (text),
211                                          TRUE);
212         g_object_unref (text);
213     }
214     else {
215         text = ibus_text_new_from_static_string ("");
216         ibus_engine_update_preedit_text ((IBusEngine *)hangul, text, 0, FALSE);
217         g_object_unref (text);
218     }
219 }
220
221 static gboolean
222 ibus_hangul_engine_process_key_event (IBusEngine     *engine,
223                                       guint           keyval,
224                                       guint           modifiers)
225 {
226     IBusHangulEngine *hangul = (IBusHangulEngine *) engine;
227
228     gboolean retval;
229     const gunichar *str;
230
231     if (modifiers & IBUS_RELEASE_MASK)
232         return FALSE;
233
234     if (modifiers & (IBUS_CONTROL_MASK | IBUS_MOD1_MASK))
235         return FALSE;
236
237     if (keyval == IBUS_BackSpace) {
238         retval = hangul_ic_backspace (hangul->context);
239     } else {
240         retval = hangul_ic_process (hangul->context, keyval);
241     }
242
243     str = hangul_ic_get_commit_string (hangul->context);
244     if (str != NULL && str[0] != 0) {
245         IBusText *text = ibus_text_new_from_ucs4 (str);
246         ibus_engine_commit_text ((IBusEngine *)hangul, text);
247         g_object_unref (text);
248     }
249
250     ibus_hangul_engine_update_preedit_text (hangul);
251
252     if (!retval)
253         ibus_hangul_engine_flush (hangul);
254
255     return retval;
256 }
257
258 static void
259 ibus_hangul_engine_flush (IBusHangulEngine *hangul)
260 {
261     const gunichar *str;
262     IBusText *text;
263
264     str = hangul_ic_flush (hangul->context);
265
266     if (str == NULL || str[0] == 0)
267         return;
268
269     text = ibus_text_new_from_ucs4 (str);
270
271     ibus_engine_hide_preedit_text ((IBusEngine *) hangul);
272     ibus_engine_commit_text ((IBusEngine *) hangul, text);
273
274     g_object_unref (text);
275 }
276
277 static void
278 ibus_hangul_engine_toggle_hangul_mode (IBusHangulEngine *hangul)
279 {
280     IBusText *text;
281     hangul->hangul_mode = ! hangul->hangul_mode;
282
283     ibus_hangul_engine_flush (hangul);
284
285     if (hangul->hangul_mode) {
286         text = ibus_text_new_from_static_string ("한");
287     }
288     else {
289         text = ibus_text_new_from_static_string ("A");
290     }
291
292     ibus_property_set_label (hangul->hangul_mode_prop, text);
293     ibus_engine_update_property ((IBusEngine *)hangul, hangul->hangul_mode_prop);
294     g_object_unref (text);
295 }
296
297 static void
298 ibus_hangul_engine_focus_in (IBusEngine *engine)
299 {
300     IBusHangulEngine *hangul = (IBusHangulEngine *) engine;
301
302     ibus_engine_register_properties (engine, hangul->prop_list);
303
304     parent_class->focus_in (engine);
305 }
306
307 static void
308 ibus_hangul_engine_focus_out (IBusEngine *engine)
309 {
310     IBusHangulEngine *hangul = (IBusHangulEngine *) engine;
311
312     ibus_hangul_engine_flush (hangul);
313
314     parent_class->focus_out ((IBusEngine *) hangul);
315 }
316
317 static void
318 ibus_hangul_engine_reset (IBusEngine *engine)
319 {
320     IBusHangulEngine *hangul = (IBusHangulEngine *) engine;
321
322     ibus_hangul_engine_flush (hangul);
323     parent_class->reset (engine);
324 }
325
326 static void
327 ibus_hangul_engine_enable (IBusEngine *engine)
328 {
329     parent_class->enable (engine);
330 }
331
332 static void
333 ibus_hangul_engine_disable (IBusEngine *engine)
334 {
335     ibus_hangul_engine_focus_out (engine);
336     parent_class->disable (engine);
337 }
338
339 static void
340 ibus_hangul_engine_page_up (IBusEngine *engine)
341 {
342     parent_class->page_up (engine);
343 }
344
345 static void
346 ibus_hangul_engine_page_down (IBusEngine *engine)
347 {
348     parent_class->page_down (engine);
349 }
350
351 static void
352 ibus_hangul_engine_cursor_up (IBusEngine *engine)
353 {
354     parent_class->cursor_up (engine);
355 }
356
357 static void
358 ibus_hangul_engine_cursor_down (IBusEngine *engine)
359 {
360     parent_class->cursor_down (engine);
361 }
362