2006-09-26 [colin] 2.5.2cvs1
authorColin Leroy <colin@colino.net>
Tue, 26 Sep 2006 20:03:22 +0000 (20:03 +0000)
committerColin Leroy <colin@colino.net>
Tue, 26 Sep 2006 20:03:22 +0000 (20:03 +0000)
* src/Makefile.am
* src/addr_compl.c
* src/addr_compl.h
* src/addrbook.c
* src/addrbook.h
* src/addressbook.c
* src/addrindex.c
* src/addrindex.h
* src/compose.c
* src/prefs_common.c
* src/prefs_filtering_action.c
* src/prefs_folder_item.c
* src/prefs_template.c
* src/stock_pixmap.c
* src/stock_pixmap.h
* src/pixmaps/addr_one.xpm
* src/pixmaps/addr_two.xpm
Add auto-completion on groups

20 files changed:
ChangeLog
PATCHSETS
configure.ac
src/Makefile.am
src/addr_compl.c
src/addr_compl.h
src/addrbook.c
src/addrbook.h
src/addressbook.c
src/addrindex.c
src/addrindex.h
src/compose.c
src/pixmaps/addr_one.xpm [new file with mode: 0644]
src/pixmaps/addr_two.xpm [new file with mode: 0644]
src/prefs_common.c
src/prefs_filtering_action.c
src/prefs_folder_item.c
src/prefs_template.c
src/stock_pixmap.c
src/stock_pixmap.h

index 87fc8f35308f0163912033a4c266dd97ffc71280..0727d5200f882c6cf26dbf79397feddf7cba75a7 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+2006-09-26 [colin]     2.5.2cvs1
+
+       * src/Makefile.am
+       * src/addr_compl.c
+       * src/addr_compl.h
+       * src/addrbook.c
+       * src/addrbook.h
+       * src/addressbook.c
+       * src/addrindex.c
+       * src/addrindex.h
+       * src/compose.c
+       * src/prefs_common.c
+       * src/prefs_filtering_action.c
+       * src/prefs_folder_item.c
+       * src/prefs_template.c
+       * src/stock_pixmap.c
+       * src/stock_pixmap.h
+       * src/pixmaps/addr_one.xpm
+       * src/pixmaps/addr_two.xpm
+               Add auto-completion on groups
+
 2006-09-26 [colin]     2.5.2
 
        * NEWS
index cc17d2e314bd33aa97884fb7fdd8fc595660f45f..2790e05b5ce3278cf641239d5123d3553c484804 100644 (file)
--- a/PATCHSETS
+++ b/PATCHSETS
 ( cvs diff -u -r 1.1.2.12 -r 1.1.2.13 src/partial_download.c;  ) > 2.5.1cvs3.patchset
 ( cvs diff -u -r 1.28.2.27 -r 1.28.2.28 src/mbox.c;  ) > 2.5.1cvs4.patchset
 ( cvs diff -u -r 1.75.2.30 -r 1.75.2.31 src/matcher.c;  ) > 2.5.1cvs5.patchset
+( cvs diff -u -r 1.155.2.41 -r 1.155.2.42 src/Makefile.am;  cvs diff -u -r 1.27.2.20 -r 1.27.2.21 src/addr_compl.c;  cvs diff -u -r 1.8.2.5 -r 1.8.2.6 src/addr_compl.h;  cvs diff -u -r 1.22.2.8 -r 1.22.2.9 src/addrbook.c;  cvs diff -u -r 1.7.2.1 -r 1.7.2.2 src/addrbook.h;  cvs diff -u -r 1.60.2.63 -r 1.60.2.64 src/addressbook.c;  cvs diff -u -r 1.28.2.18 -r 1.28.2.19 src/addrindex.c;  cvs diff -u -r 1.9.2.7 -r 1.9.2.8 src/addrindex.h;  cvs diff -u -r 1.382.2.310 -r 1.382.2.311 src/compose.c;  cvs diff -u -r 1.204.2.102 -r 1.204.2.103 src/prefs_common.c;  cvs diff -u -r 1.1.4.30 -r 1.1.4.31 src/prefs_filtering_action.c;  cvs diff -u -r 1.52.2.23 -r 1.52.2.24 src/prefs_folder_item.c;  cvs diff -u -r 1.12.2.30 -r 1.12.2.31 src/prefs_template.c;  cvs diff -u -r 1.25.2.27 -r 1.25.2.28 src/stock_pixmap.c;  cvs diff -u -r 1.18.2.18 -r 1.18.2.19 src/stock_pixmap.h;  diff -u /dev/null src/pixmaps/addr_one.xpm;  diff -u /dev/null src/pixmaps/addr_two.xpm;  ) > 2.5.2cvs1.patchset
index b1c2b1c486ade1809829403c7e282b03c5113c49..85119af9fd07f05771ce3a523a8f15f788274ec0 100644 (file)
@@ -11,7 +11,7 @@ MINOR_VERSION=5
 MICRO_VERSION=2
 INTERFACE_AGE=0
 BINARY_AGE=0
-EXTRA_VERSION=0
+EXTRA_VERSION=1
 EXTRA_RELEASE=
 EXTRA_GTK2_VERSION=
 
