aboutsummaryrefslogtreecommitdiffstats
path: root/addressbook/backend/ebook/e-card.c
diff options
context:
space:
mode:
authorJon Trowbridge <trow@ximian.com>2001-03-16 16:16:29 +0800
committerJon Trowbridge <trow@src.gnome.org>2001-03-16 16:16:29 +0800
commit57de6972c845dbae49717a4520aeed75f88f0078 (patch)
treef58e45cdbb09793d8a09506af00c70b1ca63a389 /addressbook/backend/ebook/e-card.c
parent403205b15e9f14472711ee115cae17031eb4ce7b (diff)
downloadgsoc2013-evolution-57de6972c845dbae49717a4520aeed75f88f0078.tar.gz
gsoc2013-evolution-57de6972c845dbae49717a4520aeed75f88f0078.tar.zst
gsoc2013-evolution-57de6972c845dbae49717a4520aeed75f88f0078.zip
Added addressbook querying and "cardification" functions, which are turned
2001-03-15 Jon Trowbridge <trow@ximian.com> * gui/component/e-address-widget.c: Added addressbook querying and "cardification" functions, which are turned off by default for now because of addressbook bugs. Added a popup menu option to turn queries on, so that others can enjoy the thrill of massive flaming death. * gui/component/addressbook-factory.c (main): Made warnings always be fatal. * backend/pas/pas-book-view.c: Added some debugging spew. * backend/pas/pas-backend-file.c (pas_backend_file_search): Added a little experimental code to try to make file searches scale better. #if 0/#endif-ed out for now. * contact-editor/e-contact-quick-add.c: #included e-book-util.h. * backend/ebook/e-card.c (e_card_name_match_string): Added. Looser name-matching function. (e_card_email_match_string): Added. Loose e-mail matching. * backend/ebook/e-book-view-listener.c (e_book_view_listener_check_queue): Added code to cause us to abort rather than get trapped in a 100%-CPU-consuming loop in certain situations. Now we just need to figure out how to avoid these situations altogether. * backend/ebook/e-book-util.c: Added. Now contains the simple query stuff and the open local addressbook functions. * backend/ebook/e-book.c: Moved simple query stuff and open local addressbook functions into e-book-util.c. 2001-03-15 Jon Trowbridge <trow@ximian.com> * wombat.c (main): If we can't initialize a service on startup, tell us which one before terminating. svn path=/trunk/; revision=8754
Diffstat (limited to 'addressbook/backend/ebook/e-card.c')
-rw-r--r--addressbook/backend/ebook/e-card.c202
1 files changed, 202 insertions, 0 deletions
diff --git a/addressbook/backend/ebook/e-card.c b/addressbook/backend/ebook/e-card.c
index 12877d3646..8c1f7b1905 100644
--- a/addressbook/backend/ebook/e-card.c
+++ b/addressbook/backend/ebook/e-card.c
@@ -9,6 +9,7 @@
*/
#include <config.h>
+#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -1348,6 +1349,154 @@ e_card_name_from_string(const char *full_name)
return name;
}
+
+/* This *so* doesn't belong here... at least not implemented in a
+ sucky way like this. But by getting it in here now, I can fix it
+ up w/o adding a new feature when we are in feature freeze. :-) */
+
+/* This is very Anglocentric. Maybe it should be by locale? */
+static gchar *name_synonyms[][2] = {
+ { "Jon", "John" }, /* Ah, the hacker's perogative */
+ { "Jon", "Jonathan" },
+ { "Daniel", "Dan" },
+ { "Joseph", "Joe" },
+ { "Robert", "Rob" },
+ { "Robert", "Bob" },
+ { "Richard", "Rich" },
+ { "Richard", "Dick" },
+ { "William", "Will" },
+ { "William", "Bill" },
+ { "Anthony", "Tony" },
+ { "Steven", "Steve" },
+ { "Michael", "Mike" },
+ { "Douglas", "Doug" },
+ { "Sidney", "Sid" },
+ { "Eric", "Erik" },
+ { "Chris", "Christopher" },
+ { "Chris", "Christine" },
+ { "Chris", "Christy" },
+ { "Elizabeth", "Liz" },
+ { "Jeff", "Geoff" },
+ { "Jeff", "Jeffrey" },
+ { "Jeff", "Geoffrey" },
+ { "Jim", "James" },
+ { "Abigal", "Abby" },
+ { "Amanda", "Amy" },
+ { "Amanda", "Manda" },
+ { "Di", "Diana" },
+ { "Di", "Diane" },
+ { "Maxine", "Max" },
+ { "Rebecca", "Becca" },
+ { "Rebecca", "Becky" },
+ { "Jennifer", "Jen" },
+ { "Jennifer", "Jenny" },
+ /* We could go on and on... */
+ { NULL, NULL }
+};
+
+static gboolean
+name_fragment_match (const gchar *a, const gchar *b)
+{
+ gint i;
+ gboolean nickname_match = FALSE;
+
+ if (!g_strcasecmp (a, b))
+ return TRUE;
+
+ /* Check for nicknames. Yes, the linear search blows. */
+ for (i=0; name_synonyms[i][0]; ++i) {
+ if (!g_strcasecmp (name_synonyms[i][1], a)) {
+ a = name_synonyms[i][0];
+ nickname_match = TRUE;
+ break;
+ }
+ }
+
+ for (i=0; name_synonyms[i][0]; ++i) {
+ if (!g_strcasecmp (name_synonyms[i][1], b)) {
+ b = name_synonyms[i][0];
+ nickname_match = TRUE;
+ break;
+ }
+ }
+
+ return nickname_match && !g_strcasecmp (a, b);
+}
+
+gboolean
+e_card_name_match_string (const ECardName *name, const gchar *str)
+{
+ gchar *cpy, *name_str;
+ gchar **strv, **namev;
+ gint i, j, match_count;
+ gboolean matched = FALSE;
+
+ g_return_val_if_fail (name != NULL, FALSE);
+ g_return_val_if_fail (str != NULL, FALSE);
+
+ cpy = g_strdup (str);
+ strv = g_strsplit (cpy, " ", 0);
+ for (i=0; strv[i]; ++i)
+ g_strstrip (strv[i]);
+
+ name_str = e_card_name_to_string (name);
+ namev = g_strsplit (name_str, " ", 0);
+ for (i=0; namev[i]; ++i)
+ g_strstrip (namev[i]);
+
+ match_count = 0;
+ i = j = 0;
+ while (strv[i] && namev[j]) {
+ gint k1, k2;
+
+ for (k1=0; strv[i+k1]; ++k1) {
+ if (name_fragment_match (strv[i+k1], namev[j]))
+ break;
+ }
+
+ for (k2=0; namev[j+k2]; ++k2) {
+ if (name_fragment_match (strv[i], namev[j+k2]))
+ break;
+ }
+
+ if (strv[i+k1] == NULL && namev[j+k2] == NULL) {
+ matched = FALSE;
+ goto cleanup_and_return;
+ }
+
+ ++match_count;
+
+ if (k1 < k2) {
+ i += k1+1;
+ ++j;
+ } else if (k2 < k1) {
+ ++i;
+ j += k2+1;
+ } else if (k1 == k2) {
+ i += k1+1;
+ j += k2+1;
+ }
+ }
+
+ /* This rule could be made more precise.
+ As it is, it will say that "Joe Smith" will match the name
+ "Joe Allen Smith" (which is good), but "de Icaza" will match
+ either "Miguel de Icaza" as well as Miguel's shiftless
+ brother "Roger de Icaza". In this sort of a case, the match
+ threshold should go up to 3. */
+ if (match_count >= 2)
+ matched = TRUE;
+
+
+ cleanup_and_return:
+ g_free (strv);
+ g_free (cpy);
+ g_free (namev);
+ g_free (name_str);
+
+ return matched;
+}
+
ECardArbitrary *
e_card_arbitrary_new(void)
{
@@ -1382,6 +1531,59 @@ e_card_arbitrary_free(ECardArbitrary *arbitrary)
g_free(arbitrary);
}
+/* EMail matching */
+static gboolean
+e_card_email_match_single_string (const gchar *a, const gchar *b)
+{
+ const gchar *xa = NULL, *xb = NULL;
+ gboolean match = TRUE;
+
+ for (xa=a; *xa && *xa != '@'; ++xa);
+ for (xb=b; *xb && *xb != '@'; ++xb);
+
+ if (xa-a != xb-b || *xa != *xb || g_strncasecmp (a, b, xa-a))
+ return FALSE;
+
+ if (*xa == '\0')
+ return TRUE;
+
+ /* Find the end of the string, then walk through backwards comparing.
+ This is so that we'll match joe@foobar.com and joe@mail.foobar.com.
+ */
+ while (*xa)
+ ++xa;
+ while (*xb)
+ ++xb;
+
+ while (match && *xa != '@' && *xb != '@') {
+ match = (*xa == *xb);
+ --xa;
+ --xb;
+ }
+
+ match = match && ((*xa == *xb) || (*xa == '.') || (*xb == '.'));
+
+ return match;
+}
+
+gboolean
+e_card_email_match_string (const ECard *card, const gchar *str)
+{
+ EIterator *iter;
+
+ g_return_val_if_fail (card && E_IS_CARD (card), FALSE);
+ g_return_val_if_fail (str != NULL, FALSE);
+
+ iter = e_list_get_iterator (card->email);
+ for (e_iterator_reset (iter); e_iterator_is_valid (iter); e_iterator_next (iter)) {
+ if (e_card_email_match_single_string (e_iterator_get (iter), str))
+ return TRUE;
+ }
+ gtk_object_unref (GTK_OBJECT (iter));
+
+ return FALSE;
+}
+
/*
* ECard lifecycle management and vCard loading/saving.
*/