aboutsummaryrefslogtreecommitdiff
path: root/src/addr_compl.c
diff options
context:
space:
mode:
authorhiro <hiro@ee746299-78ed-0310-b773-934348b2243d>2007-04-26 07:34:09 +0000
committerhiro <hiro@ee746299-78ed-0310-b773-934348b2243d>2007-04-26 07:34:09 +0000
commit3182d5650d74fcaed19234e4c585bf43fa0db288 (patch)
treebe6c78d16eb90edf9f378fa9bc8b71a3838ccb5e /src/addr_compl.c
parent68061831c125f588689a28344fa052ac8364797b (diff)
improved address completion.
git-svn-id: svn://sylpheed.sraoss.jp/sylpheed/trunk@1672 ee746299-78ed-0310-b773-934348b2243d
Diffstat (limited to 'src/addr_compl.c')
-rw-r--r--src/addr_compl.c222
1 files changed, 146 insertions, 76 deletions
diff --git a/src/addr_compl.c b/src/addr_compl.c
index b52a5ae2..d0af795d 100644
--- a/src/addr_compl.c
+++ b/src/addr_compl.c
@@ -79,19 +79,19 @@ typedef struct
/*******************************************************************************/
-static gint g_ref_count; /* list ref count */
-static GList *g_completion_list; /* list of strings to be checked */
-static GList *g_address_list; /* address storage */
-static GCompletion *g_completion; /* completion object */
+static gint ref_count; /* list ref count */
+static GList *completion_list; /* list of strings to be checked */
+static GList *address_list; /* address storage */
+static GCompletion *completion; /* completion object */
/* To allow for continuing completion we have to keep track of the state
* using the following variables. No need to create a context object. */
-static gint g_completion_count; /* nr of addresses incl. the prefix */
-static gint g_completion_next; /* next prev address */
-static GSList *g_completion_addresses; /* unique addresses found in the
+static gint completion_count; /* nr of addresses incl. the prefix */
+static gint completion_next; /* next prev address */
+static GSList *completion_addresses; /* unique addresses found in the
completion cache. */
-static gchar *g_completion_prefix; /* last prefix. (this is cached here
+static gchar *completion_prefix; /* last prefix. (this is cached here
* because the prefix passed to g_completion
* is g_strdown()'ed */
@@ -109,67 +109,102 @@ static gchar *completion_func(gpointer data)
static void init_all(void)
{
- g_completion = g_completion_new(completion_func);
- g_return_if_fail(g_completion != NULL);
+ completion = g_completion_new(completion_func);
+ g_return_if_fail(completion != NULL);
}
static void free_all(void)
{
GList *walk;
-
- walk = g_list_first(g_completion_list);
+
+ walk = g_list_first(completion_list);
for (; walk != NULL; walk = g_list_next(walk)) {
completion_entry *ce = (completion_entry *) walk->data;
g_free(ce->string);
- g_free(walk->data);
+ g_free(ce);
}
- g_list_free(g_completion_list);
- g_completion_list = NULL;
-
- walk = g_address_list;
+ g_list_free(completion_list);
+ completion_list = NULL;
+
+ walk = address_list;
for (; walk != NULL; walk = g_list_next(walk)) {
address_entry *ae = (address_entry *) walk->data;
g_free(ae->name);
g_free(ae->address);
- g_free(walk->data);
+ g_free(ae);
}
- g_list_free(g_address_list);
- g_address_list = NULL;
-
- g_completion_free(g_completion);
- g_completion = NULL;
+ g_list_free(address_list);
+ address_list = NULL;
+
+ g_completion_free(completion);
+ completion = NULL;
+}
+
+static gint address_entry_find_func(gconstpointer a, gconstpointer b)
+{
+ const address_entry *ae1 = a;
+ const address_entry *ae2 = b;
+ gint val;
+
+ if (!a || !b)
+ return -1;
+
+ val = strcmp(ae1->name, ae2->name);
+ if (val != 0)
+ return val;
+ val = strcmp(ae1->address, ae2->address);
+ if (val != 0)
+ return val;
+
+ return 0;
}
/* add_address() - adds address to the completion list. this function looks
* complicated, but it's only allocation checks.
*/
-static gint add_address(const gchar *name, const gchar *address)
+static gint add_address(const gchar *name, const gchar *address, const gchar *nickname)
{
address_entry *ae;
completion_entry *ce1;
completion_entry *ce2;
+ completion_entry *ce3 = NULL;
+ GList *found;
if (!name || !address) return -1;
- ae = g_new0(address_entry, 1);
ce1 = g_new0(completion_entry, 1),
ce2 = g_new0(completion_entry, 1);
+ if (nickname)
+ ce3 = g_new0(completion_entry, 1);
- g_return_val_if_fail(ae != NULL, -1);
- g_return_val_if_fail(ce1 != NULL && ce2 != NULL, -1);
-
+ ae = g_new0(address_entry, 1);
ae->name = g_strdup(name);
ae->address = g_strdup(address);
+ if ((found = g_list_find_custom(address_list, ae,
+ address_entry_find_func))) {
+ g_free(ae->name);
+ g_free(ae->address);
+ g_free(ae);
+ ae = (address_entry *)found->data;
+ } else
+ address_list = g_list_append(address_list, ae);
/* GCompletion list is case sensitive */
ce1->string = g_utf8_strdown(name, -1);
ce2->string = g_utf8_strdown(address, -1);
+ if (ce3 && nickname)
+ ce3->string = g_utf8_strdown(nickname, -1);
ce1->ref = ce2->ref = ae;
+ if (ce3)
+ ce3->ref = ae;
+
+ debug_print("adding %s <%s>\n", ae->name, ae->address);
- g_completion_list = g_list_append(g_completion_list, ce1);
- g_completion_list = g_list_append(g_completion_list, ce2);
- g_address_list = g_list_append(g_address_list, ae);
+ completion_list = g_list_append(completion_list, ce1);
+ completion_list = g_list_append(completion_list, ce2);
+ if (ce3)
+ completion_list = g_list_append(completion_list, ce3);
return 0;
}
@@ -186,18 +221,18 @@ static void read_address_book(void) {
gint start_address_completion(void)
{
clear_completion_cache();
- if (!g_ref_count) {
+ if (!ref_count) {
init_all();
/* open the address book */
read_address_book();
/* merge the completion entry list into g_completion */
- if (g_completion_list)
- g_completion_add_items(g_completion, g_completion_list);
+ if (completion_list)
+ g_completion_add_items(completion, completion_list);
}
- g_ref_count++;
- debug_print("start_address_completion ref count %d\n", g_ref_count);
+ ref_count++;
+ debug_print("start_address_completion ref count %d\n", ref_count);
- return g_list_length(g_completion_list);
+ return g_list_length(completion_list);
}
/* get_address_from_edit() - returns a possible address (or a part)
@@ -270,6 +305,36 @@ void replace_address_in_edit(GtkEntry *entry, const gchar *newtext,
gtk_editable_set_position(GTK_EDITABLE(entry), -1);
}
+#if 0
+static gint insert_address_func(gconstpointer a, gconstpointer b)
+{
+ const address_entry *ae1 = a;
+ const address_entry *ae2 = b;
+ gchar *s1, *s2;
+ gint val;
+
+ if (!a || !b)
+ return -1;
+
+ s1 = g_utf8_casefold(ae1->address, -1);
+ s2 = g_utf8_casefold(ae2->address, -1);
+ val = g_utf8_collate(s1, s2);
+ g_free(s2);
+ g_free(s1);
+ if (val != 0)
+ return val;
+ s1 = g_utf8_casefold(ae1->name, -1);
+ s2 = g_utf8_casefold(ae2->name, -1);
+ val = g_utf8_collate(s1, s2);
+ g_free(s2);
+ g_free(s1);
+ if (val != 0)
+ return val;
+
+ return 0;
+}
+#endif
+
/* complete_address() - tries to complete an addres, and returns the
* number of addresses found. use get_complete_address() to get one.
* returns zero if no match was found, otherwise the number of addresses,
@@ -285,11 +350,11 @@ guint complete_address(const gchar *str)
g_return_val_if_fail(str != NULL, 0);
clear_completion_cache();
- g_completion_prefix = g_strdup(str);
+ completion_prefix = g_strdup(str);
/* g_completion is case sensitive */
d = g_utf8_strdown(str, -1);
- result = g_completion_complete(g_completion, d, NULL);
+ result = g_completion_complete(completion, d, NULL);
count = g_list_length(result);
if (count) {
@@ -298,22 +363,27 @@ guint complete_address(const gchar *str)
result != NULL;
result = g_list_next(result)) {
ce = (completion_entry *)(result->data);
- if (NULL == g_slist_find(g_completion_addresses,
+ if (NULL == g_slist_find(completion_addresses,
ce->ref)) {
cpl++;
- g_completion_addresses =
- g_slist_append(g_completion_addresses,
+ completion_addresses =
+ g_slist_append(completion_addresses,
ce->ref);
+#if 0
+ g_slist_insert_sorted
+ (completion_addresses, ce->ref,
+ insert_address_func);
+#endif
}
}
count = cpl + 1; /* index 0 is the original prefix */
- g_completion_next = 1; /* we start at the first completed one */
+ completion_next = 1; /* we start at the first completed one */
} else {
- g_free(g_completion_prefix);
- g_completion_prefix = NULL;
+ g_free(completion_prefix);
+ completion_prefix = NULL;
}
- g_completion_count = count;
+ completion_count = count;
g_free(d);
@@ -328,13 +398,13 @@ gchar *get_complete_address(gint index)
const address_entry *p;
gchar *address = NULL;
- if (index < g_completion_count) {
+ if (index < completion_count) {
if (index == 0)
- address = g_strdup(g_completion_prefix);
+ address = g_strdup(completion_prefix);
else {
/* get something from the unique addresses */
p = (address_entry *)g_slist_nth_data
- (g_completion_addresses, index - 1);
+ (completion_addresses, index - 1);
if (p != NULL) {
if (!p->name || p->name[0] == '\0')
address = g_strdup_printf(p->address);
@@ -357,10 +427,10 @@ gchar *get_next_complete_address(void)
if (is_completion_pending()) {
gchar *res;
- res = get_complete_address(g_completion_next);
- g_completion_next += 1;
- if (g_completion_next >= g_completion_count)
- g_completion_next = 0;
+ res = get_complete_address(completion_next);
+ completion_next += 1;
+ if (completion_next >= completion_count)
+ completion_next = 0;
return res;
} else
@@ -370,15 +440,15 @@ gchar *get_next_complete_address(void)
gchar *get_prev_complete_address(void)
{
if (is_completion_pending()) {
- int n = g_completion_next - 2;
+ int n = completion_next - 2;
/* real previous */
- n = (n + (g_completion_count * 5)) % g_completion_count;
+ n = (n + (completion_count * 5)) % completion_count;
/* real next */
- g_completion_next = n + 1;
- if (g_completion_next >= g_completion_count)
- g_completion_next = 0;
+ completion_next = n + 1;
+ if (completion_next >= completion_count)
+ completion_next = 0;
return get_complete_address(n);
} else
return NULL;
@@ -387,7 +457,7 @@ gchar *get_prev_complete_address(void)
guint get_completion_count(void)
{
if (is_completion_pending())
- return g_completion_count;
+ return completion_count;
else
return 0;
}
@@ -396,15 +466,15 @@ guint get_completion_count(void)
void clear_completion_cache(void)
{
if (is_completion_pending()) {
- if (g_completion_prefix)
- g_free(g_completion_prefix);
+ if (completion_prefix)
+ g_free(completion_prefix);
- if (g_completion_addresses) {
- g_slist_free(g_completion_addresses);
- g_completion_addresses = NULL;
+ if (completion_addresses) {
+ g_slist_free(completion_addresses);
+ completion_addresses = NULL;
}
- g_completion_count = g_completion_next = 0;
+ completion_count = completion_next = 0;
}
}
@@ -412,7 +482,7 @@ gboolean is_completion_pending(void)
{
/* check if completion pending, i.e. we might satisfy a request for the next
* or previous address */
- return g_completion_count;
+ return completion_count;
}
/* invalidate_address_completion() - should be called if address book
@@ -420,30 +490,30 @@ gboolean is_completion_pending(void)
*/
gint invalidate_address_completion(void)
{
- if (g_ref_count) {
+ if (ref_count) {
/* simply the same as start_address_completion() */
debug_print("Invalidation request for address completion\n");
free_all();
init_all();
read_address_book();
- if (g_completion_list)
- g_completion_add_items(g_completion, g_completion_list);
+ if (completion_list)
+ g_completion_add_items(completion, completion_list);
clear_completion_cache();
}
- return g_list_length(g_completion_list);
+ return g_list_length(completion_list);
}
gint end_address_completion(void)
{
clear_completion_cache();
- if (0 == --g_ref_count)
+ if (0 == --ref_count)
free_all();
- debug_print("end_address_completion ref count %d\n", g_ref_count);
+ debug_print("end_address_completion ref count %d\n", ref_count);
- return g_ref_count;
+ return ref_count;
}
@@ -483,7 +553,7 @@ static gboolean completion_window_key_press
static void completion_window_advance_to_row(GtkCList *clist, gint row)
{
- g_return_if_fail(row < g_completion_count);
+ g_return_if_fail(row < completion_count);
gtk_clist_select_row(clist, row, 0);
}
@@ -496,8 +566,8 @@ static void completion_window_advance_selection(GtkCList *clist, gboolean forwar
row = GPOINTER_TO_INT(clist->selection->data);
- row = forward ? (row + 1) % g_completion_count :
- (row - 1) < 0 ? g_completion_count - 1 : row - 1;
+ row = forward ? (row + 1) % completion_count :
+ (row - 1) < 0 ? completion_count - 1 : row - 1;
gtk_clist_freeze(clist);
completion_window_advance_to_row(clist, row);