diff options
author | Claudio Saavedra <csaavedra@igalia.com> | 2010-04-27 12:23:12 +0300 |
---|---|---|
committer | Claudio Saavedra <csaavedra@igalia.com> | 2010-06-01 17:45:24 +0300 |
commit | 622634ebf812dac6f93b653b575610745d60bfd8 (patch) | |
tree | 5a73d77ee467370d35ba18766e30fa3292a42701 | |
parent | 40d712d9446feefd0839e84333c715d8ad3568f0 (diff) |
Add and use new iconv based matching methods
These methods allow for more complete matching rules, including for
example the polish Ł. Use them now in the HildonTouchSelector live
search.
Fixes: MB#9948 (Contact quick search entering L does not recognize Polish "Ł")
Fixes: NB#165083 (Contact quick search entering L does not recognize Polish "Ł")
-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); |