+static gint
+lookup_result_compare (gconstpointer a,
+ gconstpointer b)
+{
+ const GtkKeyHashEntry *entry_a = a;
+ const GtkKeyHashEntry *entry_b = b;
+ guint modifiers;
+
+ gint n_bits_a = 0;
+ gint n_bits_b = 0;
+
+ modifiers = entry_a->modifiers;
+ while (modifiers)
+ {
+ if (modifiers & 1)
+ n_bits_a++;
+ modifiers >>= 1;
+ }
+
+ modifiers = entry_b->modifiers;
+ while (modifiers)
+ {
+ if (modifiers & 1)
+ n_bits_b++;
+ modifiers >>= 1;
+ }
+
+ return n_bits_a < n_bits_b ? -1 : (n_bits_a == n_bits_b ? 0 : 1);
+
+}
+
+/* Sort a list of results so that matches with less modifiers come
+ * before matches with more modifiers
+ */
+static GSList *
+sort_lookup_results (GSList *slist)
+{
+ return g_slist_sort (slist, lookup_result_compare);
+}
+
+static gint
+lookup_result_compare_by_keyval (gconstpointer a,
+ gconstpointer b)
+{
+ const GtkKeyHashEntry *entry_a = a;
+ const GtkKeyHashEntry *entry_b = b;
+
+ if (entry_a->keyval < entry_b->keyval)
+ return -1;
+ else if (entry_a->keyval > entry_b->keyval)
+ return 1;
+ else
+ return 0;
+}
+
+static GSList *
+sort_lookup_results_by_keyval (GSList *slist)
+{
+ return g_slist_sort (slist, lookup_result_compare_by_keyval);
+}
+
+/* Return true if keyval is defined in keyboard group
+ */
+static gboolean
+keyval_in_group (GdkKeymap *keymap,
+ guint keyval,
+ gint group)
+{
+ GtkKeyHashEntry entry;
+ gint i;
+
+ gdk_keymap_get_entries_for_keyval (keymap,
+ keyval,
+ &entry.keys, &entry.n_keys);
+
+ for (i = 0; i < entry.n_keys; i++)
+ {
+ if (entry.keys[i].group == group)
+ {
+ g_free (entry.keys);
+ return TRUE;
+ }
+ }
+
+ g_free (entry.keys);
+ return FALSE;
+}
+