summaryrefslogtreecommitdiff
path: root/gtk/gtkimmodule.c
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2018-02-19 18:29:00 -0500
committerMatthias Clasen <mclasen@redhat.com>2018-02-24 21:34:40 -0500
commit29bcc38ae62e73b76f0f663e2ecc5e85bfe4ca46 (patch)
treecff130d8b76d27418228ece1187d98d79133e7c6 /gtk/gtkimmodule.c
parente6bf832514c04a224c799413bdac7489c7fe9186 (diff)
downloadgtk+-29bcc38ae62e73b76f0f663e2ecc5e85bfe4ca46.tar.gz
Convert immodules to use an extension point
Add an extension point called gtk-im-module, which requires the type GtkIMContext. Simplify the loading by using GIO infrastructure. Drop the locale filtering for now, I don't think it is really necessary nowadays. Convert existing platform modules to gio modules. Sill to do: Drop the conditional build machinery. Either always include them, or never.
Diffstat (limited to 'gtk/gtkimmodule.c')
-rw-r--r--gtk/gtkimmodule.c851
1 files changed, 92 insertions, 759 deletions
diff --git a/gtk/gtkimmodule.c b/gtk/gtkimmodule.c
index 5d517f7a7f..021b5c10b5 100644
--- a/gtk/gtkimmodule.c
+++ b/gtk/gtkimmodule.c
@@ -31,6 +31,7 @@
#include <glib/gstdio.h>
#include <gmodule.h>
+#include "gtkimmodule.h"
#include "gtkimmoduleprivate.h"
#include "gtkimcontextsimple.h"
#include "gtkmodulesprivate.h"
@@ -59,595 +60,10 @@
#include <windows.h>
#endif
-#undef GDK_DEPRECATED
-#undef GDK_DEPRECATED_FOR
-#define GDK_DEPRECATED
-#define GDK_DEPRECATED_FOR(f)
-
-/* We need to call getc() a lot in a loop. This is suboptimal,
- * as getc() does thread locking on the FILE it is given.
- * To optimize that, lock the file first, then call getc(),
- * then unlock.
- * If locking functions are not present in libc, fall back
- * to the suboptimal getc().
- */
-#if !defined(HAVE_FLOCKFILE) && !defined(HAVE__LOCK_FILE)
-# define flockfile(f) (void)1
-# define funlockfile(f) (void)1
-# define getc_unlocked(f) getc(f)
-#elif !defined(HAVE_FLOCKFILE) && defined(HAVE__LOCK_FILE)
-# define flockfile(f) _lock_file(f)
-# define funlockfile(f) _unlock_file(f)
-# define getc_unlocked(f) _getc_nolock(f)
-#endif
-
#define SIMPLE_ID "gtk-im-context-simple"
#define NONE_ID "gtk-im-context-none"
/**
- * GtkIMContextInfo:
- * @context_id: The unique identification string of the input method.
- * @context_name: The human-readable name of the input method.
- * @domain: Translation domain to be used with dgettext()
- * @domain_dirname: Name of locale directory for use with bindtextdomain()
- * @default_locales: A colon-separated list of locales where this input method
- * should be the default. The asterisk “*” sets the default for all locales.
- *
- * Bookkeeping information about a loadable input method.
- */
-
-typedef struct _GtkIMModule GtkIMModule;
-typedef struct _GtkIMModuleClass GtkIMModuleClass;
-
-#define GTK_TYPE_IM_MODULE (gtk_im_module_get_type ())
-#define GTK_IM_MODULE(im_module) (G_TYPE_CHECK_INSTANCE_CAST ((im_module), GTK_TYPE_IM_MODULE, GtkIMModule))
-#define GTK_IS_IM_MODULE(im_module) (G_TYPE_CHECK_INSTANCE_TYPE ((im_module), GTK_TYPE_IM_MODULE))
-
-struct _GtkIMModule
-{
- GTypeModule parent_instance;
-
- gboolean builtin;
-
- GModule *library;
-
- void (*list) (const GtkIMContextInfo ***contexts,
- guint *n_contexts);
- void (*init) (GTypeModule *module);
- void (*exit) (void);
- GtkIMContext *(*create) (const gchar *context_id);
-
- GtkIMContextInfo **contexts;
- guint n_contexts;
-
- gchar *path;
-};
-
-struct _GtkIMModuleClass
-{
- GTypeModuleClass parent_class;
-};
-
-static GType gtk_im_module_get_type (void);
-
-static gint n_loaded_contexts = 0;
-static GHashTable *contexts_hash = NULL;
-static GSList *modules_list = NULL;
-
-static gboolean
-gtk_im_module_load (GTypeModule *module)
-{
- GtkIMModule *im_module = GTK_IM_MODULE (module);
-
- if (!im_module->builtin)
- {
- im_module->library = g_module_open (im_module->path, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
- if (!im_module->library)
- {
- g_warning ("%s", g_module_error());
- return FALSE;
- }
-
- /* extract symbols from the lib */
- if (!g_module_symbol (im_module->library, "im_module_init",
- (gpointer *)&im_module->init) ||
- !g_module_symbol (im_module->library, "im_module_exit",
- (gpointer *)&im_module->exit) ||
- !g_module_symbol (im_module->library, "im_module_list",
- (gpointer *)&im_module->list) ||
- !g_module_symbol (im_module->library, "im_module_create",
- (gpointer *)&im_module->create))
- {
- g_warning ("%s", g_module_error());
- g_module_close (im_module->library);
-
- return FALSE;
- }
- }
-
- /* call the module's init function to let it */
- /* setup anything it needs to set up. */
- im_module->init (module);
-
- return TRUE;
-}
-
-static void
-gtk_im_module_unload (GTypeModule *module)
-{
- GtkIMModule *im_module = GTK_IM_MODULE (module);
-
- im_module->exit();
-
- if (!im_module->builtin)
- {
- g_module_close (im_module->library);
- im_module->library = NULL;
-
- im_module->init = NULL;
- im_module->exit = NULL;
- im_module->list = NULL;
- im_module->create = NULL;
- }
-}
-
-G_DEFINE_TYPE (GtkIMModule, gtk_im_module, G_TYPE_TYPE_MODULE)
-
-/* This only will ever be called if an error occurs during
- * initialization
- */
-static void
-gtk_im_module_finalize (GObject *object)
-{
- GtkIMModule *module = GTK_IM_MODULE (object);
-
- g_free (module->path);
-
- G_OBJECT_CLASS (gtk_im_module_parent_class)->finalize (object);
-}
-
-static void
-gtk_im_module_class_init (GtkIMModuleClass *class)
-{
- GTypeModuleClass *module_class = G_TYPE_MODULE_CLASS (class);
- GObjectClass *gobject_class = G_OBJECT_CLASS (class);
-
- module_class->load = gtk_im_module_load;
- module_class->unload = gtk_im_module_unload;
-
- gobject_class->finalize = gtk_im_module_finalize;
-}
-
-static void
-gtk_im_module_init (GtkIMModule* object)
-{
-}
-
-static void
-free_info (GtkIMContextInfo *info)
-{
- g_free ((char *)info->context_id);
- g_free ((char *)info->context_name);
- g_free ((char *)info->domain);
- g_free ((char *)info->domain_dirname);
- g_free ((char *)info->default_locales);
- g_free (info);
-}
-
-static void
-add_module (GtkIMModule *module, GSList *infos)
-{
- GSList *tmp_list = infos;
- gint i = 0;
- gint n = g_slist_length (infos);
- module->contexts = g_new (GtkIMContextInfo *, n);
-
- while (tmp_list)
- {
- GtkIMContextInfo *info = tmp_list->data;
-
- if (g_hash_table_lookup (contexts_hash, info->context_id))
- {
- free_info (info); /* Duplicate */
- }
- else
- {
- g_hash_table_insert (contexts_hash, (char *)info->context_id, module);
- module->contexts[i++] = tmp_list->data;
- n_loaded_contexts++;
- }
-
- tmp_list = tmp_list->next;
- }
- g_slist_free (infos);
- module->n_contexts = i;
-
- modules_list = g_slist_prepend (modules_list, module);
-}
-
-#ifdef G_OS_WIN32
-
-static void
-correct_libdir_prefix (gchar **path)
-{
- /* GTK_LIBDIR is the build-time libdir */
- if (strncmp (*path, GTK_LIBDIR, strlen (GTK_LIBDIR)) == 0)
- {
- /* This is an entry put there by make install on the
- * packager's system. On Windows a prebuilt GTK+
- * package can be installed in a random
- * location. The gtk.immodules file distributed in
- * such a package contains paths from the package
- * builder's machine. Replace the path with the real
- * one on this machine.
- */
- gchar *tem = *path;
- *path = g_strconcat (_gtk_get_libdir (), tem + strlen (GTK_LIBDIR), NULL);
- g_free (tem);
- }
-}
-
-static void
-correct_localedir_prefix (gchar **path)
-{
- /* See above */
- if (strncmp (*path, GTK_LOCALEDIR, strlen (GTK_LOCALEDIR)) == 0)
- {
- gchar *tem = *path;
- *path = g_strconcat (_gtk_get_localedir (), tem + strlen (GTK_LOCALEDIR), NULL);
- g_free (tem);
- }
-}
-#endif
-
-
-G_GNUC_UNUSED static GtkIMModule *
-add_builtin_module (const gchar *module_name,
- const GtkIMContextInfo **contexts,
- int n_contexts)
-{
- GtkIMModule *module = g_object_new (GTK_TYPE_IM_MODULE, NULL);
- GSList *infos = NULL;
- int i;
-
- for (i = 0; i < n_contexts; i++)
- {
- GtkIMContextInfo *info = g_new (GtkIMContextInfo, 1);
- info->context_id = g_strdup (contexts[i]->context_id);
- info->context_name = g_strdup (contexts[i]->context_name);
- info->domain = g_strdup (contexts[i]->domain);
- info->domain_dirname = g_strdup (contexts[i]->domain_dirname);
-#ifdef G_OS_WIN32
- correct_localedir_prefix ((char **) &info->domain_dirname);
-#endif
- info->default_locales = g_strdup (contexts[i]->default_locales);
- infos = g_slist_prepend (infos, info);
- }
-
- module->builtin = TRUE;
- g_type_module_set_name (G_TYPE_MODULE (module), module_name);
- add_module (module, infos);
-
- return module;
-}
-
-/*
- * gtk_get_im_module_path:
- *
- * Obtains the path in which to look for IM modules. See the documentation
- * of the `GTK_PATH`
- * environment variable for more details about looking up modules. This
- * function is useful solely for utilities supplied with GTK+ and should
- * not be used by applications under normal circumstances.
- *
- * Returns: (type filename): a newly-allocated string containing the
- * path in which to look for IM modules.
- */
-gchar *
-gtk_get_im_module_path (void)
-{
- gchar **paths = _gtk_get_module_path ("immodules");
- gchar *result = g_strjoinv (G_SEARCHPATH_SEPARATOR_S, paths);
- g_strfreev (paths);
-
- return result;
-}
-
-/*
- * gtk_get_im_module_file:
- *
- * Obtains the path to the IM modules file. See the documentation
- * of the `GTK_IM_MODULE_FILE`
- * environment variable for more details.
- *
- * Returns: (type filename): a newly-allocated string containing the
- * name of the file listing the IM modules available for loading
- */
-gchar *
-gtk_get_im_module_file (void)
-{
- const gchar *var = g_getenv ("GTK_IM_MODULE_FILE");
- gchar *result = NULL;
-
- if (var)
- result = g_strdup (var);
-
- if (!result)
- {
- gchar *path;
-
- var = g_getenv ("GTK_EXE_PREFIX");
-
- if (var)
- path = g_build_filename (var, "lib", "gtk-4.0", GTK_BINARY_VERSION, "immodules.cache", NULL);
- else
- path = g_build_filename (_gtk_get_libdir (), "gtk-4.0", GTK_BINARY_VERSION, "immodules.cache", NULL);
-
- return path;
- }
-
- return result;
-}
-
-static void
-gtk_im_module_initialize (void)
-{
- GString *line_buf = g_string_new (NULL);
- GString *tmp_buf = g_string_new (NULL);
- gchar *filename = gtk_get_im_module_file();
- FILE *file;
- gboolean have_error = FALSE;
-
- GtkIMModule *module = NULL;
- GSList *infos = NULL;
-
- contexts_hash = g_hash_table_new (g_str_hash, g_str_equal);
-
-#define do_builtin(m) \
- { \
- const GtkIMContextInfo **contexts; \
- int n_contexts; \
- extern void _gtk_immodule_ ## m ## _list (const GtkIMContextInfo ***contexts, \
- int *n_contexts); \
- extern void _gtk_immodule_ ## m ## _init (GTypeModule *module); \
- extern void _gtk_immodule_ ## m ## _exit (void); \
- extern GtkIMContext *_gtk_immodule_ ## m ## _create (const gchar *context_id); \
- \
- _gtk_immodule_ ## m ## _list (&contexts, &n_contexts); \
- module = add_builtin_module (#m, contexts, n_contexts); \
- module->init = _gtk_immodule_ ## m ## _init; \
- module->exit = _gtk_immodule_ ## m ## _exit; \
- module->create = _gtk_immodule_ ## m ## _create; \
- module = NULL; \
- }
-
-#ifdef INCLUDE_IM_ime
- do_builtin (ime);
-#endif
-#ifdef INCLUDE_IM_xim
- do_builtin (xim);
-#endif
-#ifdef INCLUDE_IM_broadway
- do_builtin (broadway);
-#endif
-#ifdef INCLUDE_IM_wayland
- do_builtin (wayland);
-#endif
-
-#undef do_builtin
-
- file = g_fopen (filename, "r");
- if (!file)
- {
- /* In case someone wants only the default input method,
- * we allow no file at all.
- */
- g_string_free (line_buf, TRUE);
- g_string_free (tmp_buf, TRUE);
- g_free (filename);
- return;
- }
-
- while (!have_error && gtk_read_line (file, line_buf))
- {
- const char *p;
-
- p = line_buf->str;
-
- if (!gtk_skip_space (&p))
- {
- /* Blank line marking the end of a module
- */
- if (module && *p != '#')
- {
- add_module (module, infos);
- module = NULL;
- infos = NULL;
- }
-
- continue;
- }
-
- if (!module)
- {
- /* Read a module location
- */
- module = g_object_new (GTK_TYPE_IM_MODULE, NULL);
-
- if (!gtk_scan_string (&p, tmp_buf) || gtk_skip_space (&p))
- {
- g_warning ("Error parsing context info in '%s'\n %s", filename, line_buf->str);
- have_error = TRUE;
- }
-
- module->path = g_strdup (tmp_buf->str);
-#ifdef G_OS_WIN32
- correct_libdir_prefix (&module->path);
-#endif
- g_type_module_set_name (G_TYPE_MODULE (module), module->path);
- }
- else
- {
- GtkIMContextInfo *info = g_new0 (GtkIMContextInfo, 1);
-
- /* Read information about a context type
- */
- if (!gtk_scan_string (&p, tmp_buf))
- goto context_error;
- info->context_id = g_strdup (tmp_buf->str);
-
- if (!gtk_scan_string (&p, tmp_buf))
- goto context_error;
- info->context_name = g_strdup (tmp_buf->str);
-
- if (!gtk_scan_string (&p, tmp_buf))
- goto context_error;
- info->domain = g_strdup (tmp_buf->str);
-
- if (!gtk_scan_string (&p, tmp_buf))
- goto context_error;
-
- info->domain_dirname = g_strdup (tmp_buf->str);
-#ifdef G_OS_WIN32
- correct_localedir_prefix ((char **) &info->domain_dirname);
-#endif
-
- if (!gtk_scan_string (&p, tmp_buf))
- goto context_error;
- info->default_locales = g_strdup (tmp_buf->str);
-
- if (gtk_skip_space (&p))
- goto context_error;
-
- infos = g_slist_prepend (infos, info);
- continue;
-
- context_error:
- g_warning ("Error parsing context info in '%s'\n %s", filename, line_buf->str);
- have_error = TRUE;
- }
- }
-
- if (have_error)
- {
- g_slist_free_full (infos, (GDestroyNotify)free_info);
- g_object_unref (module);
- }
- else if (module)
- add_module (module, infos);
-
- fclose (file);
- g_string_free (line_buf, TRUE);
- g_string_free (tmp_buf, TRUE);
- g_free (filename);
-}
-
-static gint
-compare_gtkimcontextinfo_name (const GtkIMContextInfo **a,
- const GtkIMContextInfo **b)
-{
- return g_utf8_collate ((*a)->context_name, (*b)->context_name);
-}
-
-/**
- * _gtk_im_module_list:
- * @contexts: location to store an array of pointers to #GtkIMContextInfo
- * this array should be freed with g_free() when you are finished.
- * The structures it points are statically allocated and should
- * not be modified or freed.
- * @n_contexts: the length of the array stored in @contexts
- *
- * List all available types of input method context
- */
-void
-_gtk_im_module_list (const GtkIMContextInfo ***contexts,
- guint *n_contexts)
-{
- int n = 0;
-
- static
-#ifndef G_OS_WIN32
- const
-#endif
- GtkIMContextInfo simple_context_info = {
- SIMPLE_ID,
- NC_("input method menu", "Simple"),
- GETTEXT_PACKAGE,
-#ifdef GTK_LOCALEDIR
- GTK_LOCALEDIR,
-#else
- "",
-#endif
- ""
- };
-
- static
-#ifndef G_OS_WIN32
- const
-#endif
- GtkIMContextInfo none_context_info = {
- NONE_ID,
- NC_("input method menu", "None"),
- GETTEXT_PACKAGE,
-#ifdef GTK_LOCALEDIR
- GTK_LOCALEDIR,
-#else
- "",
-#endif
- ""
- };
-
-#ifdef G_OS_WIN32
- static gboolean beenhere = FALSE;
-#endif
-
- if (!contexts_hash)
- gtk_im_module_initialize ();
-
-#ifdef G_OS_WIN32
- if (!beenhere)
- {
- beenhere = TRUE;
- /* correct_localedir_prefix() requires its parameter to be a
- * malloced string
- */
- simple_context_info.domain_dirname = g_strdup (simple_context_info.domain_dirname);
- correct_localedir_prefix ((char **) &simple_context_info.domain_dirname);
- none_context_info.domain_dirname = g_strdup (none_context_info.domain_dirname);
- correct_localedir_prefix ((char **) &none_context_info.domain_dirname);
- }
-#endif
-
- if (n_contexts)
- *n_contexts = n_loaded_contexts + 2;
-
- if (contexts)
- {
- GSList *tmp_list;
- int i;
-
- *contexts = g_new (const GtkIMContextInfo *, n_loaded_contexts + 2);
-
- (*contexts)[n++] = &none_context_info;
- (*contexts)[n++] = &simple_context_info;
-
- tmp_list = modules_list;
- while (tmp_list)
- {
- GtkIMModule *module = tmp_list->data;
-
- for (i=0; i<module->n_contexts; i++)
- (*contexts)[n++] = module->contexts[i];
-
- tmp_list = tmp_list->next;
- }
-
- /* first elements (Simple and None) should always be at top */
- qsort ((*contexts)+2, n-2, sizeof (GtkIMContextInfo *), (GCompareFunc)compare_gtkimcontextinfo_name);
- }
-}
-
-/**
* _gtk_im_module_create:
* @context_id: the context ID for the context type to create
*
@@ -660,85 +76,54 @@ _gtk_im_module_list (const GtkIMContextInfo ***contexts,
GtkIMContext *
_gtk_im_module_create (const gchar *context_id)
{
- GtkIMModule *im_module;
+ GIOExtensionPoint *ep;
+ GIOExtension *ext;
+ GType type;
GtkIMContext *context = NULL;
if (strcmp (context_id, NONE_ID) == 0)
return NULL;
- if (!contexts_hash)
- gtk_im_module_initialize ();
-
- if (strcmp (context_id, SIMPLE_ID) != 0)
+ ep = g_io_extension_point_lookup (GTK_IM_MODULE_EXTENSION_POINT_NAME);
+ ext = g_io_extension_point_get_extension_by_name (ep, context_id);
+ if (ext)
{
- im_module = g_hash_table_lookup (contexts_hash, context_id);
- if (!im_module)
- {
- g_warning ("Attempt to load unknown IM context type '%s'", context_id);
- }
- else
- {
- if (g_type_module_use (G_TYPE_MODULE (im_module)))
- {
- context = im_module->create (context_id);
- g_type_module_unuse (G_TYPE_MODULE (im_module));
- }
-
- if (!context)
- g_warning ("Loading IM context type '%s' failed", context_id);
- }
+ type = g_io_extension_get_type (ext);
+ context = g_object_new (type, NULL);
}
- if (!context)
- return gtk_im_context_simple_new ();
- else
- return context;
+ return context;
}
-/* Match @locale against @against.
- *
- * 'en_US' against “en_US” => 4
- * 'en_US' against “en” => 3
- * 'en', “en_UK” against “en_US” => 2
- * all locales, against “*” => 1
- */
-static gint
-match_locale (const gchar *locale,
- const gchar *against,
- gint against_len)
+static gboolean
+is_platform (const char *context_id)
{
- if (strcmp (against, "*") == 0)
- return 1;
-
- if (g_ascii_strcasecmp (locale, against) == 0)
- return 4;
-
- if (g_ascii_strncasecmp (locale, against, 2) == 0)
- return (against_len == 2) ? 3 : 2;
-
- return 0;
+ return g_strcmp0 (context_id, "wayland") == 0 ||
+ g_strcmp0 (context_id, "broadway") == 0 ||
+ g_strcmp0 (context_id, "xim") == 0 ||
+ g_strcmp0 (context_id, "ime") == 0;
}
static gboolean
-match_backend (GtkIMContextInfo *context)
+match_backend (const char *context_id)
{
#ifdef GDK_WINDOWING_WAYLAND
- if (g_strcmp0 (context->context_id, "wayland") == 0)
+ if (g_strcmp0 (context_id, "wayland") == 0)
return GDK_IS_WAYLAND_DISPLAY (gdk_display_get_default ());
#endif
#ifdef GDK_WINDOWING_BROADWAY
- if (g_strcmp0 (context->context_id, "broadway") == 0)
+ if (g_strcmp0 (context_id, "broadway") == 0)
return GDK_IS_BROADWAY_DISPLAY (gdk_display_get_default ());
#endif
#ifdef GDK_WINDOWING_X11
- if (g_strcmp0 (context->context_id, "xim") == 0)
+ if (g_strcmp0 (context_id, "xim") == 0)
return GDK_IS_X11_DISPLAY (gdk_display_get_default ());
#endif
#ifdef GDK_WINDOWING_WIN32
- if (g_strcmp0 (context->context_id, "ime") == 0)
+ if (g_strcmp0 (context_id, "ime") == 0)
return GDK_IS_WIN32_DISPLAY (gdk_display_get_default ());
#endif
@@ -755,81 +140,21 @@ lookup_immodule (gchar **immodules_list)
else if (g_strcmp0 (*immodules_list, NONE_ID) == 0)
return NONE_ID;
else
- {
- gboolean found;
- gchar *context_id;
- found = g_hash_table_lookup_extended (contexts_hash, *immodules_list,
- (gpointer *) &context_id, NULL);
- if (found)
- return context_id;
- }
+ {
+ GIOExtensionPoint *ep;
+ GIOExtension *ext;
+
+ ep = g_io_extension_point_lookup (GTK_IM_MODULE_EXTENSION_POINT_NAME);
+ ext = g_io_extension_point_get_extension_by_name (ep, *immodules_list);
+ if (ext)
+ return g_io_extension_get_name (ext);
+ }
immodules_list++;
}
return NULL;
}
-#ifdef G_OS_WIN32
-
-/* max size for LOCALE_SISO639LANGNAME and LOCALE_SISO3166CTRYNAME is 9 */
-#define MAX_NAME_SIZE 9
-
-static gchar *
-get_current_input_language (void)
-{
- LCID lcid;
- LANGID langid;
- HKL kblayout;
- int name_size;
- wchar_t name[MAX_NAME_SIZE];
- gchar *language;
- gchar *country;
- gchar *full;
-
- /* Current thread's keyboard layout */
- kblayout = GetKeyboardLayout(0);
- /* lowest word in the HKL is the LANGID */
- langid = LOWORD (kblayout);
- /* LCID is the LANGID without order */
- lcid = langid;
-
- /* Get Language ID */
- name_size = GetLocaleInfoW (lcid, LOCALE_SISO639LANGNAME, NULL, 0);
- if (name_size <= 1)
- return NULL;
-
- g_assert (name_size <= MAX_NAME_SIZE);
- GetLocaleInfoW (lcid, LOCALE_SISO639LANGNAME, name, name_size);
-
- language = g_utf16_to_utf8 (name, name_size, NULL, NULL, NULL);
- if (!language)
- return NULL;
-
- if (SUBLANGID (langid) == SUBLANG_NEUTRAL)
- return language;
-
- /* Get Country ID */
- name_size = GetLocaleInfoW (lcid, LOCALE_SISO3166CTRYNAME, NULL, 0);
- if (name_size <= 1)
- return language;
-
- g_assert (name_size <= MAX_NAME_SIZE);
- GetLocaleInfoW (lcid, LOCALE_SISO3166CTRYNAME, name, name_size);
-
- country = g_utf16_to_utf8 (name, name_size, NULL, NULL, NULL);
- if (!country)
- return language;
-
- full = g_strdup_printf ("%s_%s", language, country);
-
- g_free (language);
- g_free (country);
-
- return full;
-}
-
-#endif
-
/**
* _gtk_im_module_get_default_context_id:
*
@@ -841,26 +166,21 @@ get_current_input_language (void)
const gchar *
_gtk_im_module_get_default_context_id (void)
{
- GSList *tmp_list;
const gchar *context_id = NULL;
- gint best_goodness = 0;
- gint i;
- gchar *tmp_locale, *tmp, **immodules;
const gchar *envvar;
GtkSettings *settings;
-
- if (!contexts_hash)
- gtk_im_module_initialize ();
+ char *tmp;
envvar = g_getenv ("GTK_IM_MODULE");
if (envvar)
{
- immodules = g_strsplit (envvar, ":", 0);
- context_id = lookup_immodule (immodules);
- g_strfreev (immodules);
+ char **immodules;
+ immodules = g_strsplit (envvar, ":", 0);
+ context_id = lookup_immodule (immodules);
+ g_strfreev (immodules);
- if (context_id)
- return context_id;
+ if (context_id)
+ return context_id;
}
/* Check if the certain immodule is set in XSETTINGS. */
@@ -868,6 +188,8 @@ _gtk_im_module_get_default_context_id (void)
g_object_get (G_OBJECT (settings), "gtk-im-module", &tmp, NULL);
if (tmp)
{
+ char **immodules;
+
immodules = g_strsplit (tmp, ":", 0);
context_id = lookup_immodule (immodules);
g_strfreev (immodules);
@@ -877,57 +199,68 @@ _gtk_im_module_get_default_context_id (void)
return context_id;
}
-#ifdef G_OS_WIN32
- /* Read current input locale from the current keyboard info */
- tmp_locale = get_current_input_language ();
- if (!tmp_locale)
- /* Default to system locale when input language is unknown */
- tmp_locale = _gtk_get_lc_ctype ();
-#else
- tmp_locale = _gtk_get_lc_ctype ();
-#endif
+ GIOExtensionPoint *ep;
+ GList *list, *l;
- /* Strip the locale code down to the essentials
- */
- tmp = strchr (tmp_locale, '.');
- if (tmp)
- *tmp = '\0';
- tmp = strchr (tmp_locale, '@');
- if (tmp)
- *tmp = '\0';
-
- tmp_list = modules_list;
- while (tmp_list)
+ ep = g_io_extension_point_lookup (GTK_IM_MODULE_EXTENSION_POINT_NAME);
+ list = g_io_extension_point_get_extensions (ep);
+ for (l = list; l; l = l->next)
{
- GtkIMModule *module = tmp_list->data;
+ GIOExtension *ext = l->data;
+ const char *context_id;
- for (i = 0; i < module->n_contexts; i++)
- {
- const gchar *p;
+ context_id = g_io_extension_get_name (ext);
+ if (match_backend (context_id))
+ return context_id;
- if (!match_backend (module->contexts[i]))
- continue;
+ // FIXME: locale matching
+ if (!is_platform (context_id))
+ return context_id;
+ }
+
+ return context_id ? context_id : SIMPLE_ID;
+}
+
+void
+gtk_im_modules_init (void)
+{
+ GIOExtensionPoint *ep;
+ GIOModuleScope *scope;
+ char **paths;
+ int i;
+
+ GTK_NOTE (MODULES,
+ g_print ("Registering extension point %s\n", GTK_IM_MODULE_EXTENSION_POINT_NAME));
- p = module->contexts[i]->default_locales;
- while (p)
- {
- const gchar *q = strchr (p, ':');
- gint goodness = match_locale (tmp_locale, p, q ? q - p : strlen (p));
+ ep = g_io_extension_point_register (GTK_IM_MODULE_EXTENSION_POINT_NAME);
+ g_io_extension_point_set_required_type (ep, GTK_TYPE_IM_CONTEXT);
- if (goodness > best_goodness)
- {
- context_id = module->contexts[i]->context_id;
- best_goodness = goodness;
- }
+ g_type_ensure (gtk_im_context_simple_get_type ());
+ // other builtin im context types go here
- p = q ? q + 1 : NULL;
- }
- }
+ scope = g_io_module_scope_new (G_IO_MODULE_SCOPE_BLOCK_DUPLICATES);
- tmp_list = tmp_list->next;
+ paths = _gtk_get_module_path ("immodules");
+ for (i = 0; paths[i]; i++)
+ {
+ GTK_NOTE (MODULES,
+ g_print ("Scanning io modules in %s\n", paths[i]));
+ g_io_modules_scan_all_in_directory_with_scope (paths[i], scope);
}
+ g_strfreev (paths);
- g_free (tmp_locale);
+ g_io_module_scope_free (scope);
- return context_id ? context_id : SIMPLE_ID;
+ {
+ GList *list, *l;
+
+ list = g_io_extension_point_get_extensions (ep);
+ for (l = list; l; l = l->next)
+ {
+ GIOExtension *ext = l->data;
+ g_print ("extension: %s: type %s\n",
+ g_io_extension_get_name (ext),
+ g_type_name (g_io_extension_get_type (ext)));
+ }
+ }
}