aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/ecore/src/lib/ecore_imf/ecore_imf_context.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/ecore/src/lib/ecore_imf/ecore_imf_context.c')
-rw-r--r--libraries/ecore/src/lib/ecore_imf/ecore_imf_context.c1237
1 files changed, 1237 insertions, 0 deletions
diff --git a/libraries/ecore/src/lib/ecore_imf/ecore_imf_context.c b/libraries/ecore/src/lib/ecore_imf/ecore_imf_context.c
new file mode 100644
index 0000000..417fad3
--- /dev/null
+++ b/libraries/ecore/src/lib/ecore_imf/ecore_imf_context.c
@@ -0,0 +1,1237 @@
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 */
31EAPI Eina_List *
32ecore_imf_context_available_ids_get(void)
33{
34 return ecore_imf_module_context_ids_get();
35}
36
37EAPI Eina_List *
38ecore_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 */
51static 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 */
75EAPI const char *
76ecore_imf_context_default_id_get(void)
77{
78 return ecore_imf_context_default_id_by_canvas_type_get(NULL);
79}
80
81EAPI const char *
82ecore_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 */
147EAPI const Ecore_IMF_Context_Info *
148ecore_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 */
166EAPI Ecore_IMF_Context *
167ecore_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 */
205EAPI const Ecore_IMF_Context_Info *
206ecore_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 */
223EAPI void
224ecore_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 */
248EAPI void
249ecore_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 */
271EAPI void *
272ecore_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 */
296EAPI void
297ecore_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 */
319EAPI void *
320ecore_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 */
337EAPI void
338ecore_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 */
355EAPI void
356ecore_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 */
378EAPI void
379ecore_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 */
409EAPI void
410ecore_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 */
435EAPI void
436ecore_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 */
454EAPI void
455ecore_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 */
474EAPI void
475ecore_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 */
494EAPI void
495ecore_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 */
518EAPI void
519ecore_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 @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 */
540EAPI void
541ecore_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 @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 */
561EAPI void
562ecore_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 */
585EAPI Eina_Bool
586ecore_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 */
606EAPI void
607ecore_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 */
629EAPI Ecore_IMF_Autocapital_Type
630ecore_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 */
653EAPI void
654ecore_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 */
678EAPI void
679ecore_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 */
700EAPI Ecore_IMF_Input_Mode
701ecore_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 */
727EAPI Eina_Bool
728ecore_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 */
756EAPI Ecore_IMF_Context *
757ecore_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 */
784EAPI void
785ecore_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 */
805EAPI 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 */
837EAPI Eina_Bool
838ecore_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
861static 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 */
875EAPI void
876ecore_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 */
901EAPI void
902ecore_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 */
925EAPI void
926ecore_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
943static 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 */
960EAPI void
961ecore_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
980static 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 */
998EAPI void
999ecore_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 */
1025EAPI void
1026ecore_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 */
1045EAPI void
1046ecore_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 */
1065EAPI void
1066ecore_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 */
1085EAPI void
1086ecore_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 */
1106EAPI void
1107ecore_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 */
1130EAPI Ecore_IMF_Input_Panel_Layout
1131ecore_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 */
1157EAPI void
1158ecore_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 */
1181EAPI Ecore_IMF_Input_Panel_Lang
1182ecore_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 */
1203EAPI void
1204ecore_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 */
1225EAPI Eina_Bool
1226ecore_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