index 2e9387b64e9c74602a3c6a54f1d8719978bc9920..e6c2dac4f2be849f699fe1e823ba8d3fbae227c2 100644 (file)
@@ -290,6 +290,8 @@ BUILT_SOURCES = \
        quote_fmt_parse.h
 
 EXTRA_DIST = \
+       pixmaps/addr_one.xpm \
+       pixmaps/addr_two.xpm \
        pixmaps/address_book.xpm \
        pixmaps/address_search.xpm \
        pixmaps/address.xpm \
index 2e3b3ce72664e5267719dd2e77886357687e89a9..c174f4277f195c97ba9786e4089384898731c779 100644 (file)
  *\brief       For the GtkListStore
  */
 enum {
+       ADDR_COMPL_ICON,
        ADDR_COMPL_ADDRESS,
+       ADDR_COMPL_ISGROUP,
+       ADDR_COMPL_GROUPLIST,
        N_ADDR_COMPL_COLUMNS
 };
 
@@ -83,6 +86,7 @@ typedef struct
 {
        gchar *name;
        gchar *address;
+       GList *grp_emails;
 } address_entry;
 
 /**
@@ -102,6 +106,9 @@ 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 GHashTable *_groupAddresses_ = NULL;
+static gboolean _allowGroups_ = TRUE;
+
 /* To allow for continuing completion we have to keep track of the state
  * using the following variables. No need to create a context object. */
 
@@ -195,6 +202,7 @@ static void free_all(void)
                address_entry *ae = (address_entry *) walk->data;
                g_free(ae->name);
                g_free(ae->address);
+               g_list_free(ae->grp_emails);
                g_free(walk->data);
        }
        g_list_free(g_address_list);
@@ -202,6 +210,9 @@ static void free_all(void)
        
        g_completion_free(g_completion);
        g_completion = NULL;
+       if (_groupAddresses_)
+               g_hash_table_destroy(_groupAddresses_);
+       _groupAddresses_ = NULL;
 }
 
 /**
@@ -226,15 +237,23 @@ static void add_address1(const char *str, address_entry *ae)
  * \param name    Recipient name.
  * \param address EMail address.
  * \param alias   Alias to append.
+ * \param grp_emails the emails in case of a group. List should be freed later, 
+ * but not its strings
  * \return <code>0</code> if entry appended successfully, or <code>-1</code>
  *         if failure.
  */
 static gint add_address(const gchar *name, const gchar *address, 
-                       const gchar *nick, const gchar *alias)
+                       const gchar *nick, const gchar *alias, GList *grp_emails)
 {
        address_entry    *ae;
+       gboolean is_group = FALSE;
 
-       if (!name || !address) return -1;
+       if (!name || !address) {
+               if (!address && !nick && !alias && grp_emails) {
+                       is_group = TRUE;
+               } else
+                       return -1;
+       }
 
        ae = g_new0(address_entry, 1);
 
@@ -242,11 +261,12 @@ static gint add_address(const gchar *name, const gchar *address,
 
        ae->name    = g_strdup(name);
        ae->address = g_strdup(address);                
-
+       ae->grp_emails = grp_emails;
        g_address_list = g_list_prepend(g_address_list, ae);
 
        add_address1(name, ae);
-       add_address1(address, ae);
+       if (address != NULL)
+               add_address1(address, ae);
        
        if (nick != NULL)
                add_address1(nick, ae);
@@ -401,6 +421,20 @@ static gchar *get_address_from_edit(GtkEntry *entry, gint *start_pos)
        return str;
 } 
 
+static gchar *get_complete_address_from_name_email(const gchar *name, const gchar *email)
+{
+       gchar *address = NULL;
+       if (!name || name[0] == '\0')
+               address = g_strdup_printf("<%s>", email);
+       else if (strchr_with_skip_quote(name, '"', ','))
+               address = g_strdup_printf
+                       ("\"%s\" <%s>", name, email);
+       else
+               address = g_strdup_printf
+                       ("%s <%s>", name, email);
+       return address;
+}
+
 /**
  * Replace an incompleted address with a completed one.
  * \param entry     Address entry field.
@@ -408,12 +442,35 @@ static gchar *get_address_from_edit(GtkEntry *entry, gint *start_pos)
  * \param start_pos Insertion point in entry field.
  */
 static void replace_address_in_edit(GtkEntry *entry, const gchar *newtext,
-                            gint start_pos)
+                            gint start_pos, gboolean is_group, GList *grp_emails)
 {
        if (!newtext) return;
        gtk_editable_delete_text(GTK_EDITABLE(entry), start_pos, -1);
-       gtk_editable_insert_text(GTK_EDITABLE(entry), newtext, strlen(newtext),
+       if (!is_group) {
+               gtk_editable_insert_text(GTK_EDITABLE(entry), newtext, strlen(newtext),
                                 &start_pos);
+       } else {
+               gchar *addresses = NULL;
+               GList *cur = grp_emails;
+               for (; cur; cur = cur->next) {
+                       gchar *tmp;
+                       ItemEMail *email = (ItemEMail *)cur->data;
+                       ItemPerson *person = ( ItemPerson * ) ADDRITEM_PARENT(email);
+                       
+                       gchar *addr = get_complete_address_from_name_email(
+                               ADDRITEM_NAME(person), email->address);
+                       if (addresses)
+                               tmp = g_strdup_printf("%s, %s", addresses, addr);
+                       else
+                               tmp = g_strdup_printf("%s", addr);
+                       g_free(addr);
+                       g_free(addresses);
+                       addresses = tmp;
+               }
+               gtk_editable_insert_text(GTK_EDITABLE(entry), addresses, strlen(addresses),
+                                &start_pos);
+               g_free(addresses);
+       }
        gtk_editable_set_position(GTK_EDITABLE(entry), -1);
 }
 
@@ -490,15 +547,17 @@ gchar *get_complete_address(gint index)
                        /* get something from the unique addresses */
                        p = (address_entry *)g_slist_nth_data
                                (g_completion_addresses, index - 1);
-                       if (p != NULL) {
-                               if (!p->name || p->name[0] == '\0')
-                                       address = g_strdup_printf(p->address);
-                               else if (strchr_with_skip_quote(p->name, '"', ','))
-                                       address = g_strdup_printf
-                                               ("\"%s\" <%s>", p->name, p->address);
-                               else
-                                       address = g_strdup_printf
-                                               ("%s <%s>", p->name, p->address);
+                       if (p != NULL && p->address != NULL) {
+                               address = get_complete_address_from_name_email(p->name, p->address);
+                       } else if (p != NULL && p->address == NULL && p->name != NULL) {
+                               /* that's a group */
+                               address = g_strdup_printf("%s%s <!--___group___-->", p->name, _(" (Group)"));
+                               if (!_groupAddresses_) {
+                                       _groupAddresses_ = g_hash_table_new(NULL, g_direct_equal);
+                               }
+                               if (!g_hash_table_lookup(_groupAddresses_, GINT_TO_POINTER(g_str_hash(address)))) {
+                                       g_hash_table_insert(_groupAddresses_, GINT_TO_POINTER(g_str_hash(address)), p->grp_emails);
+                               }
                        }
                }
        }
