summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfujiwarat <takao.fujiwara1@gmail.com>2021-07-26 22:53:19 +0900
committerfujiwarat <takao.fujiwara1@gmail.com>2021-07-26 22:53:19 +0900
commit4259f16324d578aa2505cf50f2f23923d8d87e76 (patch)
tree536faa0ea409482b602883bb6b51db56bb86ea21
parentdf495660a6da492fe0cac8f7fe748f25a1c3217c (diff)
downloadibus-4259f16324d578aa2505cf50f2f23923d8d87e76.tar.gz
src/ibusenginesimple: Make Compose preedit less intrusive
Tweak the preedit display for Compose sequences to be not so distracting. We only show the Compose key when it occurs in the middle of the sequence or is the only key so far. BUG=https://gitlab.gnome.org/GNOME/gtk/-/issues/3669 BUG=https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/3220 BUG=https://blog.gtk.org/2021/03/24/input-revisited/
-rw-r--r--src/ibuscomposetable.c175
-rw-r--r--src/ibusenginesimple.c301
-rw-r--r--src/ibusenginesimpleprivate.h9
3 files changed, 325 insertions, 160 deletions
diff --git a/src/ibuscomposetable.c b/src/ibuscomposetable.c
index aa58f136..2ad21551 100644
--- a/src/ibuscomposetable.c
+++ b/src/ibuscomposetable.c
@@ -1523,23 +1523,22 @@ compare_seq_index (const void *key, const void *value)
* IBusComposeData->values[] is the gunichar array.
*/
gboolean
-ibus_compose_table_compact_check (const IBusComposeTableCompactEx *table,
- guint16
- *compose_buffer,
- int n_compose,
- gboolean
- *compose_finish,
- gunichar **output_chars)
+ibus_compose_table_compact_check (const IBusComposeTableCompactEx
+ *table,
+ guint16 *compose_buffer,
+ int n_compose,
+ gboolean *compose_finish,
+ gunichar **output_chars)
{
int row_stride;
guint16 *seq_index;
guint16 *seq;
int i;
- if (compose_finish)
- *compose_finish = FALSE;
- if (output_chars)
- *output_chars = NULL;
+ /* compose_finish and output_chars should not be initialized because
+ * ibus_compose_table_check() is called at first and
+ * engine->priv->tentative_match will be preedit after this is called.
+ */
/* Will never match, if the sequence in the compose buffer is longer
* than the sequences in the table. Further, compare_seq (key, val)
@@ -1588,7 +1587,8 @@ ibus_compose_table_compact_check (const IBusComposeTableCompactEx *table,
if (compose_finish)
*compose_finish = TRUE;
if (output_chars) {
- *output_chars = g_new (gunichar, length + 1);
+ if (!(*output_chars))
+ *output_chars = g_new (gunichar, length + 1);
for (j = 0; j < length; j++) {
(*output_chars)[j] = table->priv->data2[index + j];
}
@@ -1622,7 +1622,8 @@ ibus_compose_table_compact_check (const IBusComposeTableCompactEx *table,
if (compose_finish)
*compose_finish = TRUE;
if (output_chars) {
- *output_chars = g_new (gunichar, 2);
+ if (!(*output_chars))
+ *output_chars = g_new (gunichar, 2);
(*output_chars)[0] = seq[row_stride - 1];
(*output_chars)[1] = 0;
}
@@ -1635,16 +1636,6 @@ ibus_compose_table_compact_check (const IBusComposeTableCompactEx *table,
}
-/* Checks if a keysym is a dead key. Dead key keysym values are defined in
- * ../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_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) >= IBUS_KEY_dead_grave && (k) <= IBUS_KEY_dead_greek)
-
/* This function receives a sequence of Unicode characters and tries to
* normalize it (NFC). We check for the case the the resulting string
* has length 1 (single character).
@@ -1754,7 +1745,8 @@ ibus_check_algorithmically (const guint16 *compose_buffer,
i--;
while (i >= 0) {
combination_buffer[i+1] = ibus_keysym_to_unicode (compose_buffer[i],
- TRUE);
+ TRUE,
+ NULL);
if (!combination_buffer[i+1]) {
combination_buffer[i+1] =
ibus_keyval_to_unicode (compose_buffer[i]);
@@ -1786,66 +1778,91 @@ ibus_check_algorithmically (const guint16 *compose_buffer,
gunichar
-ibus_keysym_to_unicode (guint16 keysym,
- gboolean combining) {
-#define CASE(keysym_suffix, unicode) \
- case IBUS_KEY_dead_##keysym_suffix: return unicode
-#define CASE_COMBINE(keysym_suffix, combined_unicode, isolated_unicode) \
- case IBUS_KEY_dead_##keysym_suffix: \
- if (combining) \
- return combined_unicode; \
- else \
+ibus_keysym_to_unicode (guint16 keysym,
+ gboolean combining,
+ gboolean *need_space) {
+#define CASE(keysym_suffix, unicode, sp) \
+ case IBUS_KEY_dead_##keysym_suffix: \
+ if (need_space) \
+ *need_space = sp; \
+ return unicode
+#define CASE_COMBINE(keysym_suffix, combined_unicode, isolated_unicode, sp) \
+ case IBUS_KEY_dead_##keysym_suffix: \
+ if (need_space) \
+ *need_space = sp; \
+ if (combining) \
+ return combined_unicode; \
+ else \
return isolated_unicode
switch (keysym) {
- CASE (a, 0x03041);
- CASE (A, 0x03042);
- CASE (i, 0x03043);
- CASE (I, 0x03044);
- CASE (u, 0x03045);
- CASE (U, 0x03046);
- CASE (e, 0x03047);
- CASE (E, 0x03048);
- CASE (o, 0x03049);
- CASE (O, 0x0304A);
- CASE (abovecomma, 0x0313);
- CASE_COMBINE (abovedot, 0x0307, 0x02D9);
- CASE (abovereversedcomma, 0x0314);
- CASE_COMBINE (abovering, 0x030A, 0x02DA);
- CASE_COMBINE (acute, 0x0301, 0x00B4);
- CASE (belowbreve, 0x032E);
- CASE_COMBINE (belowcircumflex, 0x032D, 0xA788);
- CASE_COMBINE (belowcomma, 0x0326, 0x002C);
- CASE (belowdiaeresis, 0x0324);
- CASE_COMBINE (belowdot, 0x0323, 0x002E);
- CASE_COMBINE (belowmacron, 0x0331, 0x02CD);
- CASE_COMBINE (belowring, 0x030A, 0x02F3);
- CASE_COMBINE (belowtilde, 0x0330, 0x02F7);
- CASE_COMBINE (breve, 0x0306, 0x02D8);
- CASE_COMBINE (capital_schwa, 0x018F, 0x04D8);
- CASE_COMBINE (caron, 0x030C, 0x02C7);
- CASE_COMBINE (cedilla, 0x0327, 0x00B8);
- CASE_COMBINE (circumflex, 0x0302, 0x005E);
- CASE (currency, 0x00A4);
+#ifdef IBUS_ENGLISH_DEAD_KEY
+ CASE (a, 0x0363, 1);
+ CASE (A, 0x0363, 1);
+ CASE (i, 0x0365, 1);
+ CASE (I, 0x0365, 1);
+ CASE (u, 0x0367, 1);
+ CASE (U, 0x0367, 1);
+ CASE (e, 0x0364, 1);
+ CASE (E, 0x0364, 1);
+ CASE (o, 0x0366, 1);
+ CASE (O, 0x0366, 1);
+#else
+ CASE (a, 0x3041, 0);
+ CASE (A, 0x3042, 0);
+ CASE (i, 0x3043, 0);
+ CASE (I, 0x3044, 0);
+ CASE (u, 0x3045, 0);
+ CASE (U, 0x3046, 0);
+ CASE (e, 0x3047, 0);
+ CASE (E, 0x3048, 0);
+ CASE (o, 0x3049, 0);
+ CASE (O, 0x304A, 0);
+#endif
+ CASE_COMBINE (abovecomma, 0x0313, 0x02BC, 0);
+ CASE_COMBINE (abovedot, 0x0307, 0x02D9, 0);
+ CASE_COMBINE (abovereversedcomma, 0x0314, 0x02BD, 0);
+ CASE_COMBINE (abovering, 0x030A, 0x02DA, 0);
+ CASE_COMBINE (aboveverticalline, 0x030D, 0x02C8, 0);
+ CASE_COMBINE (acute, 0x0301, 0x00B4, 0);
+ CASE (belowbreve, 0x032E, 1);
+ CASE_COMBINE (belowcircumflex, 0x032D, 0xA788, 0);
+ CASE_COMBINE (belowcomma, 0x0326, 0x002C, 0);
+ CASE (belowdiaeresis, 0x0324, 1);
+ CASE_COMBINE (belowdot, 0x0323, 0x002E, 0);
+ CASE_COMBINE (belowmacron, 0x0331, 0x02CD, 0);
+ CASE_COMBINE (belowring, 0x030A, 0x02F3, 0);
+ CASE_COMBINE (belowtilde, 0x0330, 0x02F7, 0);
+ CASE_COMBINE (belowverticalline, 0x0329, 0x02CC, 0);
+ CASE_COMBINE (breve, 0x0306, 0x02D8, 0);
+ CASE_COMBINE (capital_schwa, 0x1DEA, 0x1D4A, 0);
+ CASE_COMBINE (caron, 0x030C, 0x02C7, 0);
+ CASE_COMBINE (cedilla, 0x0327, 0x00B8, 0);
+ CASE_COMBINE (circumflex, 0x0302, 0x005E, 0);
+ CASE (currency, 0x00A4, 0);
// IBUS_KEY_dead_dasia == IBUS_KEY_dead_abovereversedcomma
- CASE_COMBINE (diaeresis, 0x0308, 0x00A8);
- CASE_COMBINE (doubleacute, 0x030B, 0x02DD);
- CASE_COMBINE (doublegrave, 0x030F, 0x02F5);
- CASE_COMBINE (grave, 0x0300, 0x0060);
- CASE (greek, 0x03BC);
- CASE (hook, 0x0309);
- CASE (horn, 0x031B);
- CASE (invertedbreve, 0x032F);
- CASE_COMBINE (iota, 0x0345, 0x037A);
- CASE_COMBINE (macron, 0x0304, 0x00AF);
- CASE_COMBINE (ogonek, 0x0328, 0x02DB);
+ CASE_COMBINE (diaeresis, 0x0308, 0x00A8, 0);
+ CASE_COMBINE (doubleacute, 0x030B, 0x02DD, 0);
+ CASE_COMBINE (doublegrave, 0x030F, 0x02F5, 0);
+ CASE_COMBINE (grave, 0x0300, 0x0060, 0);
+ CASE (greek, 0x03BC, 0);
+ CASE_COMBINE (hook, 0x0309, 0x02C0, 0);
+ CASE (horn, 0x031B, 1);
+ CASE (invertedbreve, 0x032F, 1);
+ CASE_COMBINE (iota, 0x0345, 0x037A, 0);
+ CASE (longsolidusoverlay, 0x0338, 1);
+ CASE_COMBINE (lowline, 0x0332, 0x005F, 0);
+ CASE_COMBINE (macron, 0x0304, 0x00AF, 0);
+ CASE_COMBINE (ogonek, 0x0328, 0x02DB, 0);
// IBUS_KEY_dead_perispomeni == IBUS_KEY_dead_tilde
// IBUS_KEY_dead_psili == IBUS_KEY_dead_abovecomma
- CASE_COMBINE (semivoiced_sound, 0x309A, 0x309C);
- CASE_COMBINE (small_schwa, 0x1D4A, 0x04D9);
- CASE (stroke, 0x002F);
- CASE_COMBINE (tilde, 0x0303, 0x007E);
- CASE_COMBINE (voiced_sound, 0x3099, 0x309B);
+ CASE_COMBINE (semivoiced_sound, 0x309A, 0x309C, 0);
+ CASE_COMBINE (small_schwa, 0x1DEA, 0x1D4A, 0);
+ CASE (stroke, 0x0335, 1);
+ CASE_COMBINE (tilde, 0x0303, 0x007E, 0);
+ CASE_COMBINE (voiced_sound, 0x3099, 0x309B, 0);
case IBUS_KEY_Multi_key:
+ if (need_space)
+ *need_space = FALSE;
/* We only show the Compose key visibly when it is the
* only glyph in the preedit, or when it occurs in the
* middle of the sequence. Sadly, the official character,
@@ -1854,6 +1871,8 @@ ibus_keysym_to_unicode (guint16 keysym,
*/
return 0x00B7;
default:;
+ if (need_space)
+ *need_space = FALSE;
}
return 0x0;
#undef CASE
diff --git a/src/ibusenginesimple.c b/src/ibusenginesimple.c
index 699cf0d4..acfc0264 100644
--- a/src/ibusenginesimple.c
+++ b/src/ibusenginesimple.c
@@ -78,13 +78,14 @@ typedef struct {
struct _IBusEngineSimplePrivate {
guint16 *compose_buffer;
- gunichar tentative_match;
- char *tentative_emoji;
+ GString *tentative_match;
int tentative_match_len;
+ char *tentative_emoji;
guint hex_mode_enabled : 1;
guint in_hex_sequence : 1;
guint in_emoji_sequence : 1;
+ guint in_compose_sequence : 1;
guint modifiers_dropped : 1;
IBusEngineDict *emoji_dict;
IBusLookupTable *lookup_table;
@@ -178,6 +179,8 @@ ibus_engine_simple_init (IBusEngineSimple *simple)
simple->priv->hex_mode_enabled =
g_getenv("IBUS_ENABLE_CTRL_SHIFT_U") != NULL ||
g_getenv("IBUS_ENABLE_CONTROL_SHIFT_U") != NULL;
+ simple->priv->tentative_match = g_string_new ("");
+ simple->priv->tentative_match_len = 0;
}
@@ -196,6 +199,9 @@ ibus_engine_simple_destroy (IBusEngineSimple *simple)
g_clear_object (&priv->lookup_table);
g_clear_pointer (&priv->compose_buffer, g_free);
g_clear_pointer (&priv->tentative_emoji, g_free);
+ g_string_free (priv->tentative_match, TRUE);
+ priv->tentative_match = NULL;
+ priv->tentative_match_len = 0;
IBUS_OBJECT_CLASS(ibus_engine_simple_parent_class)->destroy (
IBUS_OBJECT (simple));
@@ -222,15 +228,15 @@ ibus_engine_simple_reset (IBusEngine *engine)
priv->compose_buffer[0] = 0;
- if (priv->tentative_match || priv->in_hex_sequence) {
+ if (priv->tentative_match->len > 0 || priv->in_hex_sequence) {
priv->in_hex_sequence = FALSE;
- priv->tentative_match = 0;
+ g_string_set_size (priv->tentative_match, 0);
priv->tentative_match_len = 0;
} else if (priv->tentative_emoji || priv->in_emoji_sequence) {
priv->in_emoji_sequence = FALSE;
g_clear_pointer (&priv->tentative_emoji, g_free);
} else if (!priv->in_hex_sequence && !priv->in_emoji_sequence) {
- priv->tentative_match = 0;
+ g_string_set_size (priv->tentative_match, 0);
priv->tentative_match_len = 0;
}
ibus_engine_hide_preedit_text ((IBusEngine *)simple);
@@ -244,10 +250,17 @@ ibus_engine_simple_commit_char (IBusEngineSimple *simple,
IBusEngineSimplePrivate *priv = simple->priv;
- if (priv->tentative_match || priv->in_hex_sequence) {
- priv->in_hex_sequence = FALSE;
- priv->tentative_match = 0;
+ if (priv->in_hex_sequence ||
+ priv->tentative_match_len > 0 ||
+ priv->compose_buffer[0] != 0) {
+ g_string_set_size (priv->tentative_match, 0);
priv->tentative_match_len = 0;
+ priv->in_hex_sequence = FALSE;
+ priv->in_compose_sequence = FALSE;
+ priv->compose_buffer[0] = 0;
+ /* Don't call ibus_engine_simple_update_preedit_text() inside
+ * not to call it as duplilcated.
+ */
}
if (priv->tentative_emoji || priv->in_emoji_sequence) {
priv->in_emoji_sequence = FALSE;
@@ -269,10 +282,17 @@ ibus_engine_simple_commit_str (IBusEngineSimple *simple,
backup_str = g_strdup (str);
- if (priv->tentative_match || priv->in_hex_sequence) {
- priv->in_hex_sequence = FALSE;
- priv->tentative_match = 0;
+ if (priv->in_hex_sequence ||
+ priv->tentative_match_len > 0 ||
+ priv->compose_buffer[0] != 0) {
+ g_string_set_size (priv->tentative_match, 0);
priv->tentative_match_len = 0;
+ priv->in_hex_sequence = FALSE;
+ priv->in_compose_sequence = FALSE;
+ priv->compose_buffer[0] = 0;
+ /* Don't call ibus_engine_simple_update_preedit_text() inside
+ * not to call it as duplilcated.
+ */
}
if (priv->tentative_emoji || priv->in_emoji_sequence) {
priv->in_emoji_sequence = FALSE;
@@ -288,8 +308,8 @@ static void
ibus_engine_simple_update_preedit_text (IBusEngineSimple *simple)
{
IBusEngineSimplePrivate *priv = simple->priv;
-
GString *s = g_string_new ("");
+ int i, j;
if (priv->in_hex_sequence || priv->in_emoji_sequence) {
int hexchars = 0;
@@ -305,32 +325,59 @@ ibus_engine_simple_update_preedit_text (IBusEngineSimple *simple)
ibus_keyval_to_unicode (priv->compose_buffer[hexchars++])
);
}
- } else if (priv->tentative_match) {
- g_string_append_unichar(s, priv->tentative_match);
} else if (priv->tentative_emoji && *priv->tentative_emoji) {
IBusText *text = ibus_text_new_from_string (priv->tentative_emoji);
int len = strlen (priv->tentative_emoji);
ibus_text_append_attribute (text,
IBUS_ATTR_TYPE_UNDERLINE, IBUS_ATTR_UNDERLINE_SINGLE, 0, len);
ibus_engine_update_preedit_text ((IBusEngine *)simple, text, len, TRUE);
+ g_string_free (s, TRUE);
return;
- } else {
- int hexchars = 0;
- while (priv->compose_buffer[hexchars] != 0) {
- guint16 keysym = priv->compose_buffer[hexchars];
- gunichar unichar = ibus_keysym_to_unicode (keysym, FALSE);
- if (unichar > 0) {
- g_string_append_unichar(s, unichar);
- } else {
- unichar = ibus_keyval_to_unicode (keysym);
- g_string_append_unichar(s, unichar);
- }
- if (!unichar) {
- g_warning (
+ } else if (priv->in_compose_sequence) {
+ if (priv->tentative_match->len > 0 && priv->compose_buffer[0] != 0) {
+ g_string_append (s, priv->tentative_match->str);
+ } else {
+ for (i = 0; priv->compose_buffer[i]; ++i) {
+ guint16 keysym = priv->compose_buffer[i];
+ gboolean show_keysym = TRUE;
+ gboolean need_space = FALSE;
+ gunichar ch;
+
+ if (keysym == IBUS_KEY_Multi_key) {
+ /* We only show the Compose key visibly when it is the
+ * only glyph in the preedit, or when it occurs in the
+ * middle of the sequence. Sadly, the official character,
+ * U+2384, COMPOSITION SYMBOL, is bit too distracting, so
+ * we use U+00B7, MIDDLE DOT.
+ */
+ for (j = i + 1; priv->compose_buffer[j]; j++) {
+ if (priv->compose_buffer[j] != IBUS_KEY_Multi_key) {
+ show_keysym = FALSE;
+ break;
+ }
+ }
+ if (!show_keysym)
+ continue;
+ ch = ibus_keysym_to_unicode (keysym, FALSE, NULL);
+ g_string_append_unichar (s, ch);
+ } else if (IS_DEAD_KEY (keysym)) {
+ ch = ibus_keysym_to_unicode (keysym, FALSE, &need_space);
+ if (ch) {
+ if (need_space)
+ g_string_append_c (s, ' ');
+ g_string_append_unichar (s, ch);
+ }
+ } else {
+ ch = ibus_keyval_to_unicode (keysym);
+ if (ch)
+ g_string_append_unichar(s, ch);
+ }
+ if (!ch) {
+ g_warning (
"Not found alternative character of compose key 0x%X",
- priv->compose_buffer[hexchars]);
+ priv->compose_buffer[i]);
+ }
}
- ++hexchars;
}
}
@@ -380,7 +427,7 @@ check_hex (IBusEngineSimple *simple,
CHECK_COMPOSE_BUFFER_LENGTH (n_compose);
- priv->tentative_match = 0;
+ g_string_set_size (priv->tentative_match, 0);
priv->tentative_match_len = 0;
str = g_string_new (NULL);
@@ -421,7 +468,8 @@ check_hex (IBusEngineSimple *simple,
}
if (g_unichar_validate (n)) {
- priv->tentative_match = n;
+ g_string_set_size (priv->tentative_match, 0);
+ g_string_append_unichar (priv->tentative_match, n);
priv->tentative_match_len = n_compose;
}
@@ -546,21 +594,31 @@ no_sequence_matches (IBusEngineSimple *simple,
CHECK_COMPOSE_BUFFER_LENGTH (n_compose);
+ priv->in_compose_sequence = FALSE;
+
/* No compose sequences found, check first if we have a partial
* match pending.
*/
- if (priv->tentative_match) {
+ if (priv->tentative_match_len > 0) {
+ guint16 *compose_buffer;
int len = priv->tentative_match_len;
int i;
+ char *str;
- ibus_engine_simple_commit_char (simple, priv->tentative_match);
- priv->compose_buffer[0] = 0;
+ compose_buffer = alloca (sizeof (guint16) * COMPOSE_BUFFER_SIZE);
+ memcpy (compose_buffer,
+ priv->compose_buffer,
+ sizeof (guint16) * COMPOSE_BUFFER_SIZE);
+
+ str = g_strdup (priv->tentative_match->str);
+ ibus_engine_simple_commit_str (simple, str);
+ g_free (str);
ibus_engine_simple_update_preedit_text (simple);
for (i=0; i < n_compose - len - 1; i++) {
ibus_engine_simple_process_key_event (
(IBusEngine *)simple,
- priv->compose_buffer[len + i],
+ compose_buffer[len + i],
0, 0);
}
@@ -571,6 +629,26 @@ no_sequence_matches (IBusEngineSimple *simple,
priv->compose_buffer[0] = 0;
ibus_engine_simple_update_preedit_text (simple);
} else {
+ if (n_compose == 2 && IS_DEAD_KEY (priv->compose_buffer[0])) {
+ gboolean need_space = FALSE;
+ GString *s = g_string_new ("");
+ /* dead keys are never *really* dead */
+ ch = ibus_keysym_to_unicode (priv->compose_buffer[0],
+ FALSE, &need_space);
+ if (ch) {
+ if (need_space)
+ g_string_append_c (s, ' ');
+ g_string_append_unichar (s, ch);
+ }
+ ch = ibus_keyval_to_unicode (priv->compose_buffer[1]);
+ if (ch != 0 && !g_unichar_iscntrl (ch))
+ g_string_append_unichar (s, ch);
+ ibus_engine_simple_commit_str (simple, s->str);
+ g_string_free (s, TRUE);
+ ibus_engine_simple_update_preedit_text (simple);
+ return TRUE;
+ }
+
priv->compose_buffer[0] = 0;
if (n_compose > 1) {
/* Invalid sequence */
@@ -695,19 +773,46 @@ ibus_engine_simple_set_number_on_lookup_table (IBusEngineSimple *simple,
ibus_engine_simple_update_preedit_text (simple);
}
+
static gboolean
ibus_engine_simple_check_all_compose_table (IBusEngineSimple *simple,
int n_compose)
{
IBusEngineSimplePrivate *priv = simple->priv;
+ GSList *tmp_list;
gboolean compose_finish = FALSE;
gboolean compose_match = FALSE;
GString *output = g_string_new ("");
- gboolean does_hit = FALSE;
+ gboolean success = FALSE;
gboolean is_32bit = FALSE;
- GSList *tmp_list;
gunichar *output_chars = NULL;
- gunichar output_char;
+ gunichar output_char = '\0';
+
+ if (n_compose == 2) {
+ /* Special-case deadkey-deadkey sequences.
+ * We are not doing chained deadkeys, so we
+ * want to commit the first key, and contine
+ * preediting with second.
+ */
+ if (IS_DEAD_KEY (priv->compose_buffer[0]) &&
+ IS_DEAD_KEY (priv->compose_buffer[1])) {
+ gboolean need_space = FALSE;
+ gunichar ch = ibus_keysym_to_unicode (priv->compose_buffer[0],
+ FALSE, &need_space);
+ guint16 next = priv->compose_buffer[1];
+ if (ch) {
+ if (need_space)
+ g_string_append_c (output, ' ');
+ g_string_append_unichar (output, ch);
+ ibus_engine_simple_commit_str (simple, output->str);
+ g_string_set_size (output, 0);
+
+ priv->compose_buffer[0] = next;
+ priv->compose_buffer[1] = 0;
+ n_compose = 1;
+ }
+ }
+ }
G_LOCK (global_tables);
tmp_list = global_tables;
@@ -721,7 +826,7 @@ ibus_engine_simple_check_all_compose_table (IBusEngineSimple *simple,
&compose_match,
output,
is_32bit)) {
- does_hit = TRUE;
+ success = TRUE;
break;
}
is_32bit = TRUE;
@@ -733,14 +838,15 @@ ibus_engine_simple_check_all_compose_table (IBusEngineSimple *simple,
&compose_match,
output,
is_32bit)) {
- does_hit = TRUE;
+ success = TRUE;
break;
}
tmp_list = tmp_list->next;
}
G_UNLOCK (global_tables);
- if (does_hit) {
+ if (success) {
+ priv->in_compose_sequence = TRUE;
if (compose_finish) {
if (compose_match) {
if (is_32bit) {
@@ -750,59 +856,89 @@ ibus_engine_simple_check_all_compose_table (IBusEngineSimple *simple,
g_utf8_get_char (output->str));
}
}
+ ibus_engine_simple_update_preedit_text (simple);
+ g_string_free (output, TRUE);
+ return TRUE;
} else if (compose_match) {
- priv->tentative_match = g_utf8_get_char (output->str);
+ g_string_assign (priv->tentative_match, output->str);
priv->tentative_match_len = n_compose;
+ ibus_engine_simple_update_preedit_text (simple);
+ g_string_free (output, TRUE);
+ return TRUE;
}
- ibus_engine_simple_update_preedit_text (simple);
- g_string_free (output, TRUE);
- return TRUE;
}
g_string_free (output, TRUE);
+ output = NULL;
if (ibus_compose_table_compact_check (&ibus_compose_table_compact,
priv->compose_buffer,
n_compose,
&compose_finish,
&output_chars)) {
+ priv->in_compose_sequence = TRUE;
if (compose_finish) {
- ibus_engine_simple_commit_char (simple, *output_chars);
+ if (success) {
+ g_string_append_unichar (priv->tentative_match, *output_chars);
+ priv->tentative_match_len = n_compose;
+ } else {
+ ibus_engine_simple_commit_char (simple, *output_chars);
+ priv->compose_buffer[0] = 0;
+ }
g_free (output_chars);
- priv->compose_buffer[0] = 0;
+ ibus_engine_simple_update_preedit_text (simple);
+ return TRUE;
}
- ibus_engine_simple_update_preedit_text (simple);
- return TRUE;
+ success = TRUE;
}
+ g_free (output_chars);
+ output_chars = NULL;
if (ibus_compose_table_compact_check (&ibus_compose_table_compact_32bit,
priv->compose_buffer,
n_compose,
&compose_finish,
&output_chars)) {
+ priv->in_compose_sequence = TRUE;
if (compose_finish) {
GError *error = NULL;
char *str = g_ucs4_to_utf8 (output_chars, -1, NULL, NULL, &error);
- if (str) {
- ibus_engine_simple_commit_str (simple, str);
- g_free (str);
- } else {
+ if (!str) {
g_warning ("Failed to output multiple characters: %s",
error->message);
g_error_free (error);
+ } else if (success) {
+ g_string_append (priv->tentative_match, str);
+ priv->tentative_match_len = n_compose;
+ } else {
+ ibus_engine_simple_commit_str (simple, str);
+ priv->compose_buffer[0] = 0;
}
- priv->compose_buffer[0] = 0;
+ g_free (str);
+ g_free (output_chars);
+ ibus_engine_simple_update_preedit_text (simple);
+ return TRUE;
}
- g_free (output_chars);
- ibus_engine_simple_update_preedit_text (simple);
- return TRUE;
+ success = TRUE;
}
- g_assert (!output_chars);
+ g_free (output_chars);
+ output_chars = NULL;
if (ibus_check_algorithmically (priv->compose_buffer,
n_compose,
&output_char)) {
+ priv->in_compose_sequence = TRUE;
if (output_char) {
- ibus_engine_simple_commit_char (simple, output_char);
- priv->compose_buffer[0] = 0;
+ if (success) {
+ g_string_append_unichar (priv->tentative_match, output_char);
+ priv->tentative_match_len = n_compose;
+ } else {
+ ibus_engine_simple_commit_char (simple, output_char);
+ priv->compose_buffer[0] = 0;
+ }
+ ibus_engine_simple_update_preedit_text (simple);
+ return TRUE;
}
+ success = TRUE;
+ }
+ if (success) {
ibus_engine_simple_update_preedit_text (simple);
return TRUE;
}
@@ -810,6 +946,7 @@ ibus_engine_simple_check_all_compose_table (IBusEngineSimple *simple,
return FALSE;
}
+
static gboolean
ibus_engine_simple_process_key_event (IBusEngine *engine,
guint keyval,
@@ -841,16 +978,17 @@ ibus_engine_simple_process_key_event (IBusEngine *engine,
if (priv->in_hex_sequence &&
(keyval == IBUS_KEY_Control_L || keyval == IBUS_KEY_Control_R ||
keyval == IBUS_KEY_Shift_L || keyval == IBUS_KEY_Shift_R)) {
- if (priv->tentative_match &&
- g_unichar_validate (priv->tentative_match)) {
- ibus_engine_simple_commit_char (simple, priv->tentative_match);
+ if (priv->tentative_match->len > 0) {
+ char *str = g_strdup (priv->tentative_match->str);
+ ibus_engine_simple_commit_str (simple, str);
+ g_free (str);
ibus_engine_simple_update_preedit_text (simple);
} else if (n_compose == 0) {
priv->modifiers_dropped = TRUE;
} else {
/* invalid hex sequence */
/* FIXME beep_window (event->window); */
- priv->tentative_match = 0;
+ g_string_set_size (priv->tentative_match, 0);
g_clear_pointer (&priv->tentative_emoji, g_free);
priv->in_hex_sequence = FALSE;
priv->in_emoji_sequence = FALSE;
@@ -873,7 +1011,7 @@ ibus_engine_simple_process_key_event (IBusEngine *engine,
} else {
/* invalid hex sequence */
/* FIXME beep_window (event->window); */
- priv->tentative_match = 0;
+ g_string_set_size (priv->tentative_match, 0);
g_clear_pointer (&priv->tentative_emoji, g_free);
priv->in_hex_sequence = FALSE;
priv->in_emoji_sequence = FALSE;
@@ -921,7 +1059,7 @@ ibus_engine_simple_process_key_event (IBusEngine *engine,
else if (is_hex_end) {
/* invalid hex sequence */
// beep_window (event->window);
- priv->tentative_match = 0;
+ g_string_set_size (priv->tentative_match, 0);
g_clear_pointer (&priv->tentative_emoji, g_free);
priv->in_hex_sequence = FALSE;
priv->in_emoji_sequence = FALSE;
@@ -999,7 +1137,8 @@ ibus_engine_simple_process_key_event (IBusEngine *engine,
if (n_compose > 0) {
n_compose--;
priv->compose_buffer[n_compose] = 0;
- priv->tentative_match = 0;
+ g_string_set_size (priv->tentative_match, 0);
+ priv->tentative_match_len = 0;
ibus_engine_simple_check_all_compose_table (simple, n_compose);
return TRUE;
}
@@ -1007,16 +1146,17 @@ ibus_engine_simple_process_key_event (IBusEngine *engine,
/* Check for hex sequence restart */
if (priv->in_hex_sequence && have_hex_mods && is_hex_start) {
- if (priv->tentative_match &&
- g_unichar_validate (priv->tentative_match)) {
- ibus_engine_simple_commit_char (simple, priv->tentative_match);
+ if (priv->tentative_match->len > 0 ) {
+ char *str = g_strdup (priv->tentative_match->str);
+ ibus_engine_simple_commit_str (simple, str);
+ g_free (str);
ibus_engine_simple_update_preedit_text (simple);
}
else {
/* invalid hex sequence */
if (n_compose > 0) {
// FIXME beep_window (event->window);
- priv->tentative_match = 0;
+ g_string_set_size (priv->tentative_match, 0);
priv->in_hex_sequence = FALSE;
priv->compose_buffer[0] = 0;
}
@@ -1044,7 +1184,7 @@ ibus_engine_simple_process_key_event (IBusEngine *engine,
priv->in_hex_sequence = TRUE;
priv->in_emoji_sequence = FALSE;
priv->modifiers_dropped = FALSE;
- priv->tentative_match = 0;
+ g_string_set_size (priv->tentative_match, 0);
g_clear_pointer (&priv->tentative_emoji, g_free);
// g_debug ("Start HEX MODE");
@@ -1058,7 +1198,7 @@ ibus_engine_simple_process_key_event (IBusEngine *engine,
priv->in_hex_sequence = FALSE;
priv->in_emoji_sequence = TRUE;
priv->modifiers_dropped = FALSE;
- priv->tentative_match = 0;
+ g_string_set_size (priv->tentative_match, 0);
g_clear_pointer (&priv->tentative_emoji, g_free);
// g_debug ("Start HEX MODE");
@@ -1068,7 +1208,6 @@ ibus_engine_simple_process_key_event (IBusEngine *engine,
return TRUE;
}
- /* Then, check for compose sequences */
if (priv->in_hex_sequence) {
if (hex_keyval) {
SET_COMPOSE_BUFFER_ELEMENT_NEXT (priv->compose_buffer,
@@ -1133,17 +1272,17 @@ ibus_engine_simple_process_key_event (IBusEngine *engine,
if (have_hex_mods) {
/* space or return ends the sequence, and we eat the key */
if (n_compose > 0 && is_hex_end) {
- if (priv->tentative_match &&
- g_unichar_validate (priv->tentative_match)) {
- ibus_engine_simple_commit_char (simple,
- priv->tentative_match);
- priv->compose_buffer[0] = 0;
+ if (priv->tentative_match->len > 0) {
+ char *str = g_strdup (priv->tentative_match->str);
+ ibus_engine_simple_commit_str (simple, str);
+ g_free (str);
ibus_engine_simple_update_preedit_text (simple);
+ return TRUE;
} else {
// FIXME
/* invalid hex sequence */
// beep_window (event->window);
- priv->tentative_match = 0;
+ g_string_set_size (priv->tentative_match, 0);
priv->in_hex_sequence = FALSE;
priv->compose_buffer[0] = 0;
}
@@ -1234,7 +1373,7 @@ ibus_engine_simple_process_key_event (IBusEngine *engine,
return TRUE;
}
- } else {
+ } else { /* Then, check for compose sequences */
if (ibus_engine_simple_check_all_compose_table (simple, n_compose))
return TRUE;
}
diff --git a/src/ibusenginesimpleprivate.h b/src/ibusenginesimpleprivate.h
index 5479e553..ad93d2d2 100644
--- a/src/ibusenginesimpleprivate.h
+++ b/src/ibusenginesimpleprivate.h
@@ -26,6 +26,12 @@
G_BEGIN_DECLS
+/* Checks if a keysym is a dead key. Dead key keysym values are defined in
+ * ibuskeysyms.h and the first is GDK_KEY_dead_grave.
+ */
+#define IS_DEAD_KEY(k) \
+ ((k) >= IBUS_KEY_dead_grave && (k) <= IBUS_KEY_dead_greek)
+
extern const IBusComposeTableCompactEx ibus_compose_table_compact;
extern const IBusComposeTableCompactEx ibus_compose_table_compact_32bit;
@@ -60,7 +66,8 @@ gboolean ibus_compose_table_compact_check
gboolean *compose_finish,
gunichar **output_chars);
gunichar ibus_keysym_to_unicode (guint16 keysym,
- gboolean combining);
+ gboolean combining,
+ gboolean *need_space);
G_END_DECLS