about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--Makefile8
-rw-r--r--contact_list.c162
-rw-r--r--contact_list.h1
-rw-r--r--prof_autocomplete.c16
-rw-r--r--prof_autocomplete.h11
-rw-r--r--profanity.c2
-rw-r--r--test_contact_list.c6
7 files changed, 49 insertions, 157 deletions
diff --git a/Makefile b/Makefile
index 7354809f..1a8d1675 100644
--- a/Makefile
+++ b/Makefile
@@ -9,7 +9,8 @@ OBJS = log.o windows.o title_bar.o status_bar.o input_win.o jabber.o \
        profanity.o util.o command.o history.o contact_list.o prof_history.o \
 	   contact.o preferences.o prof_autocomplete.o main.o
 TESTOBJS = test_contact_list.o contact_list.o contact.o \
-	       test_util.o test_prof_history.o prof_history.o util.o
+	       test_util.o test_prof_history.o prof_history.o util.o \
+		   prof_autocomplete.o
 
 profanity: $(OBJS)
 	$(CC) -o profanity $(OBJS) $(LIBS)
@@ -20,11 +21,12 @@ title_bar.o: windows.h
 status_bar.o: windows.h util.h
 input_win.o: windows.h preferences.h
 jabber.o: jabber.h log.h windows.h contact_list.h
-profanity.o: log.h windows.h jabber.h command.h preferences.h
+profanity.o: log.h windows.h jabber.h command.h preferences.h \
+			 contact_list.h
 util.o: util.h
 command.o: command.h util.h history.h contact_list.h
 history.o: history.h prof_history.h
-contact_list.o: contact_list.h contact.h
+contact_list.o: contact_list.h contact.h prof_autocomplete.h
 prof_history.o: prof_history.h
 contact.o: contact.h
 preferences.o: preferences.h
diff --git a/contact_list.c b/contact_list.c
index eae48963..73d5cc8d 100644
--- a/contact_list.c
+++ b/contact_list.c
@@ -28,177 +28,53 @@
 
 #include "contact.h"
 #include "contact_list.h"
+#include "prof_autocomplete.h"
 
-// internal contact list
-static GSList * _contact_list = NULL;
+static PAutocomplete ac;
 
-// state of current tab completion, currrent node 
-static GSList * _last_found = NULL;
-// and current search pattern
-static char * _search_str = NULL;
+static PContact _copy(PContact contact);
 
-static char * _search_contact_list_from(GSList * curr);
+void contact_list_init(void)
+{
+    ac = p_autocomplete_new();
+}
 
 void contact_list_clear(void)
 {
-    g_slist_free_full(_contact_list, (GDestroyNotify)p_contact_free);
-    _contact_list = NULL;
-        
-    reset_search_attempts();
+    p_autocomplete_clear(ac, (GDestroyNotify)p_contact_free);
 }
 
 void reset_search_attempts(void)
 {
-    _last_found = NULL;
-    if (_search_str != NULL) {
-        free(_search_str);
-        _search_str = NULL;
-    }
+    p_autocomplete_reset(ac);
 }
 
 void contact_list_remove(const char * const name)
 {
-    // reset last found if it points at the node to be removed
-    if (_last_found != NULL)
-        if (strcmp(p_contact_name(_last_found->data), name) == 0)
-            _last_found = NULL;
-    
-    if (!_contact_list) {
-        return;
-    } else {
-        GSList *curr = _contact_list;
-        
-        while(curr) {
-            PContact contact = curr->data;
-            if (strcmp(p_contact_name(contact), name) == 0) {
-                _contact_list = g_slist_remove(_contact_list, contact);
-                p_contact_free(contact);
-
-                return;
-            }
-
-            curr = g_slist_next(curr);
-        }
-
-        return;
-    }
+    p_autocomplete_remove(ac, name, (PStrFunc)p_contact_name, (GDestroyNotify)p_contact_free);
 }
 
 void contact_list_add(const char * const name, const char * const show, 
     const char * const status)
 {
-
-    // empty list, create new
-    if (!_contact_list) {
-        _contact_list = g_slist_append(_contact_list, 
-            p_contact_new(name, show, status));
-        
-        return;
-    } else {
-        GSList *curr = _contact_list;
-
-        while(curr) {
-            PContact curr_contact = curr->data;
-
-            // insert    
-            if (strcmp(p_contact_name(curr_contact), name) > 0) {
-                _contact_list = g_slist_insert_before(_contact_list,
-                    curr, p_contact_new(name, show, status));
-                return;
-            // update
-            } else if (strcmp(p_contact_name(curr_contact), name) == 0) {
-                p_contact_free(curr->data);
-                curr->data = p_contact_new(name, show, status);
-                return;
-            }
-
-            curr = g_slist_next(curr);
-        }
-
-        // hit end, append
-        _contact_list = g_slist_append(_contact_list, 
-            p_contact_new(name, show, status));
-        
-        return;
-    }
+    p_autocomplete_add(ac, p_contact_new(name, show, status), (PStrFunc)p_contact_name, 
+        (GDestroyNotify)p_contact_free);
 }
 
 GSList * get_contact_list(void)
 {
-    GSList *copy = NULL;
-    GSList *curr = _contact_list;
-
-    while(curr) {
-        PContact curr_contact = curr->data;
-        
-        copy = g_slist_append(copy, 
-            p_contact_new(p_contact_name(curr_contact),
-                          p_contact_show(curr_contact),
-                          p_contact_status(curr_contact)));
-
-        curr = g_slist_next(curr);
-    }
-
-    return copy;
+    return p_autocomplete_get_list(ac, (PCopyFunc)_copy);
 }
 
 char * find_contact(char *search_str)
 {
-    char *found = NULL;
-
-    // no contacts to search
-    if (!_contact_list)
-        return NULL;
-
-    // first search attempt
-    if (_last_found == NULL) {
-        _search_str = (char *) malloc((strlen(search_str) + 1) * sizeof(char));
-        strcpy(_search_str, search_str);
-
-        found = _search_contact_list_from(_contact_list);
-        return found;
-
-    // subsequent search attempt
-    } else {
-        // search from here+1 to end 
-        found = _search_contact_list_from(g_slist_next(_last_found));
-        if (found != NULL)
-            return found;
-
-        // search from beginning
-        found = _search_contact_list_from(_contact_list);
-        if (found != NULL)
-            return found;
-
-        // we found nothing, reset search
-        reset_search_attempts();
-        return NULL;
-    }
+    return p_autocomplete_complete(ac, search_str, (PStrFunc)p_contact_name);
 }
 
