2007-04-27 [colin] 2.9.1cvs31
authorColin Leroy <colin@colino.net>
Fri, 27 Apr 2007 17:12:06 +0000 (17:12 +0000)
committerColin Leroy <colin@colino.net>
Fri, 27 Apr 2007 17:12:06 +0000 (17:12 +0000)
* src/folder.c
Freeze/thaw when sync'ing flags
* src/imap.c
* src/prefs_account.c
* src/prefs_account.h
* src/etpan/imap-thread.c
* src/etpan/imap-thread.h
Add a way to use UID FETCH instead
of searches to fetch message lists
and flags. More expensive towards
bandwidth, less expensive towards
server's CPU. Probably fixes
bug 1158, 'Scanning new folders on
Exchange 2007 extremely slow'.
Patch 95% by Hoa.

ChangeLog
PATCHSETS
configure.ac
src/etpan/imap-thread.c
src/etpan/imap-thread.h
src/folder.c
src/imap.c
src/prefs_account.c
src/prefs_account.h

index 26568d130fc043d12b9a193a5cf8801535198154..61f205f06ad3e39c16ac8a823379727ea4e1b3f3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2007-04-27 [colin]     2.9.1cvs31
+
+       * src/folder.c
+               Freeze/thaw when sync'ing flags
+       * src/imap.c
+       * src/prefs_account.c
+       * src/prefs_account.h
+       * src/etpan/imap-thread.c
+       * src/etpan/imap-thread.h
+               Add a way to use UID FETCH instead
+               of searches to fetch message lists
+               and flags. More expensive towards
+               bandwidth, less expensive towards
+               server's CPU. Probably fixes 
+               bug 1158, 'Scanning new folders on 
+               Exchange 2007 extremely slow'.
+               Patch 95% by Hoa.
+
 2007-04-27 [paul]      2.9.1cvs30
 
        * src/mainwindow.c
index af56c0cb677e3b035661a15dcadb531259c327c2..252f1d4e4a1052034b3ae7d3d36469bb3e621cd7 100644 (file)
--- a/PATCHSETS
+++ b/PATCHSETS
 ( cvs diff -u -r 1.179.2.168 -r 1.179.2.169 src/imap.c;  cvs diff -u -r 1.34.2.15 -r 1.34.2.16 src/imap.h;  cvs diff -u -r 1.96.2.170 -r 1.96.2.171 src/textview.c;  ) > 2.9.1cvs28.patchset
 ( cvs diff -u -r 1.179.2.169 -r 1.179.2.170 src/imap.c;  ) > 2.9.1cvs29.patchset
 ( cvs diff -u -r 1.274.2.186 -r 1.274.2.187 src/mainwindow.c;  cvs diff -u -r 1.1.2.3 -r 1.1.2.4 src/prefs_logging.c;  ) > 2.9.1cvs30.patchset
+( cvs diff -u -r 1.213.2.142 -r 1.213.2.143 src/folder.c;  cvs diff -u -r 1.179.2.170 -r 1.179.2.171 src/imap.c;  cvs diff -u -r 1.105.2.92 -r 1.105.2.93 src/prefs_account.c;  cvs diff -u -r 1.49.2.25 -r 1.49.2.26 src/prefs_account.h;  cvs diff -u -r 1.1.4.78 -r 1.1.4.79 src/etpan/imap-thread.c;  cvs diff -u -r 1.1.4.15 -r 1.1.4.16 src/etpan/imap-thread.h;  ) > 2.9.1cvs31.patchset
index 75eee963c40487e7254932c96148a8f8ef0823ef..4f9014935fc8a03fd683dc64cce260cd33a1e101 100644 (file)
@@ -11,7 +11,7 @@ MINOR_VERSION=9
 MICRO_VERSION=1
 INTERFACE_AGE=0
 BINARY_AGE=0
-EXTRA_VERSION=30
+EXTRA_VERSION=31
 EXTRA_RELEASE=
 EXTRA_GTK2_VERSION=
 
