aboutsummaryrefslogtreecommitdiffstats
path: root/addressbook/gui
diff options
context:
space:
mode:
Diffstat (limited to 'addressbook/gui')
-rw-r--r--addressbook/gui/component/select-names/e-select-names-completion.c295
-rw-r--r--addressbook/gui/component/select-names/e-select-names-manager.c7
2 files changed, 146 insertions, 156 deletions
diff --git a/addressbook/gui/component/select-names/e-select-names-completion.c b/addressbook/gui/component/select-names/e-select-names-completion.c
index dbe54e8a6b..8639ca5871 100644
--- a/addressbook/gui/component/select-names/e-select-names-completion.c
+++ b/addressbook/gui/component/select-names/e-select-names-completion.c
@@ -87,86 +87,88 @@ static FILE *out;
*/
typedef gchar *(*BookQuerySExp) (ESelectNamesCompletion *);
-typedef gchar *(*BookQueryMatchTester) (ESelectNamesCompletion *, EDestination *, double *score);
+typedef ECompletionMatch *(*BookQueryMatchTester) (ESelectNamesCompletion *, EDestination *);
-/*
- * Nickname query
- */
-
-static gchar *
-sexp_nickname (ESelectNamesCompletion *comp)
+static void
+our_match_destroy (ECompletionMatch *match)
{
- return g_strdup_printf ("(beginswith \"nickname\" \"%s\")", comp->priv->query_text);
-
+ gtk_object_unref (GTK_OBJECT (match->user_data));
}
-static gint
-e_utf8_strncasecmp (const gchar *p, const gchar *q, gint len)
+static ECompletionMatch *
+make_match (EDestination *dest, const gchar *menu_form, double score)
{
- if (p == NULL || q == NULL) {
- if (p) return +1;
- if (q) return -1;
- return 0;
- }
+ ECompletionMatch *match = g_new0 (ECompletionMatch, 1);
+ e_completion_match_construct (match);
- if (len < 0)
- len = G_MAXINT;
-
- while (*p && *q && len > 0) {
- gunichar cp = g_utf8_get_char (p);
- gunichar cq = g_utf8_get_char (q);
+ e_completion_match_set_text (match, e_destination_get_name (dest), menu_form);
+ match->score = score;
+ match->sort_minor = e_destination_get_email_num (dest);
- if (!(g_unichar_validate (cp)
- && g_unichar_validate (cq)))
- break;
+ match->user_data = dest;
+ gtk_object_ref (GTK_OBJECT (dest));
+
+ match->destroy = our_match_destroy;
- cp = g_unichar_tolower (cp);
- cq = g_unichar_tolower (cq);
+ return match;
+}
- if (cp != cq)
- return (cp < cq) - (cp > cq);
+static void
+emailify_match (ECompletionMatch *match)
+{
+ EDestination *dest = E_DESTINATION (match->user_data);
+ ECard *card = e_destination_get_card (dest);
+ const gchar *email = e_destination_get_email (dest);
+ const gchar *menu_txt = e_completion_match_get_menu_text (match);
+
+ if (card && card->email && e_list_length (card->email) > 1) {
- p = g_utf8_next_char (p);
- q = g_utf8_next_char (q);
- --len;
- }
+ if (email && strstr (menu_txt, email) == NULL) {
+ gchar *tmp = g_strdup_printf ("%s <%s>", menu_txt, email);
+ e_completion_match_set_text (match,
+ e_completion_match_get_match_text (match),
+ tmp);
+ g_free (tmp);
+ }
- if (len) {
- if (*p)
- return +1;
- else if (*q)
- return -1;
+ match->sort_minor = e_destination_get_email_num (dest);
}
-
- return 0;
}
-static gint
-e_utf8_strcasecmp (const gchar *p, const gchar *q)
+/*
+ * Nickname query
+ */
+
+static gchar *
+sexp_nickname (ESelectNamesCompletion *comp)
{
- return e_utf8_strncasecmp (p, q, -1);
-}
+ return g_strdup_printf ("(beginswith \"nickname\" \"%s\")", comp->priv->query_text);
+}
-static gchar *
-match_nickname (ESelectNamesCompletion *comp, EDestination *dest, double *score)
+static ECompletionMatch *
+match_nickname (ESelectNamesCompletion *comp, EDestination *dest)
{
+ ECompletionMatch *match = NULL;
gint len = strlen (comp->priv->query_text);
ECard *card = e_destination_get_card (dest);
+ double score;
if (card->nickname
- && !e_utf8_strncasecmp (comp->priv->query_text, card->nickname, len)) {
+ && !g_utf8_strncasecmp (comp->priv->query_text, card->nickname, len)) {
+ ECompletionMatch *match = g_new0 (ECompletionMatch, 1);
gchar *name = e_card_name_to_string (card->name);
gchar *str;
- *score = len * 10; /* nickname gives 10 points per matching character */
-
+ score = len * 10; /* nickname gives 10 points per matching character */
str = g_strdup_printf ("(%s) %s", card->nickname, name);
+
+ match = make_match (dest, str, score);
g_free (name);
- return str;
+ g_free (str);
}
- return NULL;
+ return match;
}
/*
@@ -179,23 +181,33 @@ sexp_email (ESelectNamesCompletion *comp)
return g_strdup_printf ("(beginswith \"email\" \"%s\")", comp->priv->query_text);
}
-static gchar *
-match_email (ESelectNamesCompletion *comp, EDestination *dest, double *score)
+static ECompletionMatch *
+match_email (ESelectNamesCompletion *comp, EDestination *dest)
{
+ ECompletionMatch *match;
gint len = strlen (comp->priv->query_text);
ECard *card = e_destination_get_card (dest);
const gchar *email = e_destination_get_email (dest);
+ double score;
- if (email && !e_utf8_strncasecmp (comp->priv->query_text, email, len)) {
+ if (email && !g_utf8_strncasecmp (comp->priv->query_text, email, len)) {
+
gchar *name, *str;
- *score = len * 2; /* 2 points for each matching character */
+
+ score = len * 2; /* 2 points for each matching character */
+
name = e_card_name_to_string (card->name);
if (name && *name)
str = g_strdup_printf ("<%s> %s", email, name);
else
str = g_strdup (email);
+
+ match = make_match (dest, str, score);
+
g_free (name);
- return str;
+ g_free (str);
+
+ return match;
}
return NULL;
@@ -235,6 +247,7 @@ sexp_name (ESelectNamesCompletion *comp)
g_free (cpy);
g_free (strv);
+
return query;
}
@@ -258,7 +271,7 @@ match_name_fragment (const gchar *fragment, const gchar *txt)
gint len = strlen (txt);
while (*fragment) {
- if (!e_utf8_strncasecmp (fragment, txt, len))
+ if (!g_utf8_strncasecmp (fragment, txt, len))
return TRUE;
while (*fragment && !isspace ((gint) *fragment))
@@ -270,14 +283,17 @@ match_name_fragment (const gchar *fragment, const gchar *txt)
return FALSE;
}
-static gchar *
-match_name (ESelectNamesCompletion *comp, EDestination *dest, double *score)
+static ECompletionMatch *
+match_name (ESelectNamesCompletion *comp, EDestination *dest)
{
+ ECompletionMatch *final_match = NULL;
+ gchar *menu_text = NULL;
ECard *card;
gchar *cpy, **strv;
const gchar *email;
gint len, i, match_len = 0;
gint match = 0, first_match = 0;
+ double score = 0;
gboolean have_given, have_additional, have_family;
card = e_destination_get_card (dest);
@@ -330,28 +346,31 @@ match_name (ESelectNamesCompletion *comp, EDestination *dest, double *score)
}
- *score = match_len * 3; /* three points per match character */
+ score = match_len * 3; /* three points per match character */
if (card->nickname) {
/* We massively boost the score if the nickname exists and is the same as one of the "real" names. This keeps the
nickname from matching ahead of the real name for this card. */
len = strlen (card->nickname);
- if ((card->name->given && !e_utf8_strncasecmp (card->name->given, card->nickname, MIN (strlen (card->name->given), len)))
- || (card->name->family && !e_utf8_strncasecmp (card->name->family, card->nickname, MIN (strlen (card->name->family), len)))
- || (card->name->additional && !e_utf8_strncasecmp (card->name->additional, card->nickname, MIN (strlen (card->name->additional), len))))
- *score *= 100;
+ if ((card->name->given && !g_utf8_strncasecmp (card->name->given, card->nickname, MIN (strlen (card->name->given), len)))
+ || (card->name->family && !g_utf8_strncasecmp (card->name->family, card->nickname, MIN (strlen (card->name->family), len)))
+ || (card->name->additional && !g_utf8_strncasecmp (card->name->additional, card->nickname, MIN (strlen (card->name->additional), len))))
+ score *= 100;
}
+#if 0
+ /* This leads to some pretty counter-intuitive results, so I'm disabling it. */
email = e_destination_get_email (dest);
if (email) {
/* Do the same for the email address. */
gchar *at = strchr (email, '@');
len = at ? at-email : strlen (email);
- if ((card->name->given && !e_utf8_strncasecmp (card->name->given, email, MIN (strlen (card->name->given), len)))
- || (card->name->family && !e_utf8_strncasecmp (card->name->family, email, MIN (strlen (card->name->family), len)))
- || (card->name->additional && !e_utf8_strncasecmp (card->name->additional, email, MIN (strlen (card->name->additional), len))))
- *score *= 100;
+ if ((card->name->given && !g_utf8_strncasecmp (card->name->given, email, MIN (strlen (card->name->given), len)))
+ || (card->name->family && !g_utf8_strncasecmp (card->name->family, email, MIN (strlen (card->name->family), len)))
+ || (card->name->additional && !g_utf8_strncasecmp (card->name->additional, email, MIN (strlen (card->name->additional), len))))
+ score *= 100;
}
+#endif
have_given = card->name->given && *card->name->given;
have_additional = card->name->additional && *card->name->additional;
@@ -360,41 +379,46 @@ match_name (ESelectNamesCompletion *comp, EDestination *dest, double *score)
if (first_match == MATCHED_GIVEN_NAME) {
if (have_family)
- return g_strdup_printf ("%s %s", card->name->given, card->name->family);
+ menu_text = g_strdup_printf ("%s %s", card->name->given, card->name->family);
else
- return g_strdup_printf (card->name->given);
+ menu_text = g_strdup_printf (card->name->given);
} else if (first_match == MATCHED_ADDITIONAL_NAME) {
if (have_family) {
- return g_strdup_printf ("%s, %s%s%s",
- card->name->family,
- have_given ? card->name->given : "",
- have_given ? " " : "",
- card->name->additional);
+ menu_text = g_strdup_printf ("%s, %s%s%s",
+ card->name->family,
+ have_given ? card->name->given : "",
+ have_given ? " " : "",
+ card->name->additional);
} else {
- return g_strdup_printf ("%s%s%s",
- have_given ? card->name->given : "",
- have_given ? " " : "",
- card->name->additional);
+ menu_text = g_strdup_printf ("%s%s%s",
+ have_given ? card->name->given : "",
+ have_given ? " " : "",
+ card->name->additional);
}
} else if (first_match == MATCHED_FAMILY_NAME) {
if (have_given)
- return g_strdup_printf ("%s, %s %s",
- card->name->family,
- card->name->given,
- have_additional ? card->name->additional : "");
+ menu_text = g_strdup_printf ("%s, %s %s",
+ card->name->family,
+ card->name->given,
+ have_additional ? card->name->additional : "");
else
- return g_strdup_printf (card->name->family);
+ menu_text = g_strdup_printf (card->name->family);
+ }
+
+ if (menu_text) {
+ final_match = make_match (dest, menu_text, score);
+ g_free (menu_text);
}
- return NULL;
+ return final_match;
}
/*
@@ -407,8 +431,8 @@ sexp_initials (ESelectNamesCompletion *comp)
return NULL;
}
-static gchar *
-match_initials (ESelectNamesCompletion *comp, EDestination *dest, double *score)
+static ECompletionMatch *
+match_initials (ESelectNamesCompletion *comp, EDestination *dest)
{
return NULL;
}
@@ -480,72 +504,38 @@ book_query_sexp (ESelectNamesCompletion *comp)
* Sweep across all of our query rules and find the best score/match
* string that applies to a given destination.
*/
-static gchar *
-book_query_score (ESelectNamesCompletion *comp, EDestination *dest, double *score)
+static ECompletionMatch *
+book_query_score (ESelectNamesCompletion *comp, EDestination *dest)
{
- double best_score = -1;
- gchar *best_string = NULL;
+ ECompletionMatch *best_match = NULL;
gint i;
- g_return_val_if_fail (score, NULL);
- *score = -1;
-
g_return_val_if_fail (comp && E_IS_SELECT_NAMES_COMPLETION (comp), NULL);
g_return_val_if_fail (dest && E_IS_DESTINATION (dest), NULL);
for (i=0; i<book_query_count; ++i) {
- double this_score = -1;
- gchar *this_string = NULL;
+
+ ECompletionMatch *this_match = NULL;
if (book_queries[i].primary || !comp->priv->primary_only) {
if (book_queries[i].tester && e_destination_get_card (dest))
- this_string = book_queries[i].tester (comp, dest, &this_score);
- if (this_string) {
- if (this_score > best_score) {
- g_free (best_string);
- best_string = this_string;
- best_score = this_score;
+ this_match = book_queries[i].tester (comp, dest);
+
+ if (this_match) {
+ if (best_match == NULL || this_match->score > best_match->score) {
+ e_completion_match_unref (best_match);
+ best_match = this_match;
} else {
- g_free (this_string);
+ e_completion_match_unref (this_match);
}
}
}
}
- /* If this destination corresponds to a card w/ multiple addresses, and if the
- address isn't already in the string, append it. */
- if (best_string) {
- ECard *card = e_destination_get_card (dest);
- if (e_list_length (card->email) > 1) {
- ECardSimple *simp;
- const gchar *email = e_destination_get_email (dest);
- const gchar *simp_email;
-
- if (email && strstr (best_string, email) == NULL) {
- gchar *tmp = g_strdup_printf ("%s <%s>", best_string, email);
- g_free (best_string);
- best_string = tmp;
- }
+ if (best_match)
+ emailify_match (best_match);
- /* Give a small bonus to the primary/secondary e-mail address, so that they will
- always come in the correct order in the listing. */
- if (email) {
- simp = e_card_simple_new (card);
- simp_email = e_card_simple_get_email (simp, E_CARD_SIMPLE_EMAIL_ID_EMAIL);
- if (simp_email && !e_utf8_strcasecmp (simp_email, email)) {
- best_score += 0.2;
- }
- simp_email = e_card_simple_get_email (simp, E_CARD_SIMPLE_EMAIL_ID_EMAIL_2);
- if (simp_email && !e_utf8_strcasecmp (simp_email, email)) {
- best_score += 0.1;
- }
- gtk_object_unref (GTK_OBJECT (simp));
- }
- }
- }
-
- *score = best_score;
- return best_string;
+ return best_match;
}
static void
@@ -559,24 +549,20 @@ book_query_process_card_list (ESelectNamesCompletion *comp, const GList *cards)
for (i=0; i<e_list_length (card->email); ++i) {
EDestination *dest = e_destination_new ();
const gchar *email;
- gchar *match_text;
- double score = -1;
+ ECompletionMatch *match;
e_destination_set_card (dest, card, i);
email = e_destination_get_email (dest);
if (email && *email) {
- match_text = book_query_score (comp, dest, &score);
- if (match_text && score > 0) {
-
- e_completion_found_match_full (E_COMPLETION (comp), match_text, score, dest,
- (GtkDestroyNotify) gtk_object_unref);
+ match = book_query_score (comp, dest);
+ if (match && match->score > 0) {
+ e_completion_found_match (E_COMPLETION (comp), match);
} else {
- gtk_object_unref (GTK_OBJECT (dest));
+ e_completion_match_unref (match);
}
- g_free (match_text);
- } else {
+
gtk_object_unref (GTK_OBJECT (dest));
}
}
@@ -956,7 +942,7 @@ e_select_names_completion_do_query (ESelectNamesCompletion *comp, const gchar *q
can_reuse_cached_cards = (comp->priv->cached_query_text
&& (strlen (comp->priv->cached_query_text) <= strlen (clean))
- && !e_utf8_strncasecmp (comp->priv->cached_query_text, clean, strlen (comp->priv->cached_query_text)));
+ && !g_utf8_strncasecmp (comp->priv->cached_query_text, clean, strlen (comp->priv->cached_query_text)));
if (can_reuse_cached_cards) {
@@ -1012,7 +998,7 @@ search_override_check (SearchOverride *over, const gchar *text)
if (over == NULL || text == NULL)
return FALSE;
- return !e_utf8_strcasecmp (over->trigger, text);
+ return !g_utf8_strcasecmp (over->trigger, text);
}
@@ -1055,11 +1041,14 @@ e_select_names_completion_begin (ECompletion *comp, const gchar *text, gint pos,
if (search_override_check (&(override[j]), str)) {
gint k;
- for (k=0; override[j].text[k]; ++k)
- e_completion_found_match (comp, override[j].text[k]);
-
- if (out)
- fprintf (out, "aborting on override \"%s\"\n", override[j].trigger);
+ for (k=0; override[j].text[k]; ++k) {
+ ECompletionMatch *match = g_new (ECompletionMatch, 1);
+ e_completion_match_construct (match);
+ e_completion_match_set_text (match, text, override[j].text[k]);
+ match->score = 1;
+ e_completion_found_match (comp, match);
+ }
+
e_completion_end_search (comp);
return;
}
diff --git a/addressbook/gui/component/select-names/e-select-names-manager.c b/addressbook/gui/component/select-names/e-select-names-manager.c
index 6c06624918..9361cfa836 100644
--- a/addressbook/gui/component/select-names/e-select-names-manager.c
+++ b/addressbook/gui/component/select-names/e-select-names-manager.c
@@ -267,17 +267,18 @@ entry_destroyed(EEntry *entry, ESelectNamesManager *manager)
}
static void
-completion_handler (EEntry *entry, const gchar *text, gpointer user_data)
+completion_handler (EEntry *entry, ECompletionMatch *match)
{
ESelectNamesModel *snm;
EDestination *dest;
gint i, pos, start_pos, len;
- if (user_data == NULL)
+ if (match == NULL || match->user_data == NULL)
return;
+
snm = E_SELECT_NAMES_MODEL (gtk_object_get_data (GTK_OBJECT (entry), "select_names_model"));
- dest = E_DESTINATION (user_data);
+ dest = E_DESTINATION (match->user_data);
/* Sometimes I really long for garbage collection. Reference
counting makes you feel 31337, but sometimes it is just a