From: Jihoon Kim <imfine98@gmail.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
179    /* default prediction is EINA_TRUE, so let's make sure it's
180     * set on the immodule */
181    ecore_imf_context_prediction_allow_set(ctx, EINA_TRUE);
182
183    /* default autocapital type is SENTENCE type, so let's make sure it's
184     * set on the immodule */
185    ecore_imf_context_autocapital_type_set(ctx, ECORE_IMF_AUTOCAPITAL_TYPE_SENTENCE);
186
187    /* default input panel enabled status is EINA_TRUE, so let's make sure it's
188     * set on the immodule */
189    ecore_imf_context_input_panel_enabled_set(ctx, EINA_TRUE);
190
191    /* default input_mode is ECORE_IMF_INPUT_MODE_FULL, so let's make sure it's
192     * set on the immodule */
193    ecore_imf_context_input_mode_set(ctx, ECORE_IMF_INPUT_MODE_FULL);
194    return ctx;
195 }
196
197 /**
198  * Retrieve the info for the given Input Method Context.
199  *
200  * @param ctx An #Ecore_IMF_Context.
201  * @return Return a #Ecore_IMF_Context_Info for the given Input Method Context;
202  *         on failure it returns NULL.
203  * @ingroup Ecore_IMF_Context_Group
204  */
205 EAPI const Ecore_IMF_Context_Info *
206 ecore_imf_context_info_get(Ecore_IMF_Context *ctx)
207 {
208    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
209      {
210         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
211                          "ecore_imf_context_info_get");
212         return NULL;
213      }
214    return ctx->module->info;
215 }
216
217 /**
218  * Delete the given Input Method Context and free its memory.
219  *
220  * @param ctx An #Ecore_IMF_Context.
221  * @ingroup Ecore_IMF_Context_Group
222  */
223 EAPI void
224 ecore_imf_context_del(Ecore_IMF_Context *ctx)
225 {
226    Ecore_IMF_Func_Node *fn;
227
228    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
229      {
230         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
231                          "ecore_imf_context_del");
232         return;
233      }
234    if (ctx->klass->del) ctx->klass->del(ctx);
235
236    if (ctx->callbacks)
237      {
238         EINA_LIST_FREE(ctx->callbacks, fn)
239            free(fn);
240      }
241
242    ECORE_MAGIC_SET(ctx, ECORE_MAGIC_NONE);
243    free(ctx);
244 }
245
246 /**
247  * Set the client window for the Input Method Context; this is the
248  * Ecore_X_Window when using X11, Ecore_Win32_Window when using Win32, etc.
249  * This window is used in order to correctly position status windows, and may
250  * also be used for purposes internal to the Input Method Context.
251  *
252  * @param ctx An #Ecore_IMF_Context.
253  * @param window The client window. This may be NULL to indicate
254  *               that the previous client window no longer exists.
255  * @ingroup Ecore_IMF_Context_Group
256  */
257 EAPI void
258 ecore_imf_context_client_window_set(Ecore_IMF_Context *ctx, void *window)
259 {
260    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
261      {
262         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
263                          "ecore_imf_context_client_window_set");
264         return;
265      }
266    if (ctx->klass->client_window_set) ctx->klass->client_window_set(ctx, window);
267    ctx->window = window;
268 }
269
270 /**
271  * Get the client window of the Input Method Context
272  *
273  * See @ref ecore_imf_context_client_window_set for more details.
274  *
275  * @param ctx An #Ecore_IMF_Context.
276  * @return Return the client window.
277  * @ingroup Ecore_IMF_Context_Group
278  * @since 1.1.0
279  */
280 EAPI void *
281 ecore_imf_context_client_window_get(Ecore_IMF_Context *ctx)
282 {
283    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
284      {
285         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
286                          "ecore_imf_context_client_window_get");
287         return NULL;
288      }
289    return ctx->window;
290 }
291
292 /**
293  * Set the client canvas for the Input Method Context; this is the
294  * canvas in which the input appears.
295  * The canvas type can be determined by using the context canvas type.
296  * Actually only canvas with type "evas" (Evas *) is supported.
297  * This canvas may be used in order to correctly position status windows, and may
298  * also be used for purposes internal to the Input Method Context.
299  *
300  * @param ctx An #Ecore_IMF_Context.
301  * @param canvas The client canvas. This may be NULL to indicate
302  *               that the previous client canvas no longer exists.
303  * @ingroup Ecore_IMF_Context_Group
304  */
305 EAPI void
306 ecore_imf_context_client_canvas_set(Ecore_IMF_Context *ctx, void *canvas)
307 {
308    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
309      {
310         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
311                          "ecore_imf_context_client_canvas_set");
312         return;
313      }
314    if (ctx->klass->client_canvas_set) ctx->klass->client_canvas_set(ctx, canvas);
315    ctx->client_canvas = canvas;
316 }
317
318 /**
319  * Get the client canvas of the Input Method Context.
320  *
321  * See @ref ecore_imf_context_client_canvas_set for more details.
322  *
323  * @param ctx An #Ecore_IMF_Context.
324  * @return Return the client canvas.
325  * @ingroup Ecore_IMF_Context_Group
326  * @since 1.1.0
327  */
328 EAPI void *
329 ecore_imf_context_client_canvas_get(Ecore_IMF_Context *ctx)
330 {
331    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
332      {
333         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
334                          "ecore_imf_context_client_canvas_get");
335         return NULL;
336      }
337    return ctx->client_canvas;
338 }
339
340 /**
341  * Ask the Input Method Context to show itself.
342  *
343  * @param ctx An #Ecore_IMF_Context.
344  * @ingroup Ecore_IMF_Context_Group
345  */
346 EAPI void
347 ecore_imf_context_show(Ecore_IMF_Context *ctx)
348 {
349    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
350      {
351         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
352                          "ecore_imf_context_show");
353         return;
354      }
355    if (ctx->klass->show) ctx->klass->show(ctx);
356 }
357
358 /**
359  * Ask the Input Method Context to hide itself.
360  *
361  * @param ctx An #Ecore_IMF_Context.
362  * @ingroup Ecore_IMF_Context_Group
363  */
364 EAPI void
365 ecore_imf_context_hide(Ecore_IMF_Context *ctx)
366 {
367    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
368      {
369         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
370                          "ecore_imf_context_hide");
371         return;
372      }
373    if (ctx->klass->hide) ctx->klass->hide(ctx);
374 }
375
376 /**
377  * Retrieve the current preedit string and cursor position
378  * for the Input Method Context.
379  *
380  * @param ctx An #Ecore_IMF_Context.
381  * @param str Location to store the retrieved string. The
382  *            string retrieved must be freed with free().
383  * @param cursor_pos Location to store position of cursor (in characters)
384  *                   within the preedit string.
385  * @ingroup Ecore_IMF_Context_Group
386  */
387 EAPI void
388 ecore_imf_context_preedit_string_get(Ecore_IMF_Context *ctx, char **str, int *cursor_pos)
389 {
390    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
391      {
392         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
393                          "ecore_imf_context_preedit_string_get");
394         return;
395      }
396    if (ctx->klass->preedit_string_get)
397      ctx->klass->preedit_string_get(ctx, str, cursor_pos);
398    else
399      {
400         if (str) *str = strdup("");
401         if (cursor_pos) *cursor_pos = 0;
402      }
403 }
404
405 /**
406  * Retrieve the current preedit string, atrributes and
407  * cursor position for the Input Method Context.
408  *
409  * @param ctx An #Ecore_IMF_Context.
410  * @param str Location to store the retrieved string. The
411  *            string retrieved must be freed with free().
412  * @param attrs an Eina_List of attributes
413  * @param cursor_pos Location to store position of cursor (in characters)
414  *                   within the preedit string.
415  * @ingroup Ecore_IMF_Context_Group
416  * @since 1.1.0
417  */
418 EAPI void
419 ecore_imf_context_preedit_string_with_attributes_get(Ecore_IMF_Context *ctx, char **str, Eina_List **attrs, int *cursor_pos)
420 {
421    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
422      {
423         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
424                          "ecore_imf_context_preedit_string_with_attributes_get");
425         return;
426      }
427    if (ctx->klass->preedit_string_with_attributes_get)
428      ctx->klass->preedit_string_with_attributes_get(ctx, str, attrs, cursor_pos);
429    else
430      {
431         if (str) *str = strdup("");
432         if (attrs) *attrs = NULL;
433         if (cursor_pos) *cursor_pos = 0;
434      }
435 }
436
437 /**
438  * Notify the Input Method Context that the widget to which its
439  * correspond has gained focus.
440  *
441  * @param ctx An #Ecore_IMF_Context.
442  * @ingroup Ecore_IMF_Context_Group
443  */
444 EAPI void
445 ecore_imf_context_focus_in(Ecore_IMF_Context *ctx)
446 {
447    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
448      {
449         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
450                          "ecore_imf_context_focus_in");
451         return;
452      }
453    if (ctx->klass->focus_in) ctx->klass->focus_in(ctx);
454 }
455
456 /**
457  * Notify the Input Method Context that the widget to which its
458  * correspond has lost focus.
459  *
460  * @param ctx An #Ecore_IMF_Context.
461  * @ingroup Ecore_IMF_Context_Group
462  */
463 EAPI void
464 ecore_imf_context_focus_out(Ecore_IMF_Context *ctx)
465 {
466    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
467      {
468         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
469                          "ecore_imf_context_focus_out");
470         return;
471      }
472    if (ctx->klass->focus_out) ctx->klass->focus_out(ctx);
473 }
474
475 /**
476  * Notify the Input Method Context that a change such as a
477  * change in cursor position has been made. This will typically
478  * cause the Input Method Context to clear the preedit state.
479  *
480  * @param ctx An #Ecore_IMF_Context.
481  * @ingroup Ecore_IMF_Context_Group
482  */
483 EAPI void
484 ecore_imf_context_reset(Ecore_IMF_Context *ctx)
485 {
486    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
487      {
488         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
489                          "ecore_imf_context_reset");
490         return;
491      }
492    if (ctx->klass->reset) ctx->klass->reset(ctx);
493 }
494
495 /**
496  * Notify the Input Method Context that a change in the cursor
497  * position has been made.
498  *
499  * @param ctx An #Ecore_IMF_Context.
500  * @param cursor_pos New cursor position in characters.
501  * @ingroup Ecore_IMF_Context_Group
502  */
503 EAPI void
504 ecore_imf_context_cursor_position_set(Ecore_IMF_Context *ctx, int cursor_pos)
505 {
506    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
507      {
508         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
509                          "ecore_imf_context_cursor_position_set");
510         return;
511      }
512    if (ctx->klass->cursor_position_set) ctx->klass->cursor_position_set(ctx, cursor_pos);
513 }
514
515 /**
516  * Notify the Input Method Context that a change in the cursor
517  * location has been made. The location is relative to the canvas.
518  *
519  * @param ctx An #Ecore_IMF_Context.
520  * @param x cursor x position.
521  * @param x cursor y position.
522  * @param w cursor width.
523  * @param h cursor height.
524  * @ingroup Ecore_IMF_Context_Group
525  * @since 1.1.0
526  */
527 EAPI void
528 ecore_imf_context_cursor_location_set(Ecore_IMF_Context *ctx, int x, int y, int w, int h)
529 {
530    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
531      {
532         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
533                          "ecore_imf_context_cursor_location_set");
534         return;
535      }
536    if (ctx->klass->cursor_location_set) ctx->klass->cursor_location_set(ctx, x, y, w, h);
537 }
538
539 /**
540  * Set whether the IM context should use the preedit string
541  * to display feedback. If @c use_preedit is EINA_FALSE (default
542  * is EINA_TRUE), then the IM context may use some other method to display
543  * feedback, such as displaying it in a child of the root window.
544  *
545  * @param ctx An #Ecore_IMF_Context.
546  * @param use_preedit Whether the IM context should use the preedit string.
547  * @ingroup Ecore_IMF_Context_Group
548  */
549 EAPI void
550 ecore_imf_context_use_preedit_set(Ecore_IMF_Context *ctx, Eina_Bool use_preedit)
551 {
552    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
553      {
554         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
555                          "ecore_imf_context_use_preedit_set");
556         return;
557      }
558    if (ctx->klass->use_preedit_set) ctx->klass->use_preedit_set(ctx, use_preedit);
559 }
560
561 /**
562  * Set whether the IM context should allow to use the text prediction.
563  * If @c prediction is EINA_FALSE (default is EINA_TRUE), then the IM context will not display the text prediction window.
564  *
565  * @param ctx An #Ecore_IMF_Context.
566  * @param prediction Whether the IM context should allow to use the text prediction.
567  * @ingroup Ecore_IMF_Context_Group
568  * @since 1.1.0
569  */
570 EAPI void
571 ecore_imf_context_prediction_allow_set(Ecore_IMF_Context *ctx, Eina_Bool prediction)
572 {
573    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
574      {
575         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
576                          "ecore_imf_context_prediction_allow_set");
577         return;
578      }
579
580    ctx->allow_prediction = prediction;
581
582    if (ctx->klass->prediction_allow_set)
583      ctx->klass->prediction_allow_set(ctx, prediction);
584 }
585
586 /**
587  * Get whether the IM context should allow to use the text prediction.
588  *
589  * @param ctx An #Ecore_IMF_Context.
590  * @return EINA_TRUE if it allows to use the text prediction, otherwise EINA_FALSE.
591  * @ingroup Ecore_IMF_Context_Group
592  * @since 1.1.0
593  */
594 EAPI Eina_Bool
595 ecore_imf_context_prediction_allow_get(Ecore_IMF_Context *ctx)
596 {
597    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
598      {
599         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
600                          "ecore_imf_context_prediction_allow_get");
601         return EINA_FALSE;
602      }
603
604    return ctx->allow_prediction;
605 }
606
607 /**
608  * Set the autocapitalization type on the immodule. 
609  *
610  * @param ctx An #Ecore_IMF_Context.
611  * @param autocapital_type the autocapitalization type.
612  * @ingroup Ecore_IMF_Context_Group
613  * @since 1.1.0
614  */
615 EAPI void
616 ecore_imf_context_autocapital_type_set(Ecore_IMF_Context *ctx, Ecore_IMF_Autocapital_Type autocapital_type)
617 {
618    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
619      {
620         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
621                          "ecore_imf_context_autocapital_type_set");
622         return;
623      }
624
625    ctx->autocapital_type = autocapital_type;
626
627    if (ctx->klass->autocapital_type_set) ctx->klass->autocapital_type_set(ctx, autocapital_type);
628 }
629
630 /**
631  * Get the autocapitalization type.
632  *
633  * @param ctx An #Ecore_IMF_Context.
634  * @return The autocapital type being used by @p ctx.
635  * @ingroup Ecore_IMF_Context_Group
636  * @since 1.1.0
637  */
638 EAPI Ecore_IMF_Autocapital_Type
639 ecore_imf_context_autocapital_type_get(Ecore_IMF_Context *ctx)
640 {
641    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
642      {
643         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
644                          "ecore_imf_context_autocapital_allow_get");
645         return ECORE_IMF_AUTOCAPITAL_TYPE_NONE;
646      }
647
648    return ctx->autocapital_type;
649 }
650
651 /**
652  * Set the callback to be used on get_surrounding request.
653  *
654  * This callback will be called when the Input Method Context
655  * module requests the surrounding context.
656  *
657  * @param ctx An #Ecore_IMF_Context.
658  * @param func The callback to be called.
659  * @param data The data pointer to be passed to @p func
660  * @ingroup Ecore_IMF_Context_Group
661  */
662 EAPI void
663 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)
664 {
665    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
666      {
667         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
668                          "ecore_imf_context_retrieve_surrounding_callback_set");
669         return;
670      }
671
672    ctx->retrieve_surrounding_func = func;
673    ctx->retrieve_surrounding_data = (void *) data;
674 }
675
676 /**
677  * Set the input mode used by the Ecore Input Context.
678  *
679  * The input mode can be one of the input modes defined in
680  * #Ecore_IMF_Input_Mode. The default input mode is
681  * ECORE_IMF_INPUT_MODE_FULL.
682  *
683  * @param ctx An #Ecore_IMF_Context.
684  * @param input_mode The input mode to be used by @p ctx.
685  * @ingroup Ecore_IMF_Context_Group
686  */
687 EAPI void
688 ecore_imf_context_input_mode_set(Ecore_IMF_Context *ctx, Ecore_IMF_Input_Mode input_mode)
689 {
690    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
691      {
692         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
693                          "ecore_imf_context_input_mode_set");
694         return;
695      }
696    if (ctx->klass->input_mode_set) ctx->klass->input_mode_set(ctx, input_mode);
697    ctx->input_mode = input_mode;
698 }
699
700 /**
701  * Get the input mode being used by the Ecore Input Context.
702  *
703  * See @ref ecore_imf_context_input_mode_set for more details.
704  *
705  * @param ctx An #Ecore_IMF_Context.
706  * @return The input mode being used by @p ctx.
707  * @ingroup Ecore_IMF_Context_Group
708  */
709 EAPI Ecore_IMF_Input_Mode
710 ecore_imf_context_input_mode_get(Ecore_IMF_Context *ctx)
711 {
712    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
713      {
714         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
715                          "ecore_imf_context_input_mode_set");
716         return 0;
717      }
718    return ctx->input_mode;
719 }
720
721 /**
722  * Allow an Ecore Input Context to internally handle an event.
723  * If this function returns EINA_TRUE, then no further processing
724  * should be done for this event.
725  *
726  * Input methods must be able to accept all types of events (simply
727  * returning EINA_FALSE if the event was not handled), but there is no
728  * obligation of any events to be submitted to this function.
729  *
730  * @param ctx An #Ecore_IMF_Context.
731  * @param type The type of event defined by #Ecore_IMF_Event_Type.
732  * @param event The event itself.
733  * @return EINA_TRUE if the event was handled; otherwise EINA_FALSE.
734  * @ingroup Ecore_IMF_Context_Group
735  */
736 EAPI Eina_Bool
737 ecore_imf_context_filter_event(Ecore_IMF_Context *ctx, Ecore_IMF_Event_Type type, Ecore_IMF_Event *event)
738 {
739    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
740      {
741         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
742                          "ecore_imf_context_filter_event");
743         return EINA_FALSE;
744      }
745    if (ctx->klass->filter_event) return ctx->klass->filter_event(ctx, type, event);
746    return EINA_FALSE;
747 }
748
749 /**
750  * @defgroup Ecore_IMF_Context_Module_Group Ecore Input Method Context Module Functions
751  *
752  * Functions that should be used by Ecore Input Method Context modules.
753  */
754
755 /**
756  * Creates a new Input Method Context with klass specified by @p ctxc.
757  *
758  * This method should be used by modules implementing the Input
759  * Method Context interface.
760  *
761  * @param ctxc An #Ecore_IMF_Context_Class.
762  * @return A new #Ecore_IMF_Context; on failure it returns NULL.
763  * @ingroup Ecore_IMF_Context_Module_Group
764  */
765 EAPI Ecore_IMF_Context *
766 ecore_imf_context_new(const Ecore_IMF_Context_Class *ctxc)
767 {
768    Ecore_IMF_Context *ctx;
769
770    if (!ctxc) return NULL;
771    ctx = calloc(1, sizeof(Ecore_IMF_Context));
772    if (!ctx) return NULL;
773    ECORE_MAGIC_SET(ctx, ECORE_MAGIC_CONTEXT);
774    ctx->klass = ctxc;
775    ctx->data = NULL;
776    ctx->retrieve_surrounding_func = NULL;
777    ctx->retrieve_surrounding_data = NULL;
778    return ctx;
779 }
780
781 /**
782  * Set the Input Method Context specific data.
783  *
784  * Note that this method should be used by modules to set
785  * the Input Method Context specific data and it's not meant to
786  * be used by applications to store application specific data.
787  *
788  * @param ctx An #Ecore_IMF_Context.
789  * @param data The Input Method Context specific data.
790  * @return A new #Ecore_IMF_Context; on failure it returns NULL.
791  * @ingroup Ecore_IMF_Context_Module_Group
792  */
793 EAPI void
794 ecore_imf_context_data_set(Ecore_IMF_Context *ctx, void *data)
795 {
796    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
797      {
798         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
799                          "ecore_imf_context_data_set");
800         return;
801      }
802    ctx->data = data;
803 }
804
805 /**
806  * Get the Input Method Context specific data.
807  *
808  * See @ref ecore_imf_context_data_set for more details.
809  *
810  * @param ctx An #Ecore_IMF_Context.
811  * @return The Input Method Context specific data.
812  * @ingroup Ecore_IMF_Context_Module_Group
813  */
814 EAPI void *ecore_imf_context_data_get(Ecore_IMF_Context *ctx)
815 {
816    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
817      {
818         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
819                          "ecore_imf_context_data_get");
820         return NULL;
821      }
822    return ctx->data;
823 }
824
825 /**
826  * Retrieve context around insertion point.
827  *
828  * This function is implemented by calling the
829  * Ecore_IMF_Context::retrieve_surrounding_func (
830  * set using #ecore_imf_context_retrieve_surrounding_callback_set).
831  *
832  * There is no obligation for a widget to respond to the
833  * ::retrieve_surrounding_func, so input methods must be prepared
834  * to function without context.
835  *
836  * @param ctx An #Ecore_IMF_Context.
837  * @param text Location to store a UTF-8 encoded string of text
838  *             holding context around the insertion point.
839  *             If the function returns EINA_TRUE, then you must free
840  *             the result stored in this location with free().
841  * @param cursor_pos Location to store the position in characters of
842  *                   the insertion cursor within @text.
843  * @return EINA_TRUE if surrounding text was provided; otherwise EINA_FALSE.
844  * @ingroup Ecore_IMF_Context_Module_Group
845  */
846 EAPI Eina_Bool
847 ecore_imf_context_surrounding_get(Ecore_IMF_Context *ctx, char **text, int *cursor_pos)
848 {
849    int result = EINA_FALSE;
850
851    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
852      {
853         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
854                          "ecore_imf_context_surrounding_get");
855         return EINA_FALSE;
856      }
857
858    if (ctx->retrieve_surrounding_func)
859      {
860         result = ctx->retrieve_surrounding_func(ctx->retrieve_surrounding_data, ctx, text, cursor_pos);
861         if (!result)
862           {
863              if (text) *text = NULL;
864              if (cursor_pos) *cursor_pos = 0;
865           }
866      }
867    return result;
868 }
869
870 static void
871 _ecore_imf_event_free_preedit(void *data __UNUSED__, void *event)
872 {
873    free(event);
874 }
875
876 /**
877  * Adds ECORE_IMF_EVENT_PREEDIT_START to the event queue.
878  *
879  * ECORE_IMF_EVENT_PREEDIT_START should be added when a new preedit sequence starts.
880  *
881  * @param ctx An #Ecore_IMF_Context.
882  * @ingroup Ecore_IMF_Context_Module_Group
883  */
884 EAPI void
885 ecore_imf_context_preedit_start_event_add(Ecore_IMF_Context *ctx)
886 {
887    Ecore_IMF_Event_Commit *ev;
888
889    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
890      {
891         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
892                          "ecore_imf_context_preedit_start_event_add");
893         return;
894      }
895
896    ev = malloc(sizeof(Ecore_IMF_Event_Preedit_Start));
897    ev->ctx = ctx;
898    ecore_event_add(ECORE_IMF_EVENT_PREEDIT_START,
899                    ev, _ecore_imf_event_free_preedit, NULL);
900 }
901
902 /**
903  * Adds ECORE_IMF_EVENT_PREEDIT_END to the event queue.
904  *
905  * ECORE_IMF_EVENT_PREEDIT_END should be added when a new preedit sequence has been completed or canceled.
906  *
907  * @param ctx An #Ecore_IMF_Context.
908  * @ingroup Ecore_IMF_Context_Module_Group
909  */
910 EAPI void
911 ecore_imf_context_preedit_end_event_add(Ecore_IMF_Context *ctx)
912 {
913    Ecore_IMF_Event_Commit *ev;
914
915    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
916      {
917         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
918                          "ecore_imf_context_preedit_end_event_add");
919         return;
920      }
921
922    ev = malloc(sizeof(Ecore_IMF_Event_Preedit_End));
923    ev->ctx = ctx;
924    ecore_event_add(ECORE_IMF_EVENT_PREEDIT_END,
925                    ev, _ecore_imf_event_free_preedit, NULL);
926 }
927
928 /**
929  * Adds ECORE_IMF_EVENT_PREEDIT_CHANGED to the event queue.
930  *
931  * @param ctx An #Ecore_IMF_Context.
932  * @ingroup Ecore_IMF_Context_Module_Group
933  */
934 EAPI void
935 ecore_imf_context_preedit_changed_event_add(Ecore_IMF_Context *ctx)
936 {
937    Ecore_IMF_Event_Commit *ev;
938
939    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
940      {
941         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
942                          "ecore_imf_context_preedit_changed_event_add");
943         return;
944      }
945
946    ev = malloc(sizeof(Ecore_IMF_Event_Preedit_Changed));
947    ev->ctx = ctx;
948    ecore_event_add(ECORE_IMF_EVENT_PREEDIT_CHANGED,
949                    ev, _ecore_imf_event_free_preedit, NULL);
950 }
951
952 static void
953 _ecore_imf_event_free_commit(void *data __UNUSED__, void *event)
954 {
955    Ecore_IMF_Event_Commit *ev;
956
957    ev = event;
958    if (ev->str) free(ev->str);
959    free(ev);
960 }
961
962 /**
963  * Adds ECORE_IMF_EVENT_COMMIT to the event queue.
964  *
965  * @param ctx An #Ecore_IMF_Context.
966  * @param str The committed string.
967  * @ingroup Ecore_IMF_Context_Module_Group
968  */
969 EAPI void
970 ecore_imf_context_commit_event_add(Ecore_IMF_Context *ctx, const char *str)
971 {
972    Ecore_IMF_Event_Commit *ev;
973
974    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
975      {
976         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
977                          "ecore_imf_context_commit_event_add");
978         return;
979      }
980
981    ev = malloc(sizeof(Ecore_IMF_Event_Commit));
982    ev->ctx = ctx;
983    ev->str = str ? strdup(str) : NULL;
984    ecore_event_add(ECORE_IMF_EVENT_COMMIT,
985                    ev, _ecore_imf_event_free_commit, NULL);
986
987 }
988
989 static void
990 _ecore_imf_event_free_delete_surrounding(void *data __UNUSED__, void *event)
991 {
992    free(event);
993 }
994
995 /**
996  * Adds ECORE_IMF_EVENT_DELETE_SURROUNDING to the event queue.
997  *
998  * Asks the widget that the input context is attached to to delete characters around the cursor position
999  * by adding the ECORE_IMF_EVENT_DELETE_SURROUNDING to the event queue.
1000  * Note that offset and n_chars are in characters not in bytes.
1001  *
1002  * @param ctx An #Ecore_IMF_Context.
1003  * @param offset The start offset of surrounding to be deleted.
1004  * @param n_chars The number of characters to be deleted.
1005  * @ingroup Ecore_IMF_Context_Module_Group
1006  */
1007 EAPI void
1008 ecore_imf_context_delete_surrounding_event_add(Ecore_IMF_Context *ctx, int offset, int n_chars)
1009 {
1010    Ecore_IMF_Event_Delete_Surrounding *ev;
1011
1012    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1013      {
1014         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1015                          "ecore_imf_context_delete_surrounding_event_add");
1016         return;
1017      }
1018
1019    ev = malloc(sizeof(Ecore_IMF_Event_Delete_Surrounding));
1020    ev->ctx = ctx;
1021    ev->offset = offset;
1022    ev->n_chars = n_chars;
1023    ecore_event_add(ECORE_IMF_EVENT_DELETE_SURROUNDING,
1024                    ev, _ecore_imf_event_free_delete_surrounding, NULL);
1025 }
1026
1027 /**
1028  * Add (register) a callback function to a given context event.
1029  *
1030  * This function adds a function callback to the context @p ctx when the
1031  * event of type @p type occurs on it. The function pointer is @p
1032  * func.
1033  *
1034  * The event type @p type to trigger the function may be one of
1035  * #ECORE_IMF_CALLBACK_PREEDIT_START, #ECORE_IMF_CALLBACK_PREEDIT_END,
1036  * #ECORE_IMF_CALLBACK_PREEDIT_CHANGED, #ECORE_IMF_CALLBACK_COMMIT and
1037  * #ECORE_IMF_CALLBACK_DELETE_SURROUNDING.
1038  *
1039  * @param ctx Ecore_IMF_Context to attach a callback to.
1040  * @param type The type of event that will trigger the callback
1041  * @param func The (callback) function to be called when the event is
1042  *        triggered
1043  * @param data The data pointer to be passed to @p func
1044  * @ingroup Ecore_IMF_Context_Module_Group
1045  * @since 1.2.0
1046  */
1047 EAPI void
1048 ecore_imf_context_event_callback_add(Ecore_IMF_Context *ctx, Ecore_IMF_Callback_Type type, Ecore_IMF_Event_Cb func, const void *data)
1049 {
1050    Ecore_IMF_Func_Node *fn = NULL;
1051
1052    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1053      {
1054         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1055                          "ecore_imf_context_event_callback_add");
1056         return;
1057      }
1058
1059    if (!func) return;
1060
1061    fn = calloc(1, sizeof (Ecore_IMF_Func_Node));
1062    if (!fn) return;
1063
1064    fn->func = func;
1065    fn->data = data;
1066    fn->type = type;
1067
1068    ctx->callbacks = eina_list_append(ctx->callbacks, fn);
1069 }
1070
1071 /**
1072  * Delete (unregister) a callback function registered to a given
1073  * context event.
1074  *
1075  * This function removes a function callback from the context @p ctx when the
1076  * event of type @p type occurs on it. The function pointer is @p
1077  * func.
1078  *
1079  * @see ecore_imf_context_event_callback_add() for more details
1080  *
1081  * @param ctx Ecore_IMF_Context to remove a callback from.
1082  * @param type The type of event that was trigerring the callback
1083  * @param func The (callback) function that was to be called when the event was triggered
1084  * @return the data pointer
1085  * @ingroup Ecore_IMF_Context_Module_Group
1086  * @since 1.2.0
1087  */
1088 EAPI void *
1089 ecore_imf_context_event_callback_del(Ecore_IMF_Context *ctx, Ecore_IMF_Callback_Type type, Ecore_IMF_Event_Cb func)
1090 {
1091    Eina_List *l = NULL;
1092    Eina_List *l_next = NULL;
1093    Ecore_IMF_Func_Node *fn = NULL;
1094
1095    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1096      {
1097         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1098                          "ecore_imf_context_event_callback_del");
1099         return;
1100      }
1101
1102    if (!func) return NULL;
1103    if (!ctx->callbacks) return NULL;
1104
1105    EINA_LIST_FOREACH_SAFE(ctx->callbacks, l, l_next, fn)
1106      {
1107         if ((fn) && (fn->func == func) && (fn->type == type))
1108           {
1109              void *tmp = fn->data;
1110              free(fn);
1111              ctx->callbacks = eina_list_remove_list(ctx->callbacks, l);
1112              return tmp;
1113           }
1114      }
1115    return NULL;
1116 }
1117
1118 /**
1119  * Call a given callback on the context @p ctx.
1120  *
1121  * ecore_imf_context_preedit_start_event_add, ecore_imf_context_preedit_end_event_add, 
1122  * ecore_imf_context_preedit_changed_event_add, ecore_imf_context_commit_event_add and
1123  * ecore_imf_context_delete_surrounding_event_add APIs are asynchronous 
1124  * because those API adds each event to the event queue.
1125  *
1126  * This API provides the way to call each callback function immediately.
1127  *
1128  * @param ctx Ecore_IMF_Context.
1129  * @param type The type of event that will trigger the callback
1130  * @param event_info The pointer to event specific struct or information to
1131  *        pass to the callback functions registered on this event
1132  * @ingroup Ecore_IMF_Context_Module_Group
1133  * @since 1.2.0
1134  */
1135 EAPI void
1136 ecore_imf_context_event_callback_call(Ecore_IMF_Context *ctx, Ecore_IMF_Callback_Type type, void *event_info)
1137 {
1138    Ecore_IMF_Func_Node *fn = NULL;
1139    Eina_List *l = NULL;
1140
1141    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1142      {
1143         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1144                          "ecore_imf_context_event_callback_call");
1145         return;
1146      }
1147
1148    EINA_LIST_FOREACH(ctx->callbacks, l, fn)
1149      {
1150         if ((fn) && (fn->type == type) && (fn->func))
1151           fn->func(fn->data, ctx, event_info);
1152      }
1153 }
1154
1155 /**
1156  * Ask the Input Method Context to show the control panel of using Input Method.
1157  *
1158  * @param ctx An #Ecore_IMF_Context.
1159  * @ingroup Ecore_IMF_Context_IMControl_Group
1160  * @since 1.1.0
1161  */
1162 EAPI void
1163 ecore_imf_context_control_panel_show (Ecore_IMF_Context *ctx)
1164 {
1165    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1166      {
1167         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1168                          "ecore_imf_context_control_panel_show");
1169         return;
1170      }
1171
1172    if (ctx->klass->control_panel_show) ctx->klass->control_panel_show(ctx);
1173 }
1174
1175 /**
1176  * Ask the Input Method Context to hide the control panel of using Input Method.
1177  *
1178  * @param ctx An #Ecore_IMF_Context.
1179  * @ingroup Ecore_IMF_Context_IMControl_Group
1180  * @since 1.1.0
1181  */
1182 EAPI void
1183 ecore_imf_context_control_panel_hide (Ecore_IMF_Context *ctx)
1184 {
1185    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1186      {
1187         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1188                          "ecore_imf_context_control_panel_hide");
1189         return;
1190      }
1191
1192    if (ctx->klass->control_panel_hide) ctx->klass->control_panel_hide(ctx);
1193 }
1194
1195 /**
1196  * Ask the Input Method Context to show the input panel (virtual keyboard).
1197  *
1198  * @param ctx An #Ecore_IMF_Context.
1199  * @ingroup Ecore_IMF_Context_IMControl_Group
1200  * @since 1.1.0
1201  */
1202 EAPI void
1203 ecore_imf_context_input_panel_show(Ecore_IMF_Context *ctx)
1204 {
1205    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1206      {
1207         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1208                          "ecore_imf_context_input_panel_show");
1209         return;
1210      }
1211
1212    if (ctx->klass->show) ctx->klass->show(ctx);
1213 }
1214
1215 /**
1216  * Ask the Input Method Context to hide the input panel.
1217  *
1218  * @param ctx An #Ecore_IMF_Context.
1219  * @ingroup Ecore_IMF_Context_IMControl_Group
1220  * @since 1.1.0
1221  */
1222 EAPI void
1223 ecore_imf_context_input_panel_hide(Ecore_IMF_Context *ctx)
1224 {
1225    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1226      {
1227         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1228                          "ecore_imf_context_input_panel_hide");
1229         return;
1230      }
1231
1232    if (ctx->klass->hide) ctx->klass->hide(ctx);
1233 }
1234
1235 /**
1236  * Set the layout of the input panel.
1237  *
1238  * @param ctx An #Ecore_IMF_Context.
1239  * @param layout see #ECORE_IMF_INPUT_PANEL_LAYOUT
1240  * @ingroup Ecore_IMF_Context_IMControl_Group
1241  * @since 1.1.0
1242  */
1243 EAPI void
1244 ecore_imf_context_input_panel_layout_set (Ecore_IMF_Context *ctx, Ecore_IMF_Input_Panel_Layout layout)
1245 {
1246    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1247      {
1248         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1249                          "ecore_imf_context_input_panel_layout_set");
1250         return;
1251      }
1252
1253    if (ctx->klass->input_panel_layout_set)
1254      ctx->klass->input_panel_layout_set(ctx, layout);
1255
1256    ctx->input_panel_layout = layout;
1257 }
1258
1259 /**
1260  * Get the layout of the current active input panel.
1261  *
1262  * @param ctx An #Ecore_IMF_Context.
1263  * @return layout see #Ecore_IMF_Input_Panel_Layout
1264  * @ingroup Ecore_IMF_Context_IMControl_Group
1265  * @since 1.1.0
1266  */
1267 EAPI Ecore_IMF_Input_Panel_Layout
1268 ecore_imf_context_input_panel_layout_get (Ecore_IMF_Context *ctx)
1269 {
1270    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1271      {
1272         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1273                          "ecore_imf_context_input_panel_layout_get");
1274         return ECORE_IMF_INPUT_PANEL_LAYOUT_INVALID;
1275      }
1276
1277    if (ctx->klass->input_panel_layout_get)
1278      {
1279         return ctx->input_panel_layout;
1280      }
1281    else
1282      return ECORE_IMF_INPUT_PANEL_LAYOUT_INVALID;
1283 }
1284
1285 /**
1286  * Set the language of the input panel.
1287  * This API can be used when you want to show the English keyboard.
1288  *
1289  * @param ctx An #Ecore_IMF_Context.
1290  * @param lang the language to be set to the input panel.
1291  * @ingroup Ecore_IMF_Context_IMControl_Group
1292  * @since 1.1.0
1293  */
1294 EAPI void
1295 ecore_imf_context_input_panel_language_set (Ecore_IMF_Context *ctx, Ecore_IMF_Input_Panel_Lang lang)
1296 {
1297    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1298      {
1299         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1300                          "ecore_imf_context_input_panel_language_set");
1301         return;
1302      }
1303
1304    if (ctx->klass->input_panel_language_set) ctx->klass->input_panel_language_set(ctx, lang);
1305    ctx->input_panel_lang = lang;
1306 }
1307
1308 /**
1309  * Get the language of the input panel.
1310  *
1311  * See @ref ecore_imf_context_input_panel_language_set for more details.
1312  *
1313  * @param ctx An #Ecore_IMF_Context.
1314  * @return Ecore_IMF_Input_Panel_Lang
1315  * @ingroup Ecore_IMF_Context_IMControl_Group
1316  * @since 1.1.0
1317  */
1318 EAPI Ecore_IMF_Input_Panel_Lang
1319 ecore_imf_context_input_panel_language_get (Ecore_IMF_Context *ctx)
1320 {
1321    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1322      {
1323         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1324                          "ecore_imf_context_input_panel_language_get");
1325         return ECORE_IMF_INPUT_PANEL_LANG_AUTOMATIC;
1326      }
1327
1328    return ctx->input_panel_lang;
1329 }
1330
1331 /**
1332  * Set whether the Input Method Context should request to show the input panel automatically
1333  * when the widget has focus.
1334  *
1335  * @param ctx An #Ecore_IMF_Context.
1336  * @param enabled If true, the input panel will be shown when the widget is clicked or has focus.
1337  * @ingroup Ecore_IMF_Context_Group
1338  * @since 1.1.0
1339  */
1340 EAPI void
1341 ecore_imf_context_input_panel_enabled_set (Ecore_IMF_Context *ctx,
1342                                            Eina_Bool enabled)
1343 {
1344    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1345      {
1346         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1347                          "ecore_imf_context_input_panel_enabled_set");
1348         return;
1349      }
1350
1351    ctx->input_panel_enabled = enabled;
1352 }
1353
1354 /**
1355  * Get whether the Input Method Context requests to show the input panel automatically.
1356  *
1357  * @param ctx An #Ecore_IMF_Context.
1358  * @return Return the attribute to show the input panel automatically
1359  * @ingroup Ecore_IMF_Context_Group
1360  * @since 1.1.0
1361  */
1362 EAPI Eina_Bool
1363 ecore_imf_context_input_panel_enabled_get (Ecore_IMF_Context *ctx)
1364 {
1365    if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1366      {
1367         ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1368                          "ecore_imf_context_input_panel_enabled_get");
1369         return EINA_FALSE;
1370      }
1371
1372    return ctx->input_panel_enabled;
1373 }
1374