-static char * _search_contact_list_from(GSList * curr)
+static PContact _copy(PContact contact)
 {
-    while(curr) {
-        PContact curr_contact = curr->data;
-        
-        // match found
-        if (strncmp(p_contact_name(curr_contact), 
-                    _search_str, 
-                    strlen(_search_str)) == 0) {
-            char *result = 
-                (char *) malloc((strlen(p_contact_name(curr_contact)) + 1) 
-                    * sizeof(char));
-
-            // set pointer to last found
-            _last_found = curr;
-            
-            // return the contact, must be free'd by caller
-            strcpy(result, p_contact_name(curr_contact));
-            return result;
-        }
-
-        curr = g_slist_next(curr);
-    }
-
-    return NULL;
+    return p_contact_new(p_contact_name(contact),
+                p_contact_show(contact),
+                p_contact_status(contact));
 }
+
diff --git a/contact_list.h b/contact_list.h
index 569af8cd..72b8dd79 100644
--- a/contact_list.h
+++ b/contact_list.h
@@ -27,6 +27,7 @@
 
 #include "contact.h"
 
+void contact_list_init(void);
 void contact_list_clear(void);
 void reset_search_attempts(void);
 void contact_list_add(const char * const name, const char * const show,
diff --git a/prof_autocomplete.c b/prof_autocomplete.c
index d683d135..4bec0f6c 100644
--- a/prof_autocomplete.c
+++ b/prof_autocomplete.c
@@ -34,7 +34,7 @@ struct p_autocomplete_t {
 };
 
 
-static gchar * _search_from(PAutocomplete ac, GSList *curr,  char * (*str_func)(void *));
+static gchar * _search_from(PAutocomplete ac, GSList *curr,  PStrFunc str_func);
 
 PAutocomplete p_autocomplete_new(void)
 {
@@ -63,7 +63,7 @@ void p_autocomplete_reset(PAutocomplete ac)
     }
 }
 
