44 static void quickfill_insert_recursive (QuickFill *qf,
const char *text,
int len,
45 const char* next_char, QuickFillSort sort);
47 static void gnc_quickfill_remove_recursive (QuickFill *qf,
const gchar *text,
48 gint depth, QuickFillSort sort);
51 static QofLogModule log_module = GNC_MOD_REGISTER;
57 gnc_quickfill_new (
void)
61 if (
sizeof (guint) <
sizeof (gunichar))
63 PWARN (
"Can't use quickfill");
67 qf = g_new (QuickFill, 1);
72 qf->matches = g_hash_table_new (g_direct_hash, g_direct_equal);
81 destroy_helper (gpointer key, gpointer value, gpointer data)
83 gnc_quickfill_destroy (value);
88 gnc_quickfill_destroy (QuickFill *qf)
93 g_hash_table_foreach (qf->matches, (GHFunc)destroy_helper, NULL);
94 g_hash_table_destroy (qf->matches);
106 gnc_quickfill_purge (QuickFill *qf)
111 g_hash_table_foreach_remove (qf->matches, destroy_helper, NULL);
137 guint key = g_unichar_toupper (uc);
139 if (NULL == qf)
return NULL;
141 DEBUG (
"xaccGetQuickFill(): index = %u\n", key);
143 return g_hash_table_lookup (qf->matches, GUINT_TO_POINTER (key));
151 const char *str,
int len)
156 if (NULL == qf)
return NULL;
157 if (NULL == str)
return NULL;
160 while (*c && (len > 0))
165 uc = g_utf8_get_char (c);
168 c = g_utf8_next_char (c);
181 if (NULL == qf)
return NULL;
182 if (NULL == str)
return NULL;
191 unique_len_helper (gpointer key, gpointer value, gpointer data)
193 QuickFill **qf_p = data;
211 count = g_hash_table_size (qf->matches);
216 g_hash_table_foreach (qf->matches, unique_len_helper, &qf);
231 gchar *normalized_str;
234 if (NULL == qf)
return;
235 if (NULL == text)
return;
238 normalized_str = g_utf8_normalize (text, -1, G_NORMALIZE_NFC);
239 len = g_utf8_strlen (text, -1);
240 quickfill_insert_recursive (qf, normalized_str, len, normalized_str, sort);
241 g_free (normalized_str);
248 quickfill_insert_recursive (QuickFill *qf,
const char *text,
int len,
249 const char *next_char, QuickFillSort sort)
254 gunichar key_char_uc;
259 if ((text == NULL) || (*next_char ==
'\0'))
263 key_char_uc = g_utf8_get_char (next_char);
264 key = g_unichar_toupper (key_char_uc);
266 match_qf = g_hash_table_lookup (qf->matches, GUINT_TO_POINTER (key));
267 if (match_qf == NULL)
269 match_qf = gnc_quickfill_new ();
270 g_hash_table_insert (qf->matches, GUINT_TO_POINTER (key), match_qf);
273 old_text = match_qf->text;
277 case QUICKFILL_ALPHA:
278 if (old_text && (g_utf8_collate (text, old_text) >= 0))
285 if (old_text == NULL)
287 match_qf->text = g_strdup(text);
293 if ((len > match_qf->len) &&
294 (strncmp(text, old_text, strlen(old_text)) == 0))
298 match_qf->text = g_strdup(text);
303 quickfill_insert_recursive (match_qf, text, len, g_utf8_next_char (next_char), sort);
310 gnc_quickfill_remove (QuickFill *qf,
const gchar *text, QuickFillSort sort)
312 gchar *normalized_str;
314 if (qf == NULL)
return;
315 if (text == NULL)
return;
317 normalized_str = g_utf8_normalize (text, -1, G_NORMALIZE_NFC);
318 gnc_quickfill_remove_recursive (qf, normalized_str, 0, sort);
319 g_free (normalized_str);
332 best_text_helper (gpointer key, gpointer value, gpointer user_data)
334 QuickFill *qf = value;
337 if (best->text == NULL)
340 best->text = qf->text;
343 else if (best->text == QUICKFILL_LIFO)
349 else if (g_utf8_collate (qf->text, best->text) < 0)
352 best->text = qf->text;
359 gnc_quickfill_remove_recursive (QuickFill *qf,
const gchar *text, gint depth,
369 if (depth < g_utf8_strlen (text, -1))
374 gunichar key_char_uc;
377 key_char = g_utf8_offset_to_pointer (text, depth);
378 key_char_uc = g_utf8_get_char (key_char);
379 key = g_unichar_toupper (key_char_uc);
381 match_qf = g_hash_table_lookup (qf->matches, GUINT_TO_POINTER (key));
385 gnc_quickfill_remove_recursive (match_qf, text, depth + 1, sort);
387 if (match_qf->text == NULL)
390 g_hash_table_remove (qf->matches, GUINT_TO_POINTER (key));
391 gnc_quickfill_destroy (match_qf);
397 child_text = match_qf->text;
398 child_len = match_qf->len;
403 if (qf->text == NULL)
406 if (strcmp (text, qf->text) == 0)
410 gchar *best_text = NULL;
413 if (child_text != NULL)
416 best_text = child_text;
417 best_len = child_len;
422 if (g_hash_table_size (qf->matches) != 0)
429 g_hash_table_foreach (qf->matches, (GHFunc) best_text_helper, &bts);
430 best_text = bts.text;
431 best_len = (best_text == NULL) ? 0 : g_utf8_strlen (best_text, -1);
437 if (best_text != NULL)
439 qf->text = g_strdup(best_text);
void gnc_quickfill_insert(QuickFill *qf, const char *text, QuickFillSort sort)
Add the string "text" to the collection of searchable strings.
QuickFill * gnc_quickfill_get_char_match(QuickFill *qf, gunichar uc)
Return the subnode of the tree whose strings all hold 'c' as the next letter.
utility functions for the GnuCash UI
#define DEBUG(format, args...)
Print a debugging message.
#define PWARN(format, args...)
Log a warning.
QuickFill * gnc_quickfill_get_string_len_match(QuickFill *qf, const char *str, int len)
Same as gnc_quickfill_get_string_match(), except that the string length is explicitly specified...
QuickFill * gnc_quickfill_get_string_match(QuickFill *qf, const char *str)
Return a subnode in the tree whose strings all match the string 'str' as the next substring...
All type declarations for the whole Gnucash engine.
const char * gnc_quickfill_string(QuickFill *qf)
For the given node 'qf', return the best-guess matching string.
QuickFill is used to auto-complete typed user entries.
QuickFill * gnc_quickfill_get_unique_len_match(QuickFill *qf, int *length)
Walk a 'unique' part of the QuickFill tree.