| File: | ctk/ctkimmodule.c |
| Warning: | line 499, column 4 Potential leak of memory pointed to by 'info' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* CTK - The GIMP Toolkit | ||||
| 2 | * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald | ||||
| 3 | * | ||||
| 4 | * This library is free software; you can redistribute it and/or | ||||
| 5 | * modify it under the terms of the GNU Lesser General Public | ||||
| 6 | * License as published by the Free Software Foundation; either | ||||
| 7 | * version 2 of the License, or (at your option) any later version. | ||||
| 8 | * | ||||
| 9 | * This library is distributed in the hope that it will be useful, | ||||
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||||
| 12 | * Lesser General Public License for more details. | ||||
| 13 | * | ||||
| 14 | * You should have received a copy of the GNU Lesser General Public | ||||
| 15 | * License along with this library. If not, see <http://www.gnu.org/licenses/>.Free | ||||
| 16 | */ | ||||
| 17 | |||||
| 18 | /* | ||||
| 19 | * Modified by the CTK+ Team and others 1997-2000. See the AUTHORS | ||||
| 20 | * file for a list of people on the CTK+ Team. See the ChangeLog | ||||
| 21 | * files for a list of changes. These files are distributed with | ||||
| 22 | * CTK+ at ftp://ftp.ctk.org/pub/ctk/. | ||||
| 23 | */ | ||||
| 24 | |||||
| 25 | #include "config.h" | ||||
| 26 | |||||
| 27 | #include <errno(*__errno_location ()).h> | ||||
| 28 | #include <stdio.h> | ||||
| 29 | #include <stdlib.h> | ||||
| 30 | #include <string.h> | ||||
| 31 | |||||
| 32 | #include <glib/gstdio.h> | ||||
| 33 | #include <gmodule.h> | ||||
| 34 | #include "ctkimmoduleprivate.h" | ||||
| 35 | #include "ctkimcontextsimple.h" | ||||
| 36 | #include "ctksettings.h" | ||||
| 37 | #include "ctkprivate.h" | ||||
| 38 | #include "ctkutilsprivate.h" | ||||
| 39 | #include "ctkintl.h" | ||||
| 40 | |||||
| 41 | #ifdef CDK_WINDOWING_X11 | ||||
| 42 | #include "x11/cdkx.h" | ||||
| 43 | #endif | ||||
| 44 | |||||
| 45 | #ifdef CDK_WINDOWING_WAYLAND | ||||
| 46 | #include "wayland/cdkwayland.h" | ||||
| 47 | #endif | ||||
| 48 | |||||
| 49 | #ifdef CDK_WINDOWING_BROADWAY | ||||
| 50 | #include "broadway/cdkbroadway.h" | ||||
| 51 | #endif | ||||
| 52 | |||||
| 53 | #ifdef CDK_WINDOWING_WIN32 | ||||
| 54 | #include "win32/cdkwin32.h" | ||||
| 55 | #endif | ||||
| 56 | |||||
| 57 | #ifdef G_OS_WIN32 | ||||
| 58 | #include <windows.h> | ||||
| 59 | #endif | ||||
| 60 | |||||
| 61 | #undef CDK_DEPRECATED | ||||
| 62 | #undef CDK_DEPRECATED_FOR | ||||
| 63 | #define CDK_DEPRECATED | ||||
| 64 | #define CDK_DEPRECATED_FOR(f) | ||||
| 65 | |||||
| 66 | #include "ctkrc.h" | ||||
| 67 | |||||
| 68 | /* We need to call getc() a lot in a loop. This is suboptimal, | ||||
| 69 | * as getc() does thread locking on the FILE it is given. | ||||
| 70 | * To optimize that, lock the file first, then call getc(), | ||||
| 71 | * then unlock. | ||||
| 72 | * If locking functions are not present in libc, fall back | ||||
| 73 | * to the suboptimal getc(). | ||||
| 74 | */ | ||||
| 75 | #if !defined(HAVE_FLOCKFILE1) && !defined(HAVE__LOCK_FILE) | ||||
| 76 | # define flockfile(f) (void)1 | ||||
| 77 | # define funlockfile(f) (void)1 | ||||
| 78 | # define getc_unlocked(f) getc(f) | ||||
| 79 | #elif !defined(HAVE_FLOCKFILE1) && defined(HAVE__LOCK_FILE) | ||||
| 80 | # define flockfile(f) _lock_file(f) | ||||
| 81 | # define funlockfile(f) _unlock_file(f) | ||||
| 82 | # define getc_unlocked(f) _getc_nolock(f) | ||||
| 83 | #endif | ||||
| 84 | |||||
| 85 | #define SIMPLE_ID"ctk-im-context-simple" "ctk-im-context-simple" | ||||
| 86 | #define NONE_ID"ctk-im-context-none" "ctk-im-context-none" | ||||
| 87 | |||||
| 88 | /** | ||||
| 89 | * CtkIMContextInfo: | ||||
| 90 | * @context_id: The unique identification string of the input method. | ||||
| 91 | * @context_name: The human-readable name of the input method. | ||||
| 92 | * @domain: Translation domain to be used with dgettext() | ||||
| 93 | * @domain_dirname: Name of locale directory for use with bindtextdomain() | ||||
| 94 | * @default_locales: A colon-separated list of locales where this input method | ||||
| 95 | * should be the default. The asterisk “*” sets the default for all locales. | ||||
| 96 | * | ||||
| 97 | * Bookkeeping information about a loadable input method. | ||||
| 98 | */ | ||||
| 99 | |||||
| 100 | typedef struct _CtkIMModule CtkIMModule; | ||||
| 101 | typedef struct _CtkIMModuleClass CtkIMModuleClass; | ||||
| 102 | |||||
| 103 | #define CTK_TYPE_IM_MODULE(ctk_im_module_get_type ()) (ctk_im_module_get_type ()) | ||||
| 104 | #define CTK_IM_MODULE(im_module)((((CtkIMModule*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((im_module)), ((ctk_im_module_get_type ())))))) (G_TYPE_CHECK_INSTANCE_CAST ((im_module), CTK_TYPE_IM_MODULE, CtkIMModule)(((CtkIMModule*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((im_module)), ((ctk_im_module_get_type ())))))) | ||||
| 105 | #define CTK_IS_IM_MODULE(im_module)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ( (im_module)); GType __t = ((ctk_im_module_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))) (G_TYPE_CHECK_INSTANCE_TYPE ((im_module), CTK_TYPE_IM_MODULE)((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ( (im_module)); GType __t = ((ctk_im_module_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))) | ||||
| 106 | |||||
| 107 | struct _CtkIMModule | ||||
| 108 | { | ||||
| 109 | GTypeModule parent_instance; | ||||
| 110 | |||||
| 111 | gboolean builtin; | ||||
| 112 | |||||
| 113 | GModule *library; | ||||
| 114 | |||||
| 115 | void (*list) (const CtkIMContextInfo ***contexts, | ||||
| 116 | guint *n_contexts); | ||||
| 117 | void (*init) (GTypeModule *module); | ||||
| 118 | void (*exit) (void); | ||||
| 119 | CtkIMContext *(*create) (const gchar *context_id); | ||||
| 120 | |||||
| 121 | CtkIMContextInfo **contexts; | ||||
| 122 | guint n_contexts; | ||||
| 123 | |||||
| 124 | gchar *path; | ||||
| 125 | }; | ||||
| 126 | |||||
| 127 | struct _CtkIMModuleClass | ||||
| 128 | { | ||||
| 129 | GTypeModuleClass parent_class; | ||||
| 130 | }; | ||||
| 131 | |||||
| 132 | static GType ctk_im_module_get_type (void); | ||||
| 133 | |||||
| 134 | static gint n_loaded_contexts = 0; | ||||
| 135 | static GHashTable *contexts_hash = NULL((void*)0); | ||||
| 136 | static GSList *modules_list = NULL((void*)0); | ||||
| 137 | |||||
| 138 | static gboolean | ||||
| 139 | ctk_im_module_load (GTypeModule *module) | ||||
| 140 | { | ||||
| 141 | CtkIMModule *im_module = CTK_IM_MODULE (module)((((CtkIMModule*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((module)), ((ctk_im_module_get_type ())))))); | ||||
| 142 | |||||
| 143 | if (!im_module->builtin) | ||||
| 144 | { | ||||
| 145 | im_module->library = g_module_open (im_module->path, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL); | ||||
| 146 | if (!im_module->library) | ||||
| 147 | { | ||||
| 148 | g_warning ("%s", g_module_error()); | ||||
| 149 | return FALSE(0); | ||||
| 150 | } | ||||
| 151 | |||||
| 152 | /* extract symbols from the lib */ | ||||
| 153 | if (!g_module_symbol (im_module->library, "im_module_init", | ||||
| 154 | (gpointer *)&im_module->init) || | ||||
| 155 | !g_module_symbol (im_module->library, "im_module_exit", | ||||
| 156 | (gpointer *)&im_module->exit) || | ||||
| 157 | !g_module_symbol (im_module->library, "im_module_list", | ||||
| 158 | (gpointer *)&im_module->list) || | ||||
| 159 | !g_module_symbol (im_module->library, "im_module_create", | ||||
| 160 | (gpointer *)&im_module->create)) | ||||
| 161 | { | ||||
| 162 | g_warning ("%s", g_module_error()); | ||||
| 163 | g_module_close (im_module->library); | ||||
| 164 | |||||
| 165 | return FALSE(0); | ||||
| 166 | } | ||||
| 167 | } | ||||
| 168 | |||||
| 169 | /* call the module's init function to let it */ | ||||
| 170 | /* setup anything it needs to set up. */ | ||||
| 171 | im_module->init (module); | ||||
| 172 | |||||
| 173 | return TRUE(!(0)); | ||||
| 174 | } | ||||
| 175 | |||||
| 176 | static void | ||||
| 177 | ctk_im_module_unload (GTypeModule *module) | ||||
| 178 | { | ||||
| 179 | CtkIMModule *im_module = CTK_IM_MODULE (module)((((CtkIMModule*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((module)), ((ctk_im_module_get_type ())))))); | ||||
| 180 | |||||
| 181 | im_module->exit(); | ||||
| 182 | |||||
| 183 | if (!im_module->builtin) | ||||
| 184 | { | ||||
| 185 | g_module_close (im_module->library); | ||||
| 186 | im_module->library = NULL((void*)0); | ||||
| 187 | |||||
| 188 | im_module->init = NULL((void*)0); | ||||
| 189 | im_module->exit = NULL((void*)0); | ||||
| 190 | im_module->list = NULL((void*)0); | ||||
| 191 | im_module->create = NULL((void*)0); | ||||
| 192 | } | ||||
| 193 | } | ||||
| 194 | |||||
| 195 | G_DEFINE_TYPE (CtkIMModule, ctk_im_module, G_TYPE_TYPE_MODULE)static void ctk_im_module_init (CtkIMModule *self); static void ctk_im_module_class_init (CtkIMModuleClass *klass); static GType ctk_im_module_get_type_once (void); static gpointer ctk_im_module_parent_class = ((void*)0); static gint CtkIMModule_private_offset; static void ctk_im_module_class_intern_init (gpointer klass) { ctk_im_module_parent_class = g_type_class_peek_parent (klass); if (CtkIMModule_private_offset != 0) g_type_class_adjust_private_offset (klass, &CtkIMModule_private_offset ); ctk_im_module_class_init ((CtkIMModuleClass*) klass); } __attribute__ ((__unused__)) static inline gpointer ctk_im_module_get_instance_private (CtkIMModule *self) { return (((gpointer) ((guint8*) (self) + (glong) (CtkIMModule_private_offset)))); } GType ctk_im_module_get_type (void) { static GType static_g_define_type_id = 0; if ((__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id) == sizeof (gpointer), "Expression evaluates to false"); (void) ( 0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0)) ; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id ) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ (*(&static_g_define_type_id)) gapg_temp_newval; __typeof__ ((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id ); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5) ; gapg_temp_newval; })) && g_once_init_enter_pointer ( &static_g_define_type_id)); })) ) { GType g_define_type_id = ctk_im_module_get_type_once (); (__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id) == sizeof (gpointer) , "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id ) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer ((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id )); })) ; } return static_g_define_type_id; } __attribute__ ( (__noinline__)) static GType ctk_im_module_get_type_once (void ) { GType g_define_type_id = g_type_register_static_simple (( g_type_module_get_type ()), g_intern_static_string ("CtkIMModule" ), sizeof (CtkIMModuleClass), (GClassInitFunc)(void (*)(void) ) ctk_im_module_class_intern_init, sizeof (CtkIMModule), (GInstanceInitFunc )(void (*)(void)) ctk_im_module_init, (GTypeFlags) 0); { {{}; } } return g_define_type_id; } | ||||
| 196 | |||||
| 197 | /* This only will ever be called if an error occurs during | ||||
| 198 | * initialization | ||||
| 199 | */ | ||||
| 200 | static void | ||||
| 201 | ctk_im_module_finalize (GObject *object) | ||||
| 202 | { | ||||
| 203 | CtkIMModule *module = CTK_IM_MODULE (object)((((CtkIMModule*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((object)), ((ctk_im_module_get_type ())))))); | ||||
| 204 | |||||
| 205 | g_free (module->path); | ||||
| 206 | |||||
| 207 | G_OBJECT_CLASS (ctk_im_module_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((ctk_im_module_parent_class)), (((GType) ((20) << ( 2))))))))->finalize (object); | ||||
| 208 | } | ||||
| 209 | |||||
| 210 | static void | ||||
| 211 | ctk_im_module_class_init (CtkIMModuleClass *class) | ||||
| 212 | { | ||||
| 213 | GTypeModuleClass *module_class = G_TYPE_MODULE_CLASS (class)((((GTypeModuleClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((class)), ((g_type_module_get_type ())))))); | ||||
| 214 | GObjectClass *gobject_class = G_OBJECT_CLASS (class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((class)), (((GType) ((20) << (2)))))))); | ||||
| 215 | |||||
| 216 | module_class->load = ctk_im_module_load; | ||||
| 217 | module_class->unload = ctk_im_module_unload; | ||||
| 218 | |||||
| 219 | gobject_class->finalize = ctk_im_module_finalize; | ||||
| 220 | } | ||||
| 221 | |||||
| 222 | static void | ||||
| 223 | ctk_im_module_init (CtkIMModule* object G_GNUC_UNUSED__attribute__ ((__unused__))) | ||||
| 224 | { | ||||
| 225 | } | ||||
| 226 | |||||
| 227 | static void | ||||
| 228 | free_info (CtkIMContextInfo *info) | ||||
| 229 | { | ||||
| 230 | g_free ((char *)info->context_id); | ||||
| 231 | g_free ((char *)info->context_name); | ||||
| 232 | g_free ((char *)info->domain); | ||||
| 233 | g_free ((char *)info->domain_dirname); | ||||
| 234 | g_free ((char *)info->default_locales); | ||||
| 235 | g_free (info); | ||||
| 236 | } | ||||
| 237 | |||||
| 238 | static void | ||||
| 239 | add_module (CtkIMModule *module, GSList *infos) | ||||
| 240 | { | ||||
| 241 | GSList *tmp_list = infos; | ||||
| 242 | gint i = 0; | ||||
| 243 | gint n = g_slist_length (infos); | ||||
| 244 | module->contexts = g_new (CtkIMContextInfo *, n)((CtkIMContextInfo * *) g_malloc_n ((n), sizeof (CtkIMContextInfo *))); | ||||
| 245 | |||||
| 246 | while (tmp_list) | ||||
| 247 | { | ||||
| 248 | CtkIMContextInfo *info = tmp_list->data; | ||||
| 249 | |||||
| 250 | if (g_hash_table_lookup (contexts_hash, info->context_id)) | ||||
| 251 | { | ||||
| 252 | free_info (info); /* Duplicate */ | ||||
| 253 | } | ||||
| 254 | else | ||||
| 255 | { | ||||
| 256 | g_hash_table_insert (contexts_hash, (char *)info->context_id, module); | ||||
| 257 | module->contexts[i++] = tmp_list->data; | ||||
| 258 | n_loaded_contexts++; | ||||
| 259 | } | ||||
| 260 | |||||
| 261 | tmp_list = tmp_list->next; | ||||
| 262 | } | ||||
| 263 | g_slist_free (infos); | ||||
| 264 | module->n_contexts = i; | ||||
| 265 | |||||
| 266 | modules_list = g_slist_prepend (modules_list, module); | ||||
| 267 | } | ||||
| 268 | |||||
| 269 | #ifdef G_OS_WIN32 | ||||
| 270 | |||||
| 271 | static void | ||||
| 272 | correct_libdir_prefix (gchar **path) | ||||
| 273 | { | ||||
| 274 | /* CTK_LIBDIR is the build-time libdir */ | ||||
| 275 | if (strncmp (*path, CTK_LIBDIR"/usr/lib", strlen (CTK_LIBDIR"/usr/lib")) == 0) | ||||
| 276 | { | ||||
| 277 | /* This is an entry put there by make install on the | ||||
| 278 | * packager's system. On Windows a prebuilt CTK+ | ||||
| 279 | * package can be installed in a random | ||||
| 280 | * location. The ctk.immodules file distributed in | ||||
| 281 | * such a package contains paths from the package | ||||
| 282 | * builder's machine. Replace the path with the real | ||||
| 283 | * one on this machine. | ||||
| 284 | */ | ||||
| 285 | gchar *tem = *path; | ||||
| 286 | *path = g_strconcat (_ctk_get_libdir (), tem + strlen (CTK_LIBDIR"/usr/lib"), NULL((void*)0)); | ||||
| 287 | g_free (tem); | ||||
| 288 | } | ||||
| 289 | } | ||||
| 290 | |||||
| 291 | static void | ||||
| 292 | correct_localedir_prefix (gchar **path) | ||||
| 293 | { | ||||
| 294 | /* See above */ | ||||
| 295 | if (strncmp (*path, CTK_LOCALEDIR"/usr/share/locale", strlen (CTK_LOCALEDIR"/usr/share/locale")) == 0) | ||||
| 296 | { | ||||
| 297 | gchar *tem = *path; | ||||
| 298 | *path = g_strconcat (_ctk_get_localedir (), tem + strlen (CTK_LOCALEDIR"/usr/share/locale"), NULL((void*)0)); | ||||
| 299 | g_free (tem); | ||||
| 300 | } | ||||
| 301 | } | ||||
| 302 | #endif | ||||
| 303 | |||||
| 304 | |||||
| 305 | G_GNUC_UNUSED__attribute__ ((__unused__)) static CtkIMModule * | ||||
| 306 | add_builtin_module (const gchar *module_name, | ||||
| 307 | const CtkIMContextInfo **contexts, | ||||
| 308 | int n_contexts) | ||||
| 309 | { | ||||
| 310 | CtkIMModule *module = g_object_new (CTK_TYPE_IM_MODULE(ctk_im_module_get_type ()), NULL((void*)0)); | ||||
| 311 | GSList *infos = NULL((void*)0); | ||||
| 312 | int i; | ||||
| 313 | |||||
| 314 | for (i = 0; i < n_contexts; i++) | ||||
| 315 | { | ||||
| 316 | CtkIMContextInfo *info = g_new (CtkIMContextInfo, 1)((CtkIMContextInfo *) g_malloc_n ((1), sizeof (CtkIMContextInfo ))); | ||||
| 317 | info->context_id = g_strdup (contexts[i]->context_id)g_strdup_inline (contexts[i]->context_id); | ||||
| 318 | info->context_name = g_strdup (contexts[i]->context_name)g_strdup_inline (contexts[i]->context_name); | ||||
| 319 | info->domain = g_strdup (contexts[i]->domain)g_strdup_inline (contexts[i]->domain); | ||||
| 320 | info->domain_dirname = g_strdup (contexts[i]->domain_dirname)g_strdup_inline (contexts[i]->domain_dirname); | ||||
| 321 | #ifdef G_OS_WIN32 | ||||
| 322 | correct_localedir_prefix ((char **) &info->domain_dirname); | ||||
| 323 | #endif | ||||
| 324 | info->default_locales = g_strdup (contexts[i]->default_locales)g_strdup_inline (contexts[i]->default_locales); | ||||
| 325 | infos = g_slist_prepend (infos, info); | ||||
| 326 | } | ||||
| 327 | |||||
| 328 | module->builtin = TRUE(!(0)); | ||||
| 329 | g_type_module_set_name (G_TYPE_MODULE (module)((((GTypeModule*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((module)), ((g_type_module_get_type ())))))), module_name); | ||||
| 330 | add_module (module, infos); | ||||
| 331 | |||||
| 332 | return module; | ||||
| 333 | } | ||||
| 334 | |||||
| 335 | static void | ||||
| 336 | ctk_im_module_initialize (void) | ||||
| 337 | { | ||||
| 338 | GString *line_buf = g_string_new (NULL((void*)0)); | ||||
| 339 | GString *tmp_buf = g_string_new (NULL((void*)0)); | ||||
| 340 | gchar *filename = ctk_rc_get_im_module_file(); | ||||
| 341 | FILE *file; | ||||
| 342 | gboolean have_error = FALSE(0); | ||||
| 343 | |||||
| 344 | CtkIMModule *module = NULL((void*)0); | ||||
| 345 | GSList *infos = NULL((void*)0); | ||||
| 346 | |||||
| 347 | contexts_hash = g_hash_table_new (g_str_hash, g_str_equal); | ||||
| 348 | |||||
| 349 | #define do_builtin(m) \ | ||||
| 350 | { \ | ||||
| 351 | const CtkIMContextInfo **contexts; \ | ||||
| 352 | int n_contexts; \ | ||||
| 353 | extern void _ctk_immodule_ ## m ## _list (const CtkIMContextInfo ***contexts, \ | ||||
| 354 | int *n_contexts); \ | ||||
| 355 | extern void _ctk_immodule_ ## m ## _init (GTypeModule *module); \ | ||||
| 356 | extern void _ctk_immodule_ ## m ## _exit (void); \ | ||||
| 357 | extern CtkIMContext *_ctk_immodule_ ## m ## _create (const gchar *context_id); \ | ||||
| 358 | \ | ||||
| 359 | _ctk_immodule_ ## m ## _list (&contexts, &n_contexts); \ | ||||
| 360 | module = add_builtin_module (#m, contexts, n_contexts); \ | ||||
| 361 | module->init = _ctk_immodule_ ## m ## _init; \ | ||||
| 362 | module->exit = _ctk_immodule_ ## m ## _exit; \ | ||||
| 363 | module->create = _ctk_immodule_ ## m ## _create; \ | ||||
| 364 | module = NULL((void*)0); \ | ||||
| 365 | } | ||||
| 366 | |||||
| 367 | #ifdef INCLUDE_IM_am_et | ||||
| 368 | do_builtin (am_et); | ||||
| 369 | #endif | ||||
| 370 | #ifdef INCLUDE_IM_cedilla | ||||
| 371 | do_builtin (cedilla); | ||||
| 372 | #endif | ||||
| 373 | #ifdef INCLUDE_IM_cyrillic_translit | ||||
| 374 | do_builtin (cyrillic_translit); | ||||
| 375 | #endif | ||||
| 376 | #ifdef INCLUDE_IM_ime | ||||
| 377 | do_builtin (ime); | ||||
| 378 | #endif | ||||
| 379 | #ifdef INCLUDE_IM_inuktitut | ||||
| 380 | do_builtin (inuktitut); | ||||
| 381 | #endif | ||||
| 382 | #ifdef INCLUDE_IM_ipa | ||||
| 383 | do_builtin (ipa); | ||||
| 384 | #endif | ||||
| 385 | #ifdef INCLUDE_IM_multipress | ||||
| 386 | do_builtin (multipress); | ||||
| 387 | #endif | ||||
| 388 | #ifdef INCLUDE_IM_thai | ||||
| 389 | do_builtin (thai); | ||||
| 390 | #endif | ||||
| 391 | #ifdef INCLUDE_IM_ti_er | ||||
| 392 | do_builtin (ti_er); | ||||
| 393 | #endif | ||||
| 394 | #ifdef INCLUDE_IM_ti_et | ||||
| 395 | do_builtin (ti_et); | ||||
| 396 | #endif | ||||
| 397 | #ifdef INCLUDE_IM_viqr | ||||
| 398 | do_builtin (viqr); | ||||
| 399 | #endif | ||||
| 400 | #ifdef INCLUDE_IM_xim | ||||
| 401 | do_builtin (xim); | ||||
| 402 | #endif | ||||
| 403 | #ifdef INCLUDE_IM_broadway | ||||
| 404 | do_builtin (broadway); | ||||
| 405 | #endif | ||||
| 406 | #ifdef INCLUDE_IM_wayland | ||||
| 407 | do_builtin (wayland); | ||||
| 408 | #endif | ||||
| 409 | |||||
| 410 | #undef do_builtin | ||||
| 411 | |||||
| 412 | file = g_fopenfopen (filename, "r"); | ||||
| 413 | if (!file
| ||||
| 414 | { | ||||
| 415 | /* In case someone wants only the default input method, | ||||
| 416 | * we allow no file at all. | ||||
| 417 | */ | ||||
| 418 | g_string_free (line_buf, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) ( (line_buf), ((!(0)))) : g_string_free_and_steal (line_buf)) : (g_string_free) ((line_buf), ((!(0))))); | ||||
| 419 | g_string_free (tmp_buf, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) ( (tmp_buf), ((!(0)))) : g_string_free_and_steal (tmp_buf)) : ( g_string_free) ((tmp_buf), ((!(0))))); | ||||
| 420 | g_free (filename); | ||||
| 421 | return; | ||||
| 422 | } | ||||
| 423 | |||||
| 424 | while (!have_error
| ||||
| 425 | { | ||||
| 426 | const char *p; | ||||
| 427 | |||||
| 428 | p = line_buf->str; | ||||
| 429 | |||||
| 430 | if (!ctk_skip_space (&p)) | ||||
| 431 | { | ||||
| 432 | /* Blank line marking the end of a module | ||||
| 433 | */ | ||||
| 434 | if (module && *p != '#') | ||||
| 435 | { | ||||
| 436 | add_module (module, infos); | ||||
| 437 | module = NULL((void*)0); | ||||
| 438 | infos = NULL((void*)0); | ||||
| 439 | } | ||||
| 440 | |||||
| 441 | continue; | ||||
| 442 | } | ||||
| 443 | |||||
| 444 | if (!module
| ||||
| 445 | { | ||||
| 446 | /* Read a module location | ||||
| 447 | */ | ||||
| 448 | module = g_object_new (CTK_TYPE_IM_MODULE(ctk_im_module_get_type ()), NULL((void*)0)); | ||||
| 449 | |||||
| 450 | if (!ctk_scan_string (&p, tmp_buf) || ctk_skip_space (&p)) | ||||
| 451 | { | ||||
| 452 | g_warning ("Error parsing context info in '%s'\n %s", filename, line_buf->str); | ||||
| 453 | have_error = TRUE(!(0)); | ||||
| 454 | } | ||||
| 455 | |||||
| 456 | module->path = g_strdup (tmp_buf->str)g_strdup_inline (tmp_buf->str); | ||||
| 457 | #ifdef G_OS_WIN32 | ||||
| 458 | correct_libdir_prefix (&module->path); | ||||
| 459 | #endif | ||||
| 460 | g_type_module_set_name (G_TYPE_MODULE (module)((((GTypeModule*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((module)), ((g_type_module_get_type ())))))), module->path); | ||||
| 461 | } | ||||
| 462 | else | ||||
| 463 | { | ||||
| 464 | CtkIMContextInfo *info = g_new0 (CtkIMContextInfo, 1)((CtkIMContextInfo *) g_malloc0_n ((1), sizeof (CtkIMContextInfo ))); | ||||
| 465 | |||||
| 466 | /* Read information about a context type | ||||
| 467 | */ | ||||
| 468 | if (!ctk_scan_string (&p, tmp_buf)) | ||||
| 469 | goto context_error; | ||||
| 470 | info->context_id = g_strdup (tmp_buf->str)g_strdup_inline (tmp_buf->str); | ||||
| 471 | |||||
| 472 | if (!ctk_scan_string (&p, tmp_buf)) | ||||
| 473 | goto context_error; | ||||
| 474 | info->context_name = g_strdup (tmp_buf->str)g_strdup_inline (tmp_buf->str); | ||||
| 475 | |||||
| 476 | if (!ctk_scan_string (&p, tmp_buf)) | ||||
| 477 | goto context_error; | ||||
| 478 | info->domain = g_strdup (tmp_buf->str)g_strdup_inline (tmp_buf->str); | ||||
| 479 | |||||
| 480 | if (!ctk_scan_string (&p, tmp_buf)) | ||||
| 481 | goto context_error; | ||||
| 482 | |||||
| 483 | info->domain_dirname = g_strdup (tmp_buf->str)g_strdup_inline (tmp_buf->str); | ||||
| 484 | #ifdef G_OS_WIN32 | ||||
| 485 | correct_localedir_prefix ((char **) &info->domain_dirname); | ||||
| 486 | #endif | ||||
| 487 | |||||
| 488 | if (!ctk_scan_string (&p, tmp_buf)) | ||||
| 489 | goto context_error; | ||||
| 490 | info->default_locales = g_strdup (tmp_buf->str)g_strdup_inline (tmp_buf->str); | ||||
| 491 | |||||
| 492 | if (ctk_skip_space (&p)) | ||||
| 493 | goto context_error; | ||||
| 494 | |||||
| 495 | infos = g_slist_prepend (infos, info); | ||||
| 496 | continue; | ||||
| 497 | |||||
| 498 | context_error: | ||||
| 499 | g_warning ("Error parsing context info in '%s'\n %s", filename, line_buf->str); | ||||
| |||||
| 500 | have_error = TRUE(!(0)); | ||||
| 501 | } | ||||
| 502 | } | ||||
| 503 | |||||
| 504 | if (have_error) | ||||
| 505 | { | ||||
| 506 | g_slist_free_full (infos, (GDestroyNotify)free_info); | ||||
| 507 | g_object_unref (module); | ||||
| 508 | } | ||||
| 509 | else if (module) | ||||
| 510 | add_module (module, infos); | ||||
| 511 | |||||
| 512 | fclose (file); | ||||
| 513 | g_string_free (line_buf, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) ( (line_buf), ((!(0)))) : g_string_free_and_steal (line_buf)) : (g_string_free) ((line_buf), ((!(0))))); | ||||
| 514 | g_string_free (tmp_buf, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) ( (tmp_buf), ((!(0)))) : g_string_free_and_steal (tmp_buf)) : ( g_string_free) ((tmp_buf), ((!(0))))); | ||||
| 515 | g_free (filename); | ||||
| 516 | } | ||||
| 517 | |||||
| 518 | static gint | ||||
| 519 | compare_ctkimcontextinfo_name (const CtkIMContextInfo **a, | ||||
| 520 | const CtkIMContextInfo **b) | ||||
| 521 | { | ||||
| 522 | return g_utf8_collate ((*a)->context_name, (*b)->context_name); | ||||
| 523 | } | ||||
| 524 | |||||
| 525 | /** | ||||
| 526 | * _ctk_im_module_list: | ||||
| 527 | * @contexts: location to store an array of pointers to #CtkIMContextInfo | ||||
| 528 | * this array should be freed with g_free() when you are finished. | ||||
| 529 | * The structures it points are statically allocated and should | ||||
| 530 | * not be modified or freed. | ||||
| 531 | * @n_contexts: the length of the array stored in @contexts | ||||
| 532 | * | ||||
| 533 | * List all available types of input method context | ||||
| 534 | */ | ||||
| 535 | void | ||||
| 536 | _ctk_im_module_list (const CtkIMContextInfo ***contexts, | ||||
| 537 | guint *n_contexts) | ||||
| 538 | { | ||||
| 539 | int n = 0; | ||||
| 540 | |||||
| 541 | static | ||||
| 542 | #ifndef G_OS_WIN32 | ||||
| 543 | const | ||||
| 544 | #endif | ||||
| 545 | CtkIMContextInfo simple_context_info = { | ||||
| 546 | SIMPLE_ID"ctk-im-context-simple", | ||||
| 547 | NC_("input method menu", "Simple")("Simple"), | ||||
| 548 | GETTEXT_PACKAGE"ctk30", | ||||
| 549 | #ifdef CTK_LOCALEDIR"/usr/share/locale" | ||||
| 550 | CTK_LOCALEDIR"/usr/share/locale", | ||||
| 551 | #else | ||||
| 552 | "", | ||||
| 553 | #endif | ||||
| 554 | "" | ||||
| 555 | }; | ||||
| 556 | |||||
| 557 | static | ||||
| 558 | #ifndef G_OS_WIN32 | ||||
| 559 | const | ||||
| 560 | #endif | ||||
| 561 | CtkIMContextInfo none_context_info = { | ||||
| 562 | NONE_ID"ctk-im-context-none", | ||||
| 563 | NC_("input method menu", "None")("None"), | ||||
| 564 | GETTEXT_PACKAGE"ctk30", | ||||
| 565 | #ifdef CTK_LOCALEDIR"/usr/share/locale" | ||||
| 566 | CTK_LOCALEDIR"/usr/share/locale", | ||||
| 567 | #else | ||||
| 568 | "", | ||||
| 569 | #endif | ||||
| 570 | "" | ||||
| 571 | }; | ||||
| 572 | |||||
| 573 | #ifdef G_OS_WIN32 | ||||
| 574 | static gboolean beenhere = FALSE(0); | ||||
| 575 | #endif | ||||
| 576 | |||||
| 577 | if (!contexts_hash) | ||||
| 578 | ctk_im_module_initialize (); | ||||
| 579 | |||||
| 580 | #ifdef G_OS_WIN32 | ||||
| 581 | if (!beenhere) | ||||
| 582 | { | ||||
| 583 | beenhere = TRUE(!(0)); | ||||
| 584 | /* correct_localedir_prefix() requires its parameter to be a | ||||
| 585 | * malloced string | ||||
| 586 | */ | ||||
| 587 | simple_context_info.domain_dirname = g_strdup (simple_context_info.domain_dirname)g_strdup_inline (simple_context_info.domain_dirname); | ||||
| 588 | correct_localedir_prefix ((char **) &simple_context_info.domain_dirname); | ||||
| 589 | none_context_info.domain_dirname = g_strdup (none_context_info.domain_dirname)g_strdup_inline (none_context_info.domain_dirname); | ||||
| 590 | correct_localedir_prefix ((char **) &none_context_info.domain_dirname); | ||||
| 591 | } | ||||
| 592 | #endif | ||||
| 593 | |||||
| 594 | if (n_contexts) | ||||
| 595 | *n_contexts = n_loaded_contexts + 2; | ||||
| 596 | |||||
| 597 | if (contexts) | ||||
| 598 | { | ||||
| 599 | GSList *tmp_list; | ||||
| 600 | int i; | ||||
| 601 | |||||
| 602 | *contexts = g_new (const CtkIMContextInfo *, n_loaded_contexts + 2)((const CtkIMContextInfo * *) g_malloc_n ((n_loaded_contexts + 2), sizeof (const CtkIMContextInfo *))); | ||||
| 603 | |||||
| 604 | (*contexts)[n++] = &none_context_info; | ||||
| 605 | (*contexts)[n++] = &simple_context_info; | ||||
| 606 | |||||
| 607 | tmp_list = modules_list; | ||||
| 608 | while (tmp_list) | ||||
| 609 | { | ||||
| 610 | CtkIMModule *module = tmp_list->data; | ||||
| 611 | |||||
| 612 | for (i=0; i<module->n_contexts; i++) | ||||
| 613 | (*contexts)[n++] = module->contexts[i]; | ||||
| 614 | |||||
| 615 | tmp_list = tmp_list->next; | ||||
| 616 | } | ||||
| 617 | |||||
| 618 | /* first elements (Simple and None) should always be at top */ | ||||
| 619 | qsort ((*contexts)+2, n-2, sizeof (CtkIMContextInfo *), (GCompareFunc)compare_ctkimcontextinfo_name); | ||||
| 620 | } | ||||
| 621 | } | ||||
| 622 | |||||
| 623 | /** | ||||
| 624 | * _ctk_im_module_create: | ||||
| 625 | * @context_id: the context ID for the context type to create | ||||
| 626 | * | ||||
| 627 | * Create an IM context of a type specified by the string | ||||
| 628 | * ID @context_id. | ||||
| 629 | * | ||||
| 630 | * Returns: a newly created input context of or @context_id, or | ||||
| 631 | * if that could not be created, a newly created CtkIMContextSimple. | ||||
| 632 | */ | ||||
| 633 | CtkIMContext * | ||||
| 634 | _ctk_im_module_create (const gchar *context_id) | ||||
| 635 | { | ||||
| 636 | CtkIMModule *im_module; | ||||
| 637 | CtkIMContext *context = NULL((void*)0); | ||||
| 638 | |||||
| 639 | if (strcmp (context_id, NONE_ID"ctk-im-context-none") == 0) | ||||
| 640 | return NULL((void*)0); | ||||
| 641 | |||||
| 642 | if (!contexts_hash) | ||||
| 643 | ctk_im_module_initialize (); | ||||
| 644 | |||||
| 645 | if (strcmp (context_id, SIMPLE_ID"ctk-im-context-simple") != 0) | ||||
| 646 | { | ||||
| 647 | im_module = g_hash_table_lookup (contexts_hash, context_id); | ||||
| 648 | if (!im_module) | ||||
| 649 | { | ||||
| 650 | g_warning ("Attempt to load unknown IM context type '%s'", context_id); | ||||
| 651 | } | ||||
| 652 | else | ||||
| 653 | { | ||||
| 654 | if (g_type_module_use (G_TYPE_MODULE (im_module)((((GTypeModule*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((im_module)), ((g_type_module_get_type ())))))))) | ||||
| 655 | { | ||||
| 656 | context = im_module->create (context_id); | ||||
| 657 | g_type_module_unuse (G_TYPE_MODULE (im_module)((((GTypeModule*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((im_module)), ((g_type_module_get_type ()))))))); | ||||
| 658 | } | ||||
| 659 | |||||
| 660 | if (!context) | ||||
| 661 | g_warning ("Loading IM context type '%s' failed", context_id); | ||||
| 662 | } | ||||
| 663 | } | ||||
| 664 | |||||
| 665 | if (!context) | ||||
| 666 | return ctk_im_context_simple_new (); | ||||
| 667 | else | ||||
| 668 | return context; | ||||
| 669 | } | ||||
| 670 | |||||
| 671 | /* Match @locale against @against. | ||||
| 672 | * | ||||
| 673 | * 'en_US' against “en_US” => 4 | ||||
| 674 | * 'en_US' against “en” => 3 | ||||
| 675 | * 'en', “en_UK” against “en_US” => 2 | ||||
| 676 | * all locales, against “*” => 1 | ||||
| 677 | */ | ||||
| 678 | static gint | ||||
| 679 | match_locale (const gchar *locale, | ||||
| 680 | const gchar *against, | ||||
| 681 | gint against_len) | ||||
| 682 | { | ||||
| 683 | if (strcmp (against, "*") == 0) | ||||
| 684 | return 1; | ||||
| 685 | |||||
| 686 | if (g_ascii_strcasecmp (locale, against) == 0) | ||||
| 687 | return 4; | ||||
| 688 | |||||
| 689 | if (g_ascii_strncasecmp (locale, against, 2) == 0) | ||||
| 690 | return (against_len == 2) ? 3 : 2; | ||||
| 691 | |||||
| 692 | return 0; | ||||
| 693 | } | ||||
| 694 | |||||
| 695 | static gboolean | ||||
| 696 | match_backend (CtkIMContextInfo *context) | ||||
| 697 | { | ||||
| 698 | #ifdef CDK_WINDOWING_WAYLAND | ||||
| 699 | if (g_strcmp0 (context->context_id, "wayland") == 0) | ||||
| 700 | { | ||||
| 701 | CdkDisplay *display = cdk_display_get_default (); | ||||
| 702 | |||||
| 703 | return CDK_IS_WAYLAND_DISPLAY (display)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ( (display)); GType __t = ((cdk_wayland_display_get_type())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))) && | ||||
| 704 | cdk_wayland_display_query_registry (display, | ||||
| 705 | "zwp_text_input_manager_v3"); | ||||
| 706 | } | ||||
| 707 | if (g_strcmp0 (context->context_id, "waylandctk") == 0) | ||||
| 708 | { | ||||
| 709 | CdkDisplay *display = cdk_display_get_default (); | ||||
| 710 | |||||
| 711 | return CDK_IS_WAYLAND_DISPLAY (display)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ( (display)); GType __t = ((cdk_wayland_display_get_type())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))) && | ||||
| 712 | cdk_wayland_display_query_registry (display, | ||||
| 713 | "ctk_text_input_manager"); | ||||
| 714 | } | ||||
| 715 | #endif | ||||
| 716 | |||||
| 717 | #ifdef CDK_WINDOWING_BROADWAY | ||||
| 718 | if (g_strcmp0 (context->context_id, "broadway") == 0) | ||||
| 719 | return CDK_IS_BROADWAY_DISPLAY (cdk_display_get_default ())(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ( (cdk_display_get_default ())); GType __t = ((cdk_broadway_display_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst-> g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))); | ||||
| 720 | #endif | ||||
| 721 | |||||
| 722 | #ifdef CDK_WINDOWING_X11 | ||||
| 723 | if (g_strcmp0 (context->context_id, "xim") == 0) | ||||
| 724 | return CDK_IS_X11_DISPLAY (cdk_display_get_default ())(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ( (cdk_display_get_default ())); GType __t = ((cdk_x11_display_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst-> g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))); | ||||
| 725 | #endif | ||||
| 726 | |||||
| 727 | #ifdef CDK_WINDOWING_WIN32 | ||||
| 728 | if (g_strcmp0 (context->context_id, "ime") == 0) | ||||
| 729 | return CDK_IS_WIN32_DISPLAY (cdk_display_get_default ()); | ||||
| 730 | #endif | ||||
| 731 | |||||
| 732 | return TRUE(!(0)); | ||||
| 733 | } | ||||
| 734 | |||||
| 735 | static const gchar * | ||||
| 736 | lookup_immodule (gchar **immodules_list) | ||||
| 737 | { | ||||
| 738 | while (immodules_list && *immodules_list) | ||||
| 739 | { | ||||
| 740 | if (g_strcmp0 (*immodules_list, SIMPLE_ID"ctk-im-context-simple") == 0) | ||||
| 741 | return SIMPLE_ID"ctk-im-context-simple"; | ||||
| 742 | else if (g_strcmp0 (*immodules_list, NONE_ID"ctk-im-context-none") == 0) | ||||
| 743 | return NONE_ID"ctk-im-context-none"; | ||||
| 744 | else | ||||
| 745 | { | ||||
| 746 | gboolean found; | ||||
| 747 | gchar *context_id; | ||||
| 748 | found = g_hash_table_lookup_extended (contexts_hash, *immodules_list, | ||||
| 749 | (gpointer *) &context_id, NULL((void*)0)); | ||||
| 750 | if (found) | ||||
| 751 | return context_id; | ||||
| 752 | } | ||||
| 753 | immodules_list++; | ||||
| 754 | } | ||||
| 755 | |||||
| 756 | return NULL((void*)0); | ||||
| 757 | } | ||||
| 758 | |||||
| 759 | #ifdef G_OS_WIN32 | ||||
| 760 | |||||
| 761 | /* max size for LOCALE_SISO639LANGNAME and LOCALE_SISO3166CTRYNAME is 9 */ | ||||
| 762 | #define MAX_NAME_SIZE 9 | ||||
| 763 | |||||
| 764 | static gchar * | ||||
| 765 | get_current_input_language (void) | ||||
| 766 | { | ||||
| 767 | LCID lcid; | ||||
| 768 | LANGID langid; | ||||
| 769 | HKL kblayout; | ||||
| 770 | int name_size; | ||||
| 771 | wchar_t name[MAX_NAME_SIZE]; | ||||
| 772 | gchar *language; | ||||
| 773 | gchar *country; | ||||
| 774 | gchar *full; | ||||
| 775 | |||||
| 776 | /* Current thread's keyboard layout */ | ||||
| 777 | kblayout = GetKeyboardLayout(0); | ||||
| 778 | /* lowest word in the HKL is the LANGID */ | ||||
| 779 | langid = LOWORD (kblayout); | ||||
| 780 | /* LCID is the LANGID without order */ | ||||
| 781 | lcid = langid; | ||||
| 782 | |||||
| 783 | /* Get Language ID */ | ||||
| 784 | name_size = GetLocaleInfoW (lcid, LOCALE_SISO639LANGNAME, NULL((void*)0), 0); | ||||
| 785 | if (name_size <= 1) | ||||
| 786 | return NULL((void*)0); | ||||
| 787 | |||||
| 788 | g_assert (name_size <= MAX_NAME_SIZE)do { if (name_size <= MAX_NAME_SIZE) ; else g_assertion_message_expr ("Ctk", "ctkimmodule.c", 788, ((const char*) (__func__)), "name_size <= MAX_NAME_SIZE" ); } while (0); | ||||
| 789 | GetLocaleInfoW (lcid, LOCALE_SISO639LANGNAME, name, name_size); | ||||
| 790 | |||||
| 791 | language = g_utf16_to_utf8 (name, name_size, NULL((void*)0), NULL((void*)0), NULL((void*)0)); | ||||
| 792 | if (!language) | ||||
| 793 | return NULL((void*)0); | ||||
| 794 | |||||
| 795 | if (SUBLANGID (langid) == SUBLANG_NEUTRAL) | ||||
| 796 | return language; | ||||
| 797 | |||||
| 798 | /* Get Country ID */ | ||||
| 799 | name_size = GetLocaleInfoW (lcid, LOCALE_SISO3166CTRYNAME, NULL((void*)0), 0); | ||||
| 800 | if (name_size <= 1) | ||||
| 801 | return language; | ||||
| 802 | |||||
| 803 | g_assert (name_size <= MAX_NAME_SIZE)do { if (name_size <= MAX_NAME_SIZE) ; else g_assertion_message_expr ("Ctk", "ctkimmodule.c", 803, ((const char*) (__func__)), "name_size <= MAX_NAME_SIZE" ); } while (0); | ||||
| 804 | GetLocaleInfoW (lcid, LOCALE_SISO3166CTRYNAME, name, name_size); | ||||
| 805 | |||||
| 806 | country = g_utf16_to_utf8 (name, name_size, NULL((void*)0), NULL((void*)0), NULL((void*)0)); | ||||
| 807 | if (!country) | ||||
| 808 | return language; | ||||
| 809 | |||||
| 810 | full = g_strdup_printf ("%s_%s", language, country); | ||||
| 811 | |||||
| 812 | g_free (language); | ||||
| 813 | g_free (country); | ||||
| 814 | |||||
| 815 | return full; | ||||
| 816 | } | ||||
| 817 | |||||
| 818 | #endif | ||||
| 819 | |||||
| 820 | /** | ||||
| 821 | * _ctk_im_module_get_default_context_id: | ||||
| 822 | * | ||||
| 823 | * Return the context_id of the best IM context type | ||||
| 824 | * for the given window. | ||||
| 825 | * | ||||
| 826 | * Returns: the context ID (will never be %NULL) | ||||
| 827 | */ | ||||
| 828 | const gchar * | ||||
| 829 | _ctk_im_module_get_default_context_id (void) | ||||
| 830 | { | ||||
| 831 | GSList *tmp_list; | ||||
| 832 | const gchar *context_id = NULL((void*)0); | ||||
| 833 | gint best_goodness = 0; | ||||
| 834 | gint i; | ||||
| 835 | gchar *tmp_locale, *tmp, **immodules; | ||||
| 836 | const gchar *envvar; | ||||
| 837 | CdkScreen *screen; | ||||
| 838 | CtkSettings *settings; | ||||
| 839 | |||||
| 840 | if (!contexts_hash) | ||||
| |||||
| 841 | ctk_im_module_initialize (); | ||||
| 842 | |||||
| 843 | envvar = g_getenv ("CTK_IM_MODULE"); | ||||
| 844 | if (envvar) | ||||
| 845 | { | ||||
| 846 | immodules = g_strsplit (envvar, ":", 0); | ||||
| 847 | context_id = lookup_immodule (immodules); | ||||
| 848 | g_strfreev (immodules); | ||||
| 849 | |||||
| 850 | if (context_id) | ||||
| 851 | return context_id; | ||||
| 852 | } | ||||
| 853 | |||||
| 854 | /* Check if the certain immodule is set in XSETTINGS. | ||||
| 855 | */ | ||||
| 856 | screen = cdk_screen_get_default (); | ||||
| 857 | settings = ctk_settings_get_for_screen (screen); | ||||
| 858 | g_object_get (G_OBJECT (settings)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((settings)), (((GType) ((20) << (2)))))))), "ctk-im-module", &tmp, NULL((void*)0)); | ||||
| 859 | if (tmp) | ||||
| 860 | { | ||||
| 861 | immodules = g_strsplit (tmp, ":", 0); | ||||
| 862 | context_id = lookup_immodule (immodules); | ||||
| 863 | g_strfreev (immodules); | ||||
| 864 | g_free (tmp); | ||||
| 865 | |||||
| 866 | if (context_id) | ||||
| 867 | return context_id; | ||||
| 868 | } | ||||
| 869 | |||||
| 870 | #ifdef G_OS_WIN32 | ||||
| 871 | /* Read current input locale from the current keyboard info */ | ||||
| 872 | tmp_locale = get_current_input_language (); | ||||
| 873 | if (!tmp_locale) | ||||
| 874 | /* Default to system locale when input language is unknown */ | ||||
| 875 | tmp_locale = _ctk_get_lc_ctype (); | ||||
| 876 | #else | ||||
| 877 | tmp_locale = _ctk_get_lc_ctype (); | ||||
| 878 | #endif | ||||
| 879 | |||||
| 880 | /* Strip the locale code down to the essentials | ||||
| 881 | */ | ||||
| 882 | tmp = strchr (tmp_locale, '.'); | ||||
| 883 | if (tmp) | ||||
| 884 | *tmp = '\0'; | ||||
| 885 | tmp = strchr (tmp_locale, '@'); | ||||
| 886 | if (tmp) | ||||
| 887 | *tmp = '\0'; | ||||
| 888 | |||||
| 889 | tmp_list = modules_list; | ||||
| 890 | while (tmp_list) | ||||
| 891 | { | ||||
| 892 | CtkIMModule *module = tmp_list->data; | ||||
| 893 | |||||
| 894 | for (i = 0; i < module->n_contexts; i++) | ||||
| 895 | { | ||||
| 896 | const gchar *p; | ||||
| 897 | |||||
| 898 | if (!match_backend (module->contexts[i])) | ||||
| 899 | continue; | ||||
| 900 | |||||
| 901 | p = module->contexts[i]->default_locales; | ||||
| 902 | while (p) | ||||
| 903 | { | ||||
| 904 | const gchar *q = strchr (p, ':'); | ||||
| 905 | gint goodness = match_locale (tmp_locale, p, q ? q - p : strlen (p)); | ||||
| 906 | |||||
| 907 | if (goodness > best_goodness) | ||||
| 908 | { | ||||
| 909 | context_id = module->contexts[i]->context_id; | ||||
| 910 | best_goodness = goodness; | ||||
| 911 | } | ||||
| 912 | |||||
| 913 | p = q ? q + 1 : NULL((void*)0); | ||||
| 914 | } | ||||
| 915 | } | ||||
| 916 | |||||
| 917 | tmp_list = tmp_list->next; | ||||
| 918 | } | ||||
| 919 | |||||
| 920 | g_free (tmp_locale); | ||||
| 921 | |||||
| 922 | return context_id ? context_id : SIMPLE_ID"ctk-im-context-simple"; | ||||
| 923 | } |