summaryrefslogtreecommitdiff
path: root/src/lib/ecore_imf/ecore_imf_context.c
diff options
context:
space:
mode:
authorVincent Torri <vincent.torri@gmail.com>2012-12-02 22:35:45 +0000
committerVincent Torri <vincent.torri@gmail.com>2012-12-02 22:35:45 +0000
commit7d6010b12c47a20e492da808e3192c3f87dab619 (patch)
tree26c6fd189e046a76560c0bc740b85f4d767ae399 /src/lib/ecore_imf/ecore_imf_context.c
parent53fc441d5475155965d92da89502fe4634a561b2 (diff)
merge: add escape ecore, fix several bugs
SVN revision: 79995
Diffstat (limited to 'src/lib/ecore_imf/ecore_imf_context.c')
-rw-r--r--src/lib/ecore_imf/ecore_imf_context.c1900
1 files changed, 1900 insertions, 0 deletions
diff --git a/src/lib/ecore_imf/ecore_imf_context.c b/src/lib/ecore_imf/ecore_imf_context.c
new file mode 100644
index 0000000000..3faa5acbd5
--- /dev/null
+++ b/src/lib/ecore_imf/ecore_imf_context.c
@@ -0,0 +1,1900 @@
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 * Ecore Input Method Context Function defines the interface for EFL input methods.
21 * An input method is used by EFL text input widgets like elm_entry
22 * (based on edje_entry) to map from key events to Unicode character strings.
23 *
24 * The default input method can be set through setting the ECORE_IMF_MODULE environment variable.
25 *
26 * An input method may consume multiple key events in sequence and finally output the composed result.
27 * This is called preediting, and an input method may provide feedback about
28 * this process by displaying the intermediate composition states as preedit text.
29 *
30 * Immodule is plugin to connect your application and input method framework such as SCIM, ibus, and so on.@n
31 * ecore_imf_init() should be called to initialize and load immodule.@n
32 * ecore_imf_shutdown() is used for shutdowning and unloading immodule.
33 *
34 * An example of usage of these functions can be found at:
35 * @li @ref ecore_imf_example_c
36 */
37
38/**
39 * Get the list of the available Input Method Context ids.
40 *
41 * Note that the caller is responsible for freeing the Eina_List
42 * when finished with it. There is no need to finish the list strings.
43 *
44 * @return Return an Eina_List of strings;
45 * on failure it returns NULL.
46 * @ingroup Ecore_IMF_Context_Group
47 */
48EAPI Eina_List *
49ecore_imf_context_available_ids_get(void)
50{
51 return ecore_imf_module_context_ids_get();
52}
53
54EAPI Eina_List *
55ecore_imf_context_available_ids_by_canvas_type_get(const char *canvas_type)
56{
57 return ecore_imf_module_context_ids_by_canvas_type_get(canvas_type);
58}
59
60/*
61 * Match @locale against @against.
62 *
63 * 'en_US' against 'en_US' => 4
64 * 'en_US' against 'en' => 3
65 * 'en', 'en_UK' against 'en_US' => 2
66 * all locales, against '*' => 1
67 */
68static int
69_ecore_imf_context_match_locale(const char *locale, const char *against, int against_len)
70{
71 if (strcmp(against, "*") == 0)
72 return 1;
73
74 if (strcasecmp(locale, against) == 0)
75 return 4;
76
77 if (strncasecmp(locale, against, 2) == 0)
78 return (against_len == 2) ? 3 : 2;
79
80 return 0;
81}
82
83/**
84 * Get the id of the default Input Method Context.
85 * The id may to used to create a new instance of an Input Method
86 * Context object.
87 *
88 * @return Return a string containing the id of the default Input
89 * Method Context; on failure it returns NULL.
90 * @ingroup Ecore_IMF_Context_Group
91 */
92EAPI const char *
93ecore_imf_context_default_id_get(void)
94{
95 return ecore_imf_context_default_id_by_canvas_type_get(NULL);
96}
97
98EAPI const char *
99ecore_imf_context_default_id_by_canvas_type_get(const char *canvas_type)
100{
101 const char *id;
102 Eina_List *modules;
103 Ecore_IMF_Module *module;
104 char *locale;
105 char *tmp;
106 int best_goodness = 0;
107
108 id = getenv("ECORE_IMF_MODULE");
109 if (id)
110 {
111 if (strcmp(id, "none") == 0) return NULL;
112 if (ecore_imf_module_get(id)) return id;
113 }
114
115 modules = ecore_imf_module_available_get();
116 if (!modules) return NULL;
117
118 locale = setlocale(LC_CTYPE, NULL);
119 if (!locale) return NULL;
120
121 locale = strdup(locale);
122
123 tmp = strchr(locale, '.');
124 if (tmp) *tmp = '\0';
125 tmp = strchr(locale, '@');
126 if (tmp) *tmp = '\0';
127
128 id = NULL;
129
130 EINA_LIST_FREE(modules, module)
131 {
132 if (canvas_type &&
133 strcmp(module->info->canvas_type, canvas_type) == 0)
134 continue;
135
136 const char *p = module->info->default_locales;
137 while (p)
138 {
139 const char *q = strchr(p, ':');
140 int goodness = _ecore_imf_context_match_locale(locale, p, q ? (size_t)(q - p) : strlen (p));
141
142 if (goodness > best_goodness)
143 {
144 id = module->info->id;
145 best_goodness = goodness;
146 }
147
148 p = q ? q + 1 : NULL;
149 }
150 }
151
152 free(locale);
153 return id;
154}
155
156/**
157 * Retrieve the info for the Input Method Context with @p id.
158 *
159 * @param id The Input Method Context id to query for.
160 * @return Return a #Ecore_IMF_Context_Info for the Input Method Context with @p id;
161 * on failure it returns NULL.
162 * @ingroup Ecore_IMF_Context_Group
163 *
164 * Example
165 * @code
166 *
167 * const char *ctx_id;
168 * const Ecore_IMF_Context_Info *ctx_info;
169 * Ecore_IMF_Context *imf_context;
170 * ctx_id = ecore_imf_context_default_id_get();
171 * if (ctx_id)
172 * {
173 * ctx_info = ecore_imf_context_info_by_id_get(ctx_id);
174 * if (!ctx_info->canvas_type ||
175 * strcmp(ctx_info->canvas_type, "evas") == 0)
176 * {
177 * imf_context = ecore_imf_context_add(ctx_id);
178 * }
179 * else
180 * {
181 * ctx_id = ecore_imf_context_default_id_by_canvas_type_get("evas");
182 * if (ctx_id)
183 * {
184 * imf_context = ecore_imf_context_add(ctx_id);
185 * }
186 * }
187 * }
188 * @endcode
189 */
190EAPI const Ecore_IMF_Context_Info *
191ecore_imf_context_info_by_id_get(const char *id)
192{
193 Ecore_IMF_Module *module;
194
195 if (!id) return NULL;
196 module = ecore_imf_module_get(id);
197 if (!module) return NULL;
198 return module->info;
199}
200
201/**
202 * Create a new Input Method Context defined by the given id.
203 *
204 * @param id The Input Method Context id.
205 * @return A newly allocated Input Method Context;
206 * on failure it returns NULL.
207 * @ingroup Ecore_IMF_Context_Group
208 */
209EAPI Ecore_IMF_Context *
210ecore_imf_context_add(const char *id)
211{
212 Ecore_IMF_Context *ctx;
213
214 if (!id) return NULL;
215 ctx = ecore_imf_module_context_create(id);
216 if (!ctx || !ctx->klass) return NULL;
217 if (ctx->klass->add) ctx->klass->add(ctx);
218 /* default use_preedit is EINA_TRUE, so let's make sure it's
219 * set on the immodule */
220 ecore_imf_context_use_preedit_set(ctx, EINA_TRUE);
221
222 /* default prediction is EINA_TRUE, so let's make sure it's
223 * set on the immodule */
224 ecore_imf_context_prediction_allow_set(ctx, EINA_TRUE);
225
226 /* default autocapital type is SENTENCE type, so let's make sure it's
227 * set on the immodule */
228 ecore_imf_context_autocapital_type_set(ctx, ECORE_IMF_AUTOCAPITAL_TYPE_SENTENCE);
229
230 /* default input panel enabled status is EINA_TRUE, so let's make sure it's
231 * set on the immodule */
232 ecore_imf_context_input_panel_enabled_set(ctx, EINA_TRUE);
233
234 /* default input panel layout type is NORMAL type, so let's make sure it's
235 * set on the immodule */
236 ecore_imf_context_input_panel_layout_set(ctx, ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL);
237
238 /* default input_mode is ECORE_IMF_INPUT_MODE_FULL, so let's make sure it's
239 * set on the immodule */
240 ecore_imf_context_input_mode_set(ctx, ECORE_IMF_INPUT_MODE_FULL);
241 return ctx;
242}
243
244/**
245 * Retrieve the info for the given Input Method Context.
246 *
247 * @param ctx An #Ecore_IMF_Context.
248 * @return Return a #Ecore_IMF_Context_Info for the given Input Method Context;
249 * on failure it returns NULL.
250 * @ingroup Ecore_IMF_Context_Group
251 */
252EAPI const Ecore_IMF_Context_Info *
253ecore_imf_context_info_get(Ecore_IMF_Context *ctx)
254{
255 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
256 {
257 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
258 "ecore_imf_context_info_get");
259 return NULL;
260 }
261 return ctx->module->info;
262}
263
264/**
265 * Delete the given Input Method Context and free its memory.
266 *
267 * @param ctx An #Ecore_IMF_Context.
268 * @ingroup Ecore_IMF_Context_Group
269 */
270EAPI void
271ecore_imf_context_del(Ecore_IMF_Context *ctx)
272{
273 Ecore_IMF_Func_Node *fn;
274
275 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
276 {
277 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
278 "ecore_imf_context_del");
279 return;
280 }
281 if (ctx->klass->del) ctx->klass->del(ctx);
282
283 if (ctx->callbacks)
284 {
285 EINA_LIST_FREE(ctx->callbacks, fn)
286 free(fn);
287 }
288
289 ECORE_MAGIC_SET(ctx, ECORE_MAGIC_NONE);
290 free(ctx);
291}
292
293/**
294 * Set the client window for the Input Method Context; this is the
295 * Ecore_X_Window when using X11, Ecore_Win32_Window when using Win32, etc.
296 * This window is used in order to correctly position status windows, and may
297 * also be used for purposes internal to the Input Method Context.
298 *
299 * @param ctx An #Ecore_IMF_Context.
300 * @param window The client window. This may be @c NULL to indicate
301 * that the previous client window no longer exists.
302 * @ingroup Ecore_IMF_Context_Group
303 */
304EAPI void
305ecore_imf_context_client_window_set(Ecore_IMF_Context *ctx, void *window)
306{
307 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
308 {
309 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
310 "ecore_imf_context_client_window_set");
311 return;
312 }
313 if (ctx->klass->client_window_set) ctx->klass->client_window_set(ctx, window);
314 ctx->window = window;
315}
316
317/**
318 * Get the client window of the Input Method Context
319 *
320 * See @ref ecore_imf_context_client_window_set for more details.
321 *
322 * @param ctx An #Ecore_IMF_Context.
323 * @return Return the client window.
324 * @ingroup Ecore_IMF_Context_Group
325 * @since 1.1.0
326 */
327EAPI void *
328ecore_imf_context_client_window_get(Ecore_IMF_Context *ctx)
329{
330 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
331 {
332 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
333 "ecore_imf_context_client_window_get");
334 return NULL;
335 }
336 return ctx->window;
337}
338
339/**
340 * Set the client canvas for the Input Method Context; this is the
341 * canvas in which the input appears.
342 * The canvas type can be determined by using the context canvas type.
343 * Actually only canvas with type "evas" (Evas *) is supported.
344 * This canvas may be used in order to correctly position status windows, and may
345 * also be used for purposes internal to the Input Method Context.
346 *
347 * @param ctx An #Ecore_IMF_Context.
348 * @param canvas The client canvas. This may be @c NULL to indicate
349 * that the previous client canvas no longer exists.
350 * @ingroup Ecore_IMF_Context_Group
351 */
352EAPI void
353ecore_imf_context_client_canvas_set(Ecore_IMF_Context *ctx, void *canvas)
354{
355 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
356 {
357 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
358 "ecore_imf_context_client_canvas_set");
359 return;
360 }
361 if (ctx->klass->client_canvas_set) ctx->klass->client_canvas_set(ctx, canvas);
362 ctx->client_canvas = canvas;
363}
364
365/**
366 * Get the client canvas of the Input Method Context.
367 *
368 * See @ref ecore_imf_context_client_canvas_set for more details.
369 *
370 * @param ctx An #Ecore_IMF_Context.
371 * @return Return the client canvas.
372 * @ingroup Ecore_IMF_Context_Group
373 * @since 1.1.0
374 */
375EAPI void *
376ecore_imf_context_client_canvas_get(Ecore_IMF_Context *ctx)
377{
378 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
379 {
380 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
381 "ecore_imf_context_client_canvas_get");
382 return NULL;
383 }
384 return ctx->client_canvas;
385}
386
387/**
388 * Ask the Input Method Context to show itself.
389 *
390 * @param ctx An #Ecore_IMF_Context.
391 * @ingroup Ecore_IMF_Context_Group
392 */
393EAPI void
394ecore_imf_context_show(Ecore_IMF_Context *ctx)
395{
396 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
397 {
398 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
399 "ecore_imf_context_show");
400 return;
401 }
402 if (ctx->klass->show) ctx->klass->show(ctx);
403}
404
405/**
406 * Ask the Input Method Context to hide itself.
407 *
408 * @param ctx An #Ecore_IMF_Context.
409 * @ingroup Ecore_IMF_Context_Group
410 */
411EAPI void
412ecore_imf_context_hide(Ecore_IMF_Context *ctx)
413{
414 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
415 {
416 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
417 "ecore_imf_context_hide");
418 return;
419 }
420 if (ctx->klass->hide) ctx->klass->hide(ctx);
421}
422
423/**
424 * Retrieve the current preedit string and cursor position
425 * for the Input Method Context.
426 *
427 * @param ctx An #Ecore_IMF_Context.
428 * @param str Location to store the retrieved string. The
429 * string retrieved must be freed with free().
430 * @param cursor_pos Location to store position of cursor (in characters)
431 * within the preedit string.
432 * @ingroup Ecore_IMF_Context_Group
433 */
434EAPI void
435ecore_imf_context_preedit_string_get(Ecore_IMF_Context *ctx, char **str, int *cursor_pos)
436{
437 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
438 {
439 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
440 "ecore_imf_context_preedit_string_get");
441 return;
442 }
443 if (ctx->klass->preedit_string_get)
444 ctx->klass->preedit_string_get(ctx, str, cursor_pos);
445 else
446 {
447 if (str) *str = strdup("");
448 if (cursor_pos) *cursor_pos = 0;
449 }
450}
451
452/**
453 * Retrieve the current preedit string, attributes and
454 * cursor position for the Input Method Context.
455 *
456 * @param ctx An #Ecore_IMF_Context.
457 * @param str Location to store the retrieved string. The
458 * string retrieved must be freed with free().
459 * @param attrs an Eina_List of attributes
460 * @param cursor_pos Location to store position of cursor (in characters)
461 * within the preedit string.
462 * @ingroup Ecore_IMF_Context_Group
463 *
464 * Example
465 * @code
466 * char *preedit_string;
467 * int cursor_pos;
468 * Eina_List *attrs = NULL, *l = NULL;
469 * Ecore_IMF_Preedit_Attr *attr;
470 *
471 * ecore_imf_context_preedit_string_with_attributes_get(imf_context,
472 * &preedit_string,
473 * &attrs, &cursor_pos);
474 * if (!preedit_string) return;
475 *
476 * if (strlen(preedit_string) > 0)
477 * {
478 * if (attrs)
479 * {
480 * EINA_LIST_FOREACH(attrs, l, attr)
481 * {
482 * if (attr->preedit_type == ECORE_IMF_PREEDIT_TYPE_SUB1)
483 * {
484 * // Something to do
485 * }
486 * else if (attr->preedit_type == ECORE_IMF_PREEDIT_TYPE_SUB2)
487 * {
488 * // Something to do
489 * }
490 * else if (attr->preedit_type == ECORE_IMF_PREEDIT_TYPE_SUB3)
491 * {
492 * // Something to do
493 * }
494 * }
495 * }
496 * }
497 *
498 * // delete attribute list
499 * EINA_LIST_FREE(attrs, attr) free(attr);
500 *
501 * free(preedit_string);
502 * @endcode
503 * @since 1.1.0
504 */
505EAPI void
506ecore_imf_context_preedit_string_with_attributes_get(Ecore_IMF_Context *ctx, char **str, Eina_List **attrs, int *cursor_pos)
507{
508 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
509 {
510 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
511 "ecore_imf_context_preedit_string_with_attributes_get");
512 return;
513 }
514 if (ctx->klass->preedit_string_with_attributes_get)
515 ctx->klass->preedit_string_with_attributes_get(ctx, str, attrs, cursor_pos);
516 else
517 {
518 if (str) *str = strdup("");
519 if (attrs) *attrs = NULL;
520 if (cursor_pos) *cursor_pos = 0;
521 }
522}
523
524/**
525 * Notify the Input Method Context that the widget to which its
526 * correspond has gained focus.
527 *
528 * @param ctx An #Ecore_IMF_Context.
529 * @ingroup Ecore_IMF_Context_Group
530 *
531 * Example
532 * @code
533 * static void
534 * _focus_in_cb(void *data, Evas_Object *o, const char *emission, const char *source)
535 * {
536 * ecore_imf_context_reset(imf_context);
537 * ecore_imf_context_focus_in(imf_context);
538 * }
539 *
540 * evas_object_event_callback_add(obj, EVAS_CALLBACK_FOCUS_IN, _focus_in_cb, ed);
541 * @endcode
542 */
543EAPI void
544ecore_imf_context_focus_in(Ecore_IMF_Context *ctx)
545{
546 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
547 {
548 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
549 "ecore_imf_context_focus_in");
550 return;
551 }
552 if (ctx->klass->focus_in) ctx->klass->focus_in(ctx);
553}
554
555/**
556 * Notify the Input Method Context that the widget to which its
557 * correspond has lost focus.
558 *
559 * @param ctx An #Ecore_IMF_Context.
560 * @ingroup Ecore_IMF_Context_Group
561 *
562 * Example
563 * @code
564 * static void
565 * _focus_out_cb(void *data, Evas_Object *o, const char *emission, const char *source)
566 * {
567 * ecore_imf_context_reset(imf_context);
568 * ecore_imf_context_focus_out(imf_context);
569 * }
570 *
571 * evas_object_event_callback_add(obj, EVAS_CALLBACK_FOCUS_OUT, _focus_out_cb, ed);
572 * @endcode
573 */
574EAPI void
575ecore_imf_context_focus_out(Ecore_IMF_Context *ctx)
576{
577 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
578 {
579 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
580 "ecore_imf_context_focus_out");
581 return;
582 }
583 if (ctx->klass->focus_out) ctx->klass->focus_out(ctx);
584}
585
586/**
587 * Notify the Input Method Context that a change such as a
588 * change in cursor position has been made. This will typically
589 * cause the Input Method Context to clear the preedit state.
590 *
591 * @param ctx An #Ecore_IMF_Context.
592 * @ingroup Ecore_IMF_Context_Group
593 *
594 * Example
595 * @code
596 * static void
597 * _focus_out_cb(void *data, Evas_Object *o, const char *emission, const char *source)
598 * {
599 * ecore_imf_context_reset(imf_context);
600 * ecore_imf_context_focus_out(imf_context);
601 * }
602 *
603 * evas_object_event_callback_add(obj, EVAS_CALLBACK_FOCUS_OUT, _focus_out_cb, ed);
604 * @endcode
605 */
606EAPI void
607ecore_imf_context_reset(Ecore_IMF_Context *ctx)
608{
609 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
610 {
611 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
612 "ecore_imf_context_reset");
613 return;
614 }
615 if (ctx->klass->reset) ctx->klass->reset(ctx);
616}
617
618/**
619 * Notify the Input Method Context that a change in the cursor
620 * position has been made.
621 *
622 * @param ctx An #Ecore_IMF_Context.
623 * @param cursor_pos New cursor position in characters.
624 * @ingroup Ecore_IMF_Context_Group
625 */
626EAPI void
627ecore_imf_context_cursor_position_set(Ecore_IMF_Context *ctx, int cursor_pos)
628{
629 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
630 {
631 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
632 "ecore_imf_context_cursor_position_set");
633 return;
634 }
635 if (ctx->klass->cursor_position_set) ctx->klass->cursor_position_set(ctx, cursor_pos);
636}
637
638/**
639 * Notify the Input Method Context that a change in the cursor
640 * location has been made. The location is relative to the canvas.
641 * The cursor location can be used to determine the position of
642 * candidate word window in the immodule.
643 *
644 * @param ctx An #Ecore_IMF_Context.
645 * @param x cursor x position.
646 * @param y cursor y position.
647 * @param w cursor width.
648 * @param h cursor height.
649 * @ingroup Ecore_IMF_Context_Group
650 * @since 1.1.0
651 */
652EAPI void
653ecore_imf_context_cursor_location_set(Ecore_IMF_Context *ctx, int x, int y, int w, int h)
654{
655 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
656 {
657 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
658 "ecore_imf_context_cursor_location_set");
659 return;
660 }
661 if (ctx->klass->cursor_location_set) ctx->klass->cursor_location_set(ctx, x, y, w, h);
662}
663
664/**
665 * Set whether the IM context should use the preedit string
666 * to display feedback. If @c use_preedit is @c EINA_FALSE (default
667 * is @c EINA_TRUE), then the IM context may use some other method to display
668 * feedback, such as displaying it in a child of the root window.
669 *
670 * @param ctx An #Ecore_IMF_Context.
671 * @param use_preedit Whether the IM context should use the preedit string.
672 * @ingroup Ecore_IMF_Context_Group
673 */
674EAPI void
675ecore_imf_context_use_preedit_set(Ecore_IMF_Context *ctx, Eina_Bool use_preedit)
676{
677 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
678 {
679 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
680 "ecore_imf_context_use_preedit_set");
681 return;
682 }
683 if (ctx->klass->use_preedit_set) ctx->klass->use_preedit_set(ctx, use_preedit);
684}
685
686/**
687 * Set whether the IM context should allow to use the text prediction.
688 * If @p prediction is @c EINA_FALSE (default is @c EINA_TRUE), then the IM
689 * context will not display the text prediction window.
690 *
691 * @param ctx An #Ecore_IMF_Context.
692 * @param prediction Whether the IM context should allow to use the text prediction.
693 * @note Default value is EINA_TRUE.
694 * @ingroup Ecore_IMF_Context_Group
695 * @since 1.1.0
696 */
697EAPI void
698ecore_imf_context_prediction_allow_set(Ecore_IMF_Context *ctx, Eina_Bool prediction)
699{
700 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
701 {
702 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
703 "ecore_imf_context_prediction_allow_set");
704 return;
705 }
706
707 ctx->allow_prediction = prediction;
708
709 if (ctx->klass->prediction_allow_set)
710 ctx->klass->prediction_allow_set(ctx, prediction);
711}
712
713/**
714 * Get whether the IM context should allow to use the text prediction.
715 *
716 * @param ctx An #Ecore_IMF_Context.
717 * @return @c EINA_TRUE if it allows to use the text prediction, otherwise
718 * @c EINA_FALSE.
719 * @ingroup Ecore_IMF_Context_Group
720 * @since 1.1.0
721 */
722EAPI Eina_Bool
723ecore_imf_context_prediction_allow_get(Ecore_IMF_Context *ctx)
724{
725 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
726 {
727 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
728 "ecore_imf_context_prediction_allow_get");
729 return EINA_FALSE;
730 }
731
732 return ctx->allow_prediction;
733}
734
735/**
736 * Set the autocapitalization type on the immodule.
737 *
738 * @param ctx An #Ecore_IMF_Context.
739 * @param autocapital_type the autocapitalization type.
740 * @note Default type is ECORE_IMF_AUTOCAPITAL_TYPE_SENTENCE.
741 * @ingroup Ecore_IMF_Context_Group
742 * @since 1.1.0
743 */
744EAPI void
745ecore_imf_context_autocapital_type_set(Ecore_IMF_Context *ctx, Ecore_IMF_Autocapital_Type autocapital_type)
746{
747 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
748 {
749 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
750 "ecore_imf_context_autocapital_type_set");
751 return;
752 }
753
754 ctx->autocapital_type = autocapital_type;
755
756 if (ctx->klass->autocapital_type_set) ctx->klass->autocapital_type_set(ctx, autocapital_type);
757}
758
759/**
760 * Get the autocapitalization type.
761 *
762 * @param ctx An #Ecore_IMF_Context.
763 * @return The autocapital type being used by @p ctx.
764 * @ingroup Ecore_IMF_Context_Group
765 * @since 1.1.0
766 */
767EAPI Ecore_IMF_Autocapital_Type
768ecore_imf_context_autocapital_type_get(Ecore_IMF_Context *ctx)
769{
770 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
771 {
772 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
773 "ecore_imf_context_autocapital_allow_get");
774 return ECORE_IMF_AUTOCAPITAL_TYPE_NONE;
775 }
776
777 return ctx->autocapital_type;
778}
779
780/**
781 * Set the callback to be used on surrounding_get request.
782 *
783 * This callback will be called when the Input Method Context
784 * module requests the surrounding context.
785 *
786 * @param ctx An #Ecore_IMF_Context.
787 * @param func The callback to be called.
788 * @param data The data pointer to be passed to @p func
789 * @ingroup Ecore_IMF_Context_Group
790 */
791EAPI void
792ecore_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)
793{
794 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
795 {
796 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
797 "ecore_imf_context_retrieve_surrounding_callback_set");
798 return;
799 }
800
801 ctx->retrieve_surrounding_func = func;
802 ctx->retrieve_surrounding_data = (void *) data;
803}
804
805/**
806 * Set the input mode used by the Ecore Input Context.
807 *
808 * The input mode can be one of the input modes defined in
809 * Ecore_IMF_Input_Mode. The default input mode is
810 * ECORE_IMF_INPUT_MODE_FULL.
811 *
812 * @param ctx An #Ecore_IMF_Context.
813 * @param input_mode The input mode to be used by @p ctx.
814 * @ingroup Ecore_IMF_Context_Group
815 */
816EAPI void
817ecore_imf_context_input_mode_set(Ecore_IMF_Context *ctx, Ecore_IMF_Input_Mode input_mode)
818{
819 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
820 {
821 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
822 "ecore_imf_context_input_mode_set");
823 return;
824 }
825 if (ctx->klass->input_mode_set) ctx->klass->input_mode_set(ctx, input_mode);
826 ctx->input_mode = input_mode;
827}
828
829/**
830 * Get the input mode being used by the Ecore Input Context.
831 *
832 * See @ref ecore_imf_context_input_mode_set for more details.
833 *
834 * @param ctx An #Ecore_IMF_Context.
835 * @return The input mode being used by @p ctx.
836 * @ingroup Ecore_IMF_Context_Group
837 */
838EAPI Ecore_IMF_Input_Mode
839ecore_imf_context_input_mode_get(Ecore_IMF_Context *ctx)
840{
841 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
842 {
843 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
844 "ecore_imf_context_input_mode_set");
845 return 0;
846 }
847 return ctx->input_mode;
848}
849
850/**
851 * Allow an Ecore Input Context to internally handle an event.
852 * If this function returns @c EINA_TRUE, then no further processing
853 * should be done for this event.
854 *
855 * Input methods must be able to accept all types of events (simply
856 * returning @c EINA_FALSE if the event was not handled), but there is no
857 * obligation of any events to be submitted to this function.
858 *
859 * @param ctx An #Ecore_IMF_Context.
860 * @param type The type of event defined by #Ecore_IMF_Event_Type.
861 * @param event The event itself.
862 * @return @c EINA_TRUE if the event was handled; otherwise @c EINA_FALSE.
863 * @ingroup Ecore_IMF_Context_Group
864 *
865 * Example
866 * @code
867 * static void
868 * _key_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
869 * {
870 * Evas_Event_Key_Down *ev = event_info;
871 * if (!ev->keyname) return;
872 *
873 * if (imf_context)
874 * {
875 * Ecore_IMF_Event_Key_Down ecore_ev;
876 * ecore_imf_evas_event_key_down_wrap(ev, &ecore_ev);
877 * if (ecore_imf_context_filter_event(imf_context,
878 * ECORE_IMF_EVENT_KEY_DOWN,
879 * (Ecore_IMF_Event *)&ecore_ev))
880 * return;
881 * }
882 * }
883 *
884 * evas_object_event_callback_add(obj, EVAS_CALLBACK_KEY_DOWN, _key_down_cb, data);
885 * @endcode
886 */
887EAPI Eina_Bool
888ecore_imf_context_filter_event(Ecore_IMF_Context *ctx, Ecore_IMF_Event_Type type, Ecore_IMF_Event *event)
889{
890 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
891 {
892 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
893 "ecore_imf_context_filter_event");
894 return EINA_FALSE;
895 }
896 if (ctx->klass->filter_event) return ctx->klass->filter_event(ctx, type, event);
897 return EINA_FALSE;
898}
899
900/**
901 * @defgroup Ecore_IMF_Context_Module_Group Ecore Input Method Context Module Functions
902 *
903 * Functions that should be used by Ecore Input Method Context modules.
904 */
905
906/**
907 * Creates a new Input Method Context with klass specified by @p ctxc.
908 *
909 * This method should be used by modules implementing the Input
910 * Method Context interface.
911 *
912 * @param ctxc An #Ecore_IMF_Context_Class.
913 * @return A new #Ecore_IMF_Context; on failure it returns NULL.
914 * @ingroup Ecore_IMF_Context_Module_Group
915 */
916EAPI Ecore_IMF_Context *
917ecore_imf_context_new(const Ecore_IMF_Context_Class *ctxc)
918{
919 Ecore_IMF_Context *ctx;
920
921 if (!ctxc) return NULL;
922 ctx = calloc(1, sizeof(Ecore_IMF_Context));
923 if (!ctx) return NULL;
924 ECORE_MAGIC_SET(ctx, ECORE_MAGIC_CONTEXT);
925 ctx->klass = ctxc;
926 ctx->data = NULL;
927 ctx->retrieve_surrounding_func = NULL;
928 ctx->retrieve_surrounding_data = NULL;
929 return ctx;
930}
931
932/**
933 * Set the Input Method Context specific data.
934 *
935 * Note that this method should be used by modules to set
936 * the Input Method Context specific data and it's not meant to
937 * be used by applications to store application specific data.
938 *
939 * @param ctx An #Ecore_IMF_Context.
940 * @param data The Input Method Context specific data.
941 * @return A new #Ecore_IMF_Context; on failure it returns NULL.
942 * @ingroup Ecore_IMF_Context_Module_Group
943 */
944EAPI void
945ecore_imf_context_data_set(Ecore_IMF_Context *ctx, void *data)
946{
947 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
948 {
949 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
950 "ecore_imf_context_data_set");
951 return;
952 }
953 ctx->data = data;
954}
955
956/**
957 * Get the Input Method Context specific data.
958 *
959 * See @ref ecore_imf_context_data_set for more details.
960 *
961 * @param ctx An #Ecore_IMF_Context.
962 * @return The Input Method Context specific data.
963 * @ingroup Ecore_IMF_Context_Module_Group
964 */
965EAPI void *ecore_imf_context_data_get(Ecore_IMF_Context *ctx)
966{
967 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
968 {
969 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
970 "ecore_imf_context_data_get");
971 return NULL;
972 }
973 return ctx->data;
974}
975
976/**
977 * Retrieve context around insertion point.
978 * Input methods typically want context in order to constrain input text based on existing text;
979 * this is important for languages such as Thai where only some sequences of characters are allowed.
980 * In addition, the text around the insertion point can be used for supporting autocapital feature.
981 *
982 * This function is implemented by calling the
983 * Ecore_IMF_Context::retrieve_surrounding_func (
984 * set using #ecore_imf_context_retrieve_surrounding_callback_set).
985 *
986 * There is no obligation for a widget to respond to the
987 * retrieve_surrounding_func, so input methods must be prepared
988 * to function without context.
989 *
990 * @param ctx An #Ecore_IMF_Context.
991 * @param text Location to store a UTF-8 encoded string of text
992 * holding context around the insertion point.
993 * If the function returns @c EINA_TRUE, then you must free
994 * the result stored in this location with free().
995 * @param cursor_pos Location to store the position in characters of
996 * the insertion cursor within @p text.
997 * @return @c EINA_TRUE if surrounding text was provided; otherwise
998 * @c EINA_FALSE.
999 * @ingroup Ecore_IMF_Context_Module_Group
1000 */
1001EAPI Eina_Bool
1002ecore_imf_context_surrounding_get(Ecore_IMF_Context *ctx, char **text, int *cursor_pos)
1003{
1004 int result = EINA_FALSE;
1005
1006 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1007 {
1008 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1009 "ecore_imf_context_surrounding_get");
1010 return EINA_FALSE;
1011 }
1012
1013 if (ctx->retrieve_surrounding_func)
1014 {
1015 result = ctx->retrieve_surrounding_func(ctx->retrieve_surrounding_data, ctx, text, cursor_pos);
1016 if (!result)
1017 {
1018 if (text) *text = NULL;
1019 if (cursor_pos) *cursor_pos = 0;
1020 }
1021 }
1022 return result;
1023}
1024
1025static void
1026_ecore_imf_event_free_preedit(void *data EINA_UNUSED, void *event)
1027{
1028 free(event);
1029}
1030
1031/**
1032 * Adds ECORE_IMF_EVENT_PREEDIT_START to the event queue.
1033 *
1034 * ECORE_IMF_EVENT_PREEDIT_START should be added when a new preedit sequence starts.
1035 * It's asynchronous method to put event to the event queue.
1036 * ecore_imf_context_event_callback_call() can be used as synchronous method.
1037 *
1038 * @param ctx An #Ecore_IMF_Context.
1039 * @ingroup Ecore_IMF_Context_Module_Group
1040 */
1041EAPI void
1042ecore_imf_context_preedit_start_event_add(Ecore_IMF_Context *ctx)
1043{
1044 Ecore_IMF_Event_Commit *ev;
1045
1046 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1047 {
1048 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1049 "ecore_imf_context_preedit_start_event_add");
1050 return;
1051 }
1052
1053 ev = malloc(sizeof(Ecore_IMF_Event_Preedit_Start));
1054 ev->ctx = ctx;
1055 ecore_event_add(ECORE_IMF_EVENT_PREEDIT_START,
1056 ev, _ecore_imf_event_free_preedit, NULL);
1057}
1058
1059/**
1060 * Adds ECORE_IMF_EVENT_PREEDIT_END to the event queue.
1061 *
1062 * ECORE_IMF_EVENT_PREEDIT_END should be added when a new preedit sequence has been completed or canceled.
1063 * It's asynchronous method to put event to the event queue.
1064 * ecore_imf_context_event_callback_call() can be used as synchronous method.
1065 *
1066 * @param ctx An #Ecore_IMF_Context.
1067 * @ingroup Ecore_IMF_Context_Module_Group
1068 */
1069EAPI void
1070ecore_imf_context_preedit_end_event_add(Ecore_IMF_Context *ctx)
1071{
1072 Ecore_IMF_Event_Commit *ev;
1073
1074 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1075 {
1076 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1077 "ecore_imf_context_preedit_end_event_add");
1078 return;
1079 }
1080
1081 ev = malloc(sizeof(Ecore_IMF_Event_Preedit_End));
1082 ev->ctx = ctx;
1083 ecore_event_add(ECORE_IMF_EVENT_PREEDIT_END,
1084 ev, _ecore_imf_event_free_preedit, NULL);
1085}
1086
1087/**
1088 * Adds ECORE_IMF_EVENT_PREEDIT_CHANGED to the event queue.
1089 *
1090 * It's asynchronous method to put event to the event queue.
1091 * ecore_imf_context_event_callback_call() can be used as synchronous method.
1092 *
1093 * @param ctx An #Ecore_IMF_Context.
1094 * @ingroup Ecore_IMF_Context_Module_Group
1095 */
1096EAPI void
1097ecore_imf_context_preedit_changed_event_add(Ecore_IMF_Context *ctx)
1098{
1099 Ecore_IMF_Event_Commit *ev;
1100
1101 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1102 {
1103 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1104 "ecore_imf_context_preedit_changed_event_add");
1105 return;
1106 }
1107
1108 ev = malloc(sizeof(Ecore_IMF_Event_Preedit_Changed));
1109 ev->ctx = ctx;
1110 ecore_event_add(ECORE_IMF_EVENT_PREEDIT_CHANGED,
1111 ev, _ecore_imf_event_free_preedit, NULL);
1112}
1113
1114static void
1115_ecore_imf_event_free_commit(void *data EINA_UNUSED, void *event)
1116{
1117 Ecore_IMF_Event_Commit *ev;
1118
1119 ev = event;
1120 if (ev->str) free(ev->str);
1121 free(ev);
1122}
1123
1124/**
1125 * Adds ECORE_IMF_EVENT_COMMIT to the event queue.
1126 *
1127 * It's asynchronous method to put event to the event queue.
1128 * ecore_imf_context_event_callback_call() can be used as synchronous method.
1129 *
1130 * @param ctx An #Ecore_IMF_Context.
1131 * @param str The committed string.
1132 * @ingroup Ecore_IMF_Context_Module_Group
1133 */
1134EAPI void
1135ecore_imf_context_commit_event_add(Ecore_IMF_Context *ctx, const char *str)
1136{
1137 Ecore_IMF_Event_Commit *ev;
1138
1139 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1140 {
1141 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1142 "ecore_imf_context_commit_event_add");
1143 return;
1144 }
1145
1146 ev = malloc(sizeof(Ecore_IMF_Event_Commit));
1147 ev->ctx = ctx;
1148 ev->str = str ? strdup(str) : NULL;
1149 ecore_event_add(ECORE_IMF_EVENT_COMMIT,
1150 ev, _ecore_imf_event_free_commit, NULL);
1151
1152}
1153
1154static void
1155_ecore_imf_event_free_delete_surrounding(void *data EINA_UNUSED, void *event)
1156{
1157 free(event);
1158}
1159
1160/**
1161 * Adds ECORE_IMF_EVENT_DELETE_SURROUNDING to the event queue.
1162 *
1163 * Asks the widget that the input context is attached to to delete characters around the cursor position
1164 * by adding the ECORE_IMF_EVENT_DELETE_SURROUNDING to the event queue.
1165 * Note that offset and n_chars are in characters not in bytes.
1166 *
1167 * It's asynchronous method to put ECORE_IMF_EVENT_DELETE_SURROUNDING event to the event queue.
1168 * ecore_imf_context_event_callback_call() can be used as synchronous method.
1169 *
1170 * @param ctx An #Ecore_IMF_Context.
1171 * @param offset The start offset of surrounding to be deleted.
1172 * @param n_chars The number of characters to be deleted.
1173 * @ingroup Ecore_IMF_Context_Module_Group
1174 */
1175EAPI void
1176ecore_imf_context_delete_surrounding_event_add(Ecore_IMF_Context *ctx, int offset, int n_chars)
1177{
1178 Ecore_IMF_Event_Delete_Surrounding *ev;
1179
1180 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1181 {
1182 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1183 "ecore_imf_context_delete_surrounding_event_add");
1184 return;
1185 }
1186
1187 ev = malloc(sizeof(Ecore_IMF_Event_Delete_Surrounding));
1188 ev->ctx = ctx;
1189 ev->offset = offset;
1190 ev->n_chars = n_chars;
1191 ecore_event_add(ECORE_IMF_EVENT_DELETE_SURROUNDING,
1192 ev, _ecore_imf_event_free_delete_surrounding, NULL);
1193}
1194
1195/**
1196 * Add (register) a callback function to a given context event.
1197 *
1198 * This function adds a function callback to the context @p ctx when the
1199 * event of type @p type occurs on it. The function pointer is @p
1200 * func.
1201 *
1202 * The event type @p type to trigger the function may be one of
1203 * #ECORE_IMF_CALLBACK_PREEDIT_START, #ECORE_IMF_CALLBACK_PREEDIT_END,
1204 * #ECORE_IMF_CALLBACK_PREEDIT_CHANGED, #ECORE_IMF_CALLBACK_COMMIT and
1205 * #ECORE_IMF_CALLBACK_DELETE_SURROUNDING.
1206 *
1207 * @param ctx Ecore_IMF_Context to attach a callback to.
1208 * @param type The type of event that will trigger the callback
1209 * @param func The (callback) function to be called when the event is
1210 * triggered
1211 * @param data The data pointer to be passed to @p func
1212 * @ingroup Ecore_IMF_Context_Group
1213 * @since 1.2.0
1214 *
1215 * Example
1216 * @code
1217 * static void
1218 * _imf_event_commit_cb(void *data, Ecore_IMF_Context *ctx, void *event_info)
1219 * {
1220 * char *commit_str = event_info;
1221 * // something to do
1222 * }
1223 *
1224 * ecore_imf_context_event_callback_add(en->imf_context, ECORE_IMF_CALLBACK_COMMIT, _imf_event_commit_cb, data);
1225 * @endcode
1226 */
1227EAPI void
1228ecore_imf_context_event_callback_add(Ecore_IMF_Context *ctx, Ecore_IMF_Callback_Type type, Ecore_IMF_Event_Cb func, const void *data)
1229{
1230 Ecore_IMF_Func_Node *fn = NULL;
1231
1232 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1233 {
1234 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1235 "ecore_imf_context_event_callback_add");
1236 return;
1237 }
1238
1239 if (!func) return;
1240
1241 fn = calloc(1, sizeof (Ecore_IMF_Func_Node));
1242 if (!fn) return;
1243
1244 fn->func = func;
1245 fn->data = data;
1246 fn->type = type;
1247
1248 ctx->callbacks = eina_list_append(ctx->callbacks, fn);
1249}
1250
1251/**
1252 * Delete (unregister) a callback function registered to a given
1253 * context event.
1254 *
1255 * This function removes a function callback from the context @p ctx when the
1256 * event of type @p type occurs on it. The function pointer is @p
1257 * func.
1258 *
1259 * @see ecore_imf_context_event_callback_add() for more details
1260 *
1261 * @param ctx Ecore_IMF_Context to remove a callback from.
1262 * @param type The type of event that was triggering the callback
1263 * @param func The (callback) function that was to be called when the event was triggered
1264 * @return the data pointer
1265 * @ingroup Ecore_IMF_Context_Group
1266 * @since 1.2.0
1267 */
1268EAPI void *
1269ecore_imf_context_event_callback_del(Ecore_IMF_Context *ctx, Ecore_IMF_Callback_Type type, Ecore_IMF_Event_Cb func)
1270{
1271 Eina_List *l = NULL;
1272 Eina_List *l_next = NULL;
1273 Ecore_IMF_Func_Node *fn = NULL;
1274
1275 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1276 {
1277 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1278 "ecore_imf_context_event_callback_del");
1279 return NULL;
1280 }
1281
1282 if (!func) return NULL;
1283 if (!ctx->callbacks) return NULL;
1284
1285 EINA_LIST_FOREACH_SAFE(ctx->callbacks, l, l_next, fn)
1286 {
1287 if ((fn) && (fn->func == func) && (fn->type == type))
1288 {
1289 void *tmp = (void *)fn->data;
1290 free(fn);
1291 ctx->callbacks = eina_list_remove_list(ctx->callbacks, l);
1292 return tmp;
1293 }
1294 }
1295 return NULL;
1296}
1297
1298/**
1299 * Call a given callback on the context @p ctx.
1300 *
1301 * ecore_imf_context_preedit_start_event_add(), ecore_imf_context_preedit_end_event_add(),
1302 * ecore_imf_context_preedit_changed_event_add(), ecore_imf_context_commit_event_add() and
1303 * ecore_imf_context_delete_surrounding_event_add() APIs are asynchronous
1304 * because those API adds each event to the event queue.
1305 *
1306 * This API provides the way to call each callback function immediately.
1307 *
1308 * @param ctx Ecore_IMF_Context.
1309 * @param type The type of event that will trigger the callback
1310 * @param event_info The pointer to event specific struct or information to
1311 * pass to the callback functions registered on this event
1312 * @ingroup Ecore_IMF_Context_Module_Group
1313 * @since 1.2.0
1314 */
1315EAPI void
1316ecore_imf_context_event_callback_call(Ecore_IMF_Context *ctx, Ecore_IMF_Callback_Type type, void *event_info)
1317{
1318 Ecore_IMF_Func_Node *fn = NULL;
1319 Eina_List *l = NULL;
1320
1321 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1322 {
1323 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1324 "ecore_imf_context_event_callback_call");
1325 return;
1326 }
1327
1328 EINA_LIST_FOREACH(ctx->callbacks, l, fn)
1329 {
1330 if ((fn) && (fn->type == type) && (fn->func))
1331 fn->func(fn->data, ctx, event_info);
1332 }
1333}
1334
1335/**
1336 * Ask the Input Method Context to show the control panel of using Input Method.
1337 *
1338 * @param ctx An #Ecore_IMF_Context.
1339 * @ingroup Ecore_IMF_Context_Group
1340 * @since 1.1.0
1341 */
1342EAPI void
1343ecore_imf_context_control_panel_show(Ecore_IMF_Context *ctx)
1344{
1345 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1346 {
1347 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1348 "ecore_imf_context_control_panel_show");
1349 return;
1350 }
1351
1352 if (ctx->klass->control_panel_show) ctx->klass->control_panel_show(ctx);
1353}
1354
1355/**
1356 * Ask the Input Method Context to hide the control panel of using Input Method.
1357 *
1358 * @param ctx An #Ecore_IMF_Context.
1359 * @ingroup Ecore_IMF_Context_Group
1360 * @since 1.1.0
1361 */
1362EAPI void
1363ecore_imf_context_control_panel_hide(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_control_panel_hide");
1369 return;
1370 }
1371
1372 if (ctx->klass->control_panel_hide) ctx->klass->control_panel_hide(ctx);
1373}
1374
1375/**
1376 * Ask the Input Method Context to show the input panel (virtual keyboard).
1377 *
1378 * @param ctx An #Ecore_IMF_Context.
1379 * @ingroup Ecore_IMF_Context_Group
1380 * @since 1.1.0
1381 */
1382EAPI void
1383ecore_imf_context_input_panel_show(Ecore_IMF_Context *ctx)
1384{
1385 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1386 {
1387 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1388 "ecore_imf_context_input_panel_show");
1389 return;
1390 }
1391
1392 if (ctx->klass->show) ctx->klass->show(ctx);
1393}
1394
1395/**
1396 * Ask the Input Method Context to hide the input panel.
1397 *
1398 * @param ctx An #Ecore_IMF_Context.
1399 * @ingroup Ecore_IMF_Context_Group
1400 * @since 1.1.0
1401 */
1402EAPI void
1403ecore_imf_context_input_panel_hide(Ecore_IMF_Context *ctx)
1404{
1405 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1406 {
1407 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1408 "ecore_imf_context_input_panel_hide");
1409 return;
1410 }
1411
1412 if (ctx->klass->hide) ctx->klass->hide(ctx);
1413}
1414
1415/**
1416 * Set the layout of the input panel.
1417 *
1418 * @param ctx An #Ecore_IMF_Context.
1419 * @param layout see #Ecore_IMF_Input_Panel_Layout
1420 * @note Default layout type is ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL.
1421 * @ingroup Ecore_IMF_Context_Group
1422 * @since 1.1.0
1423 */
1424EAPI void
1425ecore_imf_context_input_panel_layout_set(Ecore_IMF_Context *ctx, Ecore_IMF_Input_Panel_Layout layout)
1426{
1427 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1428 {
1429 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1430 "ecore_imf_context_input_panel_layout_set");
1431 return;
1432 }
1433
1434 if (ctx->klass->input_panel_layout_set)
1435 ctx->klass->input_panel_layout_set(ctx, layout);
1436
1437 ctx->input_panel_layout = layout;
1438}
1439
1440/**
1441 * Get the layout of the current active input panel.
1442 *
1443 * @param ctx An #Ecore_IMF_Context.
1444 * @return layout see #Ecore_IMF_Input_Panel_Layout
1445 * @ingroup Ecore_IMF_Context_Group
1446 * @since 1.1.0
1447 */
1448EAPI Ecore_IMF_Input_Panel_Layout
1449ecore_imf_context_input_panel_layout_get(Ecore_IMF_Context *ctx)
1450{
1451 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1452 {
1453 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1454 "ecore_imf_context_input_panel_layout_get");
1455 return ECORE_IMF_INPUT_PANEL_LAYOUT_INVALID;
1456 }
1457
1458 if (ctx->klass->input_panel_layout_get)
1459 return ctx->input_panel_layout;
1460 else
1461 return ECORE_IMF_INPUT_PANEL_LAYOUT_INVALID;
1462}
1463
1464/**
1465 * Set the language of the input panel.
1466 * This API can be used when you want to show the English keyboard.
1467 *
1468 * @param ctx An #Ecore_IMF_Context.
1469 * @param lang the language to be set to the input panel.
1470 * @ingroup Ecore_IMF_Context_Group
1471 * @since 1.1.0
1472 */
1473EAPI void
1474ecore_imf_context_input_panel_language_set(Ecore_IMF_Context *ctx, Ecore_IMF_Input_Panel_Lang lang)
1475{
1476 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1477 {
1478 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1479 "ecore_imf_context_input_panel_language_set");
1480 return;
1481 }
1482
1483 if (ctx->klass->input_panel_language_set) ctx->klass->input_panel_language_set(ctx, lang);
1484 ctx->input_panel_lang = lang;
1485}
1486
1487/**
1488 * Get the language of the input panel.
1489 *
1490 * See @ref ecore_imf_context_input_panel_language_set for more details.
1491 *
1492 * @param ctx An #Ecore_IMF_Context.
1493 * @return Ecore_IMF_Input_Panel_Lang
1494 * @ingroup Ecore_IMF_Context_Group
1495 * @since 1.1.0
1496 */
1497EAPI Ecore_IMF_Input_Panel_Lang
1498ecore_imf_context_input_panel_language_get(Ecore_IMF_Context *ctx)
1499{
1500 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1501 {
1502 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1503 "ecore_imf_context_input_panel_language_get");
1504 return ECORE_IMF_INPUT_PANEL_LANG_AUTOMATIC;
1505 }
1506
1507 return ctx->input_panel_lang;
1508}
1509
1510/**
1511 * Set whether the Input Method Context should request to show the input panel automatically
1512 * when the widget has focus.
1513 *
1514 * @param ctx An #Ecore_IMF_Context.
1515 * @param enabled If true, the input panel will be shown when the widget is clicked or has focus.
1516 * @ingroup Ecore_IMF_Context_Group
1517 * @since 1.1.0
1518 */
1519EAPI void
1520ecore_imf_context_input_panel_enabled_set(Ecore_IMF_Context *ctx,
1521 Eina_Bool enabled)
1522{
1523 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1524 {
1525 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1526 "ecore_imf_context_input_panel_enabled_set");
1527 return;
1528 }
1529
1530 ctx->input_panel_enabled = enabled;
1531}
1532
1533/**
1534 * Get whether the Input Method Context requests to show the input panel automatically.
1535 *
1536 * @param ctx An #Ecore_IMF_Context.
1537 * @return Return the attribute to show the input panel automatically
1538 * @ingroup Ecore_IMF_Context_Group
1539 * @since 1.1.0
1540 */
1541EAPI Eina_Bool
1542ecore_imf_context_input_panel_enabled_get(Ecore_IMF_Context *ctx)
1543{
1544 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1545 {
1546 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1547 "ecore_imf_context_input_panel_enabled_get");
1548 return EINA_FALSE;
1549 }
1550
1551 return ctx->input_panel_enabled;
1552}
1553
1554/**
1555 * Set the input panel-specific data to deliver to the input panel.
1556 * This API is used by applications to deliver specific data to the input panel.
1557 * The data format MUST be negotiated by both application and the input panel.
1558 * The size and format of data are defined by the input panel.
1559 *
1560 * @param ctx An #Ecore_IMF_Context.
1561 * @param data The specific data to be set to the input panel.
1562 * @param len the length of data, in bytes, to send to the input panel
1563 * @ingroup Ecore_IMF_Context_Group
1564 * @since 1.2.0
1565 */
1566EAPI void
1567ecore_imf_context_input_panel_imdata_set(Ecore_IMF_Context *ctx, const void *data, int len)
1568{
1569 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1570 {
1571 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1572 "ecore_imf_context_input_panel_imdata_set");
1573 return;
1574 }
1575
1576 if (!data) return;
1577
1578 if (ctx->klass->input_panel_imdata_set)
1579 ctx->klass->input_panel_imdata_set(ctx, data, len);
1580}
1581
1582/**
1583 * Get the specific data of the current active input panel.
1584 *
1585 * @param ctx An #Ecore_IMF_Context.
1586 * @param data The specific data to be got from the input panel
1587 * @param len The length of data
1588 * @ingroup Ecore_IMF_Context_Group
1589 * @since 1.2.0
1590 */
1591EAPI void
1592ecore_imf_context_input_panel_imdata_get(Ecore_IMF_Context *ctx, void *data, int *len)
1593{
1594 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1595 {
1596 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1597 "ecore_imf_context_input_panel_imdata_get");
1598 return;
1599 }
1600
1601 if (!data) return;
1602
1603 if (ctx->klass->input_panel_imdata_get)
1604 ctx->klass->input_panel_imdata_get(ctx, data, len);
1605}
1606
1607/**
1608 * Set the "return" key type. This type is used to set string or icon on the "return" key of the input panel.
1609 *
1610 * An input panel displays the string or icon associated with this type
1611 *
1612 * @param ctx An #Ecore_IMF_Context.
1613 * @param return_key_type The type of "return" key on the input panel
1614 * @note Default type is ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT.
1615 * @ingroup Ecore_IMF_Context_Group
1616 * @since 1.2.0
1617 */
1618EAPI void
1619ecore_imf_context_input_panel_return_key_type_set(Ecore_IMF_Context *ctx, Ecore_IMF_Input_Panel_Return_Key_Type return_key_type)
1620{
1621 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1622 {
1623 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1624 "ecore_imf_context_input_panel_return_key_type_set");
1625 return;
1626 }
1627
1628 ctx->input_panel_return_key_type = return_key_type;
1629 if (ctx->klass->input_panel_return_key_type_set) ctx->klass->input_panel_return_key_type_set(ctx, return_key_type);
1630}
1631
1632/**
1633 * Get the "return" key type.
1634 *
1635 * @see ecore_imf_context_input_panel_return_key_type_set() for more details
1636 *
1637 * @param ctx An #Ecore_IMF_Context.
1638 * @return The type of "return" key on the input panel
1639 * @ingroup Ecore_IMF_Context_Group
1640 * @since 1.2.0
1641 */
1642EAPI Ecore_IMF_Input_Panel_Return_Key_Type
1643ecore_imf_context_input_panel_return_key_type_get(Ecore_IMF_Context *ctx)
1644{
1645 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1646 {
1647 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1648 "ecore_imf_context_input_panel_return_key_type_get");
1649 return EINA_FALSE;
1650 }
1651
1652 return ctx->input_panel_return_key_type;
1653}
1654
1655/**
1656 * Set the return key on the input panel to be disabled.
1657 *
1658 * @param ctx An #Ecore_IMF_Context.
1659 * @param disabled The state
1660 * @ingroup Ecore_IMF_Context_Group
1661 * @since 1.2.0
1662 */
1663EAPI void
1664ecore_imf_context_input_panel_return_key_disabled_set(Ecore_IMF_Context *ctx, Eina_Bool disabled)
1665{
1666 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1667 {
1668 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1669 "ecore_imf_context_input_panel_return_key_disabled_set");
1670 return;
1671 }
1672
1673 ctx->input_panel_return_key_disabled = disabled;
1674 if (ctx->klass->input_panel_return_key_disabled_set) ctx->klass->input_panel_return_key_disabled_set(ctx, disabled);
1675}
1676
1677/**
1678 * Get whether the return key on the input panel should be disabled or not.
1679 *
1680 * @param ctx An #Ecore_IMF_Context.
1681 * @return @c EINA_TRUE if it should be disabled.
1682 * @ingroup Ecore_IMF_Context_Group
1683 * @since 1.2.0
1684 */
1685EAPI Eina_Bool
1686ecore_imf_context_input_panel_return_key_disabled_get(Ecore_IMF_Context *ctx)
1687{
1688 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1689 {
1690 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1691 "ecore_imf_context_input_panel_return_key_disabled_get");
1692 return EINA_FALSE;
1693 }
1694
1695 return ctx->input_panel_return_key_disabled;
1696}
1697
1698/**
1699 * Set the caps lock mode on the input panel.
1700 *
1701 * @param ctx An #Ecore_IMF_Context.
1702 * @param mode Turn on caps lock on the input panel if @c EINA_TRUE.
1703 * @ingroup Ecore_IMF_Context_Group
1704 * @since 1.2.0
1705 */
1706EAPI void
1707ecore_imf_context_input_panel_caps_lock_mode_set(Ecore_IMF_Context *ctx, Eina_Bool mode)
1708{
1709 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1710 {
1711 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1712 "ecore_imf_context_input_panel_caps_lock_mode_set");
1713 return;
1714 }
1715
1716 if (ctx->klass->input_panel_caps_lock_mode_set)
1717 ctx->klass->input_panel_caps_lock_mode_set(ctx, mode);
1718
1719 ctx->input_panel_caps_lock_mode = mode;
1720}
1721
1722/**
1723 * Get the caps lock mode on the input panel.
1724 *
1725 * @param ctx An #Ecore_IMF_Context.
1726 * @return @c EINA_TRUE if the caps lock is turned on.
1727 * @ingroup Ecore_IMF_Context_Group
1728 * @since 1.2.0
1729 */
1730EAPI Eina_Bool
1731ecore_imf_context_input_panel_caps_lock_mode_get(Ecore_IMF_Context *ctx)
1732{
1733 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1734 {
1735 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1736 "ecore_imf_context_input_panel_caps_lock_mode_get");
1737 return EINA_FALSE;
1738 }
1739
1740 return ctx->input_panel_caps_lock_mode;
1741}
1742
1743/**
1744 * Get the position of the current active input panel.
1745 *
1746 * @param ctx An #Ecore_IMF_Context.
1747 * @param x top-left x co-ordinate of the input panel
1748 * @param y top-left y co-ordinate of the input panel
1749 * @param w width of the input panel
1750 * @param h height of the input panel
1751 * @ingroup Ecore_IMF_Context_Group
1752 * @since 1.3
1753 */
1754EAPI void
1755ecore_imf_context_input_panel_geometry_get(Ecore_IMF_Context *ctx, int *x, int *y, int *w, int *h)
1756{
1757 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1758 {
1759 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1760 "ecore_imf_context_input_panel_geometry_get");
1761 return;
1762 }
1763
1764 if (ctx->klass->input_panel_geometry_get)
1765 ctx->klass->input_panel_geometry_get(ctx, x, y, w, h);
1766}
1767
1768/**
1769 * Get state of current active input panel.
1770 *
1771 * @param ctx An #Ecore_IMF_Context.
1772 * @return The state of input panel.
1773 * @ingroup Ecore_IMF_Context_Group
1774 * @since 1.3
1775 */
1776EAPI Ecore_IMF_Input_Panel_State
1777ecore_imf_context_input_panel_state_get(Ecore_IMF_Context *ctx)
1778{
1779 Ecore_IMF_Input_Panel_State state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
1780 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1781 {
1782 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1783 "ecore_imf_context_input_panel_state_get");
1784 return ECORE_IMF_INPUT_PANEL_STATE_HIDE;
1785 }
1786
1787 if (ctx->klass->input_panel_state_get)
1788 state = ctx->klass->input_panel_state_get(ctx);
1789
1790 return state;
1791}
1792
1793/**
1794 * Register a callback function which will be called if there is change in input panel state,language,mode etc.
1795 * In order to deregister the callback function
1796 * Use @ref ecore_imf_context_input_panel_event_callback_del.
1797 *
1798 * @param ctx An #Ecore_IMF_Context
1799 * @param type event type
1800 * @param func the callback function
1801 * @param data application-input panel specific data.
1802 * @ingroup Ecore_IMF_Context_Group
1803 * @since 1.3
1804 */
1805EAPI void
1806ecore_imf_context_input_panel_event_callback_add(Ecore_IMF_Context *ctx,
1807 Ecore_IMF_Input_Panel_Event type,
1808 void (*func) (void *data, Ecore_IMF_Context *ctx, int value),
1809 const void *data)
1810{
1811 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1812 {
1813 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1814 "ecore_imf_context_input_panel_event_callback_add");
1815 return;
1816 }
1817
1818 if (ctx->klass->input_panel_event_callback_add)
1819 ctx->klass->input_panel_event_callback_add(ctx, type, func, (void *)data);
1820}
1821
1822/**
1823 * Unregister a callback function which will be called if there is change in input panel state, language, mode etc.
1824 *
1825 * @param ctx An #Ecore_IMF_Context.
1826 * @param type An #Ecore_IMF_Input_Panel_Event.
1827 * @param func the callback function
1828 * @ingroup Ecore_IMF_Context_Group
1829 * @since 1.3
1830 */
1831EAPI void
1832ecore_imf_context_input_panel_event_callback_del(Ecore_IMF_Context *ctx,
1833 Ecore_IMF_Input_Panel_Event type,
1834 void (*func) (void *data, Ecore_IMF_Context *ctx, int value))
1835{
1836 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1837 {
1838 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1839 "ecore_imf_context_input_panel_event_callback_del");
1840 return;
1841 }
1842
1843 if (ctx->klass->input_panel_event_callback_del)
1844 ctx->klass->input_panel_event_callback_del(ctx, type, func);
1845}
1846
1847/**
1848 * Get the current language locale of the input panel.
1849 *
1850 * ex) fr_FR
1851 *
1852 * @param ctx An #Ecore_IMF_Context.
1853 * @param lang Location to store the retrieved language string. The
1854 * string retrieved must be freed with free().
1855 * @ingroup Ecore_IMF_Context_Group
1856 * @since 1.3
1857 */
1858EAPI void
1859ecore_imf_context_input_panel_language_locale_get(Ecore_IMF_Context *ctx, char **lang)
1860{
1861 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1862 {
1863 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1864 "ecore_imf_context_input_panel_language_locale_get");
1865 return;
1866 }
1867
1868 if (ctx->klass->input_panel_language_locale_get)
1869 ctx->klass->input_panel_language_locale_get(ctx, lang);
1870 else
1871 {
1872 if (lang) *lang = strdup("");
1873 }
1874}
1875
1876/**
1877 * Get the geometry information of the candidate panel.
1878 *
1879 * @param ctx An #Ecore_IMF_Context.
1880 * @param x top-left x co-ordinate of the candidate panel
1881 * @param y top-left y co-ordinate of the candidate panel
1882 * @param w width of the candidate panel
1883 * @param h height of the candidate panel
1884 * @ingroup Ecore_IMF_Context_Group
1885 * @since 1.3
1886 */
1887EAPI void
1888ecore_imf_context_candidate_panel_geometry_get(Ecore_IMF_Context *ctx, int *x, int *y, int *w, int *h)
1889{
1890 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1891 {
1892 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1893 "ecore_imf_context_candidate_panel_geometry_get");
1894 return;
1895 }
1896
1897 if (ctx->klass->candidate_panel_geometry_get)
1898 ctx->klass->candidate_panel_geometry_get(ctx, x, y, w, h);
1899}
1900