@@ -590,7 +649,6 @@ static pthread_mutex_t _completionMutex_ = PTHREAD_MUTEX_INITIALIZER;
  * Completion queue list.
  */
 static GList *_displayQueue_ = NULL;
-
 /**
  * Current query ID.
  */
@@ -607,6 +665,7 @@ static guint _completionIdleID_ = 0;
  */
 
 #define ENTRY_DATA_TAB_HOOK    "tab_hook"      /* used to lookup entry */
+#define ENTRY_DATA_ALLOW_GROUPS        "allowgrp"      /* used to know whether to present groups */
 
 static void address_completion_mainwindow_set_focus    (GtkWindow   *window,
                                                         GtkWidget   *widget,
@@ -759,6 +818,9 @@ static void addrcompl_resize_window( CompletionWindow *cw ) {
                gtk_widget_set_size_request(cw->window, width, r.height);
 }
 
+static GdkPixbuf *group_pixbuf = NULL;
+static GdkPixbuf *email_pixbuf = NULL;
+
 /**
  * Add an address the completion window address list.
  * \param cw      Completion window.
@@ -768,12 +830,38 @@ static void addrcompl_add_entry( CompletionWindow *cw, gchar *address ) {
        GtkListStore *store;
        GtkTreeIter iter;
        GtkTreeSelection *selection;
-
+       gboolean is_group = FALSE;
+       GList *grp_emails = NULL;
        store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(cw->list_view)));
-       gtk_list_store_append(store, &iter);
+       GdkPixbuf *pixbuf;
+       
+       if (!group_pixbuf)
+               stock_pixbuf_gdk(cw->list_view, STOCK_PIXMAP_ADDR_TWO, &group_pixbuf);
+       if (!email_pixbuf)
+               stock_pixbuf_gdk(cw->list_view, STOCK_PIXMAP_ADDR_ONE, &email_pixbuf);
 
        /* printf( "\t\tAdding :%s\n", address ); */
-       gtk_list_store_set(store, &iter, ADDR_COMPL_ADDRESS, address, -1);
+       if (strstr(address, " <!--___group___-->")) {
+               is_group = TRUE;
+               if (_groupAddresses_)
+                       grp_emails = g_hash_table_lookup(_groupAddresses_, GINT_TO_POINTER(g_str_hash(address)));
+               *(strstr(address, " <!--___group___-->")) = '\0';
+               pixbuf = group_pixbuf;
+       } else if (strchr(address, '@') && strchr(address, '<') &&
+                  strchr(address, '>')) {
+               pixbuf = email_pixbuf;
+       } else
+               pixbuf = NULL;
+       
+       if (is_group && !_allowGroups_)
+               return;
+       gtk_list_store_append(store, &iter);
+       gtk_list_store_set(store, &iter, 
+                               ADDR_COMPL_ICON, pixbuf,
+                               ADDR_COMPL_ADDRESS, address, 
+                               ADDR_COMPL_ISGROUP, is_group, 
+                               ADDR_COMPL_GROUPLIST, grp_emails,
+                               -1);
        cw->listCount++;
 
        /* Resize window */
@@ -940,9 +1028,10 @@ static void completion_window_apply_selection(GtkTreeView *list_view, GtkEntry *
        GtkTreeSelection *selection;
        GtkTreeModel *model;
        GtkTreeIter iter;
-
+       gboolean is_group = FALSE;
        g_return_if_fail(list_view != NULL);
        g_return_if_fail(entry != NULL);
+       GList *grp_emails = NULL;
 
        selection = gtk_tree_view_get_selection(list_view);
        if (! gtk_tree_selection_get_selected(selection, &model, &iter))
@@ -955,11 +1044,14 @@ static void completion_window_apply_selection(GtkTreeView *list_view, GtkEntry *
        }
 
        /* Process selected item */
-       gtk_tree_model_get(model, &iter, ADDR_COMPL_ADDRESS, &text, -1);
+       gtk_tree_model_get(model, &iter, ADDR_COMPL_ADDRESS, &text, 
+                               ADDR_COMPL_ISGROUP, &is_group, 
+                               ADDR_COMPL_GROUPLIST, &grp_emails,
+                               -1);
 
        address = get_address_from_edit(entry, &cursor_pos);
        g_free(address);
-       replace_address_in_edit(entry, text, cursor_pos);
+       replace_address_in_edit(entry, text, cursor_pos, is_group, grp_emails);
        g_free(text);
 
        /* Move focus to next widget */
@@ -994,13 +1086,14 @@ void address_completion_start(GtkWidget *mainwindow)
  * Register specified entry widget for address completion.
  * \param entry Address entry field.
  */
-void address_completion_register_entry(GtkEntry *entry)
+void address_completion_register_entry(GtkEntry *entry, gboolean allow_groups)
 {
        g_return_if_fail(entry != NULL);
        g_return_if_fail(GTK_IS_ENTRY(entry));
 
        /* add hooked property */
        g_object_set_data(G_OBJECT(entry), ENTRY_DATA_TAB_HOOK, entry);
+       g_object_set_data(G_OBJECT(entry), ENTRY_DATA_ALLOW_GROUPS, GINT_TO_POINTER(allow_groups));
 
        /* add keypress event */
        g_signal_connect_closure
@@ -1056,6 +1149,7 @@ static void address_completion_mainwindow_set_focus(GtkWindow *window,
        
        if (widget && GTK_IS_ENTRY(widget) &&
            g_object_get_data(G_OBJECT(widget), ENTRY_DATA_TAB_HOOK)) {
+               _allowGroups_ = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), ENTRY_DATA_ALLOW_GROUPS));
                clear_completion_cache();
        }
 }
