/* GTK - The GIMP Toolkit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
- * Themes added by The Rasterman <raster@redhat.com>
- *
* 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
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
-#include <config.h>
+#include "config.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <glib/gstdio.h>
#include <gmodule.h>
-#include <pango/pango-utils.h>
-#include "gtkalias.h"
#include "gtkimmodule.h"
#include "gtkimcontextsimple.h"
+#include "gtksettings.h"
+#include "gtkmain.h"
#include "gtkrc.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.
+ * correct_libdir_prefix() and correct_localedir_prefix() functions
+ * below will have to move somewhere else.
*/
+#ifdef __GTK_PRIVATE_H__
+#error gtkprivate.h should not be included in this file
+#endif
+
#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;
{
GTypeModule parent_instance;
+ gboolean builtin;
+
GModule *library;
void (*list) (const GtkIMContextInfo ***contexts,
{
GtkIMModule *im_module = GTK_IM_MODULE (module);
- im_module->library = g_module_open (im_module->path, 0);
- 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);
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
parent_class->finalize (object);
}
+G_DEFINE_TYPE (GtkIMModule, gtk_im_module, G_TYPE_TYPE_MODULE)
+
static void
gtk_im_module_class_init (GtkIMModuleClass *class)
{
gobject_class->finalize = gtk_im_module_finalize;
}
-static GType
-gtk_im_module_get_type (void)
+static void
+gtk_im_module_init (GtkIMModule* object)
{
- static GType im_module_type = 0;
-
- if (!im_module_type)
- {
- static const GTypeInfo im_module_info = {
- sizeof (GtkIMModuleClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) gtk_im_module_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (GtkIMModule),
- 0, /* n_preallocs */
- NULL, /* instance_init */
- };
-
- im_module_type =
- g_type_register_static (G_TYPE_TYPE_MODULE, "GtkIMModule",
- &im_module_info, 0);
- }
-
- return im_module_type;
}
static void
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)
g_free (tem);
}
}
+
+static void
+correct_localedir_prefix (gchar **path)
+{
+ /* As above, but for GTK_LOCALEDIR. Use separate function in case
+ * GTK_LOCALEDIR isn't a subfolder of GTK_LIBDIR.
+ */
+ if (strncmp (*path, GTK_LOCALEDIR, strlen (GTK_LOCALEDIR)) == 0)
+ {
+ extern const gchar *_gtk_get_localedir ();
+ 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_init ()
+gtk_im_module_initialize (void)
{
GString *line_buf = g_string_new (NULL);
GString *tmp_buf = g_string_new (NULL);
contexts_hash = g_hash_table_new (g_str_hash, g_str_equal);
- file = fopen (filename, "r");
+#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)
{
/* In case someone wants only the default input method,
}
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);
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 (&info->domain_dirname);
+#ifdef G_OS_WIN32
+ correct_localedir_prefix ((char **) &info->domain_dirname);
#endif
if (!pango_scan_string (&p, tmp_buf))
* @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,
""
};
+#ifdef G_OS_WIN32
+ static gboolean beenhere = FALSE;
+#endif
+
if (!contexts_hash)
- gtk_im_module_init ();
+ 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);
* 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)
{
GtkIMContext *context = NULL;
if (!contexts_hash)
- gtk_im_module_init ();
+ gtk_im_module_initialize ();
if (strcmp (context_id, SIMPLE_ID) != 0)
{
/**
* _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 i;
gchar *tmp_locale, *tmp;
const gchar *envvar;
+ GdkScreen *screen;
+ GtkSettings *settings;
if (!contexts_hash)
- gtk_im_module_init ();
+ 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);
+ g_hash_table_lookup (contexts_hash, envvar)))
+ return envvar;
+
+ /* Check if the certain immodule is set in XSETTINGS.
+ */
+ if (GDK_IS_DRAWABLE (client_window))
+ {
+ screen = gdk_drawable_get_screen (GDK_DRAWABLE (client_window));
+ settings = gtk_settings_get_for_screen (screen);
+ g_object_get (G_OBJECT (settings), "gtk-im-module", &tmp, NULL);
+ if (tmp)
+ {
+ if (strcmp (tmp, SIMPLE_ID) == 0)
+ context_id = SIMPLE_ID;
+ else
+ {
+ GtkIMModule *module;
+ module = g_hash_table_lookup (contexts_hash, tmp);
+ if (module)
+ context_id = module->contexts[0]->context_id;
+ }
+ 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';
{
GtkIMModule *module = tmp_list->data;
- for (i=0; i<module->n_contexts; i++)
+ for (i = 0; i < module->n_contexts; i++)
{
const gchar *p = module->contexts[i]->default_locales;
while (p)
g_free (tmp_locale);
- return g_strdup (context_id ? context_id : SIMPLE_ID);
+ return context_id ? context_id : SIMPLE_ID;
}