From c8a43da52631defbd716cc658bd6a9f7e15ac20c Mon Sep 17 00:00:00 2001 From: Mike FABIAN Date: Tue, 8 Aug 2023 17:52:09 +0200 Subject: [PATCH 1/3] Add test case for single char compose sequence --- testsuite/gtk/compose/match | 1 + testsuite/gtk/composetable.c | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/testsuite/gtk/compose/match b/testsuite/gtk/compose/match index 1cb4e74cf5..780a26af47 100644 --- a/testsuite/gtk/compose/match +++ b/testsuite/gtk/compose/match @@ -2,3 +2,4 @@ : "?" : "🥂" : "this is a long replacement string" + : "qq" diff --git a/testsuite/gtk/composetable.c b/testsuite/gtk/composetable.c index 0ee3bac1fb..85a27b0fa7 100644 --- a/testsuite/gtk/composetable.c +++ b/testsuite/gtk/composetable.c @@ -242,6 +242,16 @@ compose_table_match (void) g_assert_true (match); g_assert_cmpstr (output->str, ==, "this is a long replacement string"); + g_string_set_size (output, 0); + + buffer[0] = GDK_KEY_q; + buffer[1] = 0; + ret = gtk_compose_table_check (table, buffer, 1, &finish, &match, output); + g_assert_true (ret); + g_assert_false (finish); + g_assert_true (match); + g_assert_cmpstr (output->str, ==, "qq"); + g_string_free (output, TRUE); g_free (file); } From a0d8678a9cf20c1cf4b901f7204a7e7c89e02ad4 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Mon, 28 Aug 2023 16:38:47 -0400 Subject: [PATCH 2/3] composetable: Accept short compose sequences Followup to 8931169e0026b2db. That commit did not do enough work to actually accept sequences of lenth 1, as pointed by Mike Fabian. --- gtk/gtkcomposetable.c | 23 ++++++++++++++++++++--- gtk/gtkcomposetable.h | 5 +++-- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/gtk/gtkcomposetable.c b/gtk/gtkcomposetable.c index b8842d9731..538003923a 100644 --- a/gtk/gtkcomposetable.c +++ b/gtk/gtkcomposetable.c @@ -1331,11 +1331,28 @@ gtk_compose_table_check (const GtkComposeTable *table, if (!seq_index) return FALSE; - if (n_compose == 1) - return TRUE; - match = FALSE; + if (n_compose == 1) + { + if (seq_index[2] - seq_index[1] > 0) + { + seq = table->data + seq_index[1]; + + value = seq[0]; + + if ((value & (1 << 15)) != 0) + g_string_append (output, &table->char_data[value & ~(1 << 15)]); + else + g_string_append_unichar (output, value); + + if (compose_match) + *compose_match = TRUE; + } + + return TRUE; + } + for (i = n_compose - 1; i < table->max_seq_len; i++) { len = i + 1; diff --git a/gtk/gtkcomposetable.h b/gtk/gtkcomposetable.h index f6665e63c0..4597858f45 100644 --- a/gtk/gtkcomposetable.h +++ b/gtk/gtkcomposetable.h @@ -30,12 +30,13 @@ typedef struct _GtkComposeTableCompact GtkComposeTableCompact; * The first part of the data contains rows of length max_seq_len + 1, * where the first element is the item of the sequence, and the * following elements are offsets to the data for sequences that - * start with the first item of length 2, ..., max_seq_len. + * start with the first item of length 1, ..., max_seq_len. * * The second part of the data contains the rest of the sequence * data. It does not have a fixed stride. For each sequence, we * put seq[2], ..., seq[len - 1], followed by the encoded value - * for this sequence. + * for this sequence. In particular for a sequence of length 1, + * the offset points directly to the value. * * The values are encoded as follows: * From dc2914e1f905fc6c82b1524b1c89fc9368bff62b Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 29 Aug 2023 12:18:49 -0400 Subject: [PATCH 3/3] composetable: Warn for things we can't handle The compose table stores the keyvals to match against in a guint16 array, so it can't handle directly encoded Unicode codepoints (which have a high bit set). Warn if we encounter those. --- gtk/gtkcomposetable.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/gtk/gtkcomposetable.c b/gtk/gtkcomposetable.c index 538003923a..a369abbd90 100644 --- a/gtk/gtkcomposetable.c +++ b/gtk/gtkcomposetable.c @@ -231,7 +231,7 @@ parse_compose_sequence (const char *seq, char *start = words[i]; char *end = strchr (words[i], '>'); char *match; - gunichar codepoint; + guint keyval; if (words[i][0] == '\0') continue; @@ -248,18 +248,24 @@ parse_compose_sequence (const char *seq, if (is_codepoint (match)) { - codepoint = (gunichar) g_ascii_strtoll (match + 1, NULL, 16); - sequence[n] = codepoint; + keyval = gdk_unicode_to_keyval ((gunichar) g_ascii_strtoll (match + 1, NULL, 16)); + if (keyval > 0xffff) + g_warning ("Can't handle >16bit keyvals"); + + sequence[n] = (guint16) keyval; sequence[n + 1] = 0; } else { - codepoint = (gunichar) gdk_keyval_from_name (match); - sequence[n] = codepoint; + keyval = gdk_keyval_from_name (match); + if (keyval > 0xffff) + g_warning ("Can't handle >16bit keyvals"); + + sequence[n] = (guint16) keyval; sequence[n + 1] = 0; } - if (codepoint == GDK_KEY_VoidSymbol) + if (keyval == GDK_KEY_VoidSymbol) g_warning ("Could not get code point of keysym %s", match); g_free (match); n++;