index 826f75e2e46d4da18d8368a0b6429f43012b3d1e..28fb56c82d4cb6bef688084a5c6a018a06e72374 100644 (file)
@@ -1524,15 +1524,19 @@ int imap_threaded_search(Folder * folder, int search_type,
 
 
 
+static int imap_get_msg_att_info(struct mailimap_msg_att * msg_att,
+                                uint32_t * puid,
+                                char ** pheaders,
+                                size_t * pref_size,
+                                struct mailimap_msg_att_dynamic ** patt_dyn);
 
 static int
-uid_list_to_env_list(clist * fetch_result, carray ** result)
+result_to_uid_list(clist * fetch_result, carray ** result)
 {
        clistiter * cur;
        int r;
        int res;
        carray * tab;
-       unsigned int i;
        
        tab = carray_new(128);
        if (tab == NULL) {
@@ -1543,31 +1547,13 @@ uid_list_to_env_list(clist * fetch_result, carray ** result)
        for(cur = clist_begin(fetch_result) ; cur != NULL ;
            cur = clist_next(cur)) {
                struct mailimap_msg_att * msg_att;
-               clistiter * item_cur;
                uint32_t uid;
-               size_t size;
                uint32_t * puid;
                
                msg_att = clist_content(cur);
                
                uid = 0;
-               size = 0;
-               for(item_cur = clist_begin(msg_att->att_list) ;
-                   item_cur != NULL ;
-                   item_cur = clist_next(item_cur)) {
-                       struct mailimap_msg_att_item * item;
-                       
-                       item = clist_content(item_cur);
-                       
-                       switch (item->att_type) {
-                       case MAILIMAP_MSG_ATT_ITEM_STATIC:
-                               switch (item->att_data.att_static->att_type) {
-                               case MAILIMAP_MSG_ATT_UID:
-                                       uid = item->att_data.att_static->att_data.att_uid;
-                                       break;
-                               }
-                       }
-               }
+               imap_get_msg_att_info(msg_att, &uid, NULL, NULL, NULL);
                
                puid = malloc(sizeof(* puid));
                if (puid == NULL) {
@@ -1589,8 +1575,7 @@ uid_list_to_env_list(clist * fetch_result, carray ** result)
        return MAILIMAP_NO_ERROR;
   
  free_list:
-       for(i = 0 ; i < carray_count(tab) ; i++)
-               mailmessage_free(carray_get(tab, i));
+       imap_fetch_uid_list_free(tab);
  err:
        return res;
 }
@@ -1644,7 +1629,7 @@ static int imap_get_messages_list(mailimap * imap,
        }
 
        env_list = NULL;
-       r = uid_list_to_env_list(fetch_result, &env_list);
+       r = result_to_uid_list(fetch_result, &env_list);
        mailimap_fetch_list_free(fetch_result);
        
        * result = env_list;
@@ -1685,9 +1670,14 @@ static void fetch_uid_run(struct etpan_thread_op * op)
        CHECK_IMAP();
 
        fetch_result = NULL;
+       mailstream_logger = NULL;
+       log_print(LOG_PROTOCOL, "IMAP4- [fetching UIDs...]\n");
+
        r = imap_get_messages_list(param->imap, param->first_index,
                                   &fetch_result);
        
+       mailstream_logger = imap_logger_cmd;
+
        result->error = r;
        result->fetch_result = fetch_result;
        debug_print("imap fetch_uid run - end %i\n", r);
@@ -1734,6 +1724,228 @@ void imap_fetch_uid_list_free(carray * uid_list)
 
 
 
+
+static int imap_flags_to_flags(struct mailimap_msg_att_dynamic * att_dyn);
+
+static int
+result_to_uid_flags_list(clist * fetch_result, carray ** result)
+{
+       clistiter * cur;
+       int r;
+       int res;
+       carray * tab;
+       
+       tab = carray_new(128);
+       if (tab == NULL) {
+               res = MAILIMAP_ERROR_MEMORY;
+               goto err;
+       }
+       
+       for(cur = clist_begin(fetch_result) ; cur != NULL ;
+           cur = clist_next(cur)) {
+               struct mailimap_msg_att * msg_att;
+               uint32_t uid;
+               uint32_t * puid;
+               struct mailimap_msg_att_dynamic * att_dyn;
+               int flags;
+               int * pflags;
+               
+               msg_att = clist_content(cur);
+               
+               uid = 0;
+               att_dyn = NULL;
+               imap_get_msg_att_info(msg_att, &uid, NULL, NULL, &att_dyn);
+               if (uid == 0)
+                       continue;
+               if (att_dyn == NULL)
+                       continue;
+               
+               flags = imap_flags_to_flags(att_dyn);
+               
+               puid = malloc(sizeof(* puid));
+               if (puid == NULL) {
+                       res = MAILIMAP_ERROR_MEMORY;
+                       goto free_list;
+               }
+               * puid = uid;
+               
+               r = carray_add(tab, puid, NULL);
+               if (r < 0) {
+                       free(puid);
+                       res = MAILIMAP_ERROR_MEMORY;
+                       goto free_list;
+               }
+               pflags = malloc(sizeof(* pflags));
+               if (pflags == NULL) {
+                       res = MAILIMAP_ERROR_MEMORY;
+                       goto free_list;
+               }
+               * pflags = flags;
+               r = carray_add(tab, pflags, NULL);
+               if (r < 0) {
+                       free(pflags);
+                       res = MAILIMAP_ERROR_MEMORY;
+                       goto free_list;
+               }
+       }
+               
+       * result = tab;
+
+       return MAILIMAP_NO_ERROR;
+  
+ free_list:
+       imap_fetch_uid_flags_list_free(tab);
+ err:
+       return res;
+}
+
+static int imap_get_messages_flags_list(mailimap * imap,
+                                       uint32_t first_index,
+                                       carray ** result)
+{
+       carray * env_list;
+       int r;
+       struct mailimap_fetch_att * fetch_att;
+       struct mailimap_fetch_type * fetch_type;
+       struct mailimap_set * set;
+       clist * fetch_result;
+       int res;
+       
+       set = mailimap_set_new_interval(first_index, 0);
+       if (set == NULL) {
+               res = MAILIMAP_ERROR_MEMORY;
+               goto err;
+       }
+
+       fetch_type = mailimap_fetch_type_new_fetch_att_list_empty();
+       if (fetch_type == NULL) {
+               res = MAILIMAP_ERROR_MEMORY;
+               goto free_set;
+       }
+
+       fetch_att = mailimap_fetch_att_new_flags();
+       if (fetch_att == NULL) {
+               res = MAILIMAP_ERROR_MEMORY;
+               goto free_fetch_type;
+       }
+       
+       r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
+       if (r != MAILIMAP_NO_ERROR) {
+               mailimap_fetch_att_free(fetch_att);
+               res = MAILIMAP_ERROR_MEMORY;
+               goto free_fetch_type;
+       }
+       
+       fetch_att = mailimap_fetch_att_new_uid();
+       if (fetch_att == NULL) {
+               res = MAILIMAP_ERROR_MEMORY;
+               goto free_fetch_type;
+       }
+
+       r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
+       if (r != MAILIMAP_NO_ERROR) {
+               mailimap_fetch_att_free(fetch_att);
+               res = MAILIMAP_ERROR_MEMORY;
+               goto free_fetch_type;
+       }
+
+       r = mailimap_uid_fetch(imap, set,
+                              fetch_type, &fetch_result);
+
+       mailimap_fetch_type_free(fetch_type);
+       mailimap_set_free(set);
+
+       if (r != MAILIMAP_NO_ERROR) {
+               res = r;
+               goto err;
+       }
+
+       env_list = NULL;
+       r = result_to_uid_flags_list(fetch_result, &env_list);
+       mailimap_fetch_list_free(fetch_result);
+       
+       * result = env_list;
+
+       return MAILIMAP_NO_ERROR;
+
+ free_fetch_type:
+       mailimap_fetch_type_free(fetch_type);
+ free_set:
+       mailimap_set_free(set);
+ err:
+       return res;
+}
+
+
+
+static void fetch_uid_flags_run(struct etpan_thread_op * op)
+{
+       struct fetch_uid_param * param;
+       struct fetch_uid_result * result;
+       carray * fetch_result;
+       int r;
+       
+       param = op->param;
+       result = op->result;
+
+       CHECK_IMAP();
+
+       fetch_result = NULL;
+       r = imap_get_messages_flags_list(param->imap, param->first_index,
+                                        &fetch_result);
+       
+       result->error = r;
+       result->fetch_result = fetch_result;
+       debug_print("imap fetch_uid run - end %i\n", r);
+}
+
+int imap_threaded_fetch_uid_flags(Folder * folder, uint32_t first_index,
+                                 carray ** fetch_result)
+{
+       struct fetch_uid_param param;
+       struct fetch_uid_result result;
+       mailimap * imap;
+       
+       debug_print("imap fetch_uid - begin\n");
+       
+       imap = get_imap(folder);
+       param.imap = imap;
+       param.first_index = first_index;
+       
+       mailstream_logger = NULL;
+       log_print(LOG_PROTOCOL, "IMAP4- [fetching flags...]\n");
+
+       threaded_run(folder, &param, &result, fetch_uid_flags_run);
+
+       mailstream_logger = imap_logger_cmd;
+
+       
+       if (result.error != MAILIMAP_NO_ERROR)
+               return result.error;
+       
+       debug_print("imap fetch_uid - end\n");
+       
+       * fetch_result = result.fetch_result;
+       
+       return result.error;
+}
+
+
+void imap_fetch_uid_flags_list_free(carray * uid_flags_list)
+{
+       unsigned int i;
+       
+       for(i = 0 ; i < carray_count(uid_flags_list) ; i ++) {
+               void * data;
+               
+               data = carray_get(uid_flags_list, i);
+               free(data);
+       }
+       carray_free(uid_flags_list);
+}
+
+
+
 static int imap_fetch(mailimap * imap,
                      uint32_t msg_index,
                      char ** result,
index 98c7f308a99d19d6b27ccea654bac6ad43759dd8..8facbfe580225b75d9f57984f95e7e6263c5cfc0 100644 (file)
@@ -86,6 +86,11 @@ int imap_threaded_fetch_uid(Folder * folder, uint32_t first_index,
 
 void imap_fetch_uid_list_free(carray * uid_list);
 
+int imap_threaded_fetch_uid_flags(Folder * folder, uint32_t first_index,
+                                 carray ** fetch_result);
+
+void imap_fetch_uid_flags_list_free(carray * uid_flags_list);
+
 int imap_threaded_fetch_content(Folder * folder, uint32_t msg_index,
                                int with_body,
                                const char * filename);
index 71059a3109557f321b1ef3243a2286b249948513..438743acdec6f62fd9bc4771ccb530617226af5a 100644 (file)
@@ -1779,6 +1779,7 @@ static gint syncronize_flags(FolderItem *item, MsgInfoList *msglist)
                MsgPermFlags permflags = 0;
                gboolean skip;
 
+               folder_item_update_freeze();
                for (cur = msglist; cur != NULL; cur = g_slist_next(cur)) {
                        msginfo = (MsgInfo *) cur->data;
                
@@ -1796,6 +1797,7 @@ static gint syncronize_flags(FolderItem *item, MsgInfoList *msglist)
                                        ~permflags & msginfo->flags.perm_flags, 0);
                        }
                }
+               folder_item_update_thaw();
        }
        folder_item_set_batch(item, FALSE);
        g_relation_destroy(relation);   
index 6c1d3dce2bed3900af2c316b621966777d5e4c55..dc23059e56d76d36df497435b547c4fd72cf6ea2 100644 (file)
@@ -401,6 +401,9 @@ static GSList * imap_get_lep_set_from_numlist(MsgNumberList *numlist);
 static GSList * imap_get_lep_set_from_msglist(MsgInfoList *msglist);
 static GSList * imap_uid_list_from_lep(clist * list);
 static GSList * imap_uid_list_from_lep_tab(carray * list);
+static GSList * imap_uid_list_from_lep_uid_flags_tab(carray * list);
+static void imap_flags_hash_from_lep_uid_flags_tab(carray * list,
+                                                  GHashTable * hash);
 static MsgInfo *imap_envelope_from_lep(struct imap_fetch_env_info * info,
                                       FolderItem *item);
 static void imap_lep_set_free(GSList *seq_list);
@@ -3330,8 +3333,8 @@ static void *get_list_of_uids_thread(void *data)
        gint ok, nummsgs = 0, lastuid_old;
        IMAPSession *session;
        GSList *uidlist, *elem;
+       int r = -1;
        clist * lep_uidlist;
-       int r;
 
        session = stuff->session;
        if (session == NULL) {
@@ -3348,32 +3351,34 @@ static void *get_list_of_uids_thread(void *data)
 
        uidlist = NULL;
        
-       r = imap_threaded_search(folder, IMAP_SEARCH_TYPE_SIMPLE, NULL,
+       if (folder->account && folder->account->low_bandwidth) {
+               r = imap_threaded_search(folder, IMAP_SEARCH_TYPE_SIMPLE, NULL,
                                 &lep_uidlist);
+       }
        
        if (r == MAILIMAP_NO_ERROR) {
-               GSList * fetchuid_list;
-               
-               fetchuid_list =
+               GSList * fetchuid_list =
                        imap_uid_list_from_lep(lep_uidlist);
                mailimap_search_result_free(lep_uidlist);
                
                uidlist = g_slist_concat(fetchuid_list, uidlist);
-       }
-       else {
-               GSList * fetchuid_list;
+       } else {
                carray * lep_uidtab;
-               
-               r = imap_threaded_fetch_uid(folder, item->lastuid + 1,
-                                           &lep_uidtab);
+               r = imap_threaded_fetch_uid(folder, 1,
+                                   &lep_uidtab);
                if (r == MAILIMAP_NO_ERROR) {
-                       fetchuid_list =
+                       GSList * fetchuid_list =
                                imap_uid_list_from_lep_tab(lep_uidtab);
                        imap_fetch_uid_list_free(lep_uidtab);
                        uidlist = g_slist_concat(fetchuid_list, uidlist);
                }
        }
        
+       if (r != MAILIMAP_NO_ERROR) {
+               stuff->done = TRUE;
+               return GINT_TO_POINTER(-1);
+       }
+
        lastuid_old = item->lastuid;
        *msgnum_list = g_slist_copy(item->uid_list);
        nummsgs = g_slist_length(*msgnum_list);
@@ -3973,39 +3978,35 @@ static /*gint*/ void *imap_get_flags_thread(void *data)
 {
        get_flags_data *stuff = (get_flags_data *)data;
        Folder *folder = stuff->folder;
-       FolderItem *item = stuff->item;
+       FolderItem *fitem = (FolderItem *) stuff->item;
        MsgInfoList *msginfo_list = stuff->msginfo_list;
        GRelation *msgflags = stuff->msgflags;
-       gboolean full_search = stuff->full_search;
+       GSList *elem;
+       GSList * fetchuid_list;
+       carray * lep_uidtab;
        IMAPSession *session;
+       gint ok;
+       int r;
+       GHashTable *flags_hash = NULL;
+       gboolean full_search = stuff->full_search;
        GSList *sorted_list = NULL;
        GSList *unseen = NULL, *answered = NULL, *flagged = NULL, *deleted = NULL;
        GSList *p_unseen, *p_answered, *p_flagged, *p_deleted;
-       GSList *elem;
        GSList *seq_list, *cur;
        gboolean reverse_seen = FALSE;
-       GString *cmd_buf;
-       gint ok;
-       gint exists_cnt, unseen_cnt;
        gboolean selected_folder;
+       gint exists_cnt, unseen_cnt;
        
-       if (folder == NULL || item == NULL) {
-               stuff->done = TRUE;
-               return GINT_TO_POINTER(-1);
-       }
-
-       debug_print("getting session...\n");
        session = imap_session_get(folder);
        if (session == NULL) {
                stuff->done = TRUE;
                return GINT_TO_POINTER(-1);
        }
-
        selected_folder = (session->mbox != NULL) &&
-                         (!strcmp(session->mbox, item->path));
+                         (!strcmp(session->mbox, fitem->path));
 
        if (!selected_folder) {
-               ok = imap_select(session, IMAP_FOLDER(folder), item->path,
+               ok = imap_select(session, IMAP_FOLDER(folder), fitem->path,
                        &exists_cnt, NULL, &unseen_cnt, NULL, TRUE);
                if (ok != IMAP_SUCCESS) {
                        stuff->done = TRUE;
@@ -4017,12 +4018,10 @@ static /*gint*/ void *imap_get_flags_thread(void *data)
                        reverse_seen = TRUE;
        } 
        else {
-               if (item->unread_msgs > item->total_msgs / 2)
+               if (fitem->unread_msgs > fitem->total_msgs / 2)
                        reverse_seen = TRUE;
        }
 
-       cmd_buf = g_string_new(NULL);
-
        sorted_list = g_slist_sort(g_slist_copy(msginfo_list), compare_msginfo);
        if (!full_search) {
                seq_list = imap_get_lep_set_from_msglist(msginfo_list);
@@ -4032,54 +4031,32 @@ static /*gint*/ void *imap_get_flags_thread(void *data)
                seq_list = g_slist_append(NULL, set);
        }
 
-       for (cur = seq_list; cur != NULL; cur = g_slist_next(cur)) {
-               struct mailimap_set * imapset;
-               clist * lep_uidlist;
-               int r;
-               
-               imapset = cur->data;
-               if (reverse_seen) {
-                       r = imap_threaded_search(folder, IMAP_SEARCH_TYPE_SEEN,
-                                                full_search ? NULL:imapset, &lep_uidlist);
-               }
-               else {
-                       r = imap_threaded_search(folder,
-                                                IMAP_SEARCH_TYPE_UNSEEN,
-                                                full_search ? NULL:imapset, &lep_uidlist);
-               }
-               if (r == MAILIMAP_NO_ERROR) {
-                       GSList * uidlist;
-                       
-                       uidlist = imap_uid_list_from_lep(lep_uidlist);
-                       mailimap_search_result_free(lep_uidlist);
-                       
-                       unseen = g_slist_concat(unseen, uidlist);
-               }
-               
-               r = imap_threaded_search(folder, IMAP_SEARCH_TYPE_FLAGGED,
-                                        full_search ? NULL:imapset, &lep_uidlist);
-               if (r == MAILIMAP_NO_ERROR) {
-                       GSList * uidlist;
+       if (folder->account && folder->account->low_bandwidth) {
+               for (cur = seq_list; cur != NULL; cur = g_slist_next(cur)) {
+                       struct mailimap_set * imapset;
+                       clist * lep_uidlist;
+                       int r;
 
-                       uidlist = imap_uid_list_from_lep(lep_uidlist);
-                       mailimap_search_result_free(lep_uidlist);
-
-                       flagged = g_slist_concat(flagged, uidlist);
-               }
-
-               if (item->opened || item->processing_pending || item == folder->inbox) {
-                       r = imap_threaded_search(folder, IMAP_SEARCH_TYPE_ANSWERED,
-                                                full_search ? NULL:imapset, &lep_uidlist);
+                       imapset = cur->data;
+                       if (reverse_seen) {
+                               r = imap_threaded_search(folder, IMAP_SEARCH_TYPE_SEEN,
+                                                        full_search ? NULL:imapset, &lep_uidlist);
+                       }
+                       else {
+                               r = imap_threaded_search(folder,
+                                                        IMAP_SEARCH_TYPE_UNSEEN,
+                                                        full_search ? NULL:imapset, &lep_uidlist);
+                       }
                        if (r == MAILIMAP_NO_ERROR) {
                                GSList * uidlist;
 
                                uidlist = imap_uid_list_from_lep(lep_uidlist);
                                mailimap_search_result_free(lep_uidlist);
 
-                               answered = g_slist_concat(answered, uidlist);
+                               unseen = g_slist_concat(unseen, uidlist);
                        }
 
-                       r = imap_threaded_search(folder, IMAP_SEARCH_TYPE_DELETED,
+                       r = imap_threaded_search(folder, IMAP_SEARCH_TYPE_FLAGGED,
                                                 full_search ? NULL:imapset, &lep_uidlist);
                        if (r == MAILIMAP_NO_ERROR) {
                                GSList * uidlist;
@@ -4087,56 +4064,111 @@ static /*gint*/ void *imap_get_flags_thread(void *data)
                                uidlist = imap_uid_list_from_lep(lep_uidlist);
                                mailimap_search_result_free(lep_uidlist);
 
-                               deleted = g_slist_concat(deleted, uidlist);
+                               flagged = g_slist_concat(flagged, uidlist);
+                       }
+
+                       if (fitem->opened || fitem->processing_pending || fitem == folder->inbox) {
+                               r = imap_threaded_search(folder, IMAP_SEARCH_TYPE_ANSWERED,
+                                                        full_search ? NULL:imapset, &lep_uidlist);
+                               if (r == MAILIMAP_NO_ERROR) {
+                                       GSList * uidlist;
+
+                                       uidlist = imap_uid_list_from_lep(lep_uidlist);
+                                       mailimap_search_result_free(lep_uidlist);
+
+                                       answered = g_slist_concat(answered, uidlist);
+                               }
+
+                               r = imap_threaded_search(folder, IMAP_SEARCH_TYPE_DELETED,
+                                                        full_search ? NULL:imapset, &lep_uidlist);
+                               if (r == MAILIMAP_NO_ERROR) {
+                                       GSList * uidlist;
+
+                                       uidlist = imap_uid_list_from_lep(lep_uidlist);
+                                       mailimap_search_result_free(lep_uidlist);
+
+                                       deleted = g_slist_concat(deleted, uidlist);
+                               }
                        }
                }
-       }
+               p_unseen = unseen;
+               p_answered = answered;
+               p_flagged = flagged;
+               p_deleted = deleted;
 
-       p_unseen = unseen;
-       p_answered = answered;
-       p_flagged = flagged;
-       p_deleted = deleted;
+       } else {
+               r = imap_threaded_fetch_uid_flags(folder, 1, &lep_uidtab);
+               if (r == MAILIMAP_NO_ERROR) {
+                       fetchuid_list =
+                               imap_uid_list_from_lep_uid_flags_tab(lep_uidtab);
 
+                       flags_hash = g_hash_table_new_full(g_int_hash, g_int_equal, free, NULL);
+                       imap_flags_hash_from_lep_uid_flags_tab(lep_uidtab, flags_hash);
+                       imap_fetch_uid_flags_list_free(lep_uidtab);
+               }
+       }
        for (elem = sorted_list; elem != NULL; elem = g_slist_next(elem)) {
                MsgInfo *msginfo;
                MsgPermFlags flags;
-               gboolean wasnew;
+               gboolean wasnew, waspostfiltered;
                
                msginfo = (MsgInfo *) elem->data;
                flags = msginfo->flags.perm_flags;
                wasnew = (flags & MSG_NEW);
-               if (item->opened || item->processing_pending || item == folder->inbox) {
-                       flags &= ~((reverse_seen ? 0 : MSG_UNREAD | MSG_NEW) | MSG_REPLIED | MSG_MARKED);
-               } else {
-                       flags &= ~((reverse_seen ? 0 : MSG_UNREAD | MSG_NEW | MSG_MARKED));
-               }
-               if (reverse_seen)
-                       flags |= MSG_UNREAD | (wasnew ? MSG_NEW : 0);
-               if (gslist_find_next_num(&p_unseen, msginfo->msgnum) == msginfo->msgnum) {
-                       if (!reverse_seen) {
-                               flags |= MSG_UNREAD | (wasnew ? MSG_NEW : 0);
+               waspostfiltered = (flags & MSG_POSTFILTERED);
+       
+               if (folder->account && folder->account->low_bandwidth) {
+                       if (fitem->opened || fitem->processing_pending || fitem == folder->inbox) {
+                               flags &= ~((reverse_seen ? 0 : MSG_UNREAD | MSG_NEW) | MSG_REPLIED | MSG_MARKED);
                        } else {
-                               flags &= ~(MSG_UNREAD | MSG_NEW);
+                               flags &= ~((reverse_seen ? 0 : MSG_UNREAD | MSG_NEW | MSG_MARKED));
+                       }
+                       if (reverse_seen)
+                               flags |= MSG_UNREAD | (wasnew ? MSG_NEW : 0);
+                       if (gslist_find_next_num(&p_unseen, msginfo->msgnum) == msginfo->msgnum) {
+                               if (!reverse_seen) {
+                                       flags |= MSG_UNREAD | (wasnew ? MSG_NEW : 0);
+                               } else {
+                                       flags &= ~(MSG_UNREAD | MSG_NEW);
+                               }
                        }
-               }
-               
-               if (gslist_find_next_num(&p_flagged, msginfo->msgnum) == msginfo->msgnum)
-                       flags |= MSG_MARKED;
-               else
-                       flags &= ~MSG_MARKED;
 
-               if (item->opened || item->processing_pending || item == folder->inbox) {
-                       if (gslist_find_next_num(&p_answered, msginfo->msgnum) == msginfo->msgnum)
-                               flags |= MSG_REPLIED;
-                       else
-                               flags &= ~MSG_REPLIED;
-                       if (gslist_find_next_num(&p_deleted, msginfo->msgnum) == msginfo->msgnum)
-                               flags |= MSG_DELETED;
+                       if (gslist_find_next_num(&p_flagged, msginfo->msgnum) == msginfo->msgnum)
+                               flags |= MSG_MARKED;
                        else
-                               flags &= ~MSG_DELETED;
+                               flags &= ~MSG_MARKED;
+
+                       if (fitem->opened || fitem->processing_pending || fitem == folder->inbox) {
+                               if (gslist_find_next_num(&p_answered, msginfo->msgnum) == msginfo->msgnum)
+                                       flags |= MSG_REPLIED;
+                               else
+                                       flags &= ~MSG_REPLIED;
+                               if (gslist_find_next_num(&p_deleted, msginfo->msgnum) == msginfo->msgnum)
+                                       flags |= MSG_DELETED;
+                               else
+                                       flags &= ~MSG_DELETED;
+                       }
+               } else {
+                       if (flags_hash != NULL) {
+                               gint * puid;
+
+                               puid = malloc(sizeof(* puid));
+                               * puid = msginfo->msgnum;
+
+                               flags = GPOINTER_TO_INT(g_hash_table_lookup(flags_hash, puid));
+                               free(puid);
+                       }
+
+                       if ((flags & MSG_UNREAD) == 0)
+                               flags &= ~MSG_NEW;
+                       else if (wasnew)
+                               flags |= MSG_NEW;
                }
+               if (waspostfiltered)
+                       flags |= MSG_POSTFILTERED;
                g_relation_insert(msgflags, msginfo, GINT_TO_POINTER(flags));
        }
+       g_hash_table_destroy(flags_hash);
 
        imap_lep_set_free(seq_list);
        g_slist_free(flagged);
@@ -4144,10 +4176,9 @@ static /*gint*/ void *imap_get_flags_thread(void *data)
        g_slist_free(answered);
        g_slist_free(unseen);
        g_slist_free(sorted_list);
-       g_string_free(cmd_buf, TRUE);
 
-       stuff->done = TRUE;
        unlock_session(session);
+       stuff->done = TRUE;
        return GINT_TO_POINTER(0);
 }
 
@@ -4511,6 +4542,45 @@ static GSList * imap_uid_list_from_lep_tab(carray * list)
        return result;
 }
 
+static GSList * imap_uid_list_from_lep_uid_flags_tab(carray * list)
+{
+       unsigned int i;
+       GSList * result;
+       
+       result = NULL;
+       
+       for(i = 0 ; i < carray_count(list) ; i += 2) {
+               uint32_t * puid;
+               
+               puid = carray_get(list, i);
+               result = g_slist_prepend(result, GINT_TO_POINTER(* puid));
+       }
+       result = g_slist_reverse(result);
+       return result;
+}
+
+static void imap_flags_hash_from_lep_uid_flags_tab(carray * list,
+                                                  GHashTable * hash)
+{
+       unsigned int i;
+       GSList * result;
+       
+       result = NULL;
+       
+       for(i = 0 ; i < carray_count(list) ; i += 2) {
+               uint32_t * puid;
+               int * pflags;
+               gint * pguid;
+               
+               puid = carray_get(list, i);
+               pflags = carray_get(list, i + 1);
+               pguid = malloc(sizeof(* pguid));
+               * pguid = * puid;
+               
+               g_hash_table_insert(hash, pguid, GINT_TO_POINTER(* pflags));
+       }
+}
+
 static MsgInfo *imap_envelope_from_lep(struct imap_fetch_env_info * info,
                                       FolderItem *item)
 {
index cd41db7977ad275417f8527478b51a2e77edce36..06d85c4f43eba3c064f3bd6dbcaa1aa73970aff1 100644 (file)
@@ -135,6 +135,7 @@ static struct Receive {
        GtkWidget *imapdir_label;
        GtkWidget *imapdir_entry;
        GtkWidget *subsonly_checkbtn;
+       GtkWidget *low_bandwidth_checkbtn;
 
        GtkWidget *frame_maxarticle;
        GtkWidget *maxarticle_label;
@@ -605,6 +606,10 @@ static PrefParam param[] = {
         &receive.subsonly_checkbtn,
         prefs_set_data_from_toggle, prefs_set_toggle},
 
+       {"low_bandwidth", "TRUE", &tmp_ac_prefs.low_bandwidth, P_BOOL,
+        &receive.low_bandwidth_checkbtn,
+        prefs_set_data_from_toggle, prefs_set_toggle},
+
        {"set_sent_folder", "FALSE", &tmp_ac_prefs.set_sent_folder, P_BOOL,
         &advanced.sent_folder_checkbtn,
         prefs_set_data_from_toggle, prefs_set_toggle},
@@ -1495,6 +1500,7 @@ static void prefs_account_receive_create(void)
        GtkWidget *imapdir_label;
        GtkWidget *imapdir_entry;
        GtkWidget *subsonly_checkbtn;
+       GtkWidget *low_bandwidth_checkbtn;
        GtkWidget *local_frame;
        GtkWidget *local_vbox;
        GtkWidget *local_hbox;
@@ -1713,6 +1719,16 @@ static void prefs_account_receive_create(void)
        PACK_CHECK_BUTTON (hbox1, subsonly_checkbtn,
                           _("Show subscribed folders only"));
 
+       hbox1 = gtk_hbox_new (FALSE, 8);
+       gtk_widget_show (hbox1);
+       gtk_box_pack_start (GTK_BOX (vbox2), hbox1, FALSE, FALSE, 4);
+
+       PACK_CHECK_BUTTON (hbox1, low_bandwidth_checkbtn,
+                          _("Bandwidth-efficient mode"));
+       gtk_tooltips_set_tip(GTK_TOOLTIPS(inbox_tooltip), low_bandwidth_checkbtn,
+                            _("This mode uses less bandwidth, but can be slower with some servers."),
+                            NULL);
+
        PACK_CHECK_BUTTON (vbox1, filter_on_recv_checkbtn,
                           _("Filter messages on receiving"));
 
@@ -1738,6 +1754,7 @@ static void prefs_account_receive_create(void)
        receive.imapdir_label           = imapdir_label;
        receive.imapdir_entry           = imapdir_entry;
        receive.subsonly_checkbtn               = subsonly_checkbtn;
+       receive.low_bandwidth_checkbtn          = low_bandwidth_checkbtn;
        receive.local_frame             = local_frame;
        receive.local_inbox_label       = local_inbox_label;
        receive.local_inbox_entry       = local_inbox_entry;
@@ -3119,6 +3136,7 @@ static void prefs_account_protocol_changed(GtkComboBox *combobox, gpointer data)
                gtk_widget_hide(receive.imapdir_label);
                gtk_widget_hide(receive.imapdir_entry);
                gtk_widget_hide(receive.subsonly_checkbtn);
+               gtk_widget_hide(receive.low_bandwidth_checkbtn);
                break;
        case A_LOCAL:
                gtk_widget_hide(protocol_optmenu->no_imap_warn_icon);
@@ -3204,6 +3222,7 @@ static void prefs_account_protocol_changed(GtkComboBox *combobox, gpointer data)
                gtk_widget_hide(receive.imapdir_label);
                gtk_widget_hide(receive.imapdir_entry);
                gtk_widget_hide(receive.subsonly_checkbtn);
+               gtk_widget_hide(receive.low_bandwidth_checkbtn);
                break;
        case A_IMAP4:
 #ifndef HAVE_LIBETPAN
@@ -3294,6 +3313,7 @@ static void prefs_account_protocol_changed(GtkComboBox *combobox, gpointer data)
                gtk_widget_show(receive.imapdir_label);
                gtk_widget_show(receive.imapdir_entry);
                gtk_widget_show(receive.subsonly_checkbtn);
+               gtk_widget_show(receive.low_bandwidth_checkbtn);
                break;
        case A_NONE:
                gtk_widget_hide(protocol_optmenu->no_imap_warn_icon);
@@ -3378,6 +3398,7 @@ static void prefs_account_protocol_changed(GtkComboBox *combobox, gpointer data)
                gtk_widget_hide(receive.imapdir_label);
                gtk_widget_hide(receive.imapdir_entry);
                gtk_widget_hide(receive.subsonly_checkbtn);
+               gtk_widget_hide(receive.low_bandwidth_checkbtn);
                break;
        case A_POP3:
        default:
@@ -3467,6 +3488,7 @@ static void prefs_account_protocol_changed(GtkComboBox *combobox, gpointer data)
                gtk_widget_hide(receive.imapdir_label);
                gtk_widget_hide(receive.imapdir_entry);
                gtk_widget_hide(receive.subsonly_checkbtn);
+               gtk_widget_hide(receive.low_bandwidth_checkbtn);
                break;
        }
 
index c4b7f9251a83e6833e827b159c9dfbe53306a2a6..df32b877814dc1312a1c8d5d742d7f99b105155c 100644 (file)
@@ -168,6 +168,7 @@ struct _PrefsAccount
 
        gchar *imap_dir;
        gboolean imap_subsonly;
+       gboolean low_bandwidth;
 
        gboolean set_sent_folder;
        gchar *sent_folder;