Base class for new input context system

Wed Apr  5 16:27:45 2000  Owen Taylor  <otaylor@redhat.com>

	* gtk/gtkimcontext.[ch]: Base class for new input context system

	* gtk/gtkimmulticontext.[ch]: Proxy input context that allows
	the real input context implementation to be loaded from modules
	and switched on the fly.

	* gtk/gtkcontextsimple.[ch]: Simple implementation of an input
	context that just does direct keysymbol => unicode translation.
This commit is contained in:
Owen Taylor
2000-04-05 20:43:15 +00:00
committed by Owen Taylor
parent afe607c835
commit 192376a9bb
6 changed files with 1088 additions and 0 deletions

243
gtk/gtkimcontext.c Normal file
View File

@@ -0,0 +1,243 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 2000 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "gtkimcontext.h"
#include "gtksignal.h"
enum {
PREEDIT_START,
PREEDIT_END,
PREEDIT_CHANGED,
COMMIT,
LAST_SIGNAL
};
static guint im_context_signals[LAST_SIGNAL] = { 0 };
static void gtk_im_context_class_init (GtkIMContextClass *class);
static void gtk_im_context_init (GtkIMContext *im_context);
GtkType
gtk_im_context_get_type (void)
{
static GtkType im_context_type = 0;
if (!im_context_type)
{
static const GtkTypeInfo im_context_info =
{
"GtkIMContext",
sizeof (GtkIMContext),
sizeof (GtkIMContextClass),
(GtkClassInitFunc) gtk_im_context_class_init,
(GtkObjectInitFunc) gtk_im_context_init,
/* reserved_1 */ NULL,
/* reserved_2 */ NULL,
(GtkClassInitFunc) NULL,
};
im_context_type = gtk_type_unique (GTK_TYPE_OBJECT, &im_context_info);
}
return im_context_type;
}
static void
gtk_im_context_class_init (GtkIMContextClass *class)
{
GtkObjectClass *object_class;
object_class = (GtkObjectClass*) class;
im_context_signals[PREEDIT_START] =
gtk_signal_new ("preedit_start",
GTK_RUN_LAST,
object_class->type,
GTK_SIGNAL_OFFSET (GtkIMContextClass, preedit_start),
gtk_marshal_NONE__NONE,
GTK_TYPE_NONE, 0);
im_context_signals[PREEDIT_END] =
gtk_signal_new ("preedit_end",
GTK_RUN_LAST,
object_class->type,
GTK_SIGNAL_OFFSET (GtkIMContextClass, preedit_end),
gtk_marshal_NONE__NONE,
GTK_TYPE_NONE, 0);
im_context_signals[PREEDIT_CHANGED] =
gtk_signal_new ("preedit_changed",
GTK_RUN_LAST,
object_class->type,
GTK_SIGNAL_OFFSET (GtkIMContextClass, preedit_changed),
gtk_marshal_NONE__NONE,
GTK_TYPE_NONE, 0);
im_context_signals[COMMIT] =
gtk_signal_new ("commit",
GTK_RUN_LAST,
object_class->type,
GTK_SIGNAL_OFFSET (GtkIMContextClass, commit),
gtk_marshal_NONE__STRING,
GTK_TYPE_NONE, 1,
GTK_TYPE_STRING);
gtk_object_class_add_signals (object_class, im_context_signals, LAST_SIGNAL);
}
static void
gtk_im_context_init (GtkIMContext *im_context)
{
}
/**
* gtk_im_context_set_client_window:
* @context: a #GtkIMContext
* @window: the client window. This may be %NULL to indicate
* that the previous client window no longer exists.
*
* Set the client window for the input context; this is the
* #GdkWindow in which the input appears. This window is
* used in order to correctly position status windows, and may
* also be used for purposes internal to the input method.
**/
void
gtk_im_context_set_client_window (GtkIMContext *context,
GdkWindow *window)
{
GtkIMContextClass *klass;
g_return_if_fail (context != NULL);
g_return_if_fail (GTK_IS_IM_CONTEXT (context));
klass = (GtkIMContextClass *)((GtkObject *)(context))->klass;
if (klass->set_client_window)
klass->set_client_window (context, window);
}
/**
* gtk_im_context_get_preedit_string:
* @context: a #GtkIMContext
* @str: location to store the retrieved string. The
* string retrieved must be freed with g_free ().
* @attrs: location to store the retrieved attribute list.
* When you are done with this list, you must
* unreference it with pango_attr_list_unref().
*
* Retrieve the current preedit string for the input context,
* and a list of attributes to apply to the string.
* This string should be displayed inserted at the insertion
* point.
**/
void
gtk_im_context_get_preedit_string (GtkIMContext *context,
gchar **str,
PangoAttrList **attrs)
{
GtkIMContextClass *klass;
g_return_if_fail (context != NULL);
g_return_if_fail (GTK_IS_IM_CONTEXT (context));
klass = (GtkIMContextClass *)((GtkObject *)(context))->klass;
if (klass->get_preedit_string)
klass->get_preedit_string (context, str, attrs);
else
{
if (str)
*str = g_strdup ("");
if (attrs)
*attrs = pango_attr_list_new ();
}
}
/**
* gtk_im_context_filter_keypress:
* @context: a #GtkIMContext
* @key: the key event
*
* Allow an input method to internally handle a key press event.
* if this function returns %TRUE, then no further processing
* should be done for this keystroke.
*
* Return value: %TRUE if the input method handled the keystroke.
*
**/
gboolean
gtk_im_context_filter_keypress (GtkIMContext *context,
GdkEventKey *key)
{
GtkIMContextClass *klass;
g_return_val_if_fail (context != NULL, FALSE);
g_return_val_if_fail (GTK_IS_IM_CONTEXT (context), FALSE);
g_return_val_if_fail (key != NULL, FALSE);
klass = (GtkIMContextClass *)((GtkObject *)(context))->klass;
if (klass->filter_keypress)
return klass->filter_keypress (context, key);
else
return FALSE;
}
/**
* gtk_im_context_focus_in:
* @context: a #GtkIMContext
*
* Notify the input method that the widget to which this
* input context corresponds has lost gained. The input method
* may, for example, change the displayed feedback to reflect
* this change.
**/
void
gtk_im_context_focus_in (GtkIMContext *context)
{
GtkIMContextClass *klass;
g_return_if_fail (context != NULL);
g_return_if_fail (GTK_IS_IM_CONTEXT (context));
klass = (GtkIMContextClass *)((GtkObject *)(context))->klass;
if (klass->focus_in)
klass->focus_in (context);
}
/**
* gtk_im_context_focus_in:
* @context: a #GtkIMContext
*
* Notify the input method that the widget to which this
* input context corresponds has lost focus. The input method
* may, for example, change the displayed feedback or reset the contexts
* state to reflect this change.
**/
void
gtk_im_context_focus_out (GtkIMContext *context)
{
GtkIMContextClass *klass;
g_return_if_fail (context != NULL);
g_return_if_fail (GTK_IS_IM_CONTEXT (context));
klass = (GtkIMContextClass *)((GtkObject *)(context))->klass;
if (klass->focus_out)
klass->focus_out (context);
}