@@ -1073,7 +1167,7 @@ static gboolean address_completion_entry_key_pressed(GtkEntry    *entry,
 {
        if (ev->keyval == GDK_Tab) {
                addrcompl_clear_queue();
-
+               _allowGroups_ = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(entry), ENTRY_DATA_ALLOW_GROUPS));
                if( address_completion_complete_address_in_entry( entry, TRUE ) ) {
                        /* route a void character to the default handler */
                        /* this is a dirty hack; we're actually changing a key
@@ -1137,20 +1231,17 @@ static gboolean address_completion_complete_address_in_entry(GtkEntry *entry,
                new = get_next_complete_address();
                g_free( new );
        }
-
 #ifndef USE_LDAP
        /* Select the address if there is only one match */
        if (ncount == 2) {
                /* Display selected address in entry field */           
                gchar *addr = get_complete_address(1);
-
-               if (addr) {
-                       replace_address_in_edit(entry, addr, cursor_pos);
-                       g_free(addr);
-               }
-
-               /* Discard the window */
-               clear_completion_cache();
+               if (addr && !strstr(addr, " <!--___group___-->")) {
+                       replace_address_in_edit(entry, addr, cursor_pos, FALSE, NULL);
+                       /* Discard the window */
+                       clear_completion_cache();
+               } 
+               g_free(addr);
        }
        /* Make sure that drop-down appears uniform! */
        else 
@@ -1194,7 +1285,8 @@ static void address_completion_create_completion_window( GtkEntry *entry_ )
                                       GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
        gtk_container_add(GTK_CONTAINER(window), scroll);
        gtk_container_add(GTK_CONTAINER(scroll), list_view);
-
+       gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll),
+               GTK_SHADOW_OUT);
        /* Use entry widget to create initial window */
        gdk_window_get_geometry(entry->window, &x, &y, &width, &height, &depth);
        gdk_window_get_deskrelative_origin (entry->window, &x, &y);
@@ -1278,7 +1370,7 @@ static gboolean completion_window_button_press(GtkWidget *widget,
                /* Clicked outside of completion window - restore */
                searchTerm = _compWindow_->searchTerm;
                g_free(get_address_from_edit(GTK_ENTRY(entry), &cursor_pos));
-               replace_address_in_edit(GTK_ENTRY(entry), searchTerm, cursor_pos);
+               replace_address_in_edit(GTK_ENTRY(entry), searchTerm, cursor_pos, FALSE, NULL);
        }
 
        clear_completion_cache();
