X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkimcontextsimple.c;h=87debf226b9baaaeb4f3c3729aa6b25b79933e0b;hb=1247a842a228980a06893e6167ae8c73a4bb6eed;hp=ebbbd08d6bce01513e35b14aa189b1e3231a16bd;hpb=9f47be221689646f4de7e9138bfccf89310f2281;p=~andy%2Fgtk diff --git a/gtk/gtkimcontextsimple.c b/gtk/gtkimcontextsimple.c index ebbbd08d6..87debf226 100644 --- a/gtk/gtkimcontextsimple.c +++ b/gtk/gtkimcontextsimple.c @@ -12,21 +12,20 @@ * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library. If not, see . */ #include "config.h" + #include #include -#include #include "gtkprivate.h" #include "gtkaccelgroup.h" #include "gtkimcontextsimple.h" #include "gtksettings.h" #include "gtkwidget.h" +#include "gtkdebug.h" #include "gtkintl.h" @@ -67,14 +66,14 @@ struct _GtkComposeTableCompact gint n_index_stride; }; -/* This file contains the table of the compose sequences, +/* This file contains the table of the compose sequences, * static const guint16 gtk_compose_seqs_compact[] = {} - * IT is generated from the compose-parse.py script. + * It is generated from the compose-parse.py script. */ #include "gtkimcontextsimpleseqs.h" -/* From the values below, the value 23 means the number of different first keysyms - * that exist in the Compose file (from Xorg). When running compose-parse.py without +/* From the values below, the value 24 means the number of different first keysyms + * that exist in the Compose file (from Xorg). When running compose-parse.py without * parameters, you get the count that you can put here. Needed when updating the * gtkimcontextsimpleseqs.h header file (contains the compose sequences). */ @@ -86,22 +85,22 @@ static const GtkComposeTableCompact gtk_compose_table_compact = { }; static const guint16 gtk_compose_ignore[] = { - GDK_Shift_L, - GDK_Shift_R, - GDK_Control_L, - GDK_Control_R, - GDK_Caps_Lock, - GDK_Shift_Lock, - GDK_Meta_L, - GDK_Meta_R, - GDK_Alt_L, - GDK_Alt_R, - GDK_Super_L, - GDK_Super_R, - GDK_Hyper_L, - GDK_Hyper_R, - GDK_Mode_switch, - GDK_ISO_Level3_Shift + GDK_KEY_Shift_L, + GDK_KEY_Shift_R, + GDK_KEY_Control_L, + GDK_KEY_Control_R, + GDK_KEY_Caps_Lock, + GDK_KEY_Shift_Lock, + GDK_KEY_Meta_L, + GDK_KEY_Meta_R, + GDK_KEY_Alt_L, + GDK_KEY_Alt_R, + GDK_KEY_Super_L, + GDK_KEY_Super_R, + GDK_KEY_Hyper_L, + GDK_KEY_Hyper_R, + GDK_KEY_Mode_switch, + GDK_KEY_ISO_Level3_Shift }; static void gtk_im_context_simple_finalize (GObject *obj); @@ -154,7 +153,7 @@ gtk_im_context_simple_finalize (GObject *obj) G_OBJECT_CLASS (gtk_im_context_simple_parent_class)->finalize (obj); } -/** +/** * gtk_im_context_simple_new: * * Creates a new #GtkIMContextSimple. @@ -252,7 +251,7 @@ check_table (GtkIMContextSimple *context_simple, guint16 *prev_seq; /* Back up to the first sequence that matches to make sure - * we find the exact match if their is one. + * we find the exact match if there is one. */ while (seq > table->data) { @@ -269,7 +268,6 @@ check_table (GtkIMContextSimple *context_simple, gunichar value = 0x10000 * seq[table->max_seq_len] + seq[table->max_seq_len + 1]; - /* We found a tentative match. See if there are any longer * sequences containing this subsequence */ @@ -280,7 +278,7 @@ check_table (GtkIMContextSimple *context_simple, { priv->tentative_match = value; priv->tentative_match_len = n_compose; - + g_signal_emit_by_name (context_simple, "preedit-changed"); return TRUE; @@ -298,14 +296,14 @@ check_table (GtkIMContextSimple *context_simple, } /* Checks if a keysym is a dead key. Dead key keysym values are defined in - * ../gdk/gdkkeysyms.h and the first is GDK_dead_grave. As X.Org is updated, + * ../gdk/gdkkeysyms.h and the first is GDK_KEY_dead_grave. As X.Org is updated, * more dead keys are added and we need to update the upper limit. - * Currently, the upper limit is GDK_dead_dasia+1. The +1 has to do with - * a temporary issue in the X.Org header files. + * Currently, the upper limit is GDK_KEY_dead_dasia+1. The +1 has to do with + * a temporary issue in the X.Org header files. * In future versions it will be just the keysym (no +1). */ #define IS_DEAD_KEY(k) \ - ((k) >= GDK_dead_grave && (k) <= (GDK_dead_dasia+1)) + ((k) >= GDK_KEY_dead_grave && (k) <= (GDK_KEY_dead_dasia+1)) #ifdef GDK_WINDOWING_WIN32 @@ -322,15 +320,15 @@ check_win32_special_cases (GtkIMContextSimple *context_simple, { GtkIMContextSimplePrivate *priv = context_simple->priv; if (n_compose == 2 && - priv->compose_buffer[1] == GDK_space) + priv->compose_buffer[1] == GDK_KEY_space) { gunichar value = 0; switch (priv->compose_buffer[0]) { - case GDK_dead_acute: + case GDK_KEY_dead_acute: value = 0x00B4; break; - case GDK_dead_diaeresis: + case GDK_KEY_dead_diaeresis: value = 0x00A8; break; } if (value > 0) @@ -366,27 +364,91 @@ check_win32_special_case_after_compact_match (GtkIMContextSimple *context_sim #endif +#ifdef GDK_WINDOWING_QUARTZ + static gboolean -check_compact_table (GtkIMContextSimple *context_simple, - const GtkComposeTableCompact *table, - gint n_compose) +check_quartz_special_cases (GtkIMContextSimple *context_simple, + gint n_compose) +{ + GtkIMContextSimplePrivate *priv = context_simple->priv; + guint value = 0; + + if (n_compose == 2) + { + switch (priv->compose_buffer[0]) + { + case GDK_KEY_dead_doubleacute: + switch (priv->compose_buffer[1]) + { + case GDK_KEY_dead_doubleacute: + case GDK_KEY_space: + value = GDK_KEY_quotedbl; break; + + case 'a': value = GDK_KEY_adiaeresis; break; + case 'A': value = GDK_KEY_Adiaeresis; break; + case 'e': value = GDK_KEY_ediaeresis; break; + case 'E': value = GDK_KEY_Ediaeresis; break; + case 'i': value = GDK_KEY_idiaeresis; break; + case 'I': value = GDK_KEY_Idiaeresis; break; + case 'o': value = GDK_KEY_odiaeresis; break; + case 'O': value = GDK_KEY_Odiaeresis; break; + case 'u': value = GDK_KEY_udiaeresis; break; + case 'U': value = GDK_KEY_Udiaeresis; break; + case 'y': value = GDK_KEY_ydiaeresis; break; + case 'Y': value = GDK_KEY_Ydiaeresis; break; + } + break; + + case GDK_KEY_dead_acute: + switch (priv->compose_buffer[1]) + { + case 'c': value = GDK_KEY_ccedilla; break; + case 'C': value = GDK_KEY_Ccedilla; break; + } + break; + } + } + + if (value > 0) + { + gtk_im_context_simple_commit_char (GTK_IM_CONTEXT (context_simple), + gdk_keyval_to_unicode (value)); + priv->compose_buffer[0] = 0; + + GTK_NOTE (MISC, g_print ("quartz: U+%04X\n", value)); + return TRUE; + } + + return FALSE; +} + +#endif + +static gboolean +check_compact_table (GtkIMContextSimple *context_simple, + const GtkComposeTableCompact *table, + gint n_compose) { GtkIMContextSimplePrivate *priv = context_simple->priv; gint row_stride; guint16 *seq_index; - guint16 *seq; + guint16 *seq; gint i; + gboolean match; + gunichar value; /* Will never match, if the sequence in the compose buffer is longer * than the sequences in the table. Further, compare_seq (key, val) - * will overrun val if key is longer than val. */ + * will overrun val if key is longer than val. + */ if (n_compose > table->max_seq_len) return FALSE; seq_index = bsearch (priv->compose_buffer, - table->data, table->n_index_size, - sizeof (guint16) * table->n_index_stride, - compare_seq_index); + table->data, + table->n_index_size, + sizeof (guint16) * table->n_index_stride, + compare_seq_index); if (!seq_index) { @@ -402,44 +464,47 @@ check_compact_table (GtkIMContextSimple *context_simple, GTK_NOTE (MISC, g_print ("compact: %d ", *seq_index)); seq = NULL; + match = FALSE; - for (i = n_compose-1; i < table->max_seq_len; i++) + for (i = n_compose - 1; i < table->max_seq_len; i++) { row_stride = i + 1; - if (seq_index[i+1] - seq_index[i] > 0) + if (seq_index[i + 1] - seq_index[i] > 0) { - seq = bsearch (priv->compose_buffer + 1, - table->data + seq_index[i], (seq_index[i+1] - seq_index[i]) / row_stride, - sizeof (guint16) * row_stride, - compare_seq); + seq = bsearch (priv->compose_buffer + 1, + table->data + seq_index[i], + (seq_index[i + 1] - seq_index[i]) / row_stride, + sizeof (guint16) * row_stride, + compare_seq); - if (seq) + if (seq) { if (i == n_compose - 1) - break; + { + value = seq[row_stride - 1]; + match = TRUE; + } else { + if (match) + { + GTK_NOTE (MISC, g_print ("tentative match U+%04X ", value)); + priv->tentative_match = value; + priv->tentative_match_len = n_compose; + } + g_signal_emit_by_name (context_simple, "preedit-changed"); - GTK_NOTE (MISC, g_print ("yes\n")); - return TRUE; + GTK_NOTE (MISC, g_print ("yes\n")); + return TRUE; } } } } - if (!seq) - { - GTK_NOTE (MISC, g_print ("no\n")); - return FALSE; - } - else + if (match) { - gunichar value; - - value = seq[row_stride - 1]; - gtk_im_context_simple_commit_char (GTK_IM_CONTEXT (context_simple), value); #ifdef G_OS_WIN32 check_win32_special_case_after_compact_match (context_simple, n_compose, value); @@ -455,7 +520,7 @@ check_compact_table (GtkIMContextSimple *context_simple, } /* This function receives a sequence of Unicode characters and tries to - * normalize it (NFC). We check for the case the the resulting string + * normalize it (NFC). We check for the case where the resulting string * has length 1 (single character). * NFC normalisation normally rearranges diacritic marks, unless these * belong to the same Canonical Combining Class. @@ -479,7 +544,8 @@ check_normalize_nfc (gunichar* combination_buffer, gint n_compose) /* Xorg reuses dead_tilde for the perispomeni diacritic mark. * We check if base character belongs to Greek Unicode block, - * and if so, we replace tilde with perispomeni. */ + * and if so, we replace tilde with perispomeni. + */ if (combination_buffer[0] >= 0x390 && combination_buffer[0] <= 0x3FF) { for (i = 1; i < n_compose; i++ ) @@ -493,7 +559,7 @@ check_normalize_nfc (gunichar* combination_buffer, gint n_compose) { g_unicode_canonical_ordering (combination_buffer_temp, n_compose); combination_utf8_temp = g_ucs4_to_utf8 (combination_buffer_temp, -1, NULL, NULL, NULL); - nfc_temp = g_utf8_normalize (combination_utf8_temp, -1, G_NORMALIZE_NFC); + nfc_temp = g_utf8_normalize (combination_utf8_temp, -1, G_NORMALIZE_NFC); if (g_utf8_strlen (nfc_temp, -1) == 1) { @@ -522,8 +588,8 @@ check_normalize_nfc (gunichar* combination_buffer, gint n_compose) } static gboolean -check_algorithmically (GtkIMContextSimple *context_simple, - gint n_compose) +check_algorithmically (GtkIMContextSimple *context_simple, + gint n_compose) { GtkIMContextSimplePrivate *priv = context_simple->priv; @@ -549,7 +615,7 @@ check_algorithmically (GtkIMContextSimple *context_simple, switch (priv->compose_buffer[i]) { #define CASE(keysym, unicode) \ - case GDK_dead_##keysym: combination_buffer[i+1] = unicode; break + case GDK_KEY_dead_##keysym: combination_buffer[i+1] = unicode; break CASE (grave, 0x0300); CASE (acute, 0x0301); @@ -588,9 +654,8 @@ check_algorithmically (GtkIMContextSimple *context_simple, i--; } - /* If the buffer normalizes to a single character, - * then modify the order of combination_buffer accordingly, if necessary, - * and return TRUE. + /* If the buffer normalizes to a single character, then modify the order + * of combination_buffer accordingly, if necessary, and return TRUE. */ if (check_normalize_nfc (combination_buffer, n_compose)) { @@ -615,8 +680,8 @@ check_algorithmically (GtkIMContextSimple *context_simple, /* In addition to the table-driven sequences, we allow Unicode hex * codes to be entered. The method chosen here is similar to the * one recommended in ISO 14755, but not exactly the same, since we - * don't want to steal 16 valuable key combinations. - * + * don't want to steal 16 valuable key combinations. + * * A hex Unicode sequence must be started with Ctrl-Shift-U, followed * by a sequence of hex digits entered with Ctrl-Shift still held. * Releasing one of the modifiers or pressing space while the modifiers @@ -627,7 +692,6 @@ check_algorithmically (GtkIMContextSimple *context_simple, * with Ctrl-Shift-U, then release the modifiers before typing any * digits, and enter the digits without modifiers. */ -#define HEX_MOD_MASK (GTK_DEFAULT_ACCEL_MOD_MASK | GDK_SHIFT_MASK) static gboolean check_hex (GtkIMContextSimple *context_simple, @@ -668,7 +732,7 @@ check_hex (GtkIMContextSimple *context_simple, n = strtoul (str->str, &nptr, 16); - /* if strtoul fails it probably means non-latin digits were used; + /* If strtoul fails it probably means non-latin digits were used; * we should in principle handle that, but we probably don't. */ if (nptr - str->str < str->len) @@ -691,26 +755,15 @@ check_hex (GtkIMContextSimple *context_simple, static void beep_window (GdkWindow *window) { - GtkWidget *widget; - - gdk_window_get_user_data (window, (gpointer) &widget); - - if (GTK_IS_WIDGET (widget)) - { - gtk_widget_error_bell (widget); - } - else - { - GdkScreen *screen = gdk_window_get_screen (GDK_DRAWABLE (window)); - gboolean beep; + GdkScreen *screen = gdk_window_get_screen (window); + gboolean beep; - g_object_get (gtk_settings_get_for_screen (screen), - "gtk-error-bell", &beep, - NULL); + g_object_get (gtk_settings_get_for_screen (screen), + "gtk-error-bell", &beep, + NULL); - if (beep) - gdk_window_beep (window); - } + if (beep) + gdk_window_beep (window); } static gboolean @@ -756,7 +809,7 @@ no_sequence_matches (GtkIMContextSimple *context_simple, } ch = gdk_keyval_to_unicode (event->keyval); - if (ch != 0) + if (ch != 0 && !g_unichar_iscntrl (ch)) { gtk_im_context_simple_commit_char (context, ch); return TRUE; @@ -777,7 +830,7 @@ is_hex_keyval (guint keyval) static guint canonical_hex_keyval (GdkEventKey *event) { - GdkKeymap *keymap = gdk_keymap_get_for_display (gdk_drawable_get_display (event->window)); + GdkKeymap *keymap = gdk_keymap_get_for_display (gdk_window_get_display (event->window)); guint keyval; guint *keyvals = NULL; gint n_vals = 0; @@ -824,8 +877,10 @@ gtk_im_context_simple_filter_keypress (GtkIMContext *context, { GtkIMContextSimple *context_simple = GTK_IM_CONTEXT_SIMPLE (context); GtkIMContextSimplePrivate *priv = context_simple->priv; + GdkDisplay *display = gdk_window_get_display (event->window); GSList *tmp_list; int n_compose = 0; + GdkModifierType hex_mod_mask; gboolean have_hex_mods; gboolean is_hex_start; gboolean is_hex_end; @@ -840,8 +895,8 @@ gtk_im_context_simple_filter_keypress (GtkIMContext *context, if (event->type == GDK_KEY_RELEASE) { if (priv->in_hex_sequence && - (event->keyval == GDK_Control_L || event->keyval == GDK_Control_R || - event->keyval == GDK_Shift_L || event->keyval == GDK_Shift_R)) + (event->keyval == GDK_KEY_Control_L || event->keyval == GDK_KEY_Control_R || + event->keyval == GDK_KEY_Shift_L || event->keyval == GDK_KEY_Shift_R)) { if (priv->tentative_match && g_unichar_validate (priv->tentative_match)) @@ -878,18 +933,22 @@ gtk_im_context_simple_filter_keypress (GtkIMContext *context, if (event->keyval == gtk_compose_ignore[i]) return FALSE; + hex_mod_mask = gdk_keymap_get_modifier_mask (gdk_keymap_get_for_display (display), + GDK_MODIFIER_INTENT_PRIMARY_ACCELERATOR); + hex_mod_mask |= GDK_SHIFT_MASK; + if (priv->in_hex_sequence && priv->modifiers_dropped) have_hex_mods = TRUE; else - have_hex_mods = (event->state & (HEX_MOD_MASK)) == HEX_MOD_MASK; - is_hex_start = event->keyval == GDK_U; - is_hex_end = (event->keyval == GDK_space || - event->keyval == GDK_KP_Space || - event->keyval == GDK_Return || - event->keyval == GDK_ISO_Enter || - event->keyval == GDK_KP_Enter); - is_backspace = event->keyval == GDK_BackSpace; - is_escape = event->keyval == GDK_Escape; + have_hex_mods = (event->state & (hex_mod_mask)) == hex_mod_mask; + is_hex_start = event->keyval == GDK_KEY_U; + is_hex_end = (event->keyval == GDK_KEY_space || + event->keyval == GDK_KEY_KP_Space || + event->keyval == GDK_KEY_Return || + event->keyval == GDK_KEY_ISO_Enter || + event->keyval == GDK_KEY_KP_Enter); + is_backspace = event->keyval == GDK_KEY_BackSpace; + is_escape = event->keyval == GDK_KEY_Escape; hex_keyval = canonical_hex_keyval (event); /* If we are already in a non-hex sequence, or @@ -905,11 +964,20 @@ gtk_im_context_simple_filter_keypress (GtkIMContext *context, (priv->in_hex_sequence && !hex_keyval && !is_hex_start && !is_hex_end && !is_escape && !is_backspace)) { - if (event->state & (GDK_MOD1_MASK | GDK_CONTROL_MASK) || + GdkDisplay *display; + GdkModifierType no_text_input_mask; + + display = gdk_window_get_display (event->window); + + no_text_input_mask = + gdk_keymap_get_modifier_mask (gdk_keymap_get_for_display (display), + GDK_MODIFIER_INTENT_NO_TEXT_INPUT); + + if (event->state & no_text_input_mask || (priv->in_hex_sequence && priv->modifiers_dropped && - (event->keyval == GDK_Return || - event->keyval == GDK_ISO_Enter || - event->keyval == GDK_KP_Enter))) + (event->keyval == GDK_KEY_Return || + event->keyval == GDK_KEY_ISO_Enter || + event->keyval == GDK_KEY_KP_Enter))) { return FALSE; } @@ -1060,6 +1128,11 @@ gtk_im_context_simple_filter_keypress (GtkIMContext *context, return TRUE; #endif +#ifdef GDK_WINDOWING_QUARTZ + if (check_quartz_special_cases (context_simple, n_compose)) + return TRUE; +#endif + if (check_compact_table (context_simple, >k_compose_table_compact, n_compose)) return TRUE; @@ -1142,7 +1215,7 @@ gtk_im_context_simple_get_preedit_string (GtkIMContext *context, } /** - * gtk_im_context_simple_add_table: + * gtk_im_context_simple_add_table: (skip) * @context_simple: A #GtkIMContextSimple * @data: the table * @max_seq_len: Maximum length of a sequence in the table