88
gtk/gtkimcontext.h Normal file
View File

@@ -0,0 +1,88 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 2000 Red Hat Software
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GTK_IM_CONTEXT_H__
#define __GTK_IM_CONTEXT_H__
#include <gdk/gdk.h>
#include <gtk/gtkobject.h>
#include <pango/pango.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define GTK_TYPE_IM_CONTEXT (gtk_im_context_get_type ())
#define GTK_IM_CONTEXT(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_IM_CONTEXT, GtkIMContext))
#define GTK_IM_CONTEXT_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_IM_CONTEXT, GtkIMContextClass))
#define GTK_IS_IM_CONTEXT(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_IM_CONTEXT))
#define GTK_IS_IM_CONTEXT_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_IM_CONTEXT))
#define GTK_IM_CONTEXT_GET_CLASS(obj) (GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_IM_CONTEXT, GtkIMContextClass))
typedef struct _GtkIMContext GtkIMContext;
typedef struct _GtkIMContextClass GtkIMContextClass;
struct _GtkIMContext
{
GtkObject object;
};
struct _GtkIMContextClass
{
GtkObjectClass parent_class;
/* Signals */
void (*preedit_start) (GtkIMContext *context);
void (*preedit_end) (GtkIMContext *context);
void (*preedit_changed) (GtkIMContext *context);
void (*commit) (GtkIMContext *context, const gchar *str);
/* Virtual functions */
void (*set_client_window) (GtkIMContext *context,
GdkWindow *window);
void (*get_preedit_string) (GtkIMContext *context,
gchar **str,
PangoAttrList **attrs);
gboolean (*filter_keypress) (GtkIMContext *context,
GdkEventKey *event);
void (*focus_in) (GtkIMContext *context);
void (*focus_out) (GtkIMContext *context);
};
GtkType gtk_im_context_get_type (void);
void gtk_im_context_set_client_window (GtkIMContext *context,
GdkWindow *window);
void gtk_im_context_get_preedit_string (GtkIMContext *context,
char **str,
PangoAttrList **attrs);
gboolean gtk_im_context_filter_keypress (GtkIMContext *context,
GdkEventKey *event);
void gtk_im_context_focus_in (GtkIMContext *context);
void gtk_im_context_focus_out (GtkIMContext *context);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GTK_IM_CONTEXT_H__ */

