X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkimmodule.c;h=e6372f2edb6763b233b81164d2618e952e98033a;hb=9f41970832b60f3cf6644dfbd154df7ec24f26ce;hp=3b126e8f447882cb1837b319ab65ca4815c6c694;hpb=e272345b5d41bfe7272f72cccc7073442db49b8d;p=~andy%2Fgtk diff --git a/gtk/gtkimmodule.c b/gtk/gtkimmodule.c index 3b126e8f4..e6372f2ed 100644 --- a/gtk/gtkimmodule.c +++ b/gtk/gtkimmodule.c @@ -1,8 +1,6 @@ /* GTK - The GIMP Toolkit * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * - * Themes added by The Rasterman - * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either @@ -14,8 +12,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * License along with this library. If not, see .Free */ /* @@ -25,7 +22,7 @@ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ -#include +#include "config.h" #include #include @@ -34,24 +31,33 @@ #include #include -#include -#include "gtkimmodule.h" +#include "gtkimmoduleprivate.h" #include "gtkimcontextsimple.h" -#include "gtkrc.h" +#include "gtksettings.h" +#include "gtkprivate.h" #include "gtkintl.h" -#include "gtkalias.h" -/* Do *not* include "gtkprivate.h" in this file. If you do, the - * correct_libdir_prefix() function below will have to move somewhere - * else. - */ +#undef GDK_DEPRECATED +#undef GDK_DEPRECATED_FOR +#define GDK_DEPRECATED +#define GDK_DEPRECATED_FOR(f) -#ifdef __GTK_PRIVATE_H__ -#error gtkprivate.h should not be included in this file -#endif +#include "deprecated/gtkrc.h" #define SIMPLE_ID "gtk-im-context-simple" +/** + * 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; @@ -63,6 +69,8 @@ struct _GtkIMModule { GTypeModule parent_instance; + gboolean builtin; + GModule *library; void (*list) (const GtkIMContextInfo ***contexts, @@ -95,30 +103,33 @@ gtk_im_module_load (GTypeModule *module) { GtkIMModule *im_module = GTK_IM_MODULE (module); - im_module->library = g_module_open (im_module->path, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL); - if (!im_module->library) + if (!im_module->builtin) { - g_warning (g_module_error()); - return FALSE; - } + 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 (g_module_error()); - g_module_close (im_module->library); - - 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 theme's init (theme_init) function to let it */ + /* call the module's init function to let it */ /* setup anything it needs to set up. */ im_module->init (module); @@ -132,13 +143,16 @@ gtk_im_module_unload (GTypeModule *module) im_module->exit(); - g_module_close (im_module->library); - im_module->library = NULL; + 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; + im_module->init = NULL; + im_module->exit = NULL; + im_module->list = NULL; + im_module->create = NULL; + } } /* This only will ever be called if an error occurs during @@ -154,7 +168,7 @@ gtk_im_module_finalize (GObject *object) parent_class->finalize (object); } -G_DEFINE_TYPE (GtkIMModule, gtk_im_module, G_TYPE_TYPE_MODULE); +G_DEFINE_TYPE (GtkIMModule, gtk_im_module, G_TYPE_TYPE_MODULE) static void gtk_im_module_class_init (GtkIMModuleClass *class) @@ -217,20 +231,12 @@ add_module (GtkIMModule *module, GSList *infos) modules_list = g_slist_prepend (modules_list, module); } -#if defined (G_OS_WIN32) && defined (GTK_LIBDIR) -/* This is needes on Win32, but not wanted when compiling with MSVC, - * as the makefile.msc doesn't define any GTK_LIBDIR value. - */ - -#define DO_CORRECT_LIBDIR_PREFIX /* Flag to check below whether to call this */ +#ifdef G_OS_WIN32 static void correct_libdir_prefix (gchar **path) { - /* GTK_LIBDIR here is supposed to still have the definition from - * Makefile.am, i.e. the build-time value. Do *not* include gtkprivate.h - * in this file. - */ + /* 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 @@ -241,15 +247,56 @@ correct_libdir_prefix (gchar **path) * builder's machine. Replace the path with the real * one on this machine. */ - extern const gchar *_gtk_get_libdir (); 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; +} + static void gtk_im_module_initialize (void) { @@ -264,6 +311,63 @@ gtk_im_module_initialize (void) 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, \ + guint *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_am_et + do_builtin (am_et); +#endif +#ifdef INCLUDE_IM_cedilla + do_builtin (cedilla); +#endif +#ifdef INCLUDE_IM_cyrillic_translit + do_builtin (cyrillic_translit); +#endif +#ifdef INCLUDE_IM_ime + do_builtin (ime); +#endif +#ifdef INCLUDE_IM_inuktitut + do_builtin (inuktitut); +#endif +#ifdef INCLUDE_IM_ipa + do_builtin (ipa); +#endif +#ifdef INCLUDE_IM_multipress + do_builtin (multipress); +#endif +#ifdef INCLUDE_IM_thai + do_builtin (thai); +#endif +#ifdef INCLUDE_IM_ti_er + do_builtin (ti_er); +#endif +#ifdef INCLUDE_IM_ti_et + do_builtin (ti_et); +#endif +#ifdef INCLUDE_IM_viqr + do_builtin (viqr); +#endif +#ifdef INCLUDE_IM_xim + do_builtin (xim); +#endif + +#undef do_builtin + file = g_fopen (filename, "r"); if (!file) { @@ -311,7 +415,7 @@ gtk_im_module_initialize (void) } module->path = g_strdup (tmp_buf->str); -#ifdef DO_CORRECT_LIBDIR_PREFIX +#ifdef G_OS_WIN32 correct_libdir_prefix (&module->path); #endif g_type_module_set_name (G_TYPE_MODULE (module), module->path); @@ -337,8 +441,8 @@ gtk_im_module_initialize (void) if (!pango_scan_string (&p, tmp_buf)) goto context_error; info->domain_dirname = g_strdup (tmp_buf->str); -#ifdef DO_CORRECT_LIBDIR_PREFIX - correct_libdir_prefix ((char **) &info->domain_dirname); +#ifdef G_OS_WIN32 + correct_localedir_prefix ((char **) &info->domain_dirname); #endif if (!pango_scan_string (&p, tmp_buf)) @@ -395,16 +499,20 @@ compare_gtkimcontextinfo_name(const GtkIMContextInfo **a, * @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 const GtkIMContextInfo simple_context_info = { + static +#ifndef G_OS_WIN32 + const +#endif + GtkIMContextInfo simple_context_info = { SIMPLE_ID, - N_("Default"), + N_("Simple"), GETTEXT_PACKAGE, #ifdef GTK_LOCALEDIR GTK_LOCALEDIR, @@ -414,9 +522,25 @@ _gtk_im_module_list (const GtkIMContextInfo ***contexts, "" }; +#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); + } +#endif + if (n_contexts) *n_contexts = (n_loaded_contexts + 1); @@ -453,8 +577,8 @@ _gtk_im_module_list (const GtkIMContextInfo ***contexts, * ID @context_id. * * Return value: a newly created input context of or @context_id, or - * if that could not be created, a newly created GtkIMContextSimple. - **/ + * if that could not be created, a newly created GtkIMContextSimple. + */ GtkIMContext * _gtk_im_module_create (const gchar *context_id) { @@ -514,39 +638,85 @@ match_locale (const gchar *locale, return 0; } +static const gchar * +lookup_immodule (gchar **immodules_list) +{ + while (immodules_list && *immodules_list) + { + if (g_strcmp0 (*immodules_list, SIMPLE_ID) == 0) + return SIMPLE_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; + } + immodules_list++; + } + + return NULL; +} + /** * _gtk_im_module_get_default_context_id: - * @locale: a locale id in the form 'en_US' + * @client_window: a window * - * Return the context_id of the best IM context type - * for the given locale ID. + * Return the context_id of the best IM context type + * for the given window. * * Return value: the context ID (will never be %NULL) - * the value is newly allocated and must be freed - * with g_free(). - **/ + */ const gchar * -_gtk_im_module_get_default_context_id (const gchar *locale) +_gtk_im_module_get_default_context_id (GdkWindow *client_window) { GSList *tmp_list; const gchar *context_id = NULL; gint best_goodness = 0; gint i; - gchar *tmp_locale, *tmp; + gchar *tmp_locale, *tmp, **immodules; const gchar *envvar; + GdkScreen *screen; + GtkSettings *settings; if (!contexts_hash) gtk_im_module_initialize (); - envvar = g_getenv ("GTK_IM_MODULE"); - if (envvar && - (strcmp (envvar, SIMPLE_ID) == 0 || - g_hash_table_lookup (contexts_hash, envvar))) - return g_strdup (envvar); + envvar = g_getenv("GTK_IM_MODULE"); + if (envvar) + { + immodules = g_strsplit(envvar, ":", 0); + context_id = lookup_immodule(immodules); + g_strfreev(immodules); + + if (context_id) + return context_id; + } + + /* Check if the certain immodule is set in XSETTINGS. + */ + if (GDK_IS_WINDOW (client_window)) + { + screen = gdk_window_get_screen (client_window); + settings = gtk_settings_get_for_screen (screen); + g_object_get (G_OBJECT (settings), "gtk-im-module", &tmp, NULL); + if (tmp) + { + immodules = g_strsplit(tmp, ":", 0); + context_id = lookup_immodule(immodules); + g_strfreev(immodules); + g_free (tmp); + + if (context_id) + return context_id; + } + } /* Strip the locale code down to the essentials */ - tmp_locale = g_strdup (locale); + tmp_locale = _gtk_get_lc_ctype (); tmp = strchr (tmp_locale, '.'); if (tmp) *tmp = '\0'; @@ -559,7 +729,7 @@ _gtk_im_module_get_default_context_id (const gchar *locale) { GtkIMModule *module = tmp_list->data; - for (i=0; in_contexts; i++) + for (i = 0; i < module->n_contexts; i++) { const gchar *p = module->contexts[i]->default_locales; while (p) @@ -582,5 +752,5 @@ _gtk_im_module_get_default_context_id (const gchar *locale) g_free (tmp_locale); - return g_strdup (context_id ? context_id : SIMPLE_ID); + return context_id ? context_id : SIMPLE_ID; }