composetable: Add api to check tables

This copies the check_table code from gtkimcontextsimple.c,
in order to have an api for tests.
This commit is contained in:
Matthias Clasen 2021-02-01 19:40:22 -05:00
parent 569294070b
commit 9ebf3fac73
2 changed files with 117 additions and 7 deletions

View File

@ -853,3 +853,106 @@ gtk_compose_table_list_add_file (GSList *compose_tables,
gtk_compose_table_save_cache (compose_table);
return g_slist_prepend (compose_tables, compose_table);
}
static int
compare_seq (const void *key, const void *value)
{
int i = 0;
const guint16 *keysyms = key;
const guint16 *seq = value;
while (keysyms[i])
{
if (keysyms[i] < seq[i])
return -1;
else if (keysyms[i] > seq[i])
return 1;
i++;
}
return 0;
}
/*
* gtk_compose_table_check:
* @table: the table to check
* @compose_buffer: the key vals to match
* @n_compose: number of non-zero key vals in @compose_buffer
* @compose_finish: (out): return location for whether there may be longer matches
* @compose_match: (out): return location for whether there is a match
* @output_value: (out): return location for the match value
*
* Looks for matches for a key sequence in @table.
*
* Returns: %TRUE if there were any matches, %FALSE otherwise
*/
gboolean
gtk_compose_table_check (const GtkComposeTable *table,
guint16 *compose_buffer,
int n_compose,
gboolean *compose_finish,
gboolean *compose_match,
gunichar *output_value)
{
int row_stride = table->max_seq_len + 2;
guint16 *seq;
*compose_finish = FALSE;
*compose_match = FALSE;
*output_value = 0;
/* 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.
*/
if (n_compose > table->max_seq_len)
return FALSE;
seq = bsearch (compose_buffer,
table->data, table->n_seqs,
sizeof (guint16) * row_stride,
compare_seq);
if (seq)
{
guint16 *prev_seq;
/* Back up to the first sequence that matches to make sure
* we find the exact match if there is one.
*/
while (seq > table->data)
{
prev_seq = seq - row_stride;
if (compare_seq (compose_buffer, prev_seq) != 0)
break;
seq = prev_seq;
}
if (n_compose == table->max_seq_len ||
seq[n_compose] == 0) /* complete sequence */
{
guint16 *next_seq;
*output_value = 0x10000 * seq[table->max_seq_len] + seq[table->max_seq_len + 1];
*compose_match = TRUE;
/* We found a tentative match. See if there are any longer
* sequences containing this subsequence
*/
next_seq = seq + row_stride;
if (next_seq < table->data + row_stride * table->n_seqs)
{
if (compare_seq (compose_buffer, next_seq) == 0)
return TRUE;
}
*compose_finish = TRUE;
return TRUE;
}
return TRUE;
}
return FALSE;
}

View File

@ -43,13 +43,20 @@ struct _GtkComposeTableCompact
};
GtkComposeTable * gtk_compose_table_new_with_file (const char *compose_file);
GSList *gtk_compose_table_list_add_array (GSList *compose_tables,
GSList * gtk_compose_table_list_add_array (GSList *compose_tables,
const guint16 *data,
int max_seq_len,
int n_seqs);
GSList *gtk_compose_table_list_add_file (GSList *compose_tables,
GSList * gtk_compose_table_list_add_file (GSList *compose_tables,
const char *compose_file);
gboolean gtk_compose_table_check (const GtkComposeTable *table,
guint16 *compose_buffer,
int n_compose,
gboolean *compose_finish,
gboolean *compose_match,
gunichar *output_value);
G_END_DECLS
#endif /* __GTK_COMPOSETABLE_H__ */