409
gtk/gtkimcontextsimple.c Normal file
View File

@@ -0,0 +1,409 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 2000 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <unicode.h>
#include <gdk/gdkkeysyms.h>
#include "gtksignal.h"
#include "gtkimcontextsimple.h"
static void gtk_im_context_simple_class_init (GtkIMContextSimpleClass *class);
static void gtk_im_context_simple_init (GtkIMContextSimple *im_context_simple);
static gboolean gtk_im_context_simple_filter_keypress (GtkIMContext *context,
GdkEventKey *key);
GtkType
gtk_im_context_simple_get_type (void)
{
static GtkType im_context_simple_type = 0;
if (!im_context_simple_type)
{
static const GtkTypeInfo im_context_simple_info =
{
"GtkIMContextSimple",
sizeof (GtkIMContextSimple),
sizeof (GtkIMContextSimpleClass),
(GtkClassInitFunc) gtk_im_context_simple_class_init,
(GtkObjectInitFunc) gtk_im_context_simple_init,
/* reserved_1 */ NULL,
/* reserved_2 */ NULL,
(GtkClassInitFunc) NULL,
};
im_context_simple_type = gtk_type_unique (GTK_TYPE_IM_CONTEXT, &im_context_simple_info);
}
return im_context_simple_type;
}
static void
gtk_im_context_simple_class_init (GtkIMContextSimpleClass *class)
{
GtkIMContextClass *im_context_class = GTK_IM_CONTEXT_CLASS (class);
im_context_class->filter_keypress = gtk_im_context_simple_filter_keypress;
}
static void
gtk_im_context_simple_init (GtkIMContextSimple *im_context_simple)
{
}
GtkIMContext *
gtk_im_context_simple_new (void)
{
return GTK_IM_CONTEXT (gtk_type_new (GTK_TYPE_IM_CONTEXT_SIMPLE));
}
static struct {
guint keyval;
unicode_char_t ch;
} keyval_to_unicode[] = {
{ GDK_space, 0x020 },
{ GDK_exclam, 0x021 },
{ GDK_quotedbl, 0x022 },
{ GDK_numbersign, 0x023 },
{ GDK_dollar, 0x024 },
{ GDK_percent, 0x025 },
{ GDK_ampersand, 0x026 },
{ GDK_apostrophe, 0x027 },
{ GDK_quoteright, 0x027 },
{ GDK_parenleft, 0x028 },
{ GDK_parenright, 0x029 },
{ GDK_asterisk, 0x02a },
{ GDK_plus, 0x02b },
{ GDK_comma, 0x02c },
{ GDK_minus, 0x02d },
{ GDK_period, 0x02e },
{ GDK_slash, 0x02f },
{ GDK_0, 0x030 },
{ GDK_1, 0x031 },
{ GDK_2, 0x032 },
{ GDK_3, 0x033 },
{ GDK_4, 0x034 },
{ GDK_5, 0x035 },
{ GDK_6, 0x036 },
{ GDK_7, 0x037 },
{ GDK_8, 0x038 },
{ GDK_9, 0x039 },
{ GDK_colon, 0x03a },
{ GDK_semicolon, 0x03b },
{ GDK_less, 0x03c },
{ GDK_equal, 0x03d },
{ GDK_greater, 0x03e },
{ GDK_question, 0x03f },
{ GDK_at, 0x040 },
{ GDK_A, 0x041 },
{ GDK_B, 0x042 },
{ GDK_C, 0x043 },
{ GDK_D, 0x044 },
{ GDK_E, 0x045 },
{ GDK_F, 0x046 },
{ GDK_G, 0x047 },
{ GDK_H, 0x048 },
{ GDK_I, 0x049 },
{ GDK_J, 0x04a },
{ GDK_K, 0x04b },
{ GDK_L, 0x04c },
{ GDK_M, 0x04d },
{ GDK_N, 0x04e },
{ GDK_O, 0x04f },
{ GDK_P, 0x050 },
{ GDK_Q, 0x051 },
{ GDK_R, 0x052 },
{ GDK_S, 0x053 },
{ GDK_T, 0x054 },
{ GDK_U, 0x055 },
{ GDK_V, 0x056 },
{ GDK_W, 0x057 },
{ GDK_X, 0x058 },
{ GDK_Y, 0x059 },
{ GDK_Z, 0x05a },
{ GDK_bracketleft, 0x05b },
{ GDK_backslash, 0x05c },
{ GDK_bracketright, 0x05d },
{ GDK_asciicircum, 0x05e },
{ GDK_underscore, 0x05f },
{ GDK_grave, 0x060 },
{ GDK_a, 0x061 },
{ GDK_b, 0x062 },
{ GDK_c, 0x063 },
{ GDK_d, 0x064 },
{ GDK_e, 0x065 },
{ GDK_f, 0x066 },
{ GDK_g, 0x067 },
{ GDK_h, 0x068 },
{ GDK_i, 0x069 },
{ GDK_j, 0x06a },
{ GDK_k, 0x06b },
{ GDK_l, 0x06c },
{ GDK_m, 0x06d },
{ GDK_n, 0x06e },
{ GDK_o, 0x06f },
{ GDK_p, 0x070 },
{ GDK_q, 0x071 },
{ GDK_r, 0x072 },
{ GDK_s, 0x073 },
{ GDK_t, 0x074 },
{ GDK_u, 0x075 },
{ GDK_v, 0x076 },
{ GDK_w, 0x077 },
{ GDK_x, 0x078 },
{ GDK_y, 0x079 },
{ GDK_z, 0x07a },
{ GDK_braceleft, 0x07b },
{ GDK_bar, 0x07c },
{ GDK_braceright, 0x07d },
{ GDK_asciitilde, 0x07e },
{ GDK_nobreakspace, 0x0a0 },
{ GDK_exclamdown, 0x0a1 },
{ GDK_cent, 0x0a2 },
{ GDK_sterling, 0x0a3 },
{ GDK_currency, 0x0a4 },
{ GDK_yen, 0x0a5 },
{ GDK_brokenbar, 0x0a6 },
{ GDK_section, 0x0a7 },
{ GDK_diaeresis, 0x0a8 },
{ GDK_copyright, 0x0a9 },
{ GDK_ordfeminine, 0x0aa },
{ GDK_guillemotleft, 0x0ab },
{ GDK_notsign, 0x0ac },
{ GDK_hyphen, 0x0ad },
{ GDK_registered, 0x0ae },
{ GDK_macron, 0x0af },
{ GDK_degree, 0x0b0 },
{ GDK_plusminus, 0x0b1 },
{ GDK_twosuperior, 0x0b2 },
{ GDK_threesuperior, 0x0b3 },
{ GDK_acute, 0x0b4 },
{ GDK_mu, 0x0b5 },
{ GDK_paragraph, 0x0b6 },
{ GDK_periodcentered, 0x0b7 },
{ GDK_cedilla, 0x0b8 },
{ GDK_onesuperior, 0x0b9 },
{ GDK_masculine, 0x0ba },
{ GDK_guillemotright, 0x0bb },
{ GDK_onequarter, 0x0bc },
{ GDK_onehalf, 0x0bd },
{ GDK_threequarters, 0x0be },
{ GDK_questiondown, 0x0bf },
{ GDK_Agrave, 0x0c0 },
{ GDK_Aacute, 0x0c1 },
{ GDK_Acircumflex, 0x0c2 },
{ GDK_Atilde, 0x0c3 },
{ GDK_Adiaeresis, 0x0c4 },
{ GDK_Aring, 0x0c5 },
{ GDK_AE, 0x0c6 },
{ GDK_Ccedilla, 0x0c7 },
{ GDK_Egrave, 0x0c8 },
{ GDK_Eacute, 0x0c9 },
{ GDK_Ecircumflex, 0x0ca },
{ GDK_Ediaeresis, 0x0cb },
{ GDK_Igrave, 0x0cc },
{ GDK_Iacute, 0x0cd },
{ GDK_Icircumflex, 0x0ce },
{ GDK_Idiaeresis, 0x0cf },
{ GDK_Eth, 0x0d0 },
{ GDK_Ntilde, 0x0d1 },
{ GDK_Ograve, 0x0d2 },
{ GDK_Oacute, 0x0d3 },
{ GDK_Ocircumflex, 0x0d4 },
{ GDK_Otilde, 0x0d5 },
{ GDK_Odiaeresis, 0x0d6 },
{ GDK_multiply, 0x0d7 },
{ GDK_Ooblique, 0x0d8 },
{ GDK_Ugrave, 0x0d9 },
{ GDK_Uacute, 0x0da },
{ GDK_Ucircumflex, 0x0db },
{ GDK_Udiaeresis, 0x0dc },
{ GDK_Yacute, 0x0dd },
{ GDK_Thorn, 0x0de },
{ GDK_ssharp, 0x0df },
{ GDK_agrave, 0x0e0 },
{ GDK_aacute, 0x0e1 },
{ GDK_acircumflex, 0x0e2 },
{ GDK_atilde, 0x0e3 },
{ GDK_adiaeresis, 0x0e4 },
{ GDK_aring, 0x0e5 },
{ GDK_ae, 0x0e6 },
{ GDK_ccedilla, 0x0e7 },
{ GDK_egrave, 0x0e8 },
{ GDK_eacute, 0x0e9 },
{ GDK_ecircumflex, 0x0ea },
{ GDK_ediaeresis, 0x0eb },
{ GDK_igrave, 0x0ec },
{ GDK_iacute, 0x0ed },
{ GDK_icircumflex, 0x0ee },
{ GDK_idiaeresis, 0x0ef },
{ GDK_eth, 0x0f0 },
{ GDK_ntilde, 0x0f1 },
{ GDK_ograve, 0x0f2 },
{ GDK_oacute, 0x0f3 },
{ GDK_ocircumflex, 0x0f4 },
{ GDK_otilde, 0x0f5 },
{ GDK_odiaeresis, 0x0f6 },
{ GDK_division, 0x0f7 },
{ GDK_oslash, 0x0f8 },
{ GDK_ugrave, 0x0f9 },
{ GDK_uacute, 0x0fa },
{ GDK_ucircumflex, 0x0fb },
{ GDK_udiaeresis, 0x0fc },
{ GDK_yacute, 0x0fd },
{ GDK_thorn, 0x0fe },
{ GDK_ydiaeresis, 0x0ff },
{ GDK_hebrew_aleph, 0x5d0 },
{ GDK_hebrew_bet, 0x5d1 },
{ GDK_hebrew_gimel, 0x5d2 },
{ GDK_hebrew_dalet, 0x5d3 },
{ GDK_hebrew_he, 0x5d4 },
{ GDK_hebrew_waw, 0x5d5 },
{ GDK_hebrew_zayin, 0x5d6 },
{ GDK_hebrew_het, 0x5d7 },
{ GDK_hebrew_tet, 0x5d8 },
{ GDK_hebrew_yod, 0x5d9 },
{ GDK_hebrew_finalkaph, 0x5da },
{ GDK_hebrew_kaph, 0x5db },
{ GDK_hebrew_lamed, 0x5dc },
{ GDK_hebrew_finalmem, 0x5dd },
{ GDK_hebrew_mem, 0x5de },
{ GDK_hebrew_finalnun, 0x5df },
{ GDK_hebrew_nun, 0x5e0 },
{ GDK_hebrew_samech, 0x5e1 },
{ GDK_hebrew_ayin, 0x5e2 },
{ GDK_hebrew_finalpe, 0x5e3 },
{ GDK_hebrew_pe, 0x5e4 },
{ GDK_hebrew_finalzade, 0x5e5 },
{ GDK_hebrew_zade, 0x5e6 },
{ GDK_hebrew_qoph, 0x5e7 },
{ GDK_hebrew_resh, 0x5e8 },
{ GDK_hebrew_shin, 0x5e9 },
{ GDK_hebrew_taw, 0x5ea }
};
static unicode_char_t
find_unicode (gint keyval)
{
gint first = 0;
gint last = G_N_ELEMENTS (keyval_to_unicode) - 1;
#define KEYVAL(ind) keyval_to_unicode[ind].keyval
if (KEYVAL (first) >= keyval)
return KEYVAL(first) == keyval ? keyval_to_unicode[first].ch : 0;
if (KEYVAL (last) <= keyval)
return KEYVAL(last) == keyval ? keyval_to_unicode[last].ch : 0;
/* Invariant: KEYVAL(first) < keyval < KEYVAL(LAST) */
do
{
gint middle = (first + last) / 2;
if (KEYVAL(middle) > keyval)
last = middle;
else if (KEYVAL(middle) == keyval)
return keyval_to_unicode[middle].ch;
else
first = middle;
}
while (last > first + 1);
return 0;
#undef KEVAL
}
/**
* unicode_guchar4_to_utf8:
* @ch: a ISO10646 character code
* @out: output buffer, must have at least 6 bytes of space.
*
* Convert a single character to utf8
*
* Return value: number of bytes written
**/
static int
ucs4_to_utf8 (unicode_char_t c, char *outbuf)
{
size_t len = 0;
int first;
int i;
if (c < 0x80)
{
first = 0;
len = 1;
}
else if (c < 0x800)
{
first = 0xc0;
len = 2;
}
else if (c < 0x10000)
{
first = 0xe0;
len = 3;
}
else if (c < 0x200000)
{
first = 0xf0;
len = 4;
}
else if (c < 0x4000000)
{
first = 0xf8;
len = 5;
}
else
{
first = 0xfc;
len = 6;
}
for (i = len - 1; i > 0; --i)
{
outbuf[i] = (c & 0x3f) | 0x80;
c >>= 6;
}
outbuf[0] = c | first;
return len;
}
static gboolean
gtk_im_context_simple_filter_keypress (GtkIMContext *context,
GdkEventKey *event)
{
unicode_char_t ch = find_unicode (event->keyval);
if (ch != 0)
{
gchar buf[7];
gint len;
len = ucs4_to_utf8 (ch, buf);
buf[len] = '\0';
gtk_signal_emit_by_name (GTK_OBJECT (context), "commit", &buf);
return TRUE;
}
else
return FALSE;
}

