diff options
author | andrunko <andrunko> | 2007-11-19 18:27:11 +0000 |
---|---|---|
committer | andrunko <andrunko@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33> | 2007-11-19 18:27:11 +0000 |
commit | 502b766d664dda3c0a10826bddd8c043a868cfa1 (patch) | |
tree | ef7b1799cd28aad59b1f2d843dbac3e1a24f2052 /legacy/ecore/src/lib/ecore_imf | |
parent | 23d39ab1541513e6681c2dd5330de5acec8fdb9b (diff) |
Added Ecore_IMF module.
Added Ecore_IMF module. This module enables different input methods to be
used with Ecore. Input methods modules can be created using the Ecore_IMF
interface.
Added ecore_evas_window_get method to allow input methods to request
the window related to a given Ecore_Evas when available.
SVN revision: 32775
Diffstat (limited to '')
-rw-r--r-- | legacy/ecore/src/lib/ecore_imf/.cvsignore | 6 | ||||
-rw-r--r-- | legacy/ecore/src/lib/ecore_imf/Ecore_IMF.h | 162 | ||||
-rw-r--r-- | legacy/ecore/src/lib/ecore_imf/Makefile.am | 31 | ||||
-rw-r--r-- | legacy/ecore/src/lib/ecore_imf/ecore_imf.c | 64 | ||||
-rw-r--r-- | legacy/ecore/src/lib/ecore_imf/ecore_imf_context.c | 740 | ||||
-rw-r--r-- | legacy/ecore/src/lib/ecore_imf/ecore_imf_module.c | 207 | ||||
-rw-r--r-- | legacy/ecore/src/lib/ecore_imf/ecore_imf_private.h | 36 |
7 files changed, 1246 insertions, 0 deletions
diff --git a/legacy/ecore/src/lib/ecore_imf/.cvsignore b/legacy/ecore/src/lib/ecore_imf/.cvsignore new file mode 100644 index 0000000000..09980ae6ba --- /dev/null +++ b/legacy/ecore/src/lib/ecore_imf/.cvsignore | |||
@@ -0,0 +1,6 @@ | |||
1 | .deps | ||
2 | .libs | ||
3 | Makefile | ||
4 | Makefile.in | ||
5 | *.lo | ||
6 | *.la | ||
diff --git a/legacy/ecore/src/lib/ecore_imf/Ecore_IMF.h b/legacy/ecore/src/lib/ecore_imf/Ecore_IMF.h new file mode 100644 index 0000000000..e640ef43fc --- /dev/null +++ b/legacy/ecore/src/lib/ecore_imf/Ecore_IMF.h | |||
@@ -0,0 +1,162 @@ | |||
1 | /* | ||
2 | * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 | ||
3 | */ | ||
4 | #ifndef _ECORE_IMF_H | ||
5 | #define _ECORE_IMF_H | ||
6 | |||
7 | #ifdef EAPI | ||
8 | #undef EAPI | ||
9 | #endif | ||
10 | #ifdef _MSC_VER | ||
11 | # ifdef BUILDING_DLL | ||
12 | # define EAPI __declspec(dllexport) | ||
13 | # else | ||
14 | # define EAPI __declspec(dllimport) | ||
15 | # endif | ||
16 | #else | ||
17 | # ifdef __GNUC__ | ||
18 | # if __GNUC__ >= 4 | ||
19 | # define EAPI __attribute__ ((visibility("default"))) | ||
20 | # else | ||
21 | # define EAPI | ||
22 | # endif | ||
23 | # else | ||
24 | # define EAPI | ||
25 | # endif | ||
26 | #endif | ||
27 | |||
28 | #include <Ecore_Data.h> | ||
29 | #include <Evas.h> | ||
30 | |||
31 | #ifdef __cplusplus | ||
32 | extern "C" { | ||
33 | #endif | ||
34 | |||
35 | typedef struct _Ecore_IMF_Event_Preedit_Start Ecore_IMF_Event_Preedit_Start; | ||
36 | typedef struct _Ecore_IMF_Event_Preedit_End Ecore_IMF_Event_Preedit_End; | ||
37 | typedef struct _Ecore_IMF_Event_Preedit_Changed Ecore_IMF_Event_Preedit_Changed; | ||
38 | typedef struct _Ecore_IMF_Event_Commit Ecore_IMF_Event_Commit; | ||
39 | typedef struct _Ecore_IMF_Event_Delete_Surrounding Ecore_IMF_Event_Delete_Surrounding; | ||
40 | |||
41 | typedef struct _Ecore_IMF_Context Ecore_IMF_Context; /**< An Input Method Context */ | ||
42 | typedef struct _Ecore_IMF_Context_Class Ecore_IMF_Context_Class; /**< An Input Method Context class */ | ||
43 | typedef struct _Ecore_IMF_Context_Info Ecore_IMF_Context_Info; /**< An Input Method Context info */ | ||
44 | |||
45 | EAPI extern int ECORE_IMF_EVENT_PREEDIT_START; | ||
46 | EAPI extern int ECORE_IMF_EVENT_PREEDIT_END; | ||
47 | EAPI extern int ECORE_IMF_EVENT_PREEDIT_CHANGED; | ||
48 | EAPI extern int ECORE_IMF_EVENT_COMMIT; | ||
49 | EAPI extern int ECORE_IMF_EVENT_DELETE_SURROUNDIND; | ||
50 | |||
51 | typedef enum | ||
52 | { | ||
53 | ECORE_IMF_INPUT_MODE_ALPHA = 1 << 0, | ||
54 | ECORE_IMF_INPUT_MODE_NUMERIC = 1 << 1, | ||
55 | ECORE_IMF_INPUT_MODE_SPECIAL = 1 << 2, | ||
56 | ECORE_IMF_INPUT_MODE_HEXA = 1 << 3, | ||
57 | ECORE_IMF_INPUT_MODE_TELE = 1 << 4, | ||
58 | ECORE_IMF_INPUT_MODE_FULL = (ECORE_IMF_INPUT_MODE_ALPHA | ECORE_IMF_INPUT_MODE_NUMERIC | ECORE_IMF_INPUT_MODE_SPECIAL), | ||
59 | ECORE_IMF_INPUT_MODE_INVISIBLE = 1 << 29, | ||
60 | ECORE_IMF_INPUT_MODE_AUTOCAP = 1 << 30 | ||
61 | } Ecore_IMF_Input_Mode; | ||
62 | |||
63 | struct _Ecore_IMF_Event_Preedit_Start | ||
64 | { | ||
65 | Ecore_IMF_Context *ctx; | ||
66 | }; | ||
67 | |||
68 | struct _Ecore_IMF_Event_Preedit_End | ||
69 | { | ||
70 | Ecore_IMF_Context *ctx; | ||
71 | }; | ||
72 | |||
73 | struct _Ecore_IMF_Event_Preedit_Changed | ||
74 | { | ||
75 | Ecore_IMF_Context *ctx; | ||
76 | }; | ||
77 | |||
78 | struct _Ecore_IMF_Event_Commit | ||
79 | { | ||
80 | Ecore_IMF_Context *ctx; | ||
81 | char *str; | ||
82 | }; | ||
83 | |||
84 | struct _Ecore_IMF_Event_Delete_Surrounding | ||
85 | { | ||
86 | Ecore_IMF_Context *ctx; | ||
87 | int offset; | ||
88 | int n_chars; | ||
89 | }; | ||
90 | |||
91 | struct _Ecore_IMF_Context_Class | ||
92 | { | ||
93 | void (*add) (Ecore_IMF_Context *ctx); | ||
94 | void (*del) (Ecore_IMF_Context *ctx); | ||
95 | void (*client_window_set) (Ecore_IMF_Context *ctx, void *window); | ||
96 | void (*show) (Ecore_IMF_Context *ctx); | ||
97 | void (*hide) (Ecore_IMF_Context *ctx); | ||
98 | void (*preedit_string_get) (Ecore_IMF_Context *ctx, char **str, int *cursor_pos); | ||
99 | void (*focus_in) (Ecore_IMF_Context *ctx); | ||
100 | void (*focus_out) (Ecore_IMF_Context *ctx); | ||
101 | void (*reset) (Ecore_IMF_Context *ctx); | ||
102 | void (*cursor_position_set) (Ecore_IMF_Context *ctx, int cursor_pos); | ||
103 | void (*use_preedit_set) (Ecore_IMF_Context *ctx, int use_preedit); | ||
104 | void (*input_mode_set) (Ecore_IMF_Context *ctx, Ecore_IMF_Input_Mode input_mode); | ||
105 | int (*filter_event) (Ecore_IMF_Context *ctx, Evas_Callback_Type type, void *event_info); | ||
106 | }; | ||
107 | |||
108 | struct _Ecore_IMF_Context_Info | ||
109 | { | ||
110 | const char *id; /* ID */ | ||
111 | const char *description; /* Human readable description */ | ||
112 | const char *default_locales; /* Languages for which this context is the default, separated by : */ | ||
113 | }; | ||
114 | |||
115 | EAPI int ecore_imf_init(void); | ||
116 | EAPI int ecore_imf_shutdown(void); | ||
117 | |||
118 | EAPI Ecore_List *ecore_imf_context_available_ids_get(void); | ||
119 | EAPI const char *ecore_imf_context_default_id_get(void); | ||
120 | EAPI const Ecore_IMF_Context_Info *ecore_imf_context_info_by_id_get(const char *id); | ||
121 | |||
122 | EAPI Ecore_IMF_Context *ecore_imf_context_add(const char *id); | ||
123 | EAPI void ecore_imf_context_del(Ecore_IMF_Context *ctx); | ||
124 | EAPI void ecore_imf_context_client_window_set(Ecore_IMF_Context *ctx, void *window); | ||
125 | EAPI void ecore_imf_context_show(Ecore_IMF_Context *ctx); | ||
126 | EAPI void ecore_imf_context_hide(Ecore_IMF_Context *ctx); | ||
127 | EAPI void ecore_imf_context_preedit_string_get(Ecore_IMF_Context *ctx, char **str, int *cursor_pos); | ||
128 | EAPI void ecore_imf_context_focus_in(Ecore_IMF_Context *ctx); | ||
129 | EAPI void ecore_imf_context_focus_out(Ecore_IMF_Context *ctx); | ||
130 | EAPI void ecore_imf_context_reset(Ecore_IMF_Context *ctx); | ||
131 | EAPI void ecore_imf_context_cursor_position_set(Ecore_IMF_Context *ctx, int cursor_pos); | ||
132 | EAPI void ecore_imf_context_use_preedit_set(Ecore_IMF_Context *ctx, int use_preedit); | ||
133 | EAPI void ecore_imf_context_retrieve_surrounding_callback_set(Ecore_IMF_Context *ctx, int (*func)(void *data, Ecore_IMF_Context *ctx, char **text, int *cursor_pos), const void *data); | ||
134 | EAPI void ecore_imf_context_input_mode_set(Ecore_IMF_Context *ctx, Ecore_IMF_Input_Mode input_mode); | ||
135 | EAPI Ecore_IMF_Input_Mode ecore_imf_context_input_mode_get(Ecore_IMF_Context *ctx); | ||
136 | EAPI int ecore_imf_context_filter_event(Ecore_IMF_Context *ctx, Evas_Callback_Type type, void *event_info); | ||
137 | |||
138 | /* plugin specific functions */ | ||
139 | EAPI Ecore_IMF_Context *ecore_imf_context_new(const Ecore_IMF_Context_Class *ctxc); | ||
140 | EAPI void ecore_imf_context_data_set(Ecore_IMF_Context *ctx, void *data); | ||
141 | EAPI void *ecore_imf_context_data_get(Ecore_IMF_Context *ctx); | ||
142 | EAPI int ecore_imf_context_surrounding_get(Ecore_IMF_Context *ctx, char **text, int *cursor_pos); | ||
143 | EAPI void ecore_imf_context_preedit_start_event_add(Ecore_IMF_Context *ctx); | ||
144 | EAPI void ecore_imf_context_preedit_end_event_add(Ecore_IMF_Context *ctx); | ||
145 | EAPI void ecore_imf_context_preedit_changed_event_add(Ecore_IMF_Context *ctx); | ||
146 | EAPI void ecore_imf_context_commit_event_add(Ecore_IMF_Context *ctx, const char *str); | ||
147 | EAPI void ecore_imf_context_delete_surrounding_event_add(Ecore_IMF_Context *ctx, int offset, int n_chars); | ||
148 | |||
149 | /* The following entry points must be exported by each input method module | ||
150 | */ | ||
151 | |||
152 | /* | ||
153 | * int imf_module_init (const Ecore_IMF_Context_Info **info); | ||
154 | * void imf_module_exit (void); | ||
155 | * Ecore_IMF_Context *imf_module_create (void); | ||
156 | */ | ||
157 | |||
158 | #ifdef __cplusplus | ||
159 | } | ||
160 | #endif | ||
161 | |||
162 | #endif | ||
diff --git a/legacy/ecore/src/lib/ecore_imf/Makefile.am b/legacy/ecore/src/lib/ecore_imf/Makefile.am new file mode 100644 index 0000000000..f363d2ae01 --- /dev/null +++ b/legacy/ecore/src/lib/ecore_imf/Makefile.am | |||
@@ -0,0 +1,31 @@ | |||
1 | MAINTAINERCLEANFILES = Makefile.in | ||
2 | |||
3 | if BUILD_ECORE_IMF | ||
4 | AM_CPPFLAGS = \ | ||
5 | -I$(top_srcdir)/src/lib/ecore \ | ||
6 | -DPACKAGE_LIB_DIR=\"$(libdir)\" \ | ||
7 | @EVAS_CFLAGS@ | ||
8 | |||
9 | lib_LTLIBRARIES = libecore_imf.la | ||
10 | include_HEADERS = \ | ||
11 | Ecore_IMF.h | ||
12 | |||
13 | libecore_imf_la_SOURCES = \ | ||
14 | ecore_imf.c \ | ||
15 | ecore_imf_context.c \ | ||
16 | ecore_imf_module.c \ | ||
17 | ecore_imf_private.h | ||
18 | |||
19 | libecore_imf_la_LIBADD = \ | ||
20 | $(top_builddir)/src/lib/ecore/libecore.la \ | ||
21 | @EVAS_LIBS@ | ||
22 | |||
23 | libecore_imf_la_LDFLAGS = -version-info @version_info@ | ||
24 | endif | ||
25 | |||
26 | EXTRA_DIST = \ | ||
27 | Ecore_IMF.h \ | ||
28 | ecore_imf.c \ | ||
29 | ecore_imf_context.c \ | ||
30 | ecore_imf_module.c \ | ||
31 | ecore_imf_private.h | ||
diff --git a/legacy/ecore/src/lib/ecore_imf/ecore_imf.c b/legacy/ecore/src/lib/ecore_imf/ecore_imf.c new file mode 100644 index 0000000000..acf7e8d693 --- /dev/null +++ b/legacy/ecore/src/lib/ecore_imf/ecore_imf.c | |||
@@ -0,0 +1,64 @@ | |||
1 | /* | ||
2 | * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 | ||
3 | */ | ||
4 | |||
5 | #include "config.h" | ||
6 | |||
7 | #include "Ecore_IMF.h" | ||
8 | |||
9 | EAPI int ECORE_IMF_EVENT_PREEDIT_START = 0; | ||
10 | EAPI int ECORE_IMF_EVENT_PREEDIT_END = 0; | ||
11 | EAPI int ECORE_IMF_EVENT_PREEDIT_CHANGED = 0; | ||
12 | EAPI int ECORE_IMF_EVENT_COMMIT = 0; | ||
13 | EAPI int ECORE_IMF_EVENT_RETRIEVE_SURROUNDIND = 0; | ||
14 | EAPI int ECORE_IMF_EVENT_DELETE_SURROUNDIND = 0; | ||
15 | |||
16 | static int init_count = 0; | ||
17 | |||
18 | /** | ||
19 | * @defgroup Ecore_IMF_Lib_Group Ecore Input Method Library Functions | ||
20 | * | ||
21 | * Utility functions that set up and shut down the Ecore Input Method | ||
22 | * library. | ||
23 | */ | ||
24 | |||
25 | /** | ||
26 | * Initialises the Ecore_IMF library. | ||
27 | * @return Number of times the library has been initialised without being | ||
28 | * shut down. | ||
29 | * @ingroup Ecore_IMF_Lib_Group | ||
30 | */ | ||
31 | EAPI int | ||
32 | ecore_imf_init(void) | ||
33 | { | ||
34 | if (++init_count != 1) return init_count; | ||
35 | |||
36 | ecore_init(); | ||
37 | ecore_imf_module_init(); | ||
38 | |||
39 | ECORE_IMF_EVENT_PREEDIT_START = ecore_event_type_new(); | ||
40 | ECORE_IMF_EVENT_PREEDIT_END = ecore_event_type_new(); | ||
41 | ECORE_IMF_EVENT_PREEDIT_CHANGED = ecore_event_type_new(); | ||
42 | ECORE_IMF_EVENT_COMMIT = ecore_event_type_new(); | ||
43 | ECORE_IMF_EVENT_RETRIEVE_SURROUNDIND = ecore_event_type_new(); | ||
44 | ECORE_IMF_EVENT_DELETE_SURROUNDIND = ecore_event_type_new(); | ||
45 | |||
46 | return init_count; | ||
47 | } | ||
48 | |||
49 | /** | ||
50 | * Shuts down the Ecore_IMF library. | ||
51 | * @return Number of times the library has been initialised without being | ||
52 | * shut down. | ||
53 | * @ingroup Ecore_IMF_Lib_Group | ||
54 | */ | ||
55 | EAPI int | ||
56 | ecore_imf_shutdown(void) | ||
57 | { | ||
58 | if (--init_count != 0) return init_count; | ||
59 | |||
60 | ecore_shutdown(); | ||
61 | ecore_imf_module_shutdown(); | ||
62 | |||
63 | return init_count; | ||
64 | } | ||
diff --git a/legacy/ecore/src/lib/ecore_imf/ecore_imf_context.c b/legacy/ecore/src/lib/ecore_imf/ecore_imf_context.c new file mode 100644 index 0000000000..11fbcb4f1e --- /dev/null +++ b/legacy/ecore/src/lib/ecore_imf/ecore_imf_context.c | |||
@@ -0,0 +1,740 @@ | |||
1 | /* | ||
2 | * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 | ||
3 | */ | ||
4 | |||
5 | #include <locale.h> | ||
6 | #include <stdlib.h> | ||
7 | |||
8 | #include "config.h" | ||
9 | |||
10 | #include "Ecore_IMF.h" | ||
11 | #include "ecore_imf_private.h" | ||
12 | |||
13 | /** | ||
14 | * @defgroup Ecore_IMF_Context_Group Ecore Input Method Context Functions | ||
15 | * | ||
16 | * Functions that operate on Ecore Input Method Context objects. | ||
17 | */ | ||
18 | |||
19 | /** | ||
20 | * Get the list of the available Input Method Context ids. | ||
21 | * | ||
22 | * Note that the caller is responsible for freeing the Ecore_List | ||
23 | * when finished with it. There is no need to finish the list strings. | ||
24 | * | ||
25 | * @return Return an Ecore_List of strings; | ||
26 | * on failure it returns NULL. | ||
27 | * @ingroup Ecore_IMF_Context_Group | ||
28 | */ | ||
29 | EAPI Ecore_List * | ||
30 | ecore_imf_context_available_ids_get(void) | ||
31 | { | ||
32 | return ecore_imf_module_context_ids_get(); | ||
33 | } | ||
34 | |||
35 | /* | ||
36 | * Match @locale against @against. | ||
37 | * | ||
38 | * 'en_US' against 'en_US' => 4 | ||
39 | * 'en_US' against 'en' => 3 | ||
40 | * 'en', 'en_UK' against 'en_US' => 2 | ||
41 | * all locales, against '*' => 1 | ||
42 | */ | ||
43 | static int | ||
44 | _ecore_imf_context_match_locale(const char *locale, const char *against, int against_len) | ||
45 | { | ||
46 | if (strcmp(against, "*") == 0) | ||
47 | return 1; | ||
48 | |||
49 | if (strcasecmp(locale, against) == 0) | ||
50 | return 4; | ||
51 | |||
52 | if (strncasecmp(locale, against, 2) == 0) | ||
53 | return (against_len == 2) ? 3 : 2; | ||
54 | |||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | /** | ||
59 | * Get the id of the default Input Method Context. | ||
60 | * The id may to used to create a new instance of an Input Method | ||
61 | * Context object. | ||
62 | * | ||
63 | * @return Return a string containing the id of the default Input | ||
64 | * Method Context; on failure it returns NULL. | ||
65 | * @ingroup Ecore_IMF_Context_Group | ||
66 | */ | ||
67 | EAPI const char * | ||
68 | ecore_imf_context_default_id_get(void) | ||
69 | { | ||
70 | const char *id; | ||
71 | Ecore_List *modules; | ||
72 | Ecore_IMF_Module *module; | ||
73 | char *locale; | ||
74 | char *tmp; | ||
75 | int best_goodness = 0; | ||
76 | |||
77 | id = getenv("ECORE_IMF_MODULE"); | ||
78 | if (id && ecore_imf_module_get(id)) return id; | ||
79 | |||
80 | modules = ecore_imf_module_available_get(); | ||
81 | if (!modules) return NULL; | ||
82 | |||
83 | locale = setlocale(LC_CTYPE, NULL); | ||
84 | if (!locale) return NULL; | ||
85 | |||
86 | locale = strdup(locale); | ||
87 | |||
88 | tmp = strchr(locale, '.'); | ||
89 | if (tmp) *tmp = '\0'; | ||
90 | tmp = strchr(locale, '@'); | ||
91 | if (tmp) *tmp = '\0'; | ||
92 | |||
93 | id = NULL; | ||
94 | |||
95 | ecore_list_first_goto(modules); | ||
96 | while ((module = ecore_list_next(modules))) | ||
97 | { | ||
98 | const char *p = module->info->default_locales; | ||
99 | while (p) | ||
100 | { | ||
101 | const char *q = strchr(p, ':'); | ||
102 | int goodness = _ecore_imf_context_match_locale(locale, p, q ? q - p : strlen (p)); | ||
103 | |||
104 | if (goodness > best_goodness) | ||
105 | { | ||
106 | id = module->info->id; | ||
107 | best_goodness = goodness; | ||
108 | } | ||
109 | |||
110 | p = q ? q + 1 : NULL; | ||
111 | } | ||
112 | } | ||
113 | ecore_list_destroy(modules); | ||
114 | |||
115 | free(locale); | ||
116 | return id; | ||
117 | } | ||
118 | |||
119 | /** | ||
120 | * Retrieve the info for the Input Method Context with @p id. | ||
121 | * | ||
122 | * @param id The Input Method Context id to query for. | ||
123 | * @return Return a #Ecore_IMF_Context_Info for the Input Method Context with @p id; | ||
124 | * on failure it returns NULL. | ||
125 | * @ingroup Ecore_IMF_Context_Group | ||
126 | */ | ||
127 | EAPI const Ecore_IMF_Context_Info * | ||
128 | ecore_imf_context_info_by_id_get(const char *id) | ||
129 | { | ||
130 | Ecore_IMF_Module *module; | ||
131 | |||
132 | if (!id) return NULL; | ||
133 | module = ecore_imf_module_get(id); | ||
134 | if (!module) return NULL; | ||
135 | return module->info; | ||
136 | } | ||
137 | |||
138 | /** | ||
139 | * Create a new Input Method Context defined by the given id. | ||
140 | * | ||
141 | * @param id The Input Method Context id. | ||
142 | * @return A newly allocated Input Method Context; | ||
143 | * on failure it returns NULL. | ||
144 | * @ingroup Ecore_IMF_Context_Group | ||
145 | */ | ||
146 | EAPI Ecore_IMF_Context * | ||
147 | ecore_imf_context_add(const char *id) | ||
148 | { | ||
149 | Ecore_IMF_Context *ctx; | ||
150 | |||
151 | if (!id) return NULL; | ||
152 | ctx = ecore_imf_module_context_create(id); | ||
153 | if (!ctx || !ctx->klass) return NULL; | ||
154 | if (ctx->klass->add) ctx->klass->add(ctx); | ||
155 | /* default use_preedit is 1, so let's make sure it's | ||
156 | * set on the immodule */ | ||
157 | ecore_imf_context_use_preedit_set(ctx, 1); | ||
158 | /* default input_mode is ECORE_IMF_INPUT_MODE_FULL, so let's make sure it's | ||
159 | * set on the immodule */ | ||
160 | ecore_imf_context_input_mode_set(ctx, ECORE_IMF_INPUT_MODE_FULL); | ||
161 | return ctx; | ||
162 | } | ||
163 | |||
164 | /** | ||
165 | * Delete the given Input Method Context and free its memory. | ||
166 | * | ||
167 | * @param ctx An #Ecore_IMF_Context. | ||
168 | * @ingroup Ecore_IMF_Context_Group | ||
169 | */ | ||
170 | EAPI void | ||
171 | ecore_imf_context_del(Ecore_IMF_Context *ctx) | ||
172 | { | ||
173 | if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT)) | ||
174 | { | ||
175 | ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT, | ||
176 | "ecore_imf_context_del"); | ||
177 | return; | ||
178 | } | ||
179 | if (ctx->klass->del) ctx->klass->del(ctx); | ||
180 | ECORE_MAGIC_SET(ctx, ECORE_MAGIC_NONE); | ||
181 | free(ctx); | ||
182 | } | ||
183 | |||
184 | /** | ||
185 | * Set the client window for the Input Method Context; this is the | ||
186 | * window returned by ecore_evas_window_get() in which the input appears. | ||
187 | * This window is used in order to correctly position status windows, and may | ||
188 | * also be used for purposes internal to the Input Method Context. | ||
189 | * | ||
190 | * @param ctx An #Ecore_IMF_Context. | ||
191 | * @param window The client window. This may be NULL to indicate | ||
192 | * that the previous client window no longer exists. | ||
193 | * @ingroup Ecore_IMF_Context_Group | ||
194 | */ | ||
195 | EAPI void | ||
196 | ecore_imf_context_client_window_set(Ecore_IMF_Context *ctx, void *window) | ||
197 | { | ||
198 | if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT)) | ||
199 | { | ||
200 | ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT, | ||
201 | "ecore_imf_context_client_window_set"); | ||
202 | return; | ||
203 | } | ||
204 | if (ctx->klass->client_window_set) ctx->klass->client_window_set(ctx, window); | ||
205 | } | ||
206 | |||
207 | /** | ||
208 | * Ask the Input Method Context to show itself. | ||
209 | * | ||
210 | * @param ctx An #Ecore_IMF_Context. | ||
211 | * @ingroup Ecore_IMF_Context_Group | ||
212 | */ | ||
213 | EAPI void | ||
214 | ecore_imf_context_show(Ecore_IMF_Context *ctx) | ||
215 | { | ||
216 | if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT)) | ||
217 | { | ||
218 | ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT, | ||
219 | "ecore_imf_context_show"); | ||
220 | return; | ||
221 | } | ||
222 | if (ctx->klass->show) ctx->klass->show(ctx); | ||
223 | } | ||
224 | |||
225 | /** | ||
226 | * Ask the Input Method Context to hide itself. | ||
227 | * | ||
228 | * @param ctx An #Ecore_IMF_Context. | ||
229 | * @ingroup Ecore_IMF_Context_Group | ||
230 | */ | ||
231 | EAPI void | ||
232 | ecore_imf_context_hide(Ecore_IMF_Context *ctx) | ||
233 | { | ||
234 | if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT)) | ||
235 | { | ||
236 | ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT, | ||
237 | "ecore_imf_context_hide"); | ||
238 | return; | ||
239 | } | ||
240 | if (ctx->klass->hide) ctx->klass->hide(ctx); | ||
241 | } | ||
242 | |||
243 | /* | ||
244 | * Retrieve the current preedit string and cursor position | ||
245 | * for the Input Method Context. | ||
246 | * | ||
247 | * @param ctx An #Ecore_IMF_Context. | ||
248 | * @param str Location to store the retrieved string. The | ||
249 | * string retrieved must be freed with free(). | ||
250 | * @param cursor_pos Location to store position of cursor (in characters) | ||
251 | * within the preedit string. | ||
252 | * @ingroup Ecore_IMF_Context_Group | ||
253 | */ | ||
254 | EAPI void | ||
255 | ecore_imf_context_preedit_string_get(Ecore_IMF_Context *ctx, char **str, int *cursor_pos) | ||
256 | { | ||
257 | if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT)) | ||
258 | { | ||
259 | ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT, | ||
260 | "ecore_imf_context_preedit_string_get"); | ||
261 | return; | ||
262 | } | ||
263 | if (ctx->klass->preedit_string_get) | ||
264 | ctx->klass->preedit_string_get(ctx, str, cursor_pos); | ||
265 | else | ||
266 | { | ||
267 | if (str) *str = strdup(""); | ||
268 | if (cursor_pos) *cursor_pos = 0; | ||
269 | } | ||
270 | } | ||
271 | |||
272 | /** | ||
273 | * Notify the Input Method Context that the widget to which its | ||
274 | * correspond has gained focus. | ||
275 | * | ||
276 | * @param ctx An #Ecore_IMF_Context. | ||
277 | * @ingroup Ecore_IMF_Context_Group | ||
278 | */ | ||
279 | EAPI void | ||
280 | ecore_imf_context_focus_in(Ecore_IMF_Context *ctx) | ||
281 | { | ||
282 | if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT)) | ||
283 | { | ||
284 | ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT, | ||
285 | "ecore_imf_context_focus_in"); | ||
286 | return; | ||
287 | } | ||
288 | if (ctx->klass->focus_in) ctx->klass->focus_in(ctx); | ||
289 | } | ||
290 | |||
291 | /** | ||
292 | * Notify the Input Method Context that the widget to which its | ||
293 | * correspond has lost focus. | ||
294 | * | ||
295 | * @param ctx An #Ecore_IMF_Context. | ||
296 | * @ingroup Ecore_IMF_Context_Group | ||
297 | */ | ||
298 | EAPI void | ||
299 | ecore_imf_context_focus_out(Ecore_IMF_Context *ctx) | ||
300 | { | ||
301 | if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT)) | ||
302 | { | ||
303 | ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT, | ||
304 | "ecore_imf_context_focus_out"); | ||
305 | return; | ||
306 | } | ||
307 | if (ctx->klass->focus_out) ctx->klass->focus_out(ctx); | ||
308 | } | ||
309 | |||
310 | /** | ||
311 | * Notify the Input Method Context that a change such as a | ||
312 | * change in cursor position has been made. This will typically | ||
313 | * cause the Input Method Context to clear the preedit state. | ||
314 | * | ||
315 | * @param ctx An #Ecore_IMF_Context. | ||
316 | * @ingroup Ecore_IMF_Context_Group | ||
317 | */ | ||
318 | EAPI void | ||
319 | ecore_imf_context_reset(Ecore_IMF_Context *ctx) | ||
320 | { | ||
321 | if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT)) | ||
322 | { | ||
323 | ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT, | ||
324 | "ecore_imf_context_reset"); | ||
325 | return; | ||
326 | } | ||
327 | if (ctx->klass->reset) ctx->klass->reset(ctx); | ||
328 | } | ||
329 | |||
330 | /** | ||
331 | * Notify the Input Method Context that a change in the cursor | ||
332 | * position has been made. | ||
333 | * | ||
334 | * @param ctx An #Ecore_IMF_Context. | ||
335 | * @param cursor_pos New cursor position in characters. | ||
336 | * @ingroup Ecore_IMF_Context_Group | ||
337 | */ | ||
338 | EAPI void | ||
339 | ecore_imf_context_cursor_position_set(Ecore_IMF_Context *ctx, int cursor_pos) | ||
340 | { | ||
341 | if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT)) | ||
342 | { | ||
343 | ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT, | ||
344 | "ecore_imf_context_cursor_position_set"); | ||
345 | return; | ||
346 | } | ||
347 | if (ctx->klass->cursor_position_set) ctx->klass->cursor_position_set(ctx, cursor_pos); | ||
348 | } | ||
349 | |||
350 | /** | ||
351 | * Set whether the IM context should use the preedit string | ||
352 | * to display feedback. If @use_preedit is 0 (default | ||
353 | * is 1), then the IM context may use some other method to display | ||
354 | * feedback, such as displaying it in a child of the root window. | ||
355 | * | ||
356 | * @param ctx An #Ecore_IMF_Context. | ||
357 | * @param use_preedit Whether the IM context should use the preedit string. | ||
358 | * @ingroup Ecore_IMF_Context_Group | ||
359 | */ | ||
360 | EAPI void | ||
361 | ecore_imf_context_use_preedit_set(Ecore_IMF_Context *ctx, int use_preedit) | ||
362 | { | ||
363 | if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT)) | ||
364 | { | ||
365 | ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT, | ||
366 | "ecore_imf_context_use_preedit_set"); | ||
367 | return; | ||
368 | } | ||
369 | if (ctx->klass->use_preedit_set) ctx->klass->use_preedit_set(ctx, use_preedit); | ||
370 | } | ||
371 | |||
372 | /** | ||
373 | * Set the callback to be used on get_surrounding request. | ||
374 | * | ||
375 | * This callback will be called when the Input Method Context | ||
376 | * module requests the surrounding context. | ||
377 | * | ||
378 | * @param ctx An #Ecore_IMF_Context. | ||
379 | * @param func The callback to be called. | ||
380 | * @param data The data pointer to be passed to @p func | ||
381 | * @ingroup Ecore_IMF_Context_Group | ||
382 | */ | ||
383 | EAPI void | ||
384 | ecore_imf_context_retrieve_surrounding_callback_set(Ecore_IMF_Context *ctx, int (*func)(void *data, Ecore_IMF_Context *ctx, char **text, int *cursor_pos), const void *data) | ||
385 | { | ||
386 | if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT)) | ||
387 | { | ||
388 | ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT, | ||
389 | "ecore_imf_context_retrieve_surrounding_callback_set"); | ||
390 | return; | ||
391 | } | ||
392 | |||
393 | ctx->retrieve_surrounding_func = func; | ||
394 | ctx->retrieve_surrounding_data = (void *) data; | ||
395 | } | ||
396 | |||
397 | /** | ||
398 | * Set the input mode used by the Ecore Input Context. | ||
399 | * | ||
400 | * The input mode can be one of the input modes defined in | ||
401 | * #Ecore_IMF_Input_Mode. The default input mode is | ||
402 | * ECORE_IMF_INPUT_MODE_FULL. | ||
403 | * | ||
404 | * @param ctx An #Ecore_IMF_Context. | ||
405 | * @param input_mode The input mode to be used by @p ctx. | ||
406 | * @ingroup Ecore_IMF_Context_Group | ||
407 | */ | ||
408 | EAPI void | ||
409 | ecore_imf_context_input_mode_set(Ecore_IMF_Context *ctx, Ecore_IMF_Input_Mode input_mode) | ||
410 | { | ||
411 | if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT)) | ||
412 | { | ||
413 | ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT, | ||
414 | "ecore_imf_context_input_mode_set"); | ||
415 | return; | ||
416 | } | ||
417 | if (ctx->klass->input_mode_set) ctx->klass->input_mode_set(ctx, input_mode); | ||
418 | ctx->input_mode = input_mode; | ||
419 | } | ||
420 | |||
421 | /** | ||
422 | * Get the input mode being used by the Ecore Input Context. | ||
423 | * | ||
424 | * See @ref ecore_imf_context_input_mode_set for more details. | ||
425 | * | ||
426 | * @param ctx An #Ecore_IMF_Context. | ||
427 | * @return The input mode being used by @p ctx. | ||
428 | * @ingroup Ecore_IMF_Context_Group | ||
429 | */ | ||
430 | EAPI Ecore_IMF_Input_Mode | ||
431 | ecore_imf_context_input_mode_get(Ecore_IMF_Context *ctx) | ||
432 | { | ||
433 | if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT)) | ||
434 | { | ||
435 | ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT, | ||
436 | "ecore_imf_context_input_mode_set"); | ||
437 | return 0; | ||
438 | } | ||
439 | return ctx->input_mode; | ||
440 | } | ||
441 | |||
442 | /** | ||
443 | * Allow an Ecore Input Context to internally handle an event. | ||
444 | * If this function returns 1, then no further processing | ||
445 | * should be done for this event. | ||
446 | * | ||
447 | * Input methods must be able to accept all types of events (simply | ||
448 | * returning 0 if the event was not handled), but there is no | ||
449 | * obligation of any events to be submitted to this function. | ||
450 | * | ||
451 | * @param ctx An #Ecore_IMF_Context. | ||
452 | * @param type The type of event defined in #Evas_Callback_Type | ||
453 | * @param event_info The event itself; This should be one of | ||
454 | * Evas_Event_* types or NULL for some event types as | ||
455 | * EVAS_CALLBACK_SHOW/HIDE for example. | ||
456 | * @return 1 if the event was handled; otherwise 0. | ||
457 | * @ingroup Ecore_IMF_Context_Group | ||
458 | */ | ||
459 | EAPI int | ||
460 | ecore_imf_context_filter_event(Ecore_IMF_Context *ctx, Evas_Callback_Type type, void *event_info) | ||
461 | { | ||
462 | if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT)) | ||
463 | { | ||
464 | ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT, | ||
465 | "ecore_imf_context_filter_event"); | ||
466 | return 0; | ||
467 | } | ||
468 | if (ctx->klass->filter_event) return ctx->klass->filter_event(ctx, type, event_info); | ||
469 | return 0; | ||
470 | } | ||
471 | |||
472 | /** | ||
473 | * @defgroup Ecore_IMF_Context_Module_Group Ecore Input Method Context Module Functions | ||
474 | * | ||
475 | * Functions that should be used by Ecore Input Method Context modules. | ||
476 | */ | ||
477 | |||
478 | /** | ||
479 | * Creates a new Input Method Context with klass specified by @p ctxc. | ||
480 | * | ||
481 | * This method should be used by modules implementing the Input | ||
482 | * Method Context interface. | ||
483 | * | ||
484 | * @param ctxc An #Ecore_IMF_Context_Class. | ||
485 | * @return A new #Ecore_IMF_Context; on failure it returns NULL. | ||
486 | * @ingroup Ecore_IMF_Context_Module_Group | ||
487 | */ | ||
488 | EAPI Ecore_IMF_Context * | ||
489 | ecore_imf_context_new(const Ecore_IMF_Context_Class *ctxc) | ||
490 | { | ||
491 | Ecore_IMF_Context *ctx; | ||
492 | |||
493 | if (!ctx) return NULL; | ||
494 | ctx = malloc(sizeof(Ecore_IMF_Context)); | ||
495 | if (!ctx) return NULL; | ||
496 | ECORE_MAGIC_SET(ctx, ECORE_MAGIC_CONTEXT); | ||
497 | ctx->klass = ctxc; | ||
498 | ctx->data = NULL; | ||
499 | ctx->retrieve_surrounding_func = NULL; | ||
500 | ctx->retrieve_surrounding_data = NULL; | ||
501 | return ctx; | ||
502 | } | ||
503 | |||
504 | /** | ||
505 | * Set the Input Method Context specific data. | ||
506 | * | ||
507 | * Note that this method should be used by modules to set | ||
508 | * the Input Method Context specific data and it's not meant to | ||
509 | * be used by applications to store application specific data. | ||
510 | * | ||
511 | * @param ctx An #Ecore_IMF_Context. | ||
512 | * @param data The Input Method Context specific data. | ||
513 | * @return A new #Ecore_IMF_Context; on failure it returns NULL. | ||
514 | * @ingroup Ecore_IMF_Context_Module_Group | ||
515 | */ | ||
516 | EAPI void | ||
517 | ecore_imf_context_data_set(Ecore_IMF_Context *ctx, void *data) | ||
518 | { | ||
519 | if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT)) | ||
520 | { | ||
521 | ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT, | ||
522 | "ecore_imf_context_data_set"); | ||
523 | return; | ||
524 | } | ||
525 | ctx->data = data; | ||
526 | } | ||
527 | |||
528 | /** | ||
529 | * Get the Input Method Context specific data. | ||
530 | * | ||
531 | * See @ref ecore_imf_context_data_set for more details. | ||
532 | * | ||
533 | * @param ctx An #Ecore_IMF_Context. | ||
534 | * @return The Input Method Context specific data. | ||
535 | * @ingroup Ecore_IMF_Context_Module_Group | ||
536 | */ | ||
537 | EAPI void *ecore_imf_context_data_get(Ecore_IMF_Context *ctx) | ||
538 | { | ||
539 | if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT)) | ||
540 | { | ||
541 | ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT, | ||
542 | "ecore_imf_context_data_get"); | ||
543 | return; | ||
544 | } | ||
545 | return ctx->data; | ||
546 | } | ||
547 | |||
548 | /** | ||
549 | * Retrieve context around insertion point. | ||
550 | * | ||
551 | * This function is implemented by calling the | ||
552 | * Ecore_IMF_Context::retrieve_surrounding_func ( | ||
553 | * set using #ecore_imf_context_retrieve_surrounding_callback_set). | ||
554 | * | ||
555 | * There is no obligation for a widget to respond to the | ||
556 | * ::retrieve_surrounding_func, so input methods must be prepared | ||
557 | * to function without context. | ||
558 | * | ||
559 | * @param ctx An #Ecore_IMF_Context. | ||
560 | * @param text Location to store a UTF-8 encoded string of text | ||
561 | * holding context around the insertion point. | ||
562 | * If the function returns 1, then you must free | ||
563 | * the result stored in this location with free(). | ||
564 | * @param cursor_pos Location to store the position in characters of | ||
565 | * the insertion cursor within @text. | ||
566 | * @return 1 if surrounding text was provided; otherwise 0. | ||
567 | * @ingroup Ecore_IMF_Context_Module_Group | ||
568 | */ | ||
569 | EAPI int | ||
570 | ecore_imf_context_surrounding_get(Ecore_IMF_Context *ctx, char **text, int *cursor_pos) | ||
571 | { | ||
572 | int result = 0; | ||
573 | |||
574 | if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT)) | ||
575 | { | ||
576 | ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT, | ||
577 | "ecore_imf_context_surrounding_get"); | ||
578 | return 0; | ||
579 | } | ||
580 | |||
581 | if (ctx->retrieve_surrounding_func) | ||
582 | { | ||
583 | result = ctx->retrieve_surrounding_func(ctx->retrieve_surrounding_data, ctx, text, cursor_pos); | ||
584 | if (!result) | ||
585 | { | ||
586 | if (text) *text = NULL; | ||
587 | if (cursor_pos) *cursor_pos = 0; | ||
588 | } | ||
589 | } | ||
590 | return result; | ||
591 | } | ||
592 | |||
593 | static void | ||
594 | _ecore_imf_event_free_preedit(void *data __UNUSED__, void *event) | ||
595 | { | ||
596 | free(event); | ||
597 | } | ||
598 | |||
599 | /** | ||
600 | * Adds ECORE_IMF_EVENT_PREEDIT_START to the event queue. | ||
601 | * | ||
602 | * @param ctx An #Ecore_IMF_Context. | ||
603 | * @ingroup Ecore_IMF_Context_Module_Group | ||
604 | */ | ||
605 | EAPI void | ||
606 | ecore_imf_context_preedit_start_event_add(Ecore_IMF_Context *ctx) | ||
607 | { | ||
608 | Ecore_IMF_Event_Commit *ev; | ||
609 | |||
610 | if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT)) | ||
611 | { | ||
612 | ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT, | ||
613 | "ecore_imf_context_preedit_start_event_add"); | ||
614 | return; | ||
615 | } | ||
616 | |||
617 | ev = malloc(sizeof(Ecore_IMF_Event_Preedit_Start)); | ||
618 | ev->ctx = ctx; | ||
619 | ecore_event_add(ECORE_IMF_EVENT_PREEDIT_START, | ||
620 | ev, _ecore_imf_event_free_preedit, NULL); | ||
621 | } | ||
622 | |||
623 | /** | ||
624 | * Adds ECORE_IMF_EVENT_PREEDIT_END to the event queue. | ||
625 | * | ||
626 | * @param ctx An #Ecore_IMF_Context. | ||
627 | * @ingroup Ecore_IMF_Context_Module_Group | ||
628 | */ | ||
629 | EAPI void | ||
630 | ecore_imf_context_preedit_end_event_add(Ecore_IMF_Context *ctx) | ||
631 | { | ||
632 | Ecore_IMF_Event_Commit *ev; | ||
633 | |||
634 | if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT)) | ||
635 | { | ||
636 | ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT, | ||
637 | "ecore_imf_context_preedit_end_event_add"); | ||
638 | return; | ||
639 | } | ||
640 | |||
641 | ev = malloc(sizeof(Ecore_IMF_Event_Preedit_End)); | ||
642 | ev->ctx = ctx; | ||
643 | ecore_event_add(ECORE_IMF_EVENT_PREEDIT_END, | ||
644 | ev, _ecore_imf_event_free_preedit, NULL); | ||
645 | } | ||
646 | |||
647 | /** | ||
648 | * Adds ECORE_IMF_EVENT_PREEDIT_CHANGED to the event queue. | ||
649 | * | ||
650 | * @param ctx An #Ecore_IMF_Context. | ||
651 | * @ingroup Ecore_IMF_Context_Module_Group | ||
652 | */ | ||
653 | EAPI void | ||
654 | ecore_imf_context_preedit_changed_event_add(Ecore_IMF_Context *ctx) | ||
655 | { | ||
656 | Ecore_IMF_Event_Commit *ev; | ||
657 | |||
658 | if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT)) | ||
659 | { | ||
660 | ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT, | ||
661 | "ecore_imf_context_preedit_changed_event_add"); | ||
662 | return; | ||
663 | } | ||
664 | |||
665 | ev = malloc(sizeof(Ecore_IMF_Event_Preedit_Changed)); | ||
666 | ev->ctx = ctx; | ||
667 | ecore_event_add(ECORE_IMF_EVENT_PREEDIT_CHANGED, | ||
668 | ev, _ecore_imf_event_free_preedit, NULL); | ||
669 | } | ||
670 | |||
671 | static void | ||
672 | _ecore_imf_event_free_commit(void *data __UNUSED__, void *event) | ||
673 | { | ||
674 | Ecore_IMF_Event_Commit *ev; | ||
675 | |||
676 | ev = event; | ||
677 | if (ev->str) free(ev->str); | ||
678 | free(ev); | ||
679 | } | ||
680 | |||
681 | /** | ||
682 | * Adds ECORE_IMF_EVENT_COMMIT to the event queue. | ||
683 | * | ||
684 | * @param ctx An #Ecore_IMF_Context. | ||
685 | * @param str The committed string. | ||
686 | * @ingroup Ecore_IMF_Context_Module_Group | ||
687 | */ | ||
688 | EAPI void | ||
689 | ecore_imf_context_commit_event_add(Ecore_IMF_Context *ctx, const char *str) | ||
690 | { | ||
691 | Ecore_IMF_Event_Commit *ev; | ||
692 | |||
693 | if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT)) | ||
694 | { | ||
695 | ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT, | ||
696 | "ecore_imf_context_commit_event_add"); | ||
697 | return; | ||
698 | } | ||
699 | |||
700 | ev = malloc(sizeof(Ecore_IMF_Event_Commit)); | ||
701 | ev->ctx = ctx; | ||
702 | ev->str = str ? strdup(str) : NULL; | ||
703 | ecore_event_add(ECORE_IMF_EVENT_COMMIT, | ||
704 | ev, _ecore_imf_event_free_commit, NULL); | ||
705 | |||
706 | } | ||
707 | |||
708 | static void | ||
709 | _ecore_imf_event_free_delete_surrounding(void *data __UNUSED__, void *event) | ||
710 | { | ||
711 | free(event); | ||
712 | } | ||
713 | |||
714 | /** | ||
715 | * Adds ECORE_IMF_EVENT_DELETE_SURROUNDIND to the event queue. | ||
716 | * | ||
717 | * @param ctx An #Ecore_IMF_Context. | ||
718 | * @param offset The start offset of surrounding to be deleted. | ||
719 | * @param n_chars The number of characters to be deleted. | ||
720 | * @ingroup Ecore_IMF_Context_Module_Group | ||
721 | */ | ||
722 | EAPI void | ||
723 | ecore_imf_context_delete_surrounding_event_add(Ecore_IMF_Context *ctx, int offset, int n_chars) | ||
724 | { | ||
725 | Ecore_IMF_Event_Delete_Surrounding *ev; | ||
726 | |||
727 | if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT)) | ||
728 | { | ||
729 | ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT, | ||
730 | "ecore_imf_context_delete_surrounding_event_add"); | ||
731 | return; | ||
732 | } | ||
733 | |||
734 | ev = malloc(sizeof(Ecore_IMF_Event_Delete_Surrounding)); | ||
735 | ev->ctx = ctx; | ||
736 | ev->offset = offset; | ||
737 | ev->n_chars = n_chars; | ||
738 | ecore_event_add(ECORE_IMF_EVENT_DELETE_SURROUNDIND, | ||
739 | ev, _ecore_imf_event_free_delete_surrounding, NULL); | ||
740 | } | ||
diff --git a/legacy/ecore/src/lib/ecore_imf/ecore_imf_module.c b/legacy/ecore/src/lib/ecore_imf/ecore_imf_module.c new file mode 100644 index 0000000000..739ac7fe77 --- /dev/null +++ b/legacy/ecore/src/lib/ecore_imf/ecore_imf_module.c | |||
@@ -0,0 +1,207 @@ | |||
1 | /* | ||
2 | * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 | ||
3 | */ | ||
4 | |||
5 | #include <limits.h> | ||
6 | #include <stdio.h> | ||
7 | #include <stdlib.h> | ||
8 | |||
9 | #include "config.h" | ||
10 | |||
11 | #include "ecore_imf_private.h" | ||
12 | |||
13 | static void _ecore_imf_module_load_all(void); | ||
14 | static void _ecore_imf_module_append(Ecore_Plugin *plugin, const Ecore_IMF_Context_Info *info, Ecore_IMF_Context *(*imf_module_create)(void)); | ||
15 | static void _ecore_imf_module_free(Ecore_IMF_Module *module); | ||
16 | static int _ecore_imf_modules_exists(const char *ctx_id); | ||
17 | |||
18 | static Ecore_Path_Group *ecore_imf_modules_path = NULL; | ||
19 | static Ecore_Hash *modules = NULL; | ||
20 | |||
21 | void | ||
22 | ecore_imf_module_init(void) | ||
23 | { | ||
24 | char pathname[PATH_MAX]; | ||
25 | const char *homedir; | ||
26 | |||
27 | ecore_imf_modules_path = ecore_path_group_new(); | ||
28 | snprintf(pathname, sizeof(pathname), "%s/ecore/immodules/", | ||
29 | PACKAGE_LIB_DIR); | ||
30 | ecore_path_group_add(ecore_imf_modules_path, pathname); | ||
31 | |||
32 | homedir = getenv("HOME"); | ||
33 | if (homedir) | ||
34 | { | ||
35 | snprintf(pathname, sizeof(pathname), "%s/.ecore/immodules/", | ||
36 | homedir); | ||
37 | ecore_path_group_add(ecore_imf_modules_path, pathname); | ||
38 | } | ||
39 | |||
40 | modules = NULL; | ||
41 | _ecore_imf_module_load_all(); | ||
42 | } | ||
43 | |||
44 | void | ||
45 | ecore_imf_module_shutdown(void) | ||
46 | { | ||
47 | if (modules) | ||
48 | { | ||
49 | ecore_hash_destroy(modules); | ||
50 | modules = NULL; | ||
51 | } | ||
52 | |||
53 | ecore_path_group_del(ecore_imf_modules_path); | ||
54 | ecore_imf_modules_path = NULL; | ||
55 | } | ||
56 | |||
57 | Ecore_List * | ||
58 | ecore_imf_module_available_get(void) | ||
59 | { | ||
60 | Ecore_List *values; | ||
61 | unsigned int i = 0; | ||
62 | |||
63 | if (!modules) return NULL; | ||
64 | |||
65 | /* ecore_hash_values() */ | ||
66 | values = ecore_list_new(); | ||
67 | while (i < ecore_prime_table[modules->size]) | ||
68 | { | ||
69 | if (modules->buckets[i]) | ||
70 | { | ||
71 | Ecore_Hash_Node *node; | ||
72 | |||
73 | for (node = modules->buckets[i]; node; node = node->next) | ||
74 | ecore_list_append(values, node->value); | ||
75 | } | ||
76 | i++; | ||
77 | } | ||
78 | ecore_list_first_goto(values); | ||
79 | |||
80 | return values; | ||
81 | } | ||
82 | |||
83 | Ecore_IMF_Module * | ||
84 | ecore_imf_module_get(const char *ctx_id) | ||
85 | { | ||
86 | if (!modules) return NULL; | ||
87 | return ecore_hash_get(modules, ctx_id); | ||
88 | } | ||
89 | |||
90 | Ecore_IMF_Context * | ||
91 | ecore_imf_module_context_create(const char *ctx_id) | ||
92 | { | ||
93 | Ecore_IMF_Module *module; | ||
94 | |||
95 | if (!modules) return NULL; | ||
96 | module = ecore_hash_get(modules, ctx_id); | ||
97 | if (module) return module->create(); | ||
98 | return NULL; | ||
99 | } | ||
100 | |||
101 | Ecore_List * | ||
102 | ecore_imf_module_context_ids_get(void) | ||
103 | { | ||
104 | if (!modules) return NULL; | ||
105 | return ecore_hash_keys(modules); | ||
106 | } | ||
107 | |||
108 | static void | ||
109 | _ecore_imf_module_load_all(void) | ||
110 | { | ||
111 | Ecore_List *avail; | ||
112 | char *filename; | ||
113 | Ecore_Plugin *plugin; | ||
114 | const Ecore_IMF_Context_Info *info = NULL; | ||
115 | int (*imf_module_init)(const Ecore_IMF_Context_Info **info); | ||
116 | Ecore_IMF_Context *(*imf_module_create)(void); | ||
117 | Ecore_IMF_Module *module; | ||
118 | |||
119 | avail = ecore_plugin_available_get(ecore_imf_modules_path); | ||
120 | if (!avail) return; | ||
121 | |||
122 | ecore_list_first_goto(avail); | ||
123 | while (filename = ecore_list_next(avail)) | ||
124 | { | ||
125 | plugin = ecore_plugin_load(ecore_imf_modules_path, filename, NULL); | ||
126 | if (!plugin) | ||
127 | { | ||
128 | fprintf(stderr, "** ecore_imf: Error loading input method plugin %s!\n", | ||
129 | filename); | ||
130 | continue; | ||
131 | } | ||
132 | |||
133 | imf_module_init = ecore_plugin_symbol_get(plugin, "imf_module_init"); | ||
134 | if (!imf_module_init || !imf_module_init(&info) || !info) | ||
135 | { | ||
136 | fprintf(stderr, "** ecore_imf: Error initializing input method plugin %s! " | ||
137 | "'imf_module_init' is missing or failed to run!", | ||
138 | filename); | ||
139 | ecore_plugin_unload(plugin); | ||
140 | continue; | ||
141 | } | ||
142 | |||
143 | if (_ecore_imf_modules_exists(info->id)) | ||
144 | { | ||
145 | fprintf(stderr, "** ecore_imf: Error loading input method plugin %s! " | ||
146 | "Plugin with id='%s' already exists!", | ||
147 | info->id); | ||
148 | ecore_plugin_unload(plugin); | ||
149 | continue; | ||
150 | } | ||
151 | |||
152 | imf_module_create = ecore_plugin_symbol_get(plugin, "imf_module_create"); | ||
153 | if (!imf_module_create) | ||
154 | { | ||
155 | fprintf(stderr, "** ecore_imf: Error setting up input method plugin %s! " | ||
156 | "'imf_module_create' is missing!", | ||
157 | filename); | ||
158 | ecore_plugin_unload(plugin); | ||
159 | continue; | ||
160 | } | ||
161 | |||
162 | _ecore_imf_module_append(plugin, info, imf_module_create); | ||
163 | } | ||
164 | |||
165 | ecore_list_destroy(avail); | ||
166 | } | ||
167 | |||
168 | static void | ||
169 | _ecore_imf_module_append(Ecore_Plugin *plugin, | ||
170 | const Ecore_IMF_Context_Info *info, | ||
171 | Ecore_IMF_Context *(*imf_module_create)(void)) | ||
172 | { | ||
173 | Ecore_IMF_Module *module; | ||
174 | |||
175 | if (!modules) | ||
176 | { | ||
177 | modules = ecore_hash_new(ecore_str_hash, ecore_str_compare); | ||
178 | ecore_hash_free_key_cb_set(modules, free); | ||
179 | ecore_hash_free_value_cb_set(modules, (Ecore_Free_Cb) _ecore_imf_module_free); | ||
180 | } | ||
181 | |||
182 | module = malloc(sizeof(Ecore_IMF_Module)); | ||
183 | module->plugin = plugin; | ||
184 | module->info = info; | ||
185 | /* cache imf_module_create as it may be used several times */ | ||
186 | module->create = imf_module_create; | ||
187 | |||
188 | ecore_hash_set(modules, strdup(info->id), module); | ||
189 | } | ||
190 | |||
191 | static void | ||
192 | _ecore_imf_module_free(Ecore_IMF_Module *module) | ||
193 | { | ||
194 | int (*imf_module_exit)(void); | ||
195 | |||
196 | imf_module_exit = ecore_plugin_symbol_get(module->plugin, "imf_module_exit"); | ||
197 | if (imf_module_exit) imf_module_exit(); | ||
198 | ecore_plugin_unload(module->plugin); | ||
199 | free(module); | ||
200 | } | ||
201 | |||
202 | static int | ||
203 | _ecore_imf_modules_exists(const char *ctx_id) | ||
204 | { | ||
205 | if (!modules) return 0; | ||
206 | return (ecore_hash_get(modules, ctx_id) != NULL); | ||
207 | } | ||
diff --git a/legacy/ecore/src/lib/ecore_imf/ecore_imf_private.h b/legacy/ecore/src/lib/ecore_imf/ecore_imf_private.h new file mode 100644 index 0000000000..8980172fda --- /dev/null +++ b/legacy/ecore/src/lib/ecore_imf/ecore_imf_private.h | |||
@@ -0,0 +1,36 @@ | |||
1 | #ifndef _ECORE_IMF_PRIVATE_H | ||
2 | #define _ECORE_IMF_PRIVATE_H | ||
3 | |||
4 | #include "Ecore_IMF.h" | ||
5 | |||
6 | #include "ecore_private.h" | ||
7 | |||
8 | #define ECORE_MAGIC_CONTEXT 0x56c1b39a | ||
9 | |||
10 | typedef struct _Ecore_IMF_Module Ecore_IMF_Module; | ||
11 | |||
12 | struct _Ecore_IMF_Context | ||
13 | { | ||
14 | ECORE_MAGIC; | ||
15 | const Ecore_IMF_Context_Class *klass; | ||
16 | void *data; | ||
17 | int input_mode; | ||
18 | int (*retrieve_surrounding_func)(void *data, Ecore_IMF_Context *ctx, char **text, int *cursor_pos); | ||
19 | void *retrieve_surrounding_data; | ||
20 | }; | ||
21 | |||
22 | struct _Ecore_IMF_Module | ||
23 | { | ||
24 | Ecore_Plugin *plugin; | ||
25 | const Ecore_IMF_Context_Info *info; | ||
26 | Ecore_IMF_Context *(*create)(void); | ||
27 | }; | ||
28 | |||
29 | void ecore_imf_module_init(void); | ||
30 | void ecore_imf_module_shutdown(void); | ||
31 | Ecore_List *ecore_imf_module_available_get(void); | ||
32 | Ecore_IMF_Module *ecore_imf_module_get(const char *ctx_id); | ||
33 | Ecore_IMF_Context *ecore_imf_module_context_create(const char *ctx_id); | ||
34 | Ecore_List *ecore_imf_module_context_ids_get(void); | ||
35 | |||
36 | #endif | ||