-void p_autocomplete_add(PAutocomplete ac, void *item, char * (*str_func)(void *), 
+void p_autocomplete_add(PAutocomplete ac, void *item, PStrFunc str_func, 
     GDestroyNotify free_func)
 {
     if (ac->items == NULL) {
@@ -97,7 +97,8 @@ void p_autocomplete_add(PAutocomplete ac, void *item, char * (*str_func)(void *)
     }
 }
 
-void p_autocomplete_remove(PAutocomplete ac, char *item, char * (*str_func)(void *),   GDestroyNotify free_func)
+void p_autocomplete_remove(PAutocomplete ac, const char * const item, 
+    PStrFunc str_func, GDestroyNotify free_func)
 {
     // reset last found if it points to the item to be removed
     if (ac->last_found != NULL)
@@ -111,8 +112,9 @@ void p_autocomplete_remove(PAutocomplete ac, char *item, char * (*str_func)(void
         
         while(curr) {
             if (g_strcmp0(str_func(curr->data), item) == 0) {
+                void *current_item = curr->data;
                 ac->items = g_slist_remove(ac->items, curr->data);
-                free_func(curr->data);
+                free_func(current_item);
                 
                 return;
             }
@@ -124,7 +126,7 @@ void p_autocomplete_remove(PAutocomplete ac, char *item, char * (*str_func)(void
     }
 }
 
-GSList * p_autocomplete_get_list(PAutocomplete ac, void * (*copy_func)(void *))
+GSList * p_autocomplete_get_list(PAutocomplete ac, PCopyFunc copy_func)
 {
     GSList *copy = NULL;
     GSList *curr = ac->items;
@@ -138,7 +140,7 @@ GSList * p_autocomplete_get_list(PAutocomplete ac, void * (*copy_func)(void *))
 }
 
 gchar * p_autocomplete_complete(PAutocomplete ac, gchar *search_str, 
-    char * (*str_func)(void *))
+    PStrFunc str_func)
 {
     gchar *found = NULL;
 
@@ -173,7 +175,7 @@ gchar * p_autocomplete_complete(PAutocomplete ac, gchar *search_str,
     }
 }
 
-static gchar * _search_from(PAutocomplete ac, GSList *curr,  char * (*str_func)(void *))
+static gchar * _search_from(PAutocomplete ac, GSList *curr, PStrFunc str_func)
 {
     while(curr) {
         
diff --git a/prof_autocomplete.h b/prof_autocomplete.h
index 554193fd..fa323502 100644
--- a/prof_autocomplete.h
+++ b/prof_autocomplete.h
@@ -26,15 +26,18 @@
 #include <glib.h>
 
 typedef struct p_autocomplete_t *PAutocomplete;
+typedef const char * (*PStrFunc)(const void *obj);
+typedef void * (*PCopyFunc)(const void *obj);
 
 PAutocomplete p_autocomplete_new(void);
 void p_autocomplete_clear(PAutocomplete ac, GDestroyNotify free_func);
 void p_autocomplete_reset(PAutocomplete ac);
-void p_autocomplete_add(PAutocomplete ac, void *item, char * (*str_func)(void *), 
+void p_autocomplete_add(PAutocomplete ac, void *item, PStrFunc str_func, 
     GDestroyNotify free_func);
-void p_autocomplete_remove(PAutocomplete ac, char *item, char * (*str_func)(void *),   GDestroyNotify free_func);
-GSList * p_autocomplete_get_list(PAutocomplete ac, void * (*copy_func)(void *));
+void p_autocomplete_remove(PAutocomplete ac, const char * const item, 
+    PStrFunc str_func, GDestroyNotify free_func);
+GSList * p_autocomplete_get_list(PAutocomplete ac, PCopyFunc copy_func);
 gchar * p_autocomplete_complete(PAutocomplete ac, gchar *search_str, 
-    char * (*str_func)(void *));
+    PStrFunc str_func);
 
 #endif
diff --git a/profanity.c b/profanity.c
index 5eacb95a..7cbf5d0f 100644
--- a/profanity.c
+++ b/profanity.c
@@ -30,6 +30,7 @@
 #include "jabber.h"
 #include "command.h"
 #include "preferences.h"
+#include "contact_list.h"
 
 static void _profanity_shutdown(void);
 
@@ -69,6 +70,7 @@ void profanity_init(const int disable_tls)
     gui_init();
     jabber_init(disable_tls);
     command_init();
+    contact_list_init();
     atexit(_profanity_shutdown);
 }
 
diff --git a/test_contact_list.c b/test_contact_list.c
index c6d0c684..599c8ca1 100644
--- a/test_contact_list.c
+++ b/test_contact_list.c
@@ -8,6 +8,11 @@
 #include "contact.h"
 #include "contact_list.h"
 
+static void setup(void)
+{
+    contact_list_init();
+}
+
 static void beforetest(void)
 {
     contact_list_clear();
@@ -452,6 +457,7 @@ static void removed_contact_not_in_search(void)
 void register_contact_list_tests(void)
 {
     TEST_MODULE("contact_list tests");
+    SETUP(setup);
     BEFORETEST(beforetest);
     AFTERTEST(aftertest);
     TEST(empty_list_when_none_added);