@@ -1383,7 +1475,7 @@ static gboolean completion_window_key_press(GtkWidget *widget,
        /* some other key, let's restore the searchTerm (orignal text) */
        searchTerm = _compWindow_->searchTerm;
        g_free(get_address_from_edit(GTK_ENTRY(entry), &cursor_pos));
-       replace_address_in_edit(GTK_ENTRY(entry), searchTerm, cursor_pos);
+       replace_address_in_edit(GTK_ENTRY(entry), searchTerm, cursor_pos, FALSE, NULL);
 
        /* make sure anything we typed comes in the edit box */
        tmp_event.type       = event->type;
@@ -1444,7 +1536,10 @@ void addrcompl_teardown( void ) {
 static GtkListStore *addr_compl_create_store(void)
 {
        return gtk_list_store_new(N_ADDR_COMPL_COLUMNS,
+                                 GDK_TYPE_PIXBUF,
                                  G_TYPE_STRING,
+                                 G_TYPE_BOOLEAN,
+                                 G_TYPE_POINTER,
                                  -1);
 }
                                             
@@ -1477,6 +1572,11 @@ static void addr_compl_create_list_view_columns(GtkWidget *list_view)
        GtkTreeViewColumn *column;
        GtkCellRenderer *renderer;
 
+       renderer = gtk_cell_renderer_pixbuf_new();
+       column = gtk_tree_view_column_new_with_attributes
+               ("", renderer,
+                "pixbuf", ADDR_COMPL_ICON, NULL);
+       gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), column);          
        renderer = gtk_cell_renderer_text_new();
        column = gtk_tree_view_column_new_with_attributes
                ("", renderer, "text", ADDR_COMPL_ADDRESS, NULL);
index 10a4ebd17bf5a8e58aa942f79fa5c597d9cb7f7d..e8ac2abc6c7146e92e5143a7dd75e10e6a0b5938 100644 (file)
@@ -31,7 +31,7 @@ gint end_address_completion           (void);
 
 /* ui functions */
 void address_completion_start          (GtkWidget *mainwindow);
-void address_completion_register_entry (GtkEntry  *entry);
+void address_completion_register_entry (GtkEntry  *entry, gboolean allow_groups);
 void address_completion_unregister_entry(GtkEntry  *entry);
 void address_completion_end            (GtkWidget *mainwindow);
 
index 3f78f1d67be4e56db8a97d1c20e16c5014775867..9901d8b0cfde3167dd902abb2f082cc2b66944c7 100644 (file)
@@ -2248,6 +2248,12 @@ GList *addrbook_get_all_persons(AddressBookFile *book)
        return addrcache_get_all_persons(book->addressCache);
 }
 
