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