59
gtk/gtkimcontextsimple.h Normal file
View File

@@ -0,0 +1,59 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 2000 Red Hat Software
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GTK_IM_CONTEXT_SIMPLE_H__
#define __GTK_IM_CONTEXT_SIMPLE_H__
#include <gtk/gtkimcontext.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define GTK_TYPE_IM_CONTEXT_SIMPLE (gtk_im_context_simple_get_type ())
#define GTK_IM_CONTEXT_SIMPLE(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_IM_CONTEXT_SIMPLE, GtkIMContextSimple))
#define GTK_IM_CONTEXT_SIMPLE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_IM_CONTEXT_SIMPLE, GtkIMContextSimpleClass))
#define GTK_IS_IM_CONTEXT_SIMPLE(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_IM_CONTEXT_SIMPLE))
#define GTK_IS_IM_CONTEXT_SIMPLE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_IM_CONTEXT_SIMPLE))
#define GTK_IM_CONTEXT_SIMPLE_GET_CLASS(obj) (GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_IM_CONTEXT_SIMPLE, GtkIMContextSimpleClass))
typedef struct _GtkIMContextSimple GtkIMContextSimple;
typedef struct _GtkIMContextSimpleClass GtkIMContextSimpleClass;
struct _GtkIMContextSimple
{
GtkIMContext object;
};
struct _GtkIMContextSimpleClass
{
GtkIMContextClass parent_class;
};
GtkType gtk_im_context_simple_get_type (void);
GtkIMContext *gtk_im_context_simple_new (void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GTK_IM_CONTEXT_SIMPLE_H__ */

228
gtk/gtkimmulticontext.c Normal file
View File

@@ -0,0 +1,228 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 2000 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "gtksignal.h"
#include "gtkimmulticontext.h"
#include "gtkimcontextsimple.h"
static void gtk_im_multicontext_class_init (GtkIMMulticontextClass *class);
static void gtk_im_multicontext_init (GtkIMMulticontext *im_multicontext);
static void gtk_im_multicontext_set_client_window (GtkIMContext *context,
GdkWindow *window);
static void gtk_im_multicontext_get_preedit_string (GtkIMContext *context,
gchar **str,
PangoAttrList **attrs);
static gboolean gtk_im_multicontext_filter_keypress (GtkIMContext *context,
GdkEventKey *event);
static void gtk_im_multicontext_focus_in (GtkIMContext *context);
static void gtk_im_multicontext_focus_out (GtkIMContext *context);
void gtk_im_multicontext_preedit_start_cb (GtkIMContext *slave,
GtkIMMulticontext *multicontext);
void gtk_im_multicontext_preedit_end_cb (GtkIMContext *slave,
GtkIMMulticontext *multicontext);
void gtk_im_multicontext_preedit_changed_cb (GtkIMContext *slave,
GtkIMMulticontext *multicontext);
void gtk_im_multicontext_commit_cb (GtkIMContext *slave,
const gchar *str,
GtkIMMulticontext *multicontext);
GtkType
gtk_im_multicontext_get_type (void)
{
static GtkType im_multicontext_type = 0;
if (!im_multicontext_type)
{
static const GtkTypeInfo im_multicontext_info =
{
"GtkIMMulticontext",
sizeof (GtkIMMulticontext),
sizeof (GtkIMMulticontextClass),
(GtkClassInitFunc) gtk_im_multicontext_class_init,
(GtkObjectInitFunc) gtk_im_multicontext_init,
/* reserved_1 */ NULL,
/* reserved_2 */ NULL,
(GtkClassInitFunc) NULL,
};
im_multicontext_type = gtk_type_unique (GTK_TYPE_IM_CONTEXT, &im_multicontext_info);
}
return im_multicontext_type;
}
static void
gtk_im_multicontext_class_init (GtkIMMulticontextClass *class)
{
GtkIMContextClass *im_context_class = GTK_IM_CONTEXT_CLASS (class);
im_context_class->set_client_window = gtk_im_multicontext_set_client_window;
im_context_class->get_preedit_string = gtk_im_multicontext_get_preedit_string;
im_context_class->filter_keypress = gtk_im_multicontext_filter_keypress;
im_context_class->focus_in = gtk_im_multicontext_focus_in;
im_context_class->focus_out = gtk_im_multicontext_focus_out;
}
static void
gtk_im_multicontext_init (GtkIMMulticontext *multicontext)
{
multicontext->slave = NULL;
}
GtkIMContext *
gtk_im_multicontext_new (void)
{
return GTK_IM_CONTEXT (gtk_type_new (GTK_TYPE_IM_MULTICONTEXT));
}
static void
gtk_im_multicontext_set_slave (GtkIMMulticontext *multicontext,
GtkIMContext *slave)
{
if (multicontext->slave)
{
gtk_signal_disconnect_by_data (GTK_OBJECT (multicontext->slave), multicontext);
gtk_object_unref (GTK_OBJECT (multicontext->slave));
}
multicontext->slave = slave;
if (multicontext->slave)
{
gtk_object_ref (GTK_OBJECT (multicontext->slave));
gtk_object_sink (GTK_OBJECT (multicontext->slave));
gtk_signal_connect (GTK_OBJECT (multicontext->slave), "preedit_start",
GTK_SIGNAL_FUNC (gtk_im_multicontext_preedit_start_cb),
multicontext);
gtk_signal_connect (GTK_OBJECT (multicontext->slave), "preedit_end",
GTK_SIGNAL_FUNC (gtk_im_multicontext_preedit_end_cb),
multicontext);
gtk_signal_connect (GTK_OBJECT (multicontext->slave), "preedit_changed",
GTK_SIGNAL_FUNC (gtk_im_multicontext_preedit_changed_cb),
multicontext);
gtk_signal_connect (GTK_OBJECT (multicontext->slave), "commit",
GTK_SIGNAL_FUNC (gtk_im_multicontext_commit_cb),
multicontext);
}
}
static GtkIMContext *
gtk_im_multicontext_get_slave (GtkIMMulticontext *multicontext)
{
if (!multicontext->slave)
gtk_im_multicontext_set_slave (multicontext, gtk_im_context_simple_new ());
return multicontext->slave;
}
static void
gtk_im_multicontext_set_client_window (GtkIMContext *context,
GdkWindow *window)
{
GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
GtkIMContext *slave = gtk_im_multicontext_get_slave (multicontext);
if (slave)
gtk_im_context_set_client_window (slave, window);
}
static void
gtk_im_multicontext_get_preedit_string (GtkIMContext *context,
gchar **str,
PangoAttrList **attrs)
{
GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
GtkIMContext *slave = gtk_im_multicontext_get_slave (multicontext);
if (slave)
gtk_im_context_get_preedit_string (slave, str, attrs);
else
{
if (str)
*str = g_strdup ("");
if (attrs)
*attrs = pango_attr_list_new ();
}
}
static gboolean
gtk_im_multicontext_filter_keypress (GtkIMContext *context,
GdkEventKey *event)
{
GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
GtkIMContext *slave = gtk_im_multicontext_get_slave (multicontext);
if (slave)
return gtk_im_context_filter_keypress (slave, event);
else
return FALSE;
}
static void
gtk_im_multicontext_focus_in (GtkIMContext *context)
{
GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
GtkIMContext *slave = gtk_im_multicontext_get_slave (multicontext);
if (slave)
return gtk_im_context_focus_in (slave);
}
static void
gtk_im_multicontext_focus_out (GtkIMContext *context)
{
GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
GtkIMContext *slave = gtk_im_multicontext_get_slave (multicontext);
if (slave)
return gtk_im_context_focus_out (slave);
}
void
gtk_im_multicontext_preedit_start_cb (GtkIMContext *slave,
GtkIMMulticontext *multicontext)
{
gtk_signal_emit_by_name (GTK_OBJECT (multicontext), "preedit_start");
}
void
gtk_im_multicontext_preedit_end_cb (GtkIMContext *slave,
GtkIMMulticontext *multicontext)
{
gtk_signal_emit_by_name (GTK_OBJECT (multicontext), "preedit_end");
}
void
gtk_im_multicontext_preedit_changed_cb (GtkIMContext *slave,
GtkIMMulticontext *multicontext)
{
gtk_signal_emit_by_name (GTK_OBJECT (multicontext), "preedit_changed");
}
void
gtk_im_multicontext_commit_cb (GtkIMContext *slave,
const gchar *str,
GtkIMMulticontext *multicontext)
{
gtk_signal_emit_by_name (GTK_OBJECT (multicontext), "commit", str);;
}

61
gtk/gtkimmulticontext.h Normal file
View File

@@ -0,0 +1,61 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 2000 Red Hat Software
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GTK_IM_MULTICONTEXT_H__
#define __GTK_IM_MULTICONTEXT_H__
#include <gtk/gtkimcontext.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define GTK_TYPE_IM_MULTICONTEXT (gtk_im_multicontext_get_type ())
#define GTK_IM_MULTICONTEXT(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_IM_MULTICONTEXT, GtkIMMulticontext))
#define GTK_IM_MULTICONTEXT_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_IM_MULTICONTEXT, GtkIMMulticontextClass))
#define GTK_IS_IM_MULTICONTEXT(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_IM_MULTICONTEXT))
#define GTK_IS_IM_MULTICONTEXT_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_IM_MULTICONTEXT))
#define GTK_IM_MULTICONTEXT_GET_CLASS(obj) (GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_IM_MULTICONTEXT, GtkIMMulticontextClass))
typedef struct _GtkIMMulticontext GtkIMMulticontext;
typedef struct _GtkIMMulticontextClass GtkIMMulticontextClass;
struct _GtkIMMulticontext
{
GtkIMContext object;
GtkIMContext *slave;
};
struct _GtkIMMulticontextClass
{
GtkIMContextClass parent_class;
};
GtkType gtk_im_multicontext_get_type (void);
GtkIMContext *gtk_im_multicontext_new (void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GTK_IM_MULTICONTEXT_H__ */