From: Jihoon Kim <jihoon48.kim@samsung.com>
[framework/uifw/ecore.git] / src / lib / ecore_imf / ecore_imf_context.c
1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #include <stdlib.h>
6 #include <string.h>
7 #include <locale.h>
8
9 #include <Ecore.h>
10 #include <ecore_private.h>
11
12 #include "Ecore_IMF.h"
13 #include "ecore_imf_private.h"
14
15 /**
16  * @defgroup Ecore_IMF_Context_Group Ecore Input Method Context Functions
17  *
18  * Functions that operate on Ecore Input Method Context objects.
19  */
20
21 /**
22  * Get the list of the available Input Method Context ids.
23  *
24  * Note that the caller is responsible for freeing the Eina_List
25  * when finished with it. There is no need to finish the list strings.
26  *
27  * @return Return an Eina_List of strings;
28  *         on failure it returns NULL.
29  * @ingroup Ecore_IMF_Context_Group
30  */
31 EAPI Eina_List *
32 ecore_imf_context_available_ids_get(void)
33 {
34    return ecore_imf_module_context_ids_get();
35 }
36
37 EAPI Eina_List *
38 ecore_imf_context_available_ids_by_canvas_type_get(const char *canvas_type)
39 {
40    return ecore_imf_module_context_ids_by_canvas_type_get(canvas_type);
41 }
42
43 /*
44  * Match @locale against @against.
45  *
46  * 'en_US' against 'en_US'       => 4
47  * 'en_US' against 'en'          => 3
48  * 'en', 'en_UK' against 'en_US' => 2
49  *  all locales, against '*'     => 1
50  */
51 static int
52 _ecore_imf_context_match_locale(const char *locale, const char *against, int against_len)
53 {
54   if (strcmp(against, "*") == 0)
55     return 1;
56
57   if (strcasecmp(locale, against) == 0)
58     return 4;
59
60   if (strncasecmp(locale, against, 2) == 0)
61     return (against_len == 2) ? 3 : 2;
62
63   return 0;
64 }
65
66 /**
67  * Get the id of the default Input Method Context.
68  * The id may to used to create a new instance of an Input Method
69  * Context object.
70  *
71  * @return Return a string containing the id of the default Input
72  *         Method Context; on failure it returns NULL.
73  * @ingroup Ecore_IMF_Context_Group
74  */
75 EAPI const char *
76 ecore_imf_context_default_id_get(void)
77 {
78    return ecore_imf_context_default_id_by_canvas_type_get(NULL);
79 }
80
81 EAPI const char *
82 ecore_imf_context_default_id_by_canvas_type_get(const char *canvas_type)
83 {
84    const char *id;
85    Eina_List *modules;
86    Ecore_IMF_Module *module;
87    char *locale;
88    char *tmp;
89    int best_goodness = 0;
90
91    id = getenv("ECORE_IMF_MODULE");
92    if (id)
93      {
94         if (strcmp(id, "none") == 0) return NULL;
95         if (ecore_imf_module_get(id)) return id;
96      }
97
98    modules = ecore_imf_module_available_get();
99    if (!modules) return NULL;
100
101    locale = setlocale(LC_CTYPE, NULL);
102    if (!locale) return NULL;
103
104    locale = strdup(locale);
105
106    tmp = strchr(locale, '.');
107    if (tmp) *tmp = '\0';
108    tmp = strchr(locale, '@');
109    if (tmp) *tmp = '\0';
110
111    id = NULL;
112
113    EINA_LIST_FREE(modules, module)
114      {
115         if (canvas_type &&
116             strcmp(module->info->canvas_type, canvas_type) == 0)
117           continue;
118
119         const char *p = module->info->default_locales;
120         while (p)
121           {
122              const char *q = strchr(p, ':');
123              int goodness = _ecore_imf_context_match_locale(locale, p, q ? (size_t)(q - p) : strlen (p));
124
125               if (goodness > best_goodness)
126                 {
127                    id = module->info->id;
128                    best_goodness = goodness;
129                 }
130
131               p = q ? q + 1 : NULL;
132           }
133      }
134
135    free(locale);
136    return id;
137 }
138
139 /**
140  * Retrieve the info for the Input Method Context with @p id.
141  *
142  * @param id The Input Method Context id to query for.
143  * @return Return a #Ecore_IMF_Context_Info for the Input Method Context with @p id;
144  *         on failure it returns NULL.
145  * @ingroup Ecore_IMF_Context_Group
146  */
147 EAPI const Ecore_IMF_Context_Info *
148 ecore_imf_context_info_by_id_get(const char *id)
149 {
150    Ecore_IMF_Module *module;
151
152    if (!id) return NULL;
153    module = ecore_imf_module_get(id);
154    if (!module) return NULL;
155    return module->info;
156 }
157
158 /**
159  * Create a new Input Method Context defined by the given id.
160  *
161  * @param id The Input Method Context id.
162  * @return A newly allocated Input Method Context;
163  *         on failure it returns NULL.
164  * @ingroup Ecore_IMF_Context_Group
165  */
166 EAPI Ecore_IMF_Context *
167 ecore_imf_context_add(const char *id)
168 {
169    Ecore_IMF_Context *ctx;
170
171    if (!id) return NULL;
172    ctx = ecore_imf_module_context_create(id);
173    if (!ctx || !ctx->klass) return NULL;
174    if (ctx->klass->add) ctx->klass->add(ctx);
175    /* default use_preedit is EINA_TRUE, so let's make sure it's
176     * set on the immodule */
177    ecore_imf_context_use_preedit_set(ctx, EINA_TRUE);
178    /* default input_mode is ECORE_IMF_INPUT_MODE_FULL, so let's make sure it's
179     * set on the immodule */
180    ecore_imf_context_input_mode_set(ctx, ECORE_IMF_INPUT_MODE_FULL);
181    return ctx;
182 }
183
184 /**
185  * Retrieve the info for the given Input Method Context.
186  *
187  * @param ctx An #Ecore_IMF_Context.
188  * @return Return a #Ecore_IMF_Context_Info for the given Input Method Context;
189  *         on failure it returns NULL.
190  * @ingroup Ecore_IMF_Context_Group
191  */
192 EAPI const Ecore_IMF_Context_Info *
193 ecore_imf_context_info_get(Ecore_IMF_Context *ctx)
194 {
195    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
196      {
197         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
198                          "ecore_imf_context_info_get");
199         return NULL;
200      }
201    return ctx->module->info;
202 }
203
204 /**
205  * Delete the given Input Method Context and free its memory.
206  *
207  * @param ctx An #Ecore_IMF_Context.
208  * @ingroup Ecore_IMF_Context_Group
209  */
210 EAPI void
211 ecore_imf_context_del(Ecore_IMF_Context *ctx)
212 {
213    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
214      {
215         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
216                          "ecore_imf_context_del");
217         return;
218      }
219    if (ctx->klass->del) ctx->klass->del(ctx);
220    ECORE_MAGIC_SET(ctx, ECORE_MAGIC_NONE);
221    free(ctx);
222 }
223
224 /**
225  * Set the client window for the Input Method Context; this is the
226  * Ecore_X_Window when using X11, Ecore_Win32_Window when using Win32, etc.
227  * This window is used in order to correctly position status windows, and may
228  * also be used for purposes internal to the Input Method Context.
229  *
230  * @param ctx An #Ecore_IMF_Context.
231  * @param window The client window. This may be NULL to indicate
232  *               that the previous client window no longer exists.
233  * @ingroup Ecore_IMF_Context_Group
234  */
235 EAPI void
236 ecore_imf_context_client_window_set(Ecore_IMF_Context *ctx, void *window)
237 {
238    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
239      {
240         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
241                          "ecore_imf_context_client_window_set");
242         return;
243      }
244    if (ctx->klass->client_window_set) ctx->klass->client_window_set(ctx, window);
245    ctx->window = window;
246 }
247
248 /**
249  * Get the client window of the Input Method Context
250  *
251  * See @ref ecore_imf_context_client_window_set for more details.
252  *
253  * @param ctx An #Ecore_IMF_Context.
254  * @return Return the client window.
255  * @ingroup Ecore_IMF_Context_Group
256  * @since 1.1.0
257  */
258 EAPI void *
259 ecore_imf_context_client_window_get(Ecore_IMF_Context *ctx)
260 {
261    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
262      {
263         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
264                          "ecore_imf_context_client_window_get");
265         return NULL;
266      }
267    return ctx->window;
268 }
269
270 /**
271  * Set the client canvas for the Input Method Context; this is the
272  * canvas in which the input appears.
273  * The canvas type can be determined by using the context canvas type.
274  * Actually only canvas with type "evas" (Evas *) is supported.
275  * This canvas may be used in order to correctly position status windows, and may
276  * also be used for purposes internal to the Input Method Context.
277  *
278  * @param ctx An #Ecore_IMF_Context.
279  * @param canvas The client canvas. This may be NULL to indicate
280  *               that the previous client canvas no longer exists.
281  * @ingroup Ecore_IMF_Context_Group
282  */
283 EAPI void
284 ecore_imf_context_client_canvas_set(Ecore_IMF_Context *ctx, void *canvas)
285 {
286    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
287      {
288         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
289                          "ecore_imf_context_client_canvas_set");
290         return;
291      }
292    if (ctx->klass->client_canvas_set) ctx->klass->client_canvas_set(ctx, canvas);
293    ctx->client_canvas = canvas;
294 }
295
296 /**
297  * Get the client canvas of the Input Method Context.
298  *
299  * See @ref ecore_imf_context_client_canvas_set for more details.
300  *
301  * @param ctx An #Ecore_IMF_Context.
302  * @return Return the client canvas.
303  * @ingroup Ecore_IMF_Context_Group
304  * @since 1.1.0
305  */
306 EAPI void *
307 ecore_imf_context_client_canvas_get(Ecore_IMF_Context *ctx)
308 {
309    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
310      {
311         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
312                          "ecore_imf_context_client_canvas_get");
313         return NULL;
314      }
315    return ctx->client_canvas;
316 }
317
318 /**
319  * Ask the Input Method Context to show itself.
320  *
321  * @param ctx An #Ecore_IMF_Context.
322  * @ingroup Ecore_IMF_Context_Group
323  */
324 EAPI void
325 ecore_imf_context_show(Ecore_IMF_Context *ctx)
326 {
327    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
328      {
329         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
330                          "ecore_imf_context_show");
331         return;
332      }
333    if (ctx->klass->show) ctx->klass->show(ctx);
334 }
335
336 /**
337  * Ask the Input Method Context to hide itself.
338  *
339  * @param ctx An #Ecore_IMF_Context.
340  * @ingroup Ecore_IMF_Context_Group
341  */
342 EAPI void
343 ecore_imf_context_hide(Ecore_IMF_Context *ctx)
344 {
345    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
346      {
347         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
348                          "ecore_imf_context_hide");
349         return;
350      }
351    if (ctx->klass->hide) ctx->klass->hide(ctx);
352 }
353
354 /**
355  * Retrieve the current preedit string and cursor position
356  * for the Input Method Context.
357  *
358  * @param ctx An #Ecore_IMF_Context.
359  * @param str Location to store the retrieved string. The
360  *            string retrieved must be freed with free().
361  * @param cursor_pos Location to store position of cursor (in characters)
362  *                   within the preedit string.
363  * @ingroup Ecore_IMF_Context_Group
364  */
365 EAPI void
366 ecore_imf_context_preedit_string_get(Ecore_IMF_Context *ctx, char **str, int *cursor_pos)
367 {
368    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
369      {
370         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
371                          "ecore_imf_context_preedit_string_get");
372         return;
373      }
374    if (ctx->klass->preedit_string_get)
375      ctx->klass->preedit_string_get(ctx, str, cursor_pos);
376    else
377      {
378         if (str) *str = strdup("");
379         if (cursor_pos) *cursor_pos = 0;
380      }
381 }
382
383 /**
384  * Retrieve the current preedit string, atrributes and
385  * cursor position for the Input Method Context.
386  *
387  * @param ctx An #Ecore_IMF_Context.
388  * @param str Location to store the retrieved string. The
389  *            string retrieved must be freed with free().
390  * @param attrs an Eina_List of attributes
391  * @param cursor_pos Location to store position of cursor (in characters)
392  *                   within the preedit string.
393  * @ingroup Ecore_IMF_Context_Group
394  * @since 1.1.0
395  */
396 EAPI void
397 ecore_imf_context_preedit_string_with_attributes_get(Ecore_IMF_Context *ctx, char **str, Eina_List **attrs, int *cursor_pos)
398 {
399    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
400      {
401         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
402                          "ecore_imf_context_preedit_string_with_attributes_get");
403         return;
404      }
405    if (ctx->klass->preedit_string_with_attributes_get)
406      ctx->klass->preedit_string_with_attributes_get(ctx, str, attrs, cursor_pos);
407    else
408      {
409         if (str) *str = strdup("");
410         if (attrs) *attrs = NULL;
411         if (cursor_pos) *cursor_pos = 0;
412      }
413 }
414
415 /**
416  * Notify the Input Method Context that the widget to which its
417  * correspond has gained focus.
418  *
419  * @param ctx An #Ecore_IMF_Context.
420  * @ingroup Ecore_IMF_Context_Group
421  */
422 EAPI void
423 ecore_imf_context_focus_in(Ecore_IMF_Context *ctx)
424 {
425    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
426      {
427         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
428                          "ecore_imf_context_focus_in");
429         return;
430      }
431    if (ctx->klass->focus_in) ctx->klass->focus_in(ctx);
432 }
433
434 /**
435  * Notify the Input Method Context that the widget to which its
436  * correspond has lost focus.
437  *
438  * @param ctx An #Ecore_IMF_Context.
439  * @ingroup Ecore_IMF_Context_Group
440  */
441 EAPI void
442 ecore_imf_context_focus_out(Ecore_IMF_Context *ctx)
443 {
444    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
445      {
446         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
447                          "ecore_imf_context_focus_out");
448         return;
449      }
450    if (ctx->klass->focus_out) ctx->klass->focus_out(ctx);
451 }
452
453 /**
454  * Notify the Input Method Context that a change such as a
455  * change in cursor position has been made. This will typically
456  * cause the Input Method Context to clear the preedit state.
457  *
458  * @param ctx An #Ecore_IMF_Context.
459  * @ingroup Ecore_IMF_Context_Group
460  */
461 EAPI void
462 ecore_imf_context_reset(Ecore_IMF_Context *ctx)
463 {
464    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
465      {
466         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
467                          "ecore_imf_context_reset");
468         return;
469      }
470    if (ctx->klass->reset) ctx->klass->reset(ctx);
471 }
472
473 /**
474  * Notify the Input Method Context that a change in the cursor
475  * position has been made.
476  *
477  * @param ctx An #Ecore_IMF_Context.
478  * @param cursor_pos New cursor position in characters.
479  * @ingroup Ecore_IMF_Context_Group
480  */
481 EAPI void
482 ecore_imf_context_cursor_position_set(Ecore_IMF_Context *ctx, int cursor_pos)
483 {
484    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
485      {
486         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
487                          "ecore_imf_context_cursor_position_set");
488         return;
489      }
490    if (ctx->klass->cursor_position_set) ctx->klass->cursor_position_set(ctx, cursor_pos);
491 }
492
493 /**
494  * Set whether the IM context should use the preedit string
495  * to display feedback. If @use_preedit is EINA_FALSE (default
496  * is EINA_TRUE), then the IM context may use some other method to display
497  * feedback, such as displaying it in a child of the root window.
498  *
499  * @param ctx An #Ecore_IMF_Context.
500  * @param use_preedit Whether the IM context should use the preedit string.
501  * @ingroup Ecore_IMF_Context_Group
502  */
503 EAPI void
504 ecore_imf_context_use_preedit_set(Ecore_IMF_Context *ctx, Eina_Bool use_preedit)
505 {
506    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
507      {
508         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
509                          "ecore_imf_context_use_preedit_set");
510         return;
511      }
512    if (ctx->klass->use_preedit_set) ctx->klass->use_preedit_set(ctx, use_preedit);
513 }
514
515 /**
516  * Set the callback to be used on get_surrounding request.
517  *
518  * This callback will be called when the Input Method Context
519  * module requests the surrounding context.
520  *
521  * @param ctx An #Ecore_IMF_Context.
522  * @param func The callback to be called.
523  * @param data The data pointer to be passed to @p func
524  * @ingroup Ecore_IMF_Context_Group
525  */
526 EAPI void
527 ecore_imf_context_retrieve_surrounding_callback_set(Ecore_IMF_Context *ctx, Eina_Bool (*func)(void *data, Ecore_IMF_Context *ctx, char **text, int *cursor_pos), const void *data)
528 {
529    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
530      {
531         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
532                          "ecore_imf_context_retrieve_surrounding_callback_set");
533         return;
534      }
535
536    ctx->retrieve_surrounding_func = func;
537    ctx->retrieve_surrounding_data = (void *) data;
538 }
539
540 /**
541  * Set the input mode used by the Ecore Input Context.
542  *
543  * The input mode can be one of the input modes defined in
544  * #Ecore_IMF_Input_Mode. The default input mode is
545  * ECORE_IMF_INPUT_MODE_FULL.
546  *
547  * @param ctx An #Ecore_IMF_Context.
548  * @param input_mode The input mode to be used by @p ctx.
549  * @ingroup Ecore_IMF_Context_Group
550  */
551 EAPI void
552 ecore_imf_context_input_mode_set(Ecore_IMF_Context *ctx, Ecore_IMF_Input_Mode input_mode)
553 {
554    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
555      {
556         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
557                          "ecore_imf_context_input_mode_set");
558         return;
559      }
560    if (ctx->klass->input_mode_set) ctx->klass->input_mode_set(ctx, input_mode);
561    ctx->input_mode = input_mode;
562 }
563
564 /**
565  * Get the input mode being used by the Ecore Input Context.
566  *
567  * See @ref ecore_imf_context_input_mode_set for more details.
568  *
569  * @param ctx An #Ecore_IMF_Context.
570  * @return The input mode being used by @p ctx.
571  * @ingroup Ecore_IMF_Context_Group
572  */
573 EAPI Ecore_IMF_Input_Mode
574 ecore_imf_context_input_mode_get(Ecore_IMF_Context *ctx)
575 {
576    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
577      {
578         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
579                          "ecore_imf_context_input_mode_set");
580         return 0;
581      }
582    return ctx->input_mode;
583 }
584
585 /**
586  * Allow an Ecore Input Context to internally handle an event.
587  * If this function returns EINA_TRUE, then no further processing
588  * should be done for this event.
589  *
590  * Input methods must be able to accept all types of events (simply
591  * returning EINA_FALSE if the event was not handled), but there is no
592  * obligation of any events to be submitted to this function.
593  *
594  * @param ctx An #Ecore_IMF_Context.
595  * @param type The type of event defined by #Ecore_IMF_Event_Type.
596  * @param event The event itself.
597  * @return EINA_TRUE if the event was handled; otherwise EINA_FALSE.
598  * @ingroup Ecore_IMF_Context_Group
599  */
600 EAPI Eina_Bool
601 ecore_imf_context_filter_event(Ecore_IMF_Context *ctx, Ecore_IMF_Event_Type type, Ecore_IMF_Event *event)
602 {
603    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
604      {
605         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
606                          "ecore_imf_context_filter_event");
607         return EINA_FALSE;
608      }
609    if (ctx->klass->filter_event) return ctx->klass->filter_event(ctx, type, event);
610    return EINA_FALSE;
611 }
612
613 /**
614  * @defgroup Ecore_IMF_Context_Module_Group Ecore Input Method Context Module Functions
615  *
616  * Functions that should be used by Ecore Input Method Context modules.
617  */
618
619 /**
620  * Creates a new Input Method Context with klass specified by @p ctxc.
621  *
622  * This method should be used by modules implementing the Input
623  * Method Context interface.
624  *
625  * @param ctxc An #Ecore_IMF_Context_Class.
626  * @return A new #Ecore_IMF_Context; on failure it returns NULL.
627  * @ingroup Ecore_IMF_Context_Module_Group
628  */
629 EAPI Ecore_IMF_Context *
630 ecore_imf_context_new(const Ecore_IMF_Context_Class *ctxc)
631 {
632    Ecore_IMF_Context *ctx;
633
634    if (!ctxc) return NULL;
635    ctx = calloc(1, sizeof(Ecore_IMF_Context));
636    if (!ctx) return NULL;
637    ECORE_MAGIC_SET(ctx, ECORE_MAGIC_CONTEXT);
638    ctx->klass = ctxc;
639    ctx->data = NULL;
640    ctx->retrieve_surrounding_func = NULL;
641    ctx->retrieve_surrounding_data = NULL;
642    return ctx;
643 }
644
645 /**
646  * Set the Input Method Context specific data.
647  *
648  * Note that this method should be used by modules to set
649  * the Input Method Context specific data and it's not meant to
650  * be used by applications to store application specific data.
651  *
652  * @param ctx An #Ecore_IMF_Context.
653  * @param data The Input Method Context specific data.
654  * @return A new #Ecore_IMF_Context; on failure it returns NULL.
655  * @ingroup Ecore_IMF_Context_Module_Group
656  */
657 EAPI void
658 ecore_imf_context_data_set(Ecore_IMF_Context *ctx, void *data)
659 {
660    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
661      {
662         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
663                          "ecore_imf_context_data_set");
664         return;
665      }
666    ctx->data = data;
667 }
668
669 /**
670  * Get the Input Method Context specific data.
671  *
672  * See @ref ecore_imf_context_data_set for more details.
673  *
674  * @param ctx An #Ecore_IMF_Context.
675  * @return The Input Method Context specific data.
676  * @ingroup Ecore_IMF_Context_Module_Group
677  */
678 EAPI void *ecore_imf_context_data_get(Ecore_IMF_Context *ctx)
679 {
680    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
681      {
682         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
683                          "ecore_imf_context_data_get");
684         return NULL;
685      }
686    return ctx->data;
687 }
688
689 /**
690  * Retrieve context around insertion point.
691  *
692  * This function is implemented by calling the
693  * Ecore_IMF_Context::retrieve_surrounding_func (
694  * set using #ecore_imf_context_retrieve_surrounding_callback_set).
695  *
696  * There is no obligation for a widget to respond to the
697  * ::retrieve_surrounding_func, so input methods must be prepared
698  * to function without context.
699  *
700  * @param ctx An #Ecore_IMF_Context.
701  * @param text Location to store a UTF-8 encoded string of text
702  *             holding context around the insertion point.
703  *             If the function returns EINA_TRUE, then you must free
704  *             the result stored in this location with free().
705  * @param cursor_pos Location to store the position in characters of
706  *                   the insertion cursor within @text.
707  * @return EINA_TRUE if surrounding text was provided; otherwise EINA_FALSE.
708  * @ingroup Ecore_IMF_Context_Module_Group
709  */
710 EAPI Eina_Bool
711 ecore_imf_context_surrounding_get(Ecore_IMF_Context *ctx, char **text, int *cursor_pos)
712 {
713    int result = EINA_FALSE;
714
715    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
716      {
717         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
718                          "ecore_imf_context_surrounding_get");
719         return EINA_FALSE;
720      }
721
722    if (ctx->retrieve_surrounding_func)
723      {
724         result = ctx->retrieve_surrounding_func(ctx->retrieve_surrounding_data, ctx, text, cursor_pos);
725         if (!result)
726           {
727              if (text) *text = NULL;
728              if (cursor_pos) *cursor_pos = 0;
729           }
730      }
731    return result;
732 }
733
734 static void
735 _ecore_imf_event_free_preedit(void *data __UNUSED__, void *event)
736 {
737    free(event);
738 }
739
740 /**
741  * Adds ECORE_IMF_EVENT_PREEDIT_START to the event queue.
742  *
743  * @param ctx An #Ecore_IMF_Context.
744  * @ingroup Ecore_IMF_Context_Module_Group
745  */
746 EAPI void
747 ecore_imf_context_preedit_start_event_add(Ecore_IMF_Context *ctx)
748 {
749    Ecore_IMF_Event_Commit *ev;
750
751    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
752      {
753         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
754                          "ecore_imf_context_preedit_start_event_add");
755         return;
756      }
757
758    ev = malloc(sizeof(Ecore_IMF_Event_Preedit_Start));
759    ev->ctx = ctx;
760    ecore_event_add(ECORE_IMF_EVENT_PREEDIT_START,
761                    ev, _ecore_imf_event_free_preedit, NULL);
762 }
763
764 /**
765  * Adds ECORE_IMF_EVENT_PREEDIT_END to the event queue.
766  *
767  * @param ctx An #Ecore_IMF_Context.
768  * @ingroup Ecore_IMF_Context_Module_Group
769  */
770 EAPI void
771 ecore_imf_context_preedit_end_event_add(Ecore_IMF_Context *ctx)
772 {
773    Ecore_IMF_Event_Commit *ev;
774
775    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
776      {
777         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
778                          "ecore_imf_context_preedit_end_event_add");
779         return;
780      }
781
782    ev = malloc(sizeof(Ecore_IMF_Event_Preedit_End));
783    ev->ctx = ctx;
784    ecore_event_add(ECORE_IMF_EVENT_PREEDIT_END,
785                    ev, _ecore_imf_event_free_preedit, NULL);
786 }
787
788 /**
789  * Adds ECORE_IMF_EVENT_PREEDIT_CHANGED to the event queue.
790  *
791  * @param ctx An #Ecore_IMF_Context.
792  * @ingroup Ecore_IMF_Context_Module_Group
793  */
794 EAPI void
795 ecore_imf_context_preedit_changed_event_add(Ecore_IMF_Context *ctx)
796 {
797    Ecore_IMF_Event_Commit *ev;
798
799    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
800      {
801         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
802                          "ecore_imf_context_preedit_changed_event_add");
803         return;
804      }
805
806    ev = malloc(sizeof(Ecore_IMF_Event_Preedit_Changed));
807    ev->ctx = ctx;
808    ecore_event_add(ECORE_IMF_EVENT_PREEDIT_CHANGED,
809                    ev, _ecore_imf_event_free_preedit, NULL);
810 }
811
812 static void
813 _ecore_imf_event_free_commit(void *data __UNUSED__, void *event)
814 {
815    Ecore_IMF_Event_Commit *ev;
816
817    ev = event;
818    if (ev->str) free(ev->str);
819    free(ev);
820 }
821
822 /**
823  * Adds ECORE_IMF_EVENT_COMMIT to the event queue.
824  *
825  * @param ctx An #Ecore_IMF_Context.
826  * @param str The committed string.
827  * @ingroup Ecore_IMF_Context_Module_Group
828  */
829 EAPI void
830 ecore_imf_context_commit_event_add(Ecore_IMF_Context *ctx, const char *str)
831 {
832    Ecore_IMF_Event_Commit *ev;
833
834    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
835      {
836         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
837                          "ecore_imf_context_commit_event_add");
838         return;
839      }
840
841    ev = malloc(sizeof(Ecore_IMF_Event_Commit));
842    ev->ctx = ctx;
843    ev->str = str ? strdup(str) : NULL;
844    ecore_event_add(ECORE_IMF_EVENT_COMMIT,
845                    ev, _ecore_imf_event_free_commit, NULL);
846
847 }
848
849 static void
850 _ecore_imf_event_free_delete_surrounding(void *data __UNUSED__, void *event)
851 {
852    free(event);
853 }
854
855 /**
856  * Adds ECORE_IMF_EVENT_DELETE_SURROUNDING to the event queue.
857  *
858  * @param ctx An #Ecore_IMF_Context.
859  * @param offset The start offset of surrounding to be deleted.
860  * @param n_chars The number of characters to be deleted.
861  * @ingroup Ecore_IMF_Context_Module_Group
862  */
863 EAPI void
864 ecore_imf_context_delete_surrounding_event_add(Ecore_IMF_Context *ctx, int offset, int n_chars)
865 {
866    Ecore_IMF_Event_Delete_Surrounding *ev;
867
868    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
869      {
870         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
871                          "ecore_imf_context_delete_surrounding_event_add");
872         return;
873      }
874
875    ev = malloc(sizeof(Ecore_IMF_Event_Delete_Surrounding));
876    ev->ctx = ctx;
877    ev->offset = offset;
878    ev->n_chars = n_chars;
879    ecore_event_add(ECORE_IMF_EVENT_DELETE_SURROUNDING,
880                    ev, _ecore_imf_event_free_delete_surrounding, NULL);
881 }