diff options
-rw-r--r-- | doc/hildon-sections.txt | 2 | ||||
-rw-r--r-- | hildon/hildon-helper.c | 65 | ||||
-rw-r--r-- | hildon/hildon-helper.h | 7 | ||||
-rw-r--r-- | hildon/hildon-touch-selector.c | 14 |
4 files changed, 82 insertions, 6 deletions
diff --git a/doc/hildon-sections.txt b/doc/hildon-sections.txt index 61df558..2297813 100644 --- a/doc/hildon-sections.txt +++ b/doc/hildon-sections.txt @@ -1334,6 +1334,8 @@ hildon_helper_set_thumb_scrollbar hildon_format_file_size_for_display hildon_helper_strip_string hildon_helper_utf8_strstrcasedecomp_needle_stripped +hildon_helper_normalize_string +hildon_helper_smart_match </SECTION> <SECTION> diff --git a/hildon/hildon-helper.c b/hildon/hildon-helper.c index 5dd65c9..76b6596 100644 --- a/hildon/hildon-helper.c +++ b/hildon/hildon-helper.c @@ -37,6 +37,7 @@ #include <config.h> #endif +#define _GNU_SOURCE #include <string.h> #include "hildon-helper.h" #include "hildon-banner.h" @@ -731,3 +732,67 @@ hildon_helper_strip_string (const gchar *string) return nuni; } + +/** + * hildon_helper_normalize_string: + * @string: a string + * + * Transform a string into an ascii equivalent representation. + * This is necessary for hildon_helper_smart_match() to work properly. + * + * Returns: a newly allocated string. + **/ +gchar * +hildon_helper_normalize_string (const gchar *string) +{ + gchar *str = g_convert (string, -1, "ascii//translit", "utf-8", NULL, NULL, NULL); + + return str; +} + +/** + * hildon_helper_smart_match: + * @haystack: a string where to find a match + * @needle: what to find + * + * Searches for the first occurence of @needle in @haystack. The search + * is performed only in the first alphanumeric character after a + * sequence of non-alphanumeric ones. This allows smart matching of words + * inside more complex strings. + * + * If @haystack itself doesn't start with an alphanumeric character, + * then the search is equivalent to strcasecmp(). + * + * To make the best of this method, it is recommended that both the needle + * and the haystack are already normalized as ASCII strings. For this, you + * should call hildon_helper_normalize_string() on both strings. + * + * Returns: a pointer to the first occurence of @needle in @haystack or %NULL + * if not found + **/ +gchar * +hildon_helper_smart_match (const gchar *haystack, const gchar *needle) +{ + if (haystack == NULL) return NULL; + if (needle == NULL) return NULL; + if (strlen (haystack) == 0) return NULL; + + gboolean skip_separators = g_ascii_isalnum (needle[0]); + + if (skip_separators) { + gint i = 0; + while (haystack[i] != '\0') { + while (haystack[i] != '\0' && !g_ascii_isalnum (haystack[i])) + i++; + if (g_ascii_strncasecmp (haystack + i, needle, strlen (needle)) == 0) { + return (gchar *)haystack + i; + } + while (g_ascii_isalnum (haystack[i])) + i++; + } + } else { + return strcasestr (haystack, needle); + } + + return NULL; +} diff --git a/hildon/hildon-helper.h b/hildon/hildon-helper.h index 8aad4b3..77e344d 100644 --- a/hildon/hildon-helper.h +++ b/hildon/hildon-helper.h @@ -69,6 +69,13 @@ hildon_helper_utf8_strstrcasedecomp_needle_stripped (const gchar *haystack, gunichar * hildon_helper_strip_string (const gchar *string); +gchar * +hildon_helper_normalize_string (const gchar *string); + +gchar * +hildon_helper_smart_match (const gchar *haystack, + const gchar *needle); + G_END_DECLS #endif /* __HILDON_HELPER_H__ */ diff --git a/hildon/hildon-touch-selector.c b/hildon/hildon-touch-selector.c index 876e47f..96d09d8 100644 --- a/hildon/hildon-touch-selector.c +++ b/hildon/hildon-touch-selector.c @@ -1004,7 +1004,7 @@ hildon_live_search_visible_func (GtkTreeModel *model, gpointer userdata) { gboolean visible = TRUE; - gchar *string; + gchar *string, *string_ascii; GSList *list_iter; HildonTouchSelectorColumn *col; HildonTouchSelector *selector; @@ -1014,15 +1014,17 @@ hildon_live_search_visible_func (GtkTreeModel *model, gint text_column = GPOINTER_TO_INT (col->priv->text_column); gtk_tree_model_get (model, iter, text_column, &string, -1); + string_ascii = hildon_helper_normalize_string (string); list_iter = selector->priv->norm_tokens; while (visible && list_iter) { - visible = (string != NULL && - hildon_helper_utf8_strstrcasedecomp_needle_stripped (string, - (gunichar *)list_iter->data) != NULL); + visible = (string_ascii != NULL && + hildon_helper_smart_match (string_ascii, + (const gchar *)list_iter->data)); list_iter = list_iter->next; } g_free (string); + g_free (string_ascii); return visible; } @@ -1034,7 +1036,7 @@ on_live_search_refilter (HildonLiveSearch *livesearch, HildonTouchSelector *selector = HILDON_TOUCH_SELECTOR (userdata); gchar **tokens = g_strsplit (hildon_live_search_get_text (livesearch), " ", -1); - gunichar *token; + gchar *token; gint i; if (selector->priv->norm_tokens != NULL) { @@ -1044,7 +1046,7 @@ on_live_search_refilter (HildonLiveSearch *livesearch, } for (i = 0; tokens [i] != NULL; i++) { - token = hildon_helper_strip_string (tokens[i]); + token = hildon_helper_normalize_string (tokens[i]); if (token != NULL) selector->priv->norm_tokens = g_slist_prepend (selector->priv->norm_tokens, token); |