diff --git a/gtk/gtkimcontext.c b/gtk/gtkimcontext.c new file mode 100644 index 0000000000..a543fdac70 --- /dev/null +++ b/gtk/gtkimcontext.c @@ -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); +} + + diff --git a/gtk/gtkimcontext.h b/gtk/gtkimcontext.h new file mode 100644 index 0000000000..cc0edd9d6e --- /dev/null +++ b/gtk/gtkimcontext.h @@ -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 +#include +#include + + +#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__ */ diff --git a/gtk/gtkimcontextsimple.c b/gtk/gtkimcontextsimple.c new file mode 100644 index 0000000000..ea1e6cc6fb --- /dev/null +++ b/gtk/gtkimcontextsimple.c @@ -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 +#include +#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; +} diff --git a/gtk/gtkimcontextsimple.h b/gtk/gtkimcontextsimple.h new file mode 100644 index 0000000000..615e045192 --- /dev/null +++ b/gtk/gtkimcontextsimple.h @@ -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 + +#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__ */ diff --git a/gtk/gtkimmulticontext.c b/gtk/gtkimmulticontext.c new file mode 100644 index 0000000000..93610ba90a --- /dev/null +++ b/gtk/gtkimmulticontext.c @@ -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);; +} + diff --git a/gtk/gtkimmulticontext.h b/gtk/gtkimmulticontext.h new file mode 100644 index 0000000000..f242c71bce --- /dev/null +++ b/gtk/gtkimmulticontext.h @@ -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 + +#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__ */