+GList *addrbook_get_all_groups(AddressBookFile *book)
+{
+       g_return_val_if_fail(book != NULL, NULL);
+       return addrcache_get_all_groups(book->addressCache);
+}
+
 /**
  * Add person and address data to address book.
  * \param  book    Address book.
index 4dca736b3a295304b696e2a49c63c14244d5db5b..d67c9d442e9a2d555f991c112143f71692c61111 100644 (file)
@@ -109,6 +109,7 @@ gchar *addrbook_gen_new_file_name   ( gint fileNum );
 gint addrbook_test_read_file           ( AddressBookFile *book, gchar *fileName );
 
 GList *addrbook_get_all_persons                ( AddressBookFile *book );
+GList *addrbook_get_all_groups         ( AddressBookFile *book );
 
 ItemPerson *addrbook_add_contact       ( AddressBookFile *book, ItemFolder *folder,
                                          const gchar *name, const gchar *address,
index 9ed355baa1343542af2d576cb64b6a15d2fde574..36cbcead981285c258a95b8597d350bed4f3b0b0 100644 (file)
@@ -622,6 +622,8 @@ void addressbook_open(Compose *target)
        }
 
        gtk_widget_show_all(addrbook.window);
+       address_completion_start(addrbook.window);
+
        addressbook_show_buttons(target == NULL, lastCanLookup, target != NULL);
        addressbook_set_target_compose(target);
 }
@@ -979,7 +981,7 @@ static void addressbook_create(void)
        entry = gtk_entry_new();
        gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
 
-       address_completion_register_entry(GTK_ENTRY(entry));
+       address_completion_register_entry(GTK_ENTRY(entry), FALSE);
 
        g_signal_connect(G_OBJECT(entry), "key_press_event",
                         G_CALLBACK(addressbook_entry_key_pressed),
@@ -1137,7 +1139,6 @@ static void addressbook_create(void)
        addrbook.menu_factory = menu_factory;
 
        addrbook.listSelected = NULL;
-       address_completion_start(window);
 
        if (!geometry.min_height) {
                geometry.min_width = ADDRESSBOOK_WIDTH;
@@ -1156,6 +1157,7 @@ static void addressbook_create(void)
  * Close address book window and save to file(s).
  */
 static gint addressbook_close( void ) {
+       address_completion_end(addrbook.window);
        gtk_widget_hide(addrbook.window);
        addressbook_export_to_file();
        return TRUE;
@@ -2838,8 +2840,8 @@ static void addressbook_edit_address_cb( gpointer data, guint action, GtkWidget
                /* Edit person - basic page */
                ItemPerson *person = ( ItemPerson * ) obj;
                if( addressbook_edit_person( abf, NULL, person, FALSE ) == NULL ) return;
-               invalidate_address_completion();
                addressbook_folder_refresh_one_person( clist, person );
+               invalidate_address_completion();
                return;
        }
        else if( obj->type == ADDR_ITEM_GROUP ) {
@@ -2848,6 +2850,7 @@ static void addressbook_edit_address_cb( gpointer data, guint action, GtkWidget
                parentNode = addrbook.treeSelected;
                node = addressbook_find_group_node( parentNode, itemGrp );
                name = ADDRITEM_NAME(itemGrp);
+               invalidate_address_completion();
        }
        else {
                return;
index f98ca944c8dcf690988bd27e42a955964d7222d1..fee6e7177d7a9fb933d2311bd51ef2f8968058ee 100644 (file)
@@ -219,6 +219,7 @@ static void addrindex_build_if_list( AddressIndex *addrIndex ) {
        iface->getListFolder = ( void * ) addrbook_get_list_folder;
        iface->getListPerson = ( void * ) addrbook_get_list_person;
        iface->getAllPersons = ( void * ) addrbook_get_all_persons;
+       iface->getAllGroups  = ( void * ) addrbook_get_all_groups;
        iface->getName       = ( void * ) addrbook_get_name;
        iface->setAccessFlag = ( void * ) addrbook_set_accessed;
        iface->searchOrder   = 0;
@@ -2791,48 +2792,67 @@ void addrindex_remove_results( AddressDataSource *ds, ItemFolder *folder ) {
 
 static void addrindex_load_completion_load_persons(
                gint (*callBackFunc) ( const gchar *, const gchar *, 
-                                      const gchar *, const gchar * ),
+                                      const gchar *, const gchar *, GList * ),
                AddressDataSource *ds)
 {
        GList *listP, *nodeP;
        GList *nodeM;
        gchar *sName;
 
-                       /* Read address book */
-                       if( addrindex_ds_get_modify_flag( ds ) ) {
-                               addrindex_ds_read_data( ds );
-                       }
+       /* Read address book */
+       if( addrindex_ds_get_modify_flag( ds ) ) {
+               addrindex_ds_read_data( ds );
+       }
 
-                       if( ! addrindex_ds_get_read_flag( ds ) ) {
-                               addrindex_ds_read_data( ds );
-                       }
+       if( ! addrindex_ds_get_read_flag( ds ) ) {
+               addrindex_ds_read_data( ds );
+       }
 
-                       /* Get all persons */
-                       listP = addrindex_ds_get_all_persons( ds );
-                       nodeP = listP;
-                       while( nodeP ) {
-                               ItemPerson *person = nodeP->data;
-                               nodeM = person->listEMail;
+       /* Get all groups */
+       listP = addrindex_ds_get_all_groups( ds );
+       nodeP = listP;
+       while( nodeP ) {
+               ItemGroup *group = nodeP->data;
+               GList *emails = NULL;
+               for (nodeM = group->listEMail; nodeM; nodeM = g_list_next(nodeM)) {
+                       ItemEMail *email = nodeM->data;
+                       if (email->address)
+                               emails = g_list_append(emails, email);
+               }
+               callBackFunc( ((AddrItemObject *)group)->name, NULL,
+                             NULL, NULL, emails );
+               nodeP = g_list_next( nodeP );
+       }
 
-                               /* Figure out name to use */
-                               sName = ADDRITEM_NAME(person);
-                               if( sName == NULL || *sName == '\0' ) {
-                                       sName = person->nickName;
-                               }
+       /* Free up the list */
+       g_list_free( listP );
+       /* Get all persons */
+       listP = addrindex_ds_get_all_persons( ds );
+       nodeP = listP;
+       while( nodeP ) {
+               ItemPerson *person = nodeP->data;
+               nodeM = person->listEMail;
 
-                               /* Process each E-Mail address */
-                               while( nodeM ) {
-                                       ItemEMail *email = nodeM->data;
-                                       
-                                       callBackFunc( sName, email->address, person->nickName, 
-                                                     ADDRITEM_NAME(email) );
-                                       
-                                       nodeM = g_list_next( nodeM );
-                               }
-                               nodeP = g_list_next( nodeP );
-                       }
-                       /* Free up the list */
-                       g_list_free( listP );
+               /* Figure out name to use */
+               sName = ADDRITEM_NAME(person);
+               if( sName == NULL || *sName == '\0' ) {
+                       sName = person->nickName;
+               }
+
+               /* Process each E-Mail address */
+               while( nodeM ) {
+                       ItemEMail *email = nodeM->data;
+
+                       callBackFunc( sName, email->address, person->nickName, 
+                                     ADDRITEM_NAME(email), NULL );
+
+                       nodeM = g_list_next( nodeM );
+               }
+               nodeP = g_list_next( nodeP );
+       }
+
+       /* Free up the list */
+       g_list_free( listP );
 }              
 
 /**
@@ -2848,7 +2868,7 @@ static void addrindex_load_completion_load_persons(
 
 gboolean addrindex_load_completion(
                gint (*callBackFunc) ( const gchar *, const gchar *, 
-                                      const gchar *, const gchar * ),
+                                      const gchar *, const gchar *, GList * ),
                gchar *folderpath )
 {
        GList *nodeIf, *nodeDS;
@@ -2903,7 +2923,7 @@ gboolean addrindex_load_completion(
                                                ItemEMail *email = nodeM->data;
 
                                                callBackFunc( sName, email->address, person->nickName, 
-                                                                 ADDRITEM_NAME(email) );
+                                                                 ADDRITEM_NAME(email), NULL );
 
                                                nodeM = g_list_next( nodeM );
                                        }
index 31e089406658685dcc8e7b557ac2ac310f99ed81..e3c0c785cee8d0363d5749050658ad26bbcba121 100644 (file)
@@ -181,7 +181,7 @@ void addrindex_remove_results               ( AddressDataSource *ds,
 gboolean addrindex_load_completion(
                gint (*callBackFunc)
                        ( const gchar *, const gchar *, 
-                         const gchar *, const gchar * ),
+                         const gchar *, const gchar *, GList * ),
                        gchar *folderpath );
 
 gboolean addrindex_load_person_attribute( const gchar *attr,
index 2aab001fa76a23e3dc31d3ed714db4c56c81ae73..f53bf68df680d504475ad45977d8fcc953ac6080 100644 (file)
@@ -5469,7 +5469,7 @@ static void compose_create_header_entry(Compose *compose)
                         G_CALLBACK(compose_drag_drop),
                         compose);
        
-       address_completion_register_entry(GTK_ENTRY(entry));
+       address_completion_register_entry(GTK_ENTRY(entry), TRUE);
 
         headerentry->compose = compose;
         headerentry->combo = combo;
diff --git a/src/pixmaps/addr_one.xpm b/src/pixmaps/addr_one.xpm
new file mode 100644 (file)
index 0000000..3c64b06
--- /dev/null
@@ -0,0 +1,45 @@
+/* XPM */
+static char * addr_one_xpm[] = {
+"16 13 29 1",
+"      c None",
+".     c #161616",
+"+     c #4D4D4D",
+"@     c #F5F5F5",
+"#     c #F4F4F4",
+"$     c #373737",
+"%     c #F3F3F3",
+"&     c #C3C3C3",
+"*     c #EAEAEA",
+"=     c #EBEBEB",
+"-     c #ADADAD",
+";     c #424242",
+">     c #EFEFEF",
+",     c #F2F2F2",
+"'     c #454545",
+")     c #4C4C4C",
+"!     c #BEBEBE",
+"~     c #D7D7D7",
+"{     c #A3A3A3",
+"]     c #F1F1F1",
+"^     c #BCBCBC",
+"/     c #E9E9E9",
+"(     c #909090",
+"_     c #C1C1C1",
+":     c #DBDBDB",
+"<     c #CECECE",
+"[     c #AAAAAA",
+"}     c #D4D4D4",
+"|     c #2D2D2D",
+" ...........    ",
+".+@@@##@@##$.   ",
+".#+##@%#%#+&.   ",
+".#*+@##@#+=-.   ",
+".@##+@#@;>==.   ",
+".,@>+'#)+#,!.   ",
+".@%+#@+#,+~{.   ",
+".#+%#@]%,^$/.   ",
+".+{{(_^:<[}|.   ",
+" ...........    ",
+"                ",
+"                ",
+"                "};
diff --git a/src/pixmaps/addr_two.xpm b/src/pixmaps/addr_two.xpm
new file mode 100644 (file)
index 0000000..ac6d07a
--- /dev/null
@@ -0,0 +1,45 @@
+/* XPM */
+static char * addr_two_xpm[] = {
+"16 13 29 1",
+"      c None",
+".     c #161616",
+"+     c #4D4D4D",
+"@     c #F5F5F5",
+"#     c #F4F4F4",
+"$     c #373737",
+"%     c #EAEAEA",
+"&     c #F3F3F3",
+"*     c #C3C3C3",
+"=     c #F2F2F2",
+"-     c #EBEBEB",
+";     c #ADADAD",
+">     c #424242",
+",     c #EFEFEF",
+"'     c #454545",
+")     c #4C4C4C",
+"!     c #BEBEBE",
+"~     c #A3A3A3",
+"{     c #D7D7D7",
+"]     c #F1F1F1",
+"^     c #BCBCBC",
+"/     c #E9E9E9",
+"(     c #909090",
+"_     c #C1C1C1",
+":     c #DBDBDB",
+"<     c #CECECE",
+"[     c #AAAAAA",
+"}     c #D4D4D4",
+"|     c #2D2D2D",
+" ...........    ",
+".+@@@##@@##$.   ",
+".#+#........... ",
+".#%.+@@@##@@##$.",
+".@#.#+##@&#&#+*.",
+".=@.#%+@##@#+-;.",
+".@&.@##+@#@>,--.",
+".#+.=@,+'#)+#=!.",
+".+~.@&+#@+#=+{~.",
+" ...#+&#@]&=^$/.",
+"   .+~~(_^:<[}|.",
+"    ........... ",
+"                "};
index 20c0c3287e203d1422f8554a48878a394b063771..b2b9a9076885a5d082b6711e449378877af69b46 100644 (file)
@@ -95,13 +95,8 @@ static PrefParam param_os_specific[] = {
          &prefs_common.widgetfont,             P_STRING, NULL, NULL, NULL},
        {"message_font_gtk2",   "Monospace 9",
         &prefs_common.textfont,                P_STRING, NULL, NULL, NULL},
-<<<<<<< prefs_common.c
         {"print_font_gtk2",     "Monospace 9",
          &prefs_common.printfont,              P_STRING, NULL, NULL, NULL},
-=======
-       {"print_font_gtk2",     "Monospace 9",
-        &prefs_common.printfont,               P_STRING, NULL, NULL, NULL},
->>>>>>> 1.204.2.101
        {"small_font_gtk2",     "Sans 9",
          &prefs_common.smallfont,              P_STRING, NULL, NULL, NULL},
        {"normal_font_gtk2",    "Sans 9",
index 3c2e3b38703de38cd943659fb5cc614692b8a238..a3b200854655a1b97efe5422a9ba5a8291df594c 100644 (file)
@@ -1138,11 +1138,15 @@ static void prefs_filtering_action_type_selection_changed(GtkList *list,
                ||  filtering_action.current_action == ACTION_REDIRECT) {
                        debug_print("unregistering address completion entry\n");
                        address_completion_unregister_entry(GTK_ENTRY(filtering_action.dest_entry));
+                       address_completion_end(filtering_action.window);
                }
                if (value == ACTION_FORWARD || value == ACTION_FORWARD_AS_ATTACHMENT
                ||  value == ACTION_REDIRECT) {
                        debug_print("registering address completion entry\n");
-                       address_completion_register_entry(GTK_ENTRY(filtering_action.dest_entry));
+                       address_completion_start(filtering_action.window);
+                       address_completion_register_entry(
+                                       GTK_ENTRY(filtering_action.dest_entry),
+                                       TRUE);
                }
                filtering_action.current_action = value;
        }
index a5904278b253bf3f8a1f9516dd1e6daece28eb7f..505c1bdcaef1375f89fbe9c595ef1754e751494b 100644 (file)
@@ -611,7 +611,8 @@ void prefs_folder_item_compose_create_widget_func(PrefsPage * page_,
                                 rowcount, rowcount + 1, GTK_EXPAND | GTK_FILL, GTK_SHRINK, 0, 0);
                SET_TOGGLE_SENSITIVITY(checkbtn_default_to, entry_default_to);
                gtk_entry_set_text(GTK_ENTRY(entry_default_to), SAFE_STRING(item->prefs->default_to));
-               address_completion_register_entry(GTK_ENTRY(entry_default_to));
+               address_completion_register_entry(GTK_ENTRY(entry_default_to),
+                               TRUE);
 
                default_to_rec_checkbtn = gtk_check_button_new();
                gtk_table_attach(GTK_TABLE(table), default_to_rec_checkbtn, 2, 3, 
@@ -631,7 +632,8 @@ void prefs_folder_item_compose_create_widget_func(PrefsPage * page_,
                                 rowcount, rowcount + 1, GTK_EXPAND | GTK_FILL, GTK_SHRINK, 0, 0);
                SET_TOGGLE_SENSITIVITY(checkbtn_default_reply_to, entry_default_reply_to);
                gtk_entry_set_text(GTK_ENTRY(entry_default_reply_to), SAFE_STRING(item->prefs->default_reply_to));
-               address_completion_register_entry(GTK_ENTRY(entry_default_reply_to));
+               address_completion_register_entry(
+                               GTK_ENTRY(entry_default_reply_to), TRUE);
 
                default_reply_to_rec_checkbtn = gtk_check_button_new();
                gtk_table_attach(GTK_TABLE(table), default_reply_to_rec_checkbtn, 2, 3, 
index d703ddf48320af84f8c9a051bac8e27bbab0fe3b..d792fc3fb1c943b5fe142c2583e631dd603f1098 100644 (file)
@@ -210,7 +210,8 @@ static void prefs_template_window_create(void)
                gtk_tooltips_set_tip(tooltips, *(tab[i].entry), tab[i].tooltips, NULL);
 
                if (tab[i].compl)
-                       address_completion_register_entry(GTK_ENTRY(*(tab[i].entry)));
+                       address_completion_register_entry(
+                               GTK_ENTRY(*(tab[i].entry)), TRUE);
        }
 
        /* template content */
index fbe04d90b855dc5764aee787070bf4b9e41b688b..47f4043d30be24bcb700e6c765979c0378aad362 100644 (file)
@@ -29,6 +29,8 @@
 #include "utils.h"
 #include "prefs_common.h"
 
+#include "pixmaps/addr_one.xpm"
+#include "pixmaps/addr_two.xpm"
 #include "pixmaps/address.xpm"
 #include "pixmaps/book.xpm"
 #include "pixmaps/category.xpm"
@@ -172,6 +174,8 @@ static void stock_pixmap_find_themes_in_dir(GList **list, const gchar *dirname);
 
 static StockPixmapData pixmaps[] =
 {
+       {addr_one_xpm                           , NULL, NULL, "addr_one", NULL},
+       {addr_two_xpm                           , NULL, NULL, "addr_two", NULL},
        {address_xpm                            , NULL, NULL, "address", NULL},
        {address_book_xpm                       , NULL, NULL, "address_book", NULL},
        {address_search_xpm                     , NULL, NULL, "address_search", NULL},
index b9922b2e7ca14a7d261ffd856b7026a6fb69d3e7..bf531d13d9585c453a61506896c55d66ec4058fb 100644 (file)
@@ -25,6 +25,8 @@
 
 typedef enum
 {
+       STOCK_PIXMAP_ADDR_ONE,
+       STOCK_PIXMAP_ADDR_TWO,
        STOCK_PIXMAP_ADDRESS,
        STOCK_PIXMAP_ADDRESS_BOOK,
        STOCK_PIXMAP_ADDRESS_SEARCH,