merge new cache branch
authorChristoph Hohmann <reboot@gmx.ch>
Sat, 29 Jun 2002 23:33:42 +0000 (23:33 +0000)
committerChristoph Hohmann <reboot@gmx.ch>
Sat, 29 Jun 2002 23:33:42 +0000 (23:33 +0000)
32 files changed:
ChangeLog.claws
Makefile.am
configure.in
po/Makefile.in.in
src/Makefile.am
src/addressbook.c
src/compose.c
src/filtering.c
src/folder.c
src/folder.h
src/folderview.c
src/gtkspell.c
src/imap.c
src/import.c
src/inc.c
src/main.c
src/mainwindow.c
src/matcher.c
src/mbox.c
src/mbox_folder.c
src/messageview.c
src/mh.c
src/mh.h
src/news.c
src/prefs_common.c
src/prefs_common.h
src/procheader.c
src/procmsg.c
src/procmsg.h
src/rfc2015.c
src/rfc2015.h
src/summaryview.c

index 3d15ab3..5f149d3 100644 (file)
@@ -1,3 +1,7 @@
+2002-06-30 [christoph] 0.7.8claws36
+
+       * merge new cache branch
+
 2002-06-29 [paul]      0.7.8claws35
 
        * configure.in
index ec0070a..2466c62 100644 (file)
@@ -6,6 +6,7 @@ EXTRA_DIST = \
        README.jp \
        ChangeLog.claws \
        README.claws \
+       README.README \
        TODO.jp \
        sylpheed.desktop \
        sylpheed.spec \
index 86e05af..fb700b0 100644 (file)
@@ -1,3 +1,4 @@
+
 dnl Process this file with autoconf to produce a configure script.
 AC_INIT(src/main.c)
 PACKAGE=sylpheed
@@ -8,7 +9,7 @@ MINOR_VERSION=7
 MICRO_VERSION=8
 INTERFACE_AGE=0
 BINARY_AGE=0
-EXTRA_VERSION=claws35
+EXTRA_VERSION=claws36
 VERSION=$MAJOR_VERSION.$MINOR_VERSION.$MICRO_VERSION$EXTRA_VERSION
 
 dnl set $target
index 32b7376..3077d1f 100644 (file)
@@ -83,7 +83,7 @@ all-no:
 
 $(srcdir)/$(PACKAGE).pot: $(POTFILES) $(srcdir)/POTFILES.in
        $(XGETTEXT) --default-domain=$(PACKAGE) --directory=$(top_srcdir) \
-         --add-comments --keyword=_ --keyword=N_ \
+         --add-comments --no-location --keyword=_ --keyword=N_ \
          --files-from=$(srcdir)/POTFILES.in \
        && test ! -f $(PACKAGE).po \
           || ( rm -f $(srcdir)/$(PACKAGE).pot \
index 4aca5c1..3f76751 100644 (file)
@@ -135,7 +135,8 @@ sylpheed_SOURCES = \
        matcher_parser_lex.l matcher_parser_lex.h \
        matcher_parser_parse.y matcher_parser.h matcher_parser_parse.h \
        string_match.h string_match.c \
-       selective_download.c selective_download.h
+       selective_download.c selective_download.h \
+       msgcache.h msgcache.c
 
 BUILT_SOURCES = \
        quote_fmt_lex.c \
index 7dd057f..61fce2c 100644 (file)
@@ -431,11 +431,12 @@ void addressbook_open(Compose *target)
                addressbook_load_tree();
                gtk_ctree_select(GTK_CTREE(addrbook.ctree),
                                 GTK_CTREE_NODE(GTK_CLIST(addrbook.ctree)->row_list));
-       } else
+       }
+       else {
                gtk_widget_hide(addrbook.window);
+       }
 
        gtk_widget_show_all(addrbook.window);
-
        addressbook_set_target_compose(target);
 }
 
@@ -458,7 +459,6 @@ void addressbook_destroy() {
 void addressbook_set_target_compose(Compose *target)
 {
        addrbook.target_compose = target;
-
        addressbook_button_set_sensitive();
 }
 
index 2534af3..1fc1a3c 100644 (file)
@@ -3329,7 +3329,6 @@ static gint compose_remove_reedit_target(Compose *compose)
        item = msginfo->folder;
        g_return_val_if_fail(item != NULL, -1);
 
-       folder_item_scan(item);
        if (procmsg_msg_exist(msginfo) &&
            (item->stype == F_DRAFT || item->stype == F_QUEUE)) {
                if (folder_item_remove_msg(item, msginfo->msgnum) < 0) {
@@ -3548,8 +3547,6 @@ static gint compose_queue_sub(Compose *compose, gint *msgnum, FolderItem **item,
                                (compose->targetinfo->folder, TRUE);
        }
 
-       procmsg_add_flags(queue, num, flag);
-       folder_item_scan(queue);
        folderview_update_item(queue, TRUE);
 
        if((msgnum != NULL) && (item != NULL)) {
@@ -6146,7 +6143,8 @@ static void compose_draft_cb(gpointer data, guint action, GtkWidget *widget)
        gint msgnum;
        MsgFlags flag = {0, 0};
        static gboolean lock = FALSE;
-
+       MsgInfo *newmsginfo;
+       
        if (lock) return;
 
        draft = account_get_special_folder(compose->account, F_DRAFT);
@@ -6163,7 +6161,6 @@ static void compose_draft_cb(gpointer data, guint action, GtkWidget *widget)
                return;
        }
 
-       folder_item_scan(draft);
        if ((msgnum = folder_item_add_msg(draft, tmp, TRUE)) < 0) {
                unlink(tmp);
                g_free(tmp);
@@ -6181,10 +6178,11 @@ static void compose_draft_cb(gpointer data, guint action, GtkWidget *widget)
                                               TRUE);
        }
 
-       procmsg_add_flags(draft, msgnum, flag);
-       folder_item_scan(draft);
+       newmsginfo = folder_item_fetch_msginfo(draft, msgnum);
+       procmsg_msginfo_unset_flags(newmsginfo, ~0, ~0);
        folderview_update_item(draft, TRUE);
-
+       procmsg_msginfo_free(newmsginfo);
+       
        lock = FALSE;
 
        /* 0: quit editing  1: keep editing */
@@ -6205,7 +6203,7 @@ static void compose_draft_cb(gpointer data, guint action, GtkWidget *widget)
                g_free(path);
 
                procmsg_msginfo_free(compose->targetinfo);
-               compose->targetinfo = g_new0(MsgInfo, 1);
+               compose->targetinfo = procmsg_msginfo_new();
                compose->targetinfo->msgnum = msgnum;
                compose->targetinfo->size = s.st_size;
                compose->targetinfo->mtime = s.st_mtime;
index 8756c53..69eb039 100644 (file)
@@ -138,7 +138,6 @@ static gboolean filteringaction_apply(FilteringAction * action, MsgInfo * info,
                        val = GPOINTER_TO_INT(g_hash_table_lookup
                                              (folder_table, dest_folder));
                        if (val == 0) {
-                               folder_item_scan(dest_folder);
                                g_hash_table_insert(folder_table, dest_folder,
                                                    GINT_TO_POINTER(1));
                        }
@@ -159,7 +158,6 @@ static gboolean filteringaction_apply(FilteringAction * action, MsgInfo * info,
                        val = GPOINTER_TO_INT(g_hash_table_lookup
                                              (folder_table, dest_folder));
                        if (val == 0) {
-                               folder_item_scan(dest_folder);
                                g_hash_table_insert(folder_table, dest_folder,
                                                    GINT_TO_POINTER(1));
                        }
index 17ea90c..554ac6e 100644 (file)
@@ -26,6 +26,9 @@
 #include <glib.h>
 #include <stdio.h>
 #include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
 #include <stdlib.h>
 
 #include "intl.h"
 #include "xml.h"
 #include "codeconv.h"
 #include "prefs.h"
+#include "prefs_common.h"
 #include "account.h"
 #include "prefs_account.h"
 #include "prefs_folder_item.h"
+#include "procheader.h"
 
 static GList *folder_list = NULL;
 
@@ -60,6 +65,8 @@ static void folder_update_op_count_rec        (GNode          *node);
 static void folder_get_persist_prefs_recursive
                                        (GNode *node, GHashTable *pptable);
 static gboolean persist_prefs_free     (gpointer key, gpointer val, gpointer data);
+void folder_item_read_cache            (FolderItem *item);
+void folder_item_write_cache           (FolderItem *item);
 
 
 Folder *folder_new(FolderType type, const gchar *name, const gchar *path)
@@ -94,6 +101,8 @@ static void folder_init(Folder *folder, const gchar *name)
        g_return_if_fail(folder != NULL);
 
        folder_set_name(folder, name);
+
+       /* Init folder data */
        folder->type = F_UNKNOWN;
        folder->account = NULL;
        folder->inbox = NULL;
@@ -101,8 +110,17 @@ static void folder_init(Folder *folder, const gchar *name)
        folder->draft = NULL;
        folder->queue = NULL;
        folder->trash = NULL;
+
+       /* Init Folder functions */
+       folder->fetch_msg = NULL;
+       folder->fetch_msginfo = NULL;
+       folder->fetch_msginfos = NULL;
+       folder->get_num_list = NULL;
        folder->ui_func = NULL;
        folder->ui_func_data = NULL;
+       folder->check_msgnum_validity = NULL;
+
+       /* Create root folder item */
        item = folder_item_new(name, NULL);
        item->folder = folder;
        folder->node = g_node_new(item);
@@ -194,6 +212,7 @@ FolderItem *folder_item_new(const gchar *name, const gchar *path)
        item->unread = 0;
        item->total = 0;
        item->last_num = -1;
+       item->cache = NULL;
        item->no_sub = FALSE;
        item->no_select = FALSE;
        item->collapsed = FALSE;
@@ -250,6 +269,7 @@ void folder_item_destroy(FolderItem *item)
 
        g_free(item->name);
        g_free(item->path);
+       msgcache_destroy(item->cache);
        g_free(item);
 }
 
@@ -383,45 +403,68 @@ struct TotalMsgCount
        guint total;
 };
 
-static gboolean folder_count_total_msgs_func(GNode *node, gpointer data)
+struct FuncToAllFoldersData
+{
+       FolderItemFunc  function;
+       gpointer        data;
+};
+
+static gboolean folder_func_to_all_folders_func(GNode *node, gpointer data)
 {
        FolderItem *item;
-       struct TotalMsgCount *count = (struct TotalMsgCount *)data;
+       struct FuncToAllFoldersData *function_data = (struct FuncToAllFoldersData *) data;
 
        g_return_val_if_fail(node->data != NULL, FALSE);
 
        item = FOLDER_ITEM(node->data);
-       count->new += item->new;
-       count->unread += item->unread;
-       count->total += item->total;
+       g_return_val_if_fail(item != NULL, FALSE);
+
+       function_data->function(item, function_data->data);
 
        return FALSE;
 }
 
-void folder_count_total_msgs(guint *new, guint *unread, guint *total)
+void folder_func_to_all_folders(FolderItemFunc function, gpointer data)
 {
        GList *list;
        Folder *folder;
-       struct TotalMsgCount count;
-
-       count.new = count.unread = count.total = 0;
-
-       debug_print(_("Counting total number of messages...\n"));
+       struct FuncToAllFoldersData function_data;
+       
+       function_data.function = function;
+       function_data.data = data;
 
        for (list = folder_list; list != NULL; list = list->next) {
                folder = FOLDER(list->data);
                if (folder->node)
                        g_node_traverse(folder->node, G_PRE_ORDER,
                                        G_TRAVERSE_ALL, -1,
-                                       folder_count_total_msgs_func,
-                                       &count);
+                                       folder_func_to_all_folders_func,
+                                       &function_data);
        }
+}
+
+static void folder_count_total_msgs_func(FolderItem *item, gpointer data)
+{
+       struct TotalMsgCount *count = (struct TotalMsgCount *)data;
+
+       count->new += item->new;
+       count->unread += item->unread;
+       count->total += item->total;
+}
+
+void folder_count_total_msgs(guint *new, guint *unread, guint *total)
+{
+       struct TotalMsgCount count;
+
+       count.new = count.unread = count.total = 0;
+
+       debug_print(_("Counting total number of messages...\n"));
+
+       folder_func_to_all_folders(folder_count_total_msgs_func, &count);
 
        *new = count.new;
        *unread = count.unread;
        *total = count.total;
-
-       return;
 }
 
 Folder *folder_find_from_path(const gchar *path)
@@ -746,14 +789,199 @@ gchar *folder_item_get_path(FolderItem *item)
        return path;
 }
 
+void folder_item_set_default_flags(FolderItem *dest, MsgFlags *flags)
+{
+       if (!(dest->stype == F_OUTBOX ||
+             dest->stype == F_QUEUE  ||
+             dest->stype == F_DRAFT  ||
+             dest->stype == F_TRASH)) {
+               flags->perm_flags = MSG_NEW|MSG_UNREAD;
+       } else {
+               flags->perm_flags = 0;
+       }
+       flags->tmp_flags = MSG_CACHED;
+       if (dest->folder->type == F_MH) {
+               if (dest->stype == F_QUEUE) {
+                       MSG_SET_TMP_FLAGS(*flags, MSG_QUEUED);
+               } else if (dest->stype == F_DRAFT) {
+                       MSG_SET_TMP_FLAGS(*flags, MSG_DRAFT);
+               }
+       } else if (dest->folder->type == F_IMAP) {
+               MSG_SET_TMP_FLAGS(*flags, MSG_IMAP);
+       } else if (dest->folder->type == F_NEWS) {
+               MSG_SET_TMP_FLAGS(*flags, MSG_NEWS);
+       }
+}
+
+typedef enum {
+    IN_CACHE  = 1 << 0,
+    IN_FOLDER = 1 << 1,
+} FolderScanInfo;
+
 gint folder_item_scan(FolderItem *item)
 {
        Folder *folder;
+       GSList *folder_list, *cache_list, *elem, *new_list = NULL;
+       gint i;
+       guint min = 0xffffffff, max = 0, cache_max = 0, maxgetcount = 0;
+       FolderScanInfo *folderscaninfo;
 
        g_return_val_if_fail(item != NULL, -1);
+       if(item->path == NULL) return -1;
 
        folder = item->folder;
-       return folder->scan(folder, item);
+
+       g_return_val_if_fail(folder != NULL, -1);
+       g_return_val_if_fail(folder->get_num_list != NULL, -1);
+
+       debug_print(_("Scanning folder %s for cache changes.\n"), item->path);
+
+       /* Get list of messages for folder and cache */
+       if(!folder->check_msgnum_validity || 
+          folder->check_msgnum_validity(folder, item)) {
+               if(!item->cache)
+                       folder_item_read_cache(item);
+               cache_list = msgcache_get_msg_list(item->cache);
+       } else {
+               if(item->cache)
+                       msgcache_destroy(item->cache);
+               item->cache = msgcache_new();
+               cache_list = NULL;
+       }
+       folder_list = folder->get_num_list(item->folder, item);
+
+       /* Get min und max number in folder */
+       for(elem = cache_list; elem != NULL; elem = elem->next) {
+               MsgInfo *msginfo = (MsgInfo *)elem->data;
+
+               min = MIN(msginfo->msgnum, min);
+               max = MAX(msginfo->msgnum, max);
+       }
+       cache_max = max;
+       for(elem = folder_list; elem != NULL; elem = elem->next) {
+               guint num = GPOINTER_TO_INT(elem->data);
+
+               min = MIN(num, min);
+               max = MAX(num, max);
+       }
+
+       debug_print("Folder message number range from %d to %d\n", min, max);
+
+       if(max == 0) {
+               for(elem = cache_list; elem != NULL; elem = elem->next) {
+                       MsgInfo *msginfo = (MsgInfo *)elem->data;
+
+                       procmsg_msginfo_free(msginfo);
+               }
+               g_slist_free(folder_list);
+               g_slist_free(cache_list);
+
+               return 0;
+       }
+
+       folderscaninfo = g_new0(FolderScanInfo, max - min + 1);
+
+       for(elem = folder_list; elem != NULL; elem = elem->next) {
+               guint num = GPOINTER_TO_INT(elem->data);
+
+               folderscaninfo[num - min] |= IN_FOLDER;
+       }
+       for(elem = cache_list; elem != NULL; elem = elem->next) {
+               MsgInfo *msginfo = (MsgInfo *)elem->data;
+
+               folderscaninfo[msginfo->msgnum - min] |= IN_CACHE;
+               procmsg_msginfo_free(msginfo);
+       }
+
+       for(i = max - min; i >= 0; i--) {
+               guint num;
+
+               num = i + min;
+               /* Add message to cache if in folder and not in cache */
+               if( (folderscaninfo[i] & IN_FOLDER) && 
+                  !(folderscaninfo[i] & IN_CACHE) && 
+                   (folder->type != F_NEWS ||
+                       ((prefs_common.max_articles == 0) || (num > (max - prefs_common.max_articles))) &&
+                       (num > cache_max))
+                   ) {
+                       new_list = g_slist_prepend(new_list, GINT_TO_POINTER(num));
+                       debug_print(_("Remembered message %d for fetching\n"), num);
+               }
+               /* Remove message from cache if not in folder and in cache */
+               if(!(folderscaninfo[i] & IN_FOLDER) && 
+                   (folderscaninfo[i] & IN_CACHE)) {
+                       msgcache_remove_msg(item->cache, i + min);
+                       debug_print(_("Removed message %d from cache.\n"), num);
+               }
+               /* Check if msginfo needs update if in cache and in folder */
+               if((folderscaninfo[i] & IN_FOLDER) && 
+                  (folderscaninfo[i] & IN_CACHE) &&
+                  (folder->is_msg_changed != NULL)) {
+                       MsgInfo *msginfo;
+
+                       msginfo = msgcache_get_msg(item->cache, num);
+                       if(folder->is_msg_changed(folder, item, msginfo)) {
+                               MsgInfo *newmsginfo;
+
+                               msgcache_remove_msg(item->cache, msginfo->msgnum);
+
+                               newmsginfo = folder->fetch_msginfo(folder, item, num);
+                               msgcache_add_msg(item->cache, newmsginfo);
+                               procmsg_msginfo_free(newmsginfo);
+
+                               debug_print(_("Updated msginfo for message %d.\n"), num);
+                       }
+                       procmsg_msginfo_free(msginfo);
+               }
+       }
+
+       if(folder->fetch_msginfos) {
+               GSList *newmsg_list;
+               MsgInfo *msginfo;
+               
+               if(new_list) {
+                       newmsg_list = folder->fetch_msginfos(folder, item, new_list);
+                       for(elem = newmsg_list; elem != NULL; elem = g_slist_next(elem)) {
+                               msginfo = (MsgInfo *) elem->data;
+                               msgcache_add_msg(item->cache, msginfo);
+                               if(MSG_IS_NEW(msginfo->flags))
+                                       item->new++;
+                               if(MSG_IS_UNREAD(msginfo->flags))
+                                       item->unread++;
+                               item->total++;
+                               procmsg_msginfo_free(msginfo);
+                       }
+                       g_slist_free(newmsg_list);
+                       folderview_update_item(item, FALSE);
+               }
+       } else if (folder->fetch_msginfo) {
+               for(elem = new_list; elem != NULL; elem = g_slist_next(elem)) {
+                       MsgFlags flags;
+                       MsgInfo *msginfo;
+                       guint num;
+
+                       num = GPOINTER_TO_INT(elem->data);
+                       msginfo = folder->fetch_msginfo(folder, item, num);
+                       if(msginfo != NULL) {
+                               msgcache_add_msg(item->cache, msginfo);
+                               if(MSG_IS_NEW(msginfo->flags))
+                                   item->new++;
+                               if(MSG_IS_UNREAD(msginfo->flags))
+                                   item->unread++;
+                               item->total++;
+                               procmsg_msginfo_free(msginfo);
+                               debug_print(_("Added newly found message %d to cache.\n"), num);
+                       }
+               }
+               folderview_update_item(item, FALSE);
+       }
+
+       g_slist_free(folder_list);
+       g_slist_free(cache_list);
+       g_slist_free(new_list);
+       g_free(folderscaninfo);
+
+       return 0;
 }
 
 static void folder_item_scan_foreach_func(gpointer key, gpointer val,
@@ -767,6 +995,158 @@ void folder_item_scan_foreach(GHashTable *table)
        g_hash_table_foreach(table, folder_item_scan_foreach_func, NULL);
 }
 
+void folder_count_total_cache_memusage(FolderItem *item, gpointer data)
+{
+       gint *memusage = (gint *)data;
+
+       if(item->cache == NULL)
+               return;
+       
+       *memusage += msgcache_get_memory_usage(item->cache);
+}
+
+gint folder_cache_time_compare_func(gconstpointer a, gconstpointer b)
+{
+       FolderItem *fa = (FolderItem *)a;
+       FolderItem *fb = (FolderItem *)b;
+       
+       return (gint) (msgcache_get_last_access_time(fa->cache) - msgcache_get_last_access_time(fb->cache));
+}
+
+void folder_find_expired_caches(FolderItem *item, gpointer data)
+{
+       GSList **folder_item_list = (GSList **)data;
+       gint difftime, expiretime;
+       
+       if(item->cache == NULL)
+               return;
+
+       difftime = (gint) (time(NULL) - msgcache_get_last_access_time(item->cache));
+       expiretime = prefs_common.cache_min_keep_time * 60;
+       debug_print(_("Cache unused time: %d (Expire time: %d)\n"), difftime, expiretime);
+       if(difftime > expiretime) {
+               *folder_item_list = g_slist_insert_sorted(*folder_item_list, item, folder_cache_time_compare_func);
+       }
+}
+
+void folder_item_free_cache(FolderItem *item)
+{
+       g_return_if_fail(item != NULL);
+       g_return_if_fail(item->cache != NULL);
+       
+       folder_item_write_cache(item);
+       msgcache_destroy(item->cache);
+       item->cache = NULL;
+}
+
+void folder_clean_cache_memory()
+{
+       gint memusage = 0;
+
+       folder_func_to_all_folders(folder_count_total_cache_memusage, &memusage);       
+       debug_print(_("Total cache memory usage: %d\n"), memusage);
+       
+       if(memusage > (prefs_common.cache_max_mem_usage * 1024)) {
+               GSList *folder_item_list = NULL, *listitem;
+               
+               debug_print(_("Trying to free cache memory\n"));
+
+               folder_func_to_all_folders(folder_find_expired_caches, &folder_item_list);      
+               listitem = folder_item_list;
+               while((listitem != NULL) && (memusage > (prefs_common.cache_max_mem_usage * 1024))) {
+                       FolderItem *item = (FolderItem *)(listitem->data);
+
+                       debug_print(_("Freeing cache memory for %s\n"), item->path);
+                       memusage -= msgcache_get_memory_usage(item->cache);
+                       folder_item_free_cache(item);
+                       listitem = listitem->next;
+               }
+               g_slist_free(folder_item_list);
+       }
+}
+
+void folder_item_read_cache(FolderItem *item)
+{
+       gchar *cache_file, *mark_file;
+       
+       g_return_if_fail(item != NULL);
+
+       cache_file = folder_item_get_cache_file(item);
+       mark_file = folder_item_get_mark_file(item);
+       item->cache = msgcache_read_cache(item, cache_file);
+       if(!item->cache) {
+               item->cache = msgcache_new();
+               folder_item_scan(item);
+       }
+       msgcache_read_mark(item->cache, mark_file);
+       g_free(cache_file);
+       g_free(mark_file);
+
+       folder_clean_cache_memory();
+}
+
+void folder_item_write_cache(FolderItem *item)
+{
+       gchar *cache_file, *mark_file;
+       PrefsFolderItem *prefs;
+       gint filemode = 0;
+       gchar *id;
+       
+       if (!item || !item->path || !item->cache)
+               return;
+
+       id = folder_item_get_identifier(item);
+       debug_print(_("Save cache for folder %s\n"), id);
+       g_free(id);
+
+       cache_file = folder_item_get_cache_file(item);
+       mark_file = folder_item_get_mark_file(item);
+       if(msgcache_write(cache_file, mark_file, item->cache) < 0) {
+               prefs = item->prefs;
+               if (prefs && prefs->enable_folder_chmod && prefs->folder_chmod) {
+                       /* for cache file */
+                       filemode = prefs->folder_chmod;
+                       if (filemode & S_IRGRP) filemode |= S_IWGRP;
+                       if (filemode & S_IROTH) filemode |= S_IWOTH;
+                       chmod(cache_file, filemode);
+               }
+        }
+
+       g_free(cache_file);
+       g_free(mark_file);
+}
+
+MsgInfo *folder_item_fetch_msginfo(FolderItem *item, gint num)
+{
+       Folder *folder;
+       MsgInfo *msginfo;
+       
+       g_return_val_if_fail(item != NULL, NULL);
+       
+       folder = item->folder;
+       if(!item->cache)
+               folder_item_read_cache(item);
+       
+       if(msginfo = msgcache_get_msg(item->cache, num))
+               return msginfo;
+       
+       g_return_val_if_fail(folder->fetch_msginfo, NULL);
+       msginfo = folder->fetch_msginfo(folder, item, num);
+       return msginfo;
+}
+
+GSList *folder_item_get_msg_list(FolderItem *item)
+{
+       g_return_val_if_fail(item != NULL, NULL);
+       
+       if(item->cache == 0)
+               folder_item_read_cache(item);
+
+       g_return_val_if_fail(item->cache != NULL, NULL);
+       
+       return msgcache_get_msg_list(item->cache);
+}
+
 gchar *folder_item_fetch_msg(FolderItem *item, gint num)
 {
        Folder *folder;
@@ -775,11 +1155,8 @@ gchar *folder_item_fetch_msg(FolderItem *item, gint num)
 
        folder = item->folder;
 
-       g_return_val_if_fail(folder->scan != NULL, NULL);
        g_return_val_if_fail(folder->fetch_msg != NULL, NULL);
 
-       if (item->last_num < 0) folder->scan(folder, item);
-
        return folder->fetch_msg(folder, item, num);
 }
 
@@ -788,19 +1165,33 @@ gint folder_item_add_msg(FolderItem *dest, const gchar *file,
 {
        Folder *folder;
        gint num;
+       MsgInfo *msginfo;
 
        g_return_val_if_fail(dest != NULL, -1);
        g_return_val_if_fail(file != NULL, -1);
 
        folder = dest->folder;
 
-       g_return_val_if_fail(folder->scan != NULL, -1);
        g_return_val_if_fail(folder->add_msg != NULL, -1);
 
-       if (dest->last_num < 0) folder->scan(folder, dest);
+       if (!dest->cache)
+               folder_item_read_cache(dest);
 
        num = folder->add_msg(folder, dest, file, remove_source);
-       if (num > 0) dest->last_num = num;
+
+        if (num > 0) {
+               msginfo = folder->fetch_msginfo(folder, dest, num);
+
+               if(MSG_IS_NEW(msginfo->flags))
+                       dest->new++;
+               if(MSG_IS_UNREAD(msginfo->flags))
+                       dest->unread++;
+               dest->total++;
+
+                dest->last_num = num;
+                msgcache_add_msg(dest->cache, msginfo);
+               procmsg_msginfo_free(msginfo);
+        }
 
        return num;
 }
@@ -836,34 +1227,53 @@ gint folder_item_move_msg(FolderItem *dest, MsgInfo *msginfo)
 
        folder = dest->folder;
 
-       g_return_val_if_fail(folder->scan != NULL, -1);
        g_return_val_if_fail(folder->remove_msg != NULL, -1);
        g_return_val_if_fail(folder->copy_msg != NULL, -1);
 
-       if (dest->last_num < 0) folder->scan(folder, dest);
+       if (!dest->cache) folder_item_read_cache(dest);
 
        src_folder = msginfo->folder->folder;
 
        num = folder->copy_msg(folder, dest, msginfo);
        
        if (num != -1) {
+               MsgInfo *newmsginfo;
+
+               newmsginfo = folder->fetch_msginfo(folder, dest, num);
+               newmsginfo->flags.perm_flags = msginfo->flags.perm_flags;
+               if (dest->stype == F_OUTBOX ||
+                   dest->stype == F_QUEUE  ||
+                   dest->stype == F_DRAFT  ||
+                   dest->stype == F_TRASH)
+                       MSG_UNSET_PERM_FLAGS(newmsginfo->flags,
+                                            MSG_NEW|MSG_UNREAD|MSG_DELETED);
+               msgcache_add_msg(dest->cache, newmsginfo);
+
                /* CLAWS */
-               g_assert(src_folder);
-               g_assert(src_folder->remove_msg);
-               src_folder->remove_msg(src_folder,
-                                      msginfo->folder,
-                                      msginfo->msgnum);
-       }                                      
+               if(src_folder->remove_msg) {
+                       src_folder->remove_msg(src_folder,
+                                              msginfo->folder,
+                                              msginfo->msgnum);
+               }
+                msgcache_remove_msg(msginfo->folder->cache, msginfo->msgnum);
+
+               if (MSG_IS_NEW(msginfo->flags))
+                       msginfo->folder->new--;
+               if (MSG_IS_NEW(newmsginfo->flags))
+                       dest->new++;
+               if (MSG_IS_UNREAD(msginfo->flags))
+                       msginfo->folder->unread--;
+               if (MSG_IS_UNREAD(newmsginfo->flags))
+                       dest->unread++;
+               msginfo->folder->total--;
+               dest->total++;
+
+               procmsg_msginfo_free(newmsginfo);
+       }
        
        if (folder->finished_copy)
                folder->finished_copy(folder, dest);
 
-       src_folder = msginfo->folder->folder;
-
-       if (msginfo->folder && src_folder->scan)
-               src_folder->scan(src_folder, msginfo->folder);
-       folder->scan(folder, dest);
-
        return num;
 }
 
@@ -893,17 +1303,17 @@ gint folder_item_move_msgs_with_dest(FolderItem *dest, GSList *msglist)
        FolderItem * item;
        GSList * l;
        gchar * filename;
+       gint num;
 
        g_return_val_if_fail(dest != NULL, -1);
        g_return_val_if_fail(msglist != NULL, -1);
 
        folder = dest->folder;
 
-       g_return_val_if_fail(folder->scan != NULL, -1);
        g_return_val_if_fail(folder->copy_msg != NULL, -1);
        g_return_val_if_fail(folder->remove_msg != NULL, -1);
 
-       if (dest->last_num < 0) folder->scan(folder, dest);
+       if (!dest->cache) folder_item_read_cache(dest);
 
        item = NULL;
        for(l = msglist ; l != NULL ; l = g_slist_next(l)) {
@@ -911,20 +1321,46 @@ gint folder_item_move_msgs_with_dest(FolderItem *dest, GSList *msglist)
 
                if (!item && msginfo->folder != NULL)
                        item = msginfo->folder;
-
-               if (folder->copy_msg(folder, dest, msginfo) != -1)
+               if (!item->cache) folder_item_read_cache(dest);
+
+               num = folder->copy_msg(folder, dest, msginfo);
+               if (num != -1) {
+                       MsgInfo *newmsginfo;
+
+                       newmsginfo = folder->fetch_msginfo(folder, dest, num);
+                       if(newmsginfo) {
+                               newmsginfo->flags.perm_flags = msginfo->flags.perm_flags;
+                               if (dest->stype == F_OUTBOX ||
+                                   dest->stype == F_QUEUE  ||
+                                   dest->stype == F_DRAFT  ||
+                                   dest->stype == F_TRASH)
+                                       MSG_UNSET_PERM_FLAGS(newmsginfo->flags,
+                                                            MSG_NEW|MSG_UNREAD|MSG_DELETED);
+                               msgcache_add_msg(dest->cache, newmsginfo);
+
+                               if (MSG_IS_NEW(msginfo->flags))
+                                       msginfo->folder->new--;
+                               if (MSG_IS_NEW(newmsginfo->flags))
+                                       dest->new++;
+                               if (MSG_IS_UNREAD(msginfo->flags))
+                                       msginfo->folder->unread--;
+                               if (MSG_IS_UNREAD(newmsginfo->flags))
+                                       dest->unread++;
+                               msginfo->folder->total--;
+                               dest->total++;
+
+                               procmsg_msginfo_free(newmsginfo);
+                       }
                        item->folder->remove_msg(item->folder,
                                                 msginfo->folder,
                                                 msginfo->msgnum);
-       }
+                       msgcache_remove_msg(item->cache, msginfo->msgnum);
+               }
+       }
 
        if (folder->finished_copy)
                folder->finished_copy(folder, dest);
 
-       if (item && item->folder->scan)
-               item->folder->scan(item->folder, item);
-       folder->scan(folder, dest);
-
        return dest->last_num;
 }
 
@@ -959,18 +1395,36 @@ gint folder_item_copy_msg(FolderItem *dest, MsgInfo *msginfo)
 
        folder = dest->folder;
 
-       g_return_val_if_fail(folder->scan != NULL, -1);
        g_return_val_if_fail(folder->copy_msg != NULL, -1);
 
-       if (dest->last_num < 0) folder->scan(folder, dest);
+       if (!dest->cache) folder_item_read_cache(dest);
        
        num = folder->copy_msg(folder, dest, msginfo);
+       if (num != -1) {
+               MsgInfo *newmsginfo;
+
+               newmsginfo = folder->fetch_msginfo(folder, dest, num);
+               newmsginfo->flags.perm_flags = msginfo->flags.perm_flags;
+               if (dest->stype == F_OUTBOX ||
+                   dest->stype == F_QUEUE  ||
+                   dest->stype == F_DRAFT  ||
+                   dest->stype == F_TRASH)
+                       MSG_UNSET_PERM_FLAGS(newmsginfo->flags,
+                                            MSG_NEW|MSG_UNREAD|MSG_DELETED);
+               msgcache_add_msg(dest->cache, newmsginfo);
+
+               if (MSG_IS_NEW(newmsginfo->flags))
+                       dest->new++;
+               if (MSG_IS_UNREAD(newmsginfo->flags))
+                       dest->unread++;
+               dest->total++;
+
+               procmsg_msginfo_free(newmsginfo);
+       }
 
        if (folder->finished_copy)
                folder->finished_copy(folder, dest);
 
-       folder->scan(folder, dest);
-
        return num;
 }
 
@@ -1006,22 +1460,42 @@ gint folder_item_copy_msgs_with_dest(FolderItem *dest, GSList *msglist)
 
        folder = dest->folder;
  
-       g_return_val_if_fail(folder->scan != NULL, -1);
        g_return_val_if_fail(folder->copy_msg != NULL, -1);
 
-       if (dest->last_num < 0) folder->scan(folder, dest);
+       if (!dest->cache) folder_item_read_cache(dest);
 
        for(l = msglist ; l != NULL ; l = g_slist_next(l)) {
                MsgInfo * msginfo = (MsgInfo *) l->data;
 
-               folder->copy_msg(folder, dest, msginfo);
+               num = folder->copy_msg(folder, dest, msginfo);
+               if (num != -1) {
+                       MsgInfo *newmsginfo;
+
+                       newmsginfo = folder->fetch_msginfo(folder, dest, num);
+                       if(newmsginfo) {
+                               newmsginfo->flags.perm_flags = msginfo->flags.perm_flags;
+                               if (dest->stype == F_OUTBOX ||
+                                   dest->stype == F_QUEUE  ||
+                                   dest->stype == F_DRAFT  ||
+                                   dest->stype == F_TRASH)
+                                       MSG_UNSET_PERM_FLAGS(newmsginfo->flags,
+                                                            MSG_NEW|MSG_UNREAD|MSG_DELETED);
+                               msgcache_add_msg(dest->cache, newmsginfo);
+
+                               if (MSG_IS_NEW(newmsginfo->flags))
+                                       dest->new++;
+                               if (MSG_IS_UNREAD(newmsginfo->flags))
+                                       dest->unread++;
+                               dest->total++;
+
+                               procmsg_msginfo_free(newmsginfo);
+                       }
+               }
        }
 
        if (folder->finished_copy)
                folder->finished_copy(folder, dest);
 
-       folder->scan(folder, dest);
-
        return dest->last_num;
 }
 
@@ -1029,15 +1503,23 @@ gint folder_item_remove_msg(FolderItem *item, gint num)
 {
        Folder *folder;
        gint ret;
+       MsgInfo *msginfo;
 
        g_return_val_if_fail(item != NULL, -1);
 
        folder = item->folder;
-       if (item->last_num < 0) folder->scan(folder, item);
+       if (!item->cache) folder_item_read_cache(item);
 
        ret = folder->remove_msg(folder, item, num);
-       if (ret == 0 && num == item->last_num)
-               folder->scan(folder, item);
+
+       msginfo = msgcache_get_msg(item->cache, num);
+       if(MSG_IS_NEW(msginfo->flags))
+               item->new--;
+       if(MSG_IS_UNREAD(msginfo->flags))
+               item->unread--;
+       item->total--;
+       procmsg_msginfo_free(msginfo);
+       msgcache_remove_msg(item->cache, num);
 
        return ret;
 }
@@ -1048,11 +1530,14 @@ gint folder_item_remove_msgs(FolderItem *item, GSList *msglist)
 
        g_return_val_if_fail(item != NULL, -1);
 
+       if (!item->cache) folder_item_read_cache(item);
+
        while (msglist != NULL) {
                MsgInfo *msginfo = (MsgInfo *)msglist->data;
 
                ret = folder_item_remove_msg(item, msginfo->msgnum);
                if (ret != 0) break;
+               msgcache_remove_msg(item->cache, msginfo->msgnum);
                msglist = msglist->next;
        }
 
@@ -1068,14 +1553,11 @@ gint folder_item_remove_all_msg(FolderItem *item)
 
        folder = item->folder;
 
-       g_return_val_if_fail(folder->scan != NULL, -1);
        g_return_val_if_fail(folder->remove_all_msg != NULL, -1);
 
-       if (item->last_num < 0) folder->scan(folder, item);
-
        result = folder->remove_all_msg(folder, item);
 
-       if (result == 0){
+       if (result == 0) {
                if (folder->finished_remove)
                        folder->finished_remove(folder, item);
        }
index bd22c65..4baf398 100644 (file)
@@ -36,6 +36,7 @@ typedef struct _FolderItem    FolderItem;
 #include "prefs_account.h"
 #include "session.h"
 #include "procmsg.h"
+#include "msgcache.h"
 
 #define FOLDER(obj)            ((Folder *)obj)
 #define FOLDER_TYPE(obj)       (FOLDER(obj)->type)
@@ -101,6 +102,8 @@ typedef void (*FolderUIFunc)                (Folder         *folder,
 typedef void (*FolderDestroyNotify)    (Folder         *folder,
                                         FolderItem     *item,
                                         gpointer        data);
+typedef void (*FolderItemFunc)         (FolderItem     *item,
+                                        gpointer        data);
 
 struct _Folder
 {
@@ -125,12 +128,20 @@ struct _Folder
        GHashTable *newsart;
 
        /* virtual functions */
+/*
        GSList * (*get_msg_list)        (Folder         *folder,
                                         FolderItem     *item,
                                         gboolean        use_cache);
+*/
        gchar *  (*fetch_msg)           (Folder         *folder,
                                         FolderItem     *item,
                                         gint            num);
+       MsgInfo *(*fetch_msginfo)       (Folder         *folder,
+                                        FolderItem     *item,
+                                        gint            num);
+       GSList  *(*fetch_msginfos)      (Folder         *folder,
+                                        FolderItem     *item,
+                                        GSList         *msgnum_list);
        gint     (*add_msg)             (Folder         *folder,
                                         FolderItem     *dest,
                                         const gchar    *file,
@@ -155,7 +166,8 @@ struct _Folder
        gboolean (*is_msg_changed)      (Folder         *folder,
                                         FolderItem     *item,
                                         MsgInfo        *msginfo);
-       gint     (*scan)                (Folder         *folder,
+       gint     (*scan)                (Folder         *folder);
+       GSList  * (*get_num_list)       (Folder         *folder,
                                         FolderItem     *item);
        void     (*scan_tree)           (Folder         *folder);
 
@@ -174,7 +186,8 @@ struct _Folder
                                         FolderItem     *item,
                                         MsgInfo        *info);
        void     (*finished_copy)       (Folder * folder, FolderItem * item);
-       void     (*finished_remove)       (Folder * folder, FolderItem * item);
+       void     (*finished_remove)     (Folder * folder, FolderItem * item);
+       gboolean (*check_msgnum_validity) (Folder * folder, FolderItem * item);
 };
 
 struct _LocalFolder
@@ -214,6 +227,8 @@ struct _FolderItem
 
        gint last_num;
 
+       MsgCache *cache;
+
        /* special flags */
        guint no_sub         : 1; /* no child allowed?    */
        guint no_select      : 1; /* not selectable?      */
@@ -282,6 +297,8 @@ GList *folder_get_list              (void);
 gint   folder_read_list                (void);
 void   folder_write_list       (void);
 void   folder_update_op_count          (void);
+void   folder_func_to_all_folders      (FolderItemFunc function,
+                                        gpointer data);
 void   folder_count_total_msgs (guint          *new,
                                 guint          *unread,
                                 guint          *total);
@@ -306,6 +323,9 @@ void folder_set_missing_folders             (void);
 gchar *folder_item_get_path            (FolderItem     *item);
 gint   folder_item_scan                        (FolderItem     *item);
 void   folder_item_scan_foreach                (GHashTable     *table);
+MsgInfo *folder_item_fetch_msginfo     (FolderItem     *item,
+                                        gint            num);
+GSList *folder_item_get_msg_list       (FolderItem     *item);
 gchar *folder_item_fetch_msg           (FolderItem     *item,
                                         gint            num);
 gint   folder_item_add_msg             (FolderItem     *dest,
@@ -337,5 +357,6 @@ const PersistPrefs *folder_get_persist_prefs
                                        (GHashTable *pptable, const char *name);
 
 void folder_item_restore_persist_prefs (FolderItem *item, GHashTable *pptable);
+void folder_clean_cache_memory         ();
 
 #endif /* __FOLDER_H__ */
index 4382b8e..a21aad0 100644 (file)
@@ -1616,7 +1616,7 @@ static void folderview_selected(GtkCTree *ctree, GtkCTreeNode *row,
                        (folderview->mainwin,
                         item->folder->type == F_NEWS ? 
                         COMPOSEBUTTON_NEWS : COMPOSEBUTTON_MAIL);
-        
+
        if (item->path)
                debug_print(_("Folder %s is selected\n"), item->path);
 
@@ -1633,8 +1633,14 @@ static void folderview_selected(GtkCTree *ctree, GtkCTreeNode *row,
                        gdk_pointer_ungrab(GDK_CURRENT_TIME);
        }
 
+       if((item->folder->type == F_IMAP) || (item->folder->type == F_NEWS)) {
+               folder_item_scan(item);
+       }
+
        opened = summary_show(folderview->summaryview, item, FALSE);
 
+       folder_clean_cache_memory();
+       
        if (!opened) {
                gtkut_ctree_set_focus_row(ctree, folderview->opened);
                gtk_ctree_select(ctree, folderview->opened);
index 5da47a8..2287435 100644 (file)
@@ -1900,6 +1900,18 @@ static void populate_submenu(GtkPspell *gtkpspell, GtkWidget *menu)
        item = gtk_menu_item_new();
         gtk_widget_show(item);
         gtk_menu_append(GTK_MENU(menu), item);
+               
+       item = gtk_check_menu_item_new_with_label(_("Fast Mode"));
+       if (ispell || gtkpspell->gtkpspeller->sug_mode == PSPELL_FASTMODE)
+               gtk_widget_set_sensitive(GTK_WIDGET(item),FALSE);
+       if (!ispell && gtkpspell->gtkpspeller->sug_mode == PSPELL_FASTMODE)
+               gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item),TRUE);
+       else
+               gtk_signal_connect(GTK_OBJECT(item), "activate",
+                                  GTK_SIGNAL_FUNC(set_sug_mode_cb),
+                                  gtkpspell);
+       gtk_widget_show(item);
+       gtk_menu_append(GTK_MENU(menu), item);
 
        if (gtkpspell->use_alternate && gtkpspell->alternate_speller) {
                dictname = g_strdup_printf(_("Use alternate (%s)"), 
index a4a05f5..edddafd 100644 (file)
@@ -270,6 +270,11 @@ static gchar *imap_locale_to_modified_utf7 (const gchar    *from);
 
 static gboolean imap_rename_folder_func                (GNode          *node,
                                                 gpointer        data);
+GSList *imap_get_num_list                      (Folder         *folder,
+                                                FolderItem     *item);
+MsgInfo *imap_fetch_msginfo                    (Folder         *folder,
+                                                FolderItem     *item,
+                                                gint            num);
 
 
 Folder *imap_folder_new(const gchar *name, const gchar *path)
@@ -294,7 +299,9 @@ static void imap_folder_init(Folder *folder, const gchar *name,
 
        folder->type = F_IMAP;
 
+/*
        folder->get_msg_list        = imap_get_msg_list;
+*/
        folder->fetch_msg           = imap_fetch_msg;
        folder->add_msg             = imap_add_msg;
        folder->move_msg            = imap_move_msg;
@@ -304,12 +311,17 @@ static void imap_folder_init(Folder *folder, const gchar *name,
        folder->remove_msg          = imap_remove_msg;
        folder->remove_all_msg      = imap_remove_all_msg;
        folder->is_msg_changed      = imap_is_msg_changed;
+/*
        folder->scan                = imap_scan_folder;
+*/
        folder->scan_tree           = imap_scan_tree;
        folder->create_tree         = imap_create_tree;
        folder->create_folder       = imap_create_folder;
        folder->rename_folder       = imap_rename_folder;
        folder->remove_folder       = imap_remove_folder;
+
+       folder->get_num_list        = imap_get_num_list;
+       folder->fetch_msginfo       = imap_fetch_msginfo;
 }
 
 static IMAPSession *imap_session_get(Folder *folder)
@@ -3012,3 +3024,87 @@ static gboolean imap_rename_folder_func(GNode *node, gpointer data)
 
        return FALSE;
 }
+
+GSList *imap_get_num_list(Folder *folder, FolderItem *item)
+{
+       IMAPSession *session;
+       GSList *msgnum_list = NULL;
+       gint i;
+       gint ok, exists = 0, recent = 0, unseen = 0;
+       guint32 uid_validity = 0;
+       guint32 uid = 0;
+
+       g_return_val_if_fail(folder != NULL, NULL);
+       g_return_val_if_fail(item != NULL, NULL);
+       g_return_val_if_fail(item->path != NULL, NULL);
+       g_return_val_if_fail(folder->type == F_IMAP, NULL);
+       g_return_val_if_fail(folder->account != NULL, NULL);
+
+       session = imap_session_get(folder);
+       g_return_val_if_fail(session != NULL, NULL);
+
+       ok = imap_select(session, IMAP_FOLDER(folder), item->path,
+                        &exists, &recent, &unseen, &uid_validity);
+       if (ok != IMAP_SUCCESS)
+               return NULL;
+
+       for(i = 1; i <= exists; i++) {
+               ok = imap_get_uid(session, i, &uid);
+               if (ok != IMAP_SUCCESS)
+                       return msgnum_list;
+               msgnum_list = g_slist_prepend(msgnum_list, GINT_TO_POINTER(uid));
+       }
+       
+       return msgnum_list;
+}
+
+MsgInfo *imap_fetch_msginfo (Folder *folder, FolderItem *item, gint num)
+{
+       gchar *tmp;
+       IMAPSession *session;
+       GString *str;
+       MsgInfo *msginfo;
+       
+       g_return_val_if_fail(folder != NULL, NULL);
+       g_return_val_if_fail(item != NULL, NULL);
+       g_return_val_if_fail(item->folder != NULL, NULL);
+       g_return_val_if_fail(item->folder->type == F_IMAP, NULL);
+
+       session = imap_session_get(folder);
+       g_return_val_if_fail(session != NULL, NULL);
+
+       if (imap_cmd_envelope(SESSION(session)->sock, num, num)
+           != IMAP_SUCCESS) {
+               log_warning(_("can't get envelope\n"));
+               return NULL;
+       }
+
+       str = g_string_new(NULL);
+
+       if ((tmp = sock_getline(SESSION(session)->sock)) == NULL) {
+               log_warning(_("error occurred while getting envelope.\n"));
+               g_string_free(str, TRUE);
+               return NULL;
+       }
+       strretchomp(tmp);
+       log_print("IMAP4< %s\n", tmp);
+       g_string_assign(str, tmp);
+       g_free(tmp);
+
+       msginfo = imap_parse_envelope(SESSION(session)->sock, item, str);
+       if (!msginfo) {
+               log_warning(_("can't parse envelope: %s\n"), str->str);
+       }
+
+       tmp = NULL;
+       do {
+               g_free(tmp);
+               tmp = sock_getline(SESSION(session)->sock);
+       } while (!(tmp == NULL || tmp[0] != '*' || tmp[1] != ' '));
+       
+       msginfo->folder = item;
+
+       g_string_free(str, TRUE);
+       
+       return msginfo;
+}
index 4518db7..8333c45 100644 (file)
@@ -107,7 +107,6 @@ gint import_mbox(FolderItem *default_dest)
                                g_warning("Can't find the folder.\n");
                        } else {
                                ok = proc_mbox(dest, filename, NULL);
-                               folder_item_scan(dest);
                                folderview_update_item(dest, TRUE);
                        }
                }
index 7e8e236..1411cf3 100644 (file)
--- a/src/inc.c
+++ b/src/inc.c
@@ -581,8 +581,7 @@ static gint inc_start(IncProgressDialog *inc_dialog)
                        /* get list of messages in processing */
                        processing = folder_get_default_processing();
                        folder_item_scan(processing);
-                       folder = processing->folder;
-                       msglist = folder->get_msg_list(folder, processing, FALSE);
+                       msglist = folder_item_get_msg_list(processing);
 
                        /* process messages */
                        for(msglist_element = msglist; msglist_element != NULL; msglist_element = msglist_element->next) {
@@ -605,11 +604,8 @@ static gint inc_start(IncProgressDialog *inc_dialog)
 
                new_msgs += pop3_state->cur_total_num;
 
-               if (!prefs_common.scan_all_after_inc) {
-                       folder_item_scan_foreach(pop3_state->folder_table);
-                       folderview_update_item_foreach
-                               (pop3_state->folder_table);
-               }
+               folderview_update_item_foreach
+                       (pop3_state->folder_table);
 
                if (pop3_state->error_val == PS_AUTHFAIL &&
                    pop3_state->ac_prefs->tmp_pass) {
@@ -1036,7 +1032,6 @@ gint inc_drop_message(const gchar *file, Pop3State *state)
        val = GPOINTER_TO_INT(g_hash_table_lookup
                              (state->folder_table, dropfolder));
        if (val == 0) {
-               folder_item_scan(dropfolder);
                g_hash_table_insert(state->folder_table, dropfolder,
                                    GINT_TO_POINTER(1));
        }
@@ -1191,12 +1186,10 @@ static gint get_spool(FolderItem *dest, const gchar *mbox)
                if (!prefs_common.scan_all_after_inc) {
                g_hash_table_insert(folder_table, dest,
                                    GINT_TO_POINTER(1));
-                       folder_item_scan_foreach(folder_table);
                        folderview_update_item_foreach(folder_table);
                }
                g_hash_table_destroy(folder_table);
        } else if (!prefs_common.scan_all_after_inc) {
-               folder_item_scan(dest);
                folderview_update_item(dest, FALSE);
        }
 
index b51eeda..b591696 100644 (file)
@@ -389,6 +389,14 @@ static gint get_queued_message_num(void)
        return queue->total;
 }
 
+static void save_all_caches(FolderItem *item, gpointer data)
+{
+       if(!item->cache)
+               return;
+               
+       folder_item_write_cache(item);
+}
+
 void app_will_exit(GtkWidget *widget, gpointer data)
 {
        MainWindow *mainwin = data;
@@ -422,6 +430,7 @@ void app_will_exit(GtkWidget *widget, gpointer data)
        /* save all state before exiting */
        folder_write_list();
        summary_write_cache(mainwin->summaryview);
+       folder_func_to_all_folders(save_all_caches, NULL);
 
        main_window_get_size(mainwin);
        main_window_get_position(mainwin);
index a6f4d9b..64decf9 100644 (file)
@@ -1447,7 +1447,6 @@ void main_window_empty_trash(MainWindow *mainwin, gboolean confirm)
        for (list = folder_get_list(); list != NULL; list = list->next) {
                folder = list->data;
                if (folder && folder->trash && folder->trash->total != 0) {
-                       folder_item_scan(folder->trash);
                        folderview_update_item(folder->trash, TRUE);
                }
        }
@@ -3128,6 +3127,7 @@ static void update_summary_cb(MainWindow *mainwin, guint action,
                                            folderview->opened);
        if (!fitem) return;
 
+       folder_item_scan(fitem);
        summary_show(mainwin->summaryview, fitem, TRUE);
 }
 
index 5d5d2d2..5a4005f 100644 (file)
@@ -305,7 +305,7 @@ gboolean matcherprop_match_execute(MatcherProp * prop, MsgInfo * info)
                return FALSE;
 
        retval = system(cmd);
-       debug_print(_("Command exit code: %i\n"), retval);
+       debug_print(_("Command exit code: %d\n"), retval);
 
        return (retval == 0);
 }
index 56b5c06..a1cc501 100644 (file)
@@ -214,7 +214,6 @@ gint proc_mbox(FolderItem *dest, const gchar *mbox, GHashTable *folder_table)
                                val = GPOINTER_TO_INT(g_hash_table_lookup
                                                      (folder_table, dropfolder));
                                if (val == 0) {
-                                       folder_item_scan(dropfolder);
                                        g_hash_table_insert(folder_table, dropfolder,
                                                            GINT_TO_POINTER(1));
                                }
@@ -232,7 +231,6 @@ gint proc_mbox(FolderItem *dest, const gchar *mbox, GHashTable *folder_table)
                        unlink(tmp_file);
                        return -1;
                }
-               folder_item_scan(dropfolder);
 
                if (global_processing) {
                        /* CLAWS: new filtering */
@@ -411,7 +409,7 @@ gint export_to_mbox(FolderItem *src, const gchar *mbox)
                return -1;
        }
 
-       mlist = src->folder->get_msg_list(src->folder, src, TRUE);
+       mlist = folder_item_get_msg_list(src);
 
        for (cur = mlist; cur != NULL; cur = cur->next) {
                msginfo = (MsgInfo *)cur->data;
index 451169e..9dc5651 100644 (file)
@@ -46,6 +46,10 @@ static gboolean mbox_purge_deleted(gchar * mbox);
 static gchar * mbox_get_new_path(FolderItem * parent, gchar * name);
 static gchar * mbox_get_folderitem_name(gchar * name);
 
+MsgInfo *mbox_fetch_msginfo(Folder *folder, FolderItem *item, gint num);
+GSList *mbox_get_num_list(Folder *folder, FolderItem *item);
+gboolean mbox_check_msgnum_validity(Folder *folder, FolderItem *item);
+
 Folder *mbox_folder_new(const gchar *name, const gchar *path)
 {
        Folder *folder;
@@ -67,17 +71,25 @@ static void mbox_folder_init(Folder *folder, const gchar *name, const gchar *pat
 
        folder->type = F_MBOX;
 
+/*
        folder->get_msg_list        = mbox_get_msg_list;
+*/
        folder->fetch_msg           = mbox_fetch_msg;
+       folder->fetch_msginfo       = mbox_fetch_msginfo;
        folder->add_msg             = mbox_add_msg;
        folder->copy_msg            = mbox_copy_msg;
        folder->remove_msg          = mbox_remove_msg;
        folder->remove_all_msg      = mbox_remove_all_msg;
+/*
        folder->scan                = mbox_scan_folder;
+*/
+       folder->get_num_list        = mbox_get_num_list;
        folder->create_tree         = mbox_create_tree;
        folder->create_folder       = mbox_create_folder;
        folder->rename_folder       = mbox_rename_folder;
        folder->remove_folder       = mbox_remove_folder;
+       folder->check_msgnum_validity
+                                   = mbox_check_msgnum_validity;
 }
 
 static gchar * mbox_folder_create_parent(const gchar * path)
@@ -1349,7 +1361,6 @@ gchar *mbox_fetch_msg(Folder *folder, FolderItem *item, gint num)
        gchar *filename;
        
        g_return_val_if_fail(item != NULL, NULL);
-       g_return_val_if_fail(num > 0 && num <= item->last_num, NULL);
 
        path = folder_item_get_path(item);
        if (!is_dir_exist(path))
@@ -1504,7 +1515,7 @@ gint mbox_remove_msg(Folder *folder, FolderItem *item, gint num)
        msg = mbox_cache_get_msg(mbox_path, num);
 
        g_free(mbox_path);
-       
+
        if (msg != NULL)
                MSG_SET_PERM_FLAGS(msg->flags, MSG_REALLY_DELETED);
 
@@ -2044,7 +2055,7 @@ static gboolean mbox_purge_deleted(gchar * mbox)
 
        for(l = msg_list ; l != NULL ; l = g_list_next(l)) {
                struct _message * msg = (struct _message *) l->data;
-               if (MSG_IS_INVALID(msg->flags) && MSG_IS_REALLY_DELETED(msg->flags)) {
+               if (!MSG_IS_INVALID(msg->flags) && MSG_IS_REALLY_DELETED(msg->flags)) {
                        modification = TRUE;
                        break;
                }
@@ -2257,3 +2268,119 @@ gint mbox_remove_folder(Folder *folder, FolderItem *item)
        return 0;
 }
 
+GSList *mbox_get_num_list(Folder *folder, FolderItem *item)
+{
+       GSList *mlist;
+       GList * l;
+       FILE * fp;
+       gchar * mbox_path;
+
+       mlist = NULL;
+
+       mbox_path = mbox_folder_get_path(item);
+
+       if (mbox_path == NULL)
+               return NULL;
+
+       mbox_purge_deleted(mbox_path);
+
+       fp = fopen(mbox_path, "rb");
+       
+       if (fp == NULL) {
+               g_free(mbox_path);
+               return NULL;
+       }
+
+       mbox_lockread_file(fp, mbox_path);
+
+       mbox_cache_synchronize_from_file(fp, mbox_path, TRUE);
+
+       item->last_num = mbox_cache_get_count(mbox_path);
+
+       for(l = mbox_cache_get_msg_list(mbox_path) ; l != NULL ;
+           l = g_list_next(l)) {
+               struct _message * msg;
+
+               msg = (struct _message *) l->data;
+
+               if (MSG_IS_INVALID(msg->flags) || !MSG_IS_REALLY_DELETED(msg->flags)) {
+                       mlist = g_slist_append(mlist, GINT_TO_POINTER(msg->msgnum));
+               } else {
+                       MSG_SET_PERM_FLAGS(msg->flags, MSG_REALLY_DELETED);
+               }
+       }
+
+       mbox_unlock_file(fp, mbox_path);
+
+       g_free(mbox_path);
+
+       fclose(fp);
+
+       return mlist;
+}
+
+MsgInfo *mbox_fetch_msginfo(Folder *folder, FolderItem *item, gint num)
+{
+       gchar *mbox_path;
+       struct _message *msg;
+       FILE *src;
+       MsgInfo *msginfo;
+       
+       g_return_val_if_fail(folder != NULL, NULL);
+       g_return_val_if_fail(item != NULL, NULL);
+
+       mbox_path = mbox_folder_get_path(item);
+
+       g_return_val_if_fail(mbox_path != NULL, NULL);
+       
+       src = fopen(mbox_path, "rb");
+       if (src == NULL) {
+               g_free(mbox_path);
+               return NULL;
+       }
+       mbox_lockread_file(src, mbox_path);
+       mbox_cache_synchronize_from_file(src, mbox_path, TRUE);
+
+       msg = mbox_cache_get_msg(mbox_path, num);
+       if (msg == NULL) {
+               mbox_unlock_file(src, mbox_path);
+               fclose(src);
+               g_free(mbox_path);
+               return NULL;
+       }
+       
+       fseek(src, msg->header, SEEK_SET);
+       msginfo = mbox_parse_msg(src, msg, item);
+
+       mbox_unlock_file(src, mbox_path);
+       fclose(src);
+       g_free(mbox_path);
+
+       return msginfo;
+}
+
+gboolean mbox_check_msgnum_validity(Folder *folder, FolderItem *item)
+{
+       mboxcache * old_cache;
+       gboolean scan_new = TRUE;
+       struct stat s;
+       gchar *filename;
+
+       filename = mbox_folder_get_path(item);
+       
+       old_cache = mbox_cache_get_mbox(filename);
+
+       if (old_cache != NULL) {
+               if (stat(filename, &s) < 0) {
+                       FILE_OP_ERROR(filename, "stat");
+               } else if (old_cache->mtime == s.st_mtime) {
+                       debug_print("Folder is not modified.\n");
+                       scan_new = FALSE;
+               }
+       }
+
+       g_free(filename);
+       
+       return !scan_new;
+}
+
index 6605c6a..4afbb02 100644 (file)
@@ -181,7 +181,7 @@ static gint disposition_notification_queue(PrefsAccount * account,
                                           gchar * to, const gchar *file)
 {
        FolderItem *queue;
-       gchar *tmp, *queue_path;
+       gchar *tmp;
        FILE *fp, *src_fp;
        GSList *cur;
        gchar buf[BUFFSIZE];
@@ -254,32 +254,14 @@ static gint disposition_notification_queue(PrefsAccount * account,
        }
 
        queue = folder_get_default_queue();
-       folder_item_scan(queue);
-       queue_path = folder_item_get_path(queue);
-       if (!is_dir_exist(queue_path))
-               make_dir_hier(queue_path);
        if ((num = folder_item_add_msg(queue, tmp, TRUE)) < 0) {
                g_warning(_("can't queue the message\n"));
                unlink(tmp);
                g_free(tmp);
-               g_free(queue_path);
                return -1;
        }
        g_free(tmp);
 
-       if ((fp = procmsg_open_mark_file(queue_path, TRUE)) == NULL)
-               g_warning(_("can't open mark file\n"));
-       else {
-               MsgInfo newmsginfo;
-
-               newmsginfo.msgnum = num;
-               newmsginfo.flags.perm_flags = newmsginfo.flags.tmp_flags = 0;
-               procmsg_write_flags(&newmsginfo, fp);
-               fclose(fp);
-       }
-       g_free(queue_path);
-
-       folder_item_scan(queue);
        folderview_update_item(queue, TRUE);
 
        return 0;
index 5aa3903..a888a88 100644 (file)
--- a/src/mh.c
+++ b/src/mh.c
@@ -47,7 +47,57 @@ static void  mh_folder_init                  (Folder         *folder,
                                                 const gchar    *name,
                                                 const gchar    *path);
 
-static gchar   *mh_get_new_msg_filename                (FolderItem     *dest);
+GSList  *mh_get_msg_list       (Folder         *folder,
+                                FolderItem     *item,
+                                gboolean        use_cache);
+gchar   *mh_fetch_msg          (Folder         *folder,
+                                FolderItem     *item,
+                                gint            num);
+MsgInfo   *mh_fetch_msginfo    (Folder         *folder,
+                                FolderItem     *item,
+                                gint            num);
+gint     mh_add_msg            (Folder         *folder,
+                                FolderItem     *dest,
+                                const gchar    *file,
+                                gboolean        remove_source);
+gint     mh_move_msg           (Folder         *folder,
+                                FolderItem     *dest,
+                                MsgInfo        *msginfo);
+gint     mh_move_msgs_with_dest        (Folder         *folder,
+                                FolderItem     *dest,
+                                GSList         *msglist);
+gint     mh_copy_msg           (Folder         *folder,
+                                FolderItem     *dest,
+                                MsgInfo        *msginfo);
+gint     mh_copy_msgs_with_dest        (Folder         *folder,
+                                FolderItem     *dest,
+                                GSList         *msglist);
+gint     mh_remove_msg         (Folder         *folder,
+                                FolderItem     *item,
+                                gint            num);
+gint     mh_remove_all_msg     (Folder         *folder,
+                                FolderItem     *item);
+gboolean mh_is_msg_changed     (Folder         *folder,
+                                FolderItem     *item,
+                                MsgInfo        *msginfo);
+
+gint    mh_scan_folder         (Folder         *folder,
+                                FolderItem     *item);
+GSList *mh_get_num_list                (Folder         *folder,
+                                FolderItem     *item);
+void    mh_scan_tree           (Folder         *folder);
+
+gint    mh_create_tree         (Folder         *folder);
+FolderItem *mh_create_folder   (Folder         *folder,
+                                FolderItem     *parent,
+                                const gchar    *name);
+gint    mh_rename_folder       (Folder         *folder,
+                                FolderItem     *item,
+                                const gchar    *name);
+gint    mh_remove_folder       (Folder         *folder,
+                                FolderItem     *item);
+
+gchar   *mh_get_new_msg_filename               (FolderItem     *dest);
 
 static GSList  *mh_get_uncached_msgs           (GHashTable     *msg_table,
                                                 FolderItem     *item);
@@ -81,8 +131,11 @@ static void mh_folder_init(Folder *folder, const gchar *name, const gchar *path)
 
        folder->type = F_MH;
 
+/*
        folder->get_msg_list        = mh_get_msg_list;
+*/
        folder->fetch_msg           = mh_fetch_msg;
+       folder->fetch_msginfo       = mh_fetch_msginfo;
        folder->add_msg             = mh_add_msg;
        folder->move_msg            = mh_move_msg;
        folder->move_msgs_with_dest = mh_move_msgs_with_dest;
@@ -91,7 +144,10 @@ static void mh_folder_init(Folder *folder, const gchar *name, const gchar *path)
        folder->remove_msg          = mh_remove_msg;
        folder->remove_all_msg      = mh_remove_all_msg;
        folder->is_msg_changed      = mh_is_msg_changed;
+/*
        folder->scan                = mh_scan_folder;
+*/
+       folder->get_num_list        = mh_get_num_list;
        folder->scan_tree           = mh_scan_tree;
        folder->create_tree         = mh_create_tree;
        folder->create_folder       = mh_create_folder;
@@ -99,6 +155,85 @@ static void mh_folder_init(Folder *folder, const gchar *name, const gchar *path)
        folder->remove_folder       = mh_remove_folder;
 }
 
+void mh_get_last_num(Folder *folder, FolderItem *item)
+{
+       gchar *path;
+       DIR *dp;
+       struct dirent *d;
+       struct stat s;
+       gint max = 0;
+       gint num;
+
+       g_return_if_fail(item != NULL);
+
+       debug_print("mh_get_last_num(): Scanning %s ...\n", item->path);
+
+       path = folder_item_get_path(item);
+       g_return_if_fail(path != NULL);
+       if (change_dir(path) < 0) {
+               g_free(path);
+               return;
+       }
+       g_free(path);
+
+       if ((dp = opendir(".")) == NULL) {
+               FILE_OP_ERROR(item->path, "opendir");
+               return;
+       }
+
+       while ((d = readdir(dp)) != NULL) {
+               if ((num = to_number(d->d_name)) >= 0 &&
+                   stat(d->d_name, &s) == 0 &&
+                   S_ISREG(s.st_mode)) {
+                       if (max < num)
+                               max = num;
+               }
+       }
+       closedir(dp);
+
+       debug_print(_("Last number in dir %s = %d\n"), item->path, max);
+       item->last_num = max;
+}
+
+GSList *mh_get_num_list(Folder *folder, FolderItem *item)
+{
+
+       gchar *path;
+       DIR *dp;
+       struct dirent *d;
+       struct stat s;
+       gint num;
+       GSList *list = NULL;
+
+       g_return_val_if_fail(item != NULL, NULL);
+
+       debug_print("mh_get_last_num(): Scanning %s ...\n", item->path);
+
+       path = folder_item_get_path(item);
+       g_return_val_if_fail(path != NULL, NULL);
+       if (change_dir(path) < 0) {
+               g_free(path);
+               return NULL;
+       }
+       g_free(path);
+
+       if ((dp = opendir(".")) == NULL) {
+               FILE_OP_ERROR(item->path, "opendir");
+               return NULL;
+       }
+
+       while ((d = readdir(dp)) != NULL) {
+               if ((num = to_number(d->d_name)) >= 0 &&
+                   stat(d->d_name, &s) == 0 &&
+                   S_ISREG(s.st_mode)) {
+                       list = g_slist_prepend(list, GINT_TO_POINTER(num));
+               }
+       }
+       closedir(dp);
+
+       return list;
+}
+
 GSList *mh_get_msg_list(Folder *folder, FolderItem *item, gboolean use_cache)
 {
        GSList *mlist;
@@ -166,7 +301,7 @@ gchar *mh_fetch_msg(Folder *folder, FolderItem *item, gint num)
        gchar *file;
 
        g_return_val_if_fail(item != NULL, NULL);
-       g_return_val_if_fail(num > 0 && num <= item->last_num, NULL);
+       g_return_val_if_fail(num > 0, NULL);
 
        path = folder_item_get_path(item);
        file = g_strconcat(path, G_DIR_SEPARATOR_S, itos(num), NULL);
@@ -179,7 +314,43 @@ gchar *mh_fetch_msg(Folder *folder, FolderItem *item, gint num)
        return file;
 }
 
-static gchar *mh_get_new_msg_filename(FolderItem *dest)
+MsgInfo *mh_fetch_msginfo(Folder *folder, FolderItem *item, gint num)
+{
+       gchar *path;
+       gchar *file;
+       MsgFlags flags;
+       MsgInfo *msginfo;
+       struct stat s;
+
+       g_return_val_if_fail(item != NULL, NULL);
+       g_return_val_if_fail(num > 0, NULL);
+
+       path = folder_item_get_path(item);
+       file = g_strconcat(path, G_DIR_SEPARATOR_S, itos(num), NULL);
+       g_free(path);
+       if (!is_file_exist(file)) {
+               g_free(file);
+               return NULL;
+       }
+
+       folder_item_set_default_flags(item, &flags);
+       msginfo = procheader_parse_file(file, flags, TRUE, FALSE);
+       msginfo->msgnum = num;
+       msginfo->folder = item;
+
+       if (stat(file, &s) < 0) {
+               FILE_OP_ERROR(file, "stat");
+               msginfo->size = 0;
+               msginfo->mtime = 0;
+       } else {
+               msginfo->size = s.st_size;
+               msginfo->mtime = s.st_mtime;
+       }
+
+       return msginfo;
+}
+
+gchar *mh_get_new_msg_filename(FolderItem *dest)
 {
        gchar *destfile;
        gchar *destpath;
@@ -230,7 +401,7 @@ gint mh_add_msg(Folder *folder, FolderItem *dest, const gchar *file,
        g_return_val_if_fail(file != NULL, -1);
 
        if (dest->last_num < 0) {
-               mh_scan_folder(folder, dest);
+               mh_get_last_num(folder, dest);
                if (dest->last_num < 0) return -1;
        }
 
@@ -274,7 +445,7 @@ static gint mh_do_move(Folder *folder, FolderItem *dest, MsgInfo *msginfo)
        }
 
        if (dest->last_num < 0) {
-               mh_scan_folder(folder, dest);
+               mh_get_last_num(folder, dest);
                if (dest->last_num < 0) return -1;
        }
 
@@ -313,27 +484,6 @@ static gint mh_do_move(Folder *folder, FolderItem *dest, MsgInfo *msginfo)
        g_free(destfile);
        dest->last_num++;
 
-       destdir = folder_item_get_path(dest);
-       if ((fp = procmsg_open_mark_file(destdir, TRUE)) == NULL)
-               g_warning(_("Can't open mark file.\n"));
-       else {
-               SET_DEST_MSG_FLAGS(fp, dest, msginfo);
-               if (filemode) {
-#if HAVE_FCHMOD
-                       fchmod(fileno(fp), filemode);
-#else
-                       gchar *markfile;
-
-                       markfile = folder_item_get_mark_file(dest);
-                       if (markfile) {
-                               chmod(markfile, filemode);
-                               g_free(markfile);
-                       }
-#endif
-               }
-
-               fclose(fp);
-       }
        g_free(destdir);
 
        return dest->last_num;
@@ -380,7 +530,6 @@ gint mh_move_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo)
 static gint mh_do_move_msgs_with_dest(Folder *folder, FolderItem *dest,
                                      GSList *msglist)
 {
-       gchar *destdir;
        gchar *srcfile;
        gchar *destfile;
        FILE *fp;
@@ -392,16 +541,12 @@ static gint mh_do_move_msgs_with_dest(Folder *folder, FolderItem *dest,
        g_return_val_if_fail(msglist != NULL, -1);
 
        if (dest->last_num < 0) {
-               mh_scan_folder(folder, dest);
+               mh_get_last_num(folder, dest);
                if (dest->last_num < 0) return -1;
        }
 
        prefs = dest->prefs;
 
-       destdir = folder_item_get_path(dest);
-       if ((fp = procmsg_open_mark_file(destdir, TRUE)) == NULL)
-               g_warning(_("Can't open mark file.\n"));
-
        for (cur = msglist; cur != NULL; cur = cur->next) {
                msginfo = (MsgInfo *)cur->data;
 
@@ -428,15 +573,8 @@ static gint mh_do_move_msgs_with_dest(Folder *folder, FolderItem *dest,
                g_free(srcfile);
                g_free(destfile);
                dest->last_num++;
-
-               if (fp) {
-                       SET_DEST_MSG_FLAGS(fp, dest, msginfo);
-               }
        }
 
-       g_free(destdir);
-       if (fp) fclose(fp);
-
        return dest->last_num;
 }
 
@@ -461,10 +599,9 @@ gint mh_move_msgs_with_dest(Folder *folder, FolderItem *dest, GSList *msglist)
 
 gint mh_copy_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo)
 {
-       gchar *destdir;
        gchar *srcfile;
        gchar *destfile;
-       FILE *fp;
+       gchar *destdir;
        gint filemode = 0;
        PrefsFolderItem *prefs;
 
@@ -477,7 +614,7 @@ gint mh_copy_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo)
        }
 
        if (dest->last_num < 0) {
-               mh_scan_folder(folder, dest);
+               mh_get_last_num(folder, dest);
                if (dest->last_num < 0) return -1;
        }
 
@@ -491,6 +628,13 @@ gint mh_copy_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo)
                    msginfo->msgnum, dest->path);
 
        srcfile = procmsg_get_message_file(msginfo);
+       destfile = mh_get_new_msg_filename(dest);
+       if(!destfile) {
+               g_free(srcfile);
+               return -1;
+       }
+       
+       dest->op_count--;
 
        if (copy_file(srcfile, destfile) < 0) {
                FILE_OP_ERROR(srcfile, "copy");
@@ -513,30 +657,6 @@ gint mh_copy_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo)
        g_free(destfile);
        dest->last_num++;
 
-       destdir = folder_item_get_path(dest);
-       if ((fp = procmsg_open_mark_file(destdir, TRUE)) == NULL)
-               g_warning(_("Can't open mark file.\n"));
-       else {
-               SET_DEST_MSG_FLAGS(fp, dest, msginfo);
-
-               if (filemode) {
-#if HAVE_FCHMOD
-                       fchmod(fileno(fp), filemode);
-#else
-                       gchar *markfile;
-
-                       markfile = folder_item_get_mark_file(dest);
-                       if (markfile) {
-                               chmod(markfile, filemode);
-                               g_free(markfile);
-                       }
-#endif
-               }
-
-               fclose(fp);
-       }
-       g_free(destdir);
-
        return dest->last_num;
 }
 
@@ -585,10 +705,8 @@ gint mh_copy_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo)
 
 gint mh_copy_msgs_with_dest(Folder *folder, FolderItem *dest, GSList *msglist)
 {
-       gchar *destdir;
        gchar *srcfile;
        gchar *destfile;
-       FILE *fp;
        GSList *cur;
        MsgInfo *msginfo;
 
@@ -596,17 +714,10 @@ gint mh_copy_msgs_with_dest(Folder *folder, FolderItem *dest, GSList *msglist)
        g_return_val_if_fail(msglist != NULL, -1);
 
        if (dest->last_num < 0) {
-               mh_scan_folder(folder, dest);
+               mh_get_last_num(folder, dest);
                if (dest->last_num < 0) return -1;
        }
 
-       destdir = folder_item_get_path(dest);
-       if (!is_dir_exist(destdir))
-               make_dir_hier(destdir);
-
-       if ((fp = procmsg_open_mark_file(destdir, TRUE)) == NULL)
-               g_warning(_("Can't open mark file.\n"));
-
        for (cur = msglist; cur != NULL; cur = cur->next) {
                msginfo = (MsgInfo *)cur->data;
 
@@ -632,21 +743,15 @@ gint mh_copy_msgs_with_dest(Folder *folder, FolderItem *dest, GSList *msglist)
                g_free(srcfile);
                g_free(destfile);
                dest->last_num++;
-
-               if (fp) {
-                       SET_DEST_MSG_FLAGS(fp, dest, msginfo);
-               }
        }
 
-       g_free(destdir);
-       if (fp) fclose(fp);
-
        return dest->last_num;
 }
 
 gint mh_remove_msg(Folder *folder, FolderItem *item, gint num)
 {
        gchar *file;
+       MsgInfo *msginfo;
 
        g_return_val_if_fail(item != NULL, -1);
 
@@ -724,14 +829,16 @@ gint mh_scan_folder(Folder *folder, FolderItem *item)
                if ((num = to_number(d->d_name)) >= 0 &&
                    stat(d->d_name, &s) == 0 &&
                    S_ISREG(s.st_mode)) {
+/*
                        n_msg++;
+*/
                        if (max < num)
                                max = num;
                }
        }
-
        closedir(dp);
 
+/*
        if (n_msg == 0)
                item->new = item->unread = item->total = 0;
        else {
@@ -746,7 +853,7 @@ gint mh_scan_folder(Folder *folder, FolderItem *item)
                item->unread = unread;
                item->total = n_msg;
        }
-
+*/
        debug_print(_("Last number in dir %s = %d\n"), item->path, max);
        item->last_num = max;
 
index a1749ce..69e2870 100644 (file)
--- a/src/mh.h
+++ b/src/mh.h
@@ -38,49 +38,4 @@ Folder       *mh_folder_new          (const gchar    *name,
                                 const gchar    *path);
 void     mh_folder_destroy     (MHFolder       *folder);
 
-GSList  *mh_get_msg_list       (Folder         *folder,
-                                FolderItem     *item,
-                                gboolean        use_cache);
-gchar   *mh_fetch_msg          (Folder         *folder,
-                                FolderItem     *item,
-                                gint            num);
-gint     mh_add_msg            (Folder         *folder,
-                                FolderItem     *dest,
-                                const gchar    *file,
-                                gboolean        remove_source);
-gint     mh_move_msg           (Folder         *folder,
-                                FolderItem     *dest,
-                                MsgInfo        *msginfo);
-gint     mh_move_msgs_with_dest        (Folder         *folder,
-                                FolderItem     *dest,
-                                GSList         *msglist);
-gint     mh_copy_msg           (Folder         *folder,
-                                FolderItem     *dest,
-                                MsgInfo        *msginfo);
-gint     mh_copy_msgs_with_dest        (Folder         *folder,
-                                FolderItem     *dest,
-                                GSList         *msglist);
-gint     mh_remove_msg         (Folder         *folder,
-                                FolderItem     *item,
-                                gint            num);
-gint     mh_remove_all_msg     (Folder         *folder,
-                                FolderItem     *item);
-gboolean mh_is_msg_changed     (Folder         *folder,
-                                FolderItem     *item,
-                                MsgInfo        *msginfo);
-
-gint    mh_scan_folder         (Folder         *folder,
-                                FolderItem     *item);
-void    mh_scan_tree           (Folder         *folder);
-
-gint    mh_create_tree         (Folder         *folder);
-FolderItem *mh_create_folder   (Folder         *folder,
-                                FolderItem     *parent,
-                                const gchar    *name);
-gint    mh_rename_folder       (Folder         *folder,
-                                FolderItem     *item,
-                                const gchar    *name);
-gint    mh_remove_folder       (Folder         *folder,
-                                FolderItem     *item);
-
 #endif /* __MH_H__ */
index bbb2f03..ea87fc9 100644 (file)
@@ -105,6 +105,14 @@ static void news_delete_all_articles        (FolderItem    *item);
 static gint news_remove_msg             (Folder        *folder, 
                                          FolderItem    *item, 
                                          gint           num);
+GSList *news_get_num_list               (Folder        *folder, 
+                                         FolderItem    *item);
+MsgInfo *news_fetch_msginfo             (Folder        *folder, 
+                                         FolderItem    *item,
+                                         gint           num);
+GSList *news_fetch_msginfos             (Folder        *folder,
+                                         FolderItem    *item,
+                                         GSList        *msgnum_list);
 
 Folder *news_folder_new(const gchar *name, const gchar *path)
 {
@@ -128,10 +136,17 @@ static void news_folder_init(Folder *folder, const gchar *name,
 
        folder->type = F_NEWS;
 
+/*
        folder->get_msg_list = news_get_article_list;
+*/
        folder->fetch_msg    = news_fetch_msg;
+/*
        folder->scan         = news_scan_group;
+*/
        folder->remove_msg   = news_remove_msg;
+       folder->get_num_list = news_get_num_list;
+       folder->fetch_msginfo = news_fetch_msginfo;
+       folder->fetch_msginfos = news_fetch_msginfos;
 }
 
 #if USE_SSL
@@ -850,7 +865,7 @@ static MsgInfo *news_parse_xover(const gchar *xover_str)
        line_int = atoi(line);
 
        /* set MsgInfo */
-       msginfo = g_new0(MsgInfo, 1);
+       msginfo = procmsg_msginfo_new();
        msginfo->msgnum = num;
        msginfo->size = size_int;
 
@@ -1003,3 +1018,250 @@ gint news_cancel_article(Folder * folder, MsgInfo * msginfo)
 
        return 0;
 }
+
+GSList *news_get_num_list(Folder *folder, FolderItem *item)
+{
+       NNTPSession *session;
+       gint i, ok, num, first, last;
+       GSList *msgnum_list = NULL;
+
+       session = news_session_get(folder);
+       g_return_val_if_fail(session != NULL, NULL);
+       g_return_val_if_fail(item != NULL, NULL);
+       g_return_val_if_fail(item->folder != NULL, NULL);
+       g_return_val_if_fail(item->folder->type == F_NEWS, NULL);
+
+       ok = news_select_group(session, item->path, &num, &first, &last);
+       if (ok != NN_SUCCESS) {
+               log_warning(_("can't set group: %s\n"), item->path);
+               return NULL;
+       }
+
+       if(last < first) {
+               log_warning(_("invalid article range: %d - %d\n"),
+                           first, last);
+               return NULL;
+       }
+
+       for(i = first; i <= last; i++) {
+               msgnum_list = g_slist_prepend(msgnum_list, GINT_TO_POINTER(i));
+       }
+
+       return msgnum_list;
+}
+
+#define READ_TO_LISTEND(hdr) \
+       while (!(buf[0] == '.' && buf[1] == '\r')) { \
+               if (sock_gets(SESSION(session)->sock, buf, sizeof(buf)) < 0) { \
+                       log_warning(_("error occurred while getting " hdr ".\n")); \
+                       return msginfo; \
+               } \
+       }
+
+MsgInfo *news_fetch_msginfo(Folder *folder, FolderItem *item, gint num)
+{
+       NNTPSession *session;
+       MsgInfo *msginfo = NULL;
+       gchar buf[NNTPBUFSIZE];
+
+       session = news_session_get(folder);
+       g_return_val_if_fail(session != NULL, NULL);
+       g_return_val_if_fail(item != NULL, NULL);
+       g_return_val_if_fail(item->folder != NULL, NULL);
+       g_return_val_if_fail(item->folder->type == F_NEWS, NULL);
+
+       log_message(_("getting xover %d in %s...\n"),
+                   num, item->path);
+       if (nntp_xover(session->nntp_sock, num, num) != NN_SUCCESS) {
+               log_warning(_("can't get xover\n"));
+               return NULL;
+       }
+       
+       if (sock_gets(SESSION(session)->sock, buf, sizeof(buf)) < 0) {
+               log_warning(_("error occurred while getting xover.\n"));
+               return NULL;
+       }
+       
+       msginfo = news_parse_xover(buf);
+       if (!msginfo) {
+               log_warning(_("invalid xover line: %s\n"), buf);
+       }
+
+       READ_TO_LISTEND("xover");
+
+       if(!msginfo)
+               return NULL;
+       
+       msginfo->folder = item;
+       msginfo->flags.perm_flags = MSG_NEW|MSG_UNREAD;
+       msginfo->flags.tmp_flags = MSG_NEWS;
+       msginfo->newsgroups = g_strdup(item->path);
+
+       if (nntp_xhdr(session->nntp_sock, "to", num, num) != NN_SUCCESS) {
+               log_warning(_("can't get xhdr\n"));
+               return msginfo;
+       }
+
+       if (sock_gets(SESSION(session)->sock, buf, sizeof(buf)) < 0) {
+               log_warning(_("error occurred while getting xhdr.\n"));
+               return msginfo;
+       }
+
+       msginfo->to = news_parse_xhdr(buf, msginfo);
+
+       READ_TO_LISTEND("xhdr (to)");
+
+       if (nntp_xhdr(session->nntp_sock, "cc", num, num) != NN_SUCCESS) {
+               log_warning(_("can't get xhdr\n"));
+               return msginfo;
+       }
+
+       if (sock_gets(SESSION(session)->sock, buf, sizeof(buf)) < 0) {
+               log_warning(_("error occurred while getting xhdr.\n"));
+               return msginfo;
+       }
+
+       msginfo->cc = news_parse_xhdr(buf, msginfo);
+
+       READ_TO_LISTEND("xhdr (cc)");
+
+       return msginfo;
+}
+
+static GSList *news_fetch_msginfo_from_to(NNTPSession *session, FolderItem *item, guint begin, guint end)
+{
+       gchar buf[NNTPBUFSIZE];
+       GSList *newlist = NULL;
+       GSList *llast = NULL;
+       MsgInfo *msginfo;
+
+       g_return_val_if_fail(session != NULL, NULL);
+       g_return_val_if_fail(item != NULL, NULL);
+
+       log_message(_("getting xover %d - %d in %s...\n"),
+                   begin, end, item->path);
+       if (nntp_xover(session->nntp_sock, begin, end) != NN_SUCCESS) {
+               log_warning(_("can't get xover\n"));
+               return NULL;
+       }
+
+       for (;;) {
+               if (sock_gets(SESSION(session)->sock, buf, sizeof(buf)) < 0) {
+                       log_warning(_("error occurred while getting xover.\n"));
+                       return newlist;
+               }
+
+               if (buf[0] == '.' && buf[1] == '\r') break;
+
+               msginfo = news_parse_xover(buf);
+               if (!msginfo) {
+                       log_warning(_("invalid xover line: %s\n"), buf);
+                       continue;
+               }
+
+               msginfo->folder = item;
+               msginfo->flags.perm_flags = MSG_NEW|MSG_UNREAD;
+               msginfo->flags.tmp_flags = MSG_NEWS;
+               msginfo->newsgroups = g_strdup(item->path);
+
+               if (!newlist)
+                       llast = newlist = g_slist_append(newlist, msginfo);
+               else {
+                       llast = g_slist_append(llast, msginfo);
+                       llast = llast->next;
+               }
+       }
+
+       if (nntp_xhdr(session->nntp_sock, "to", begin, end) != NN_SUCCESS) {
+               log_warning(_("can't get xhdr\n"));
+               return newlist;
+       }
+
+       llast = newlist;
+
+       for (;;) {
+               if (sock_gets(SESSION(session)->sock, buf, sizeof(buf)) < 0) {
+                       log_warning(_("error occurred while getting xhdr.\n"));
+                       return newlist;
+               }
+
+               if (buf[0] == '.' && buf[1] == '\r') break;
+               if (!llast) {
+                       g_warning("llast == NULL\n");
+                       continue;
+               }
+
+               msginfo = (MsgInfo *)llast->data;
+               msginfo->to = news_parse_xhdr(buf, msginfo);
+
+               llast = llast->next;
+       }
+
+       if (nntp_xhdr(session->nntp_sock, "cc", begin, end) != NN_SUCCESS) {
+               log_warning(_("can't get xhdr\n"));
+               return newlist;
+       }
+
+       llast = newlist;
+
+       for (;;) {
+               if (sock_gets(SESSION(session)->sock, buf, sizeof(buf)) < 0) {
+                       log_warning(_("error occurred while getting xhdr.\n"));
+                       return newlist;
+               }
+
+               if (buf[0] == '.' && buf[1] == '\r') break;
+               if (!llast) {
+                       g_warning("llast == NULL\n");
+                       continue;
+               }
+
+               msginfo = (MsgInfo *)llast->data;
+               msginfo->cc = news_parse_xhdr(buf, msginfo);
+
+               llast = llast->next;
+       }
+
+       return newlist;
+}
+
+gint news_fetch_msgnum_sort(gconstpointer a, gconstpointer b)
+{
+       return (GPOINTER_TO_INT(a) - GPOINTER_TO_INT(b));
+}
+
+GSList *news_fetch_msginfos(Folder *folder, FolderItem *item, GSList *msgnum_list)
+{
+       NNTPSession *session;
+       GSList *elem, *msginfo_list = NULL, *tmp_msgnum_list, *tmp_msginfo_list;
+       guint first, last, next;
+       
+       g_return_val_if_fail(folder != NULL, NULL);
+       g_return_val_if_fail(folder->type == F_NEWS, NULL);
+       g_return_val_if_fail(msgnum_list != NULL, NULL);
+       g_return_val_if_fail(item != NULL, NULL);
+       
+       session = news_session_get(folder);
+       g_return_val_if_fail(session != NULL, NULL);
+
+       tmp_msgnum_list = g_slist_copy(msgnum_list);
+       tmp_msgnum_list = g_slist_sort(tmp_msgnum_list, news_fetch_msgnum_sort);
+
+       first = GPOINTER_TO_INT(tmp_msgnum_list->data);
+       last = first;
+       for(elem = g_slist_next(tmp_msgnum_list); elem != NULL; elem = g_slist_next(elem)) {
+               next = GPOINTER_TO_INT(elem->data);
+               if(next != (last + 1)) {
+                       tmp_msginfo_list = news_fetch_msginfo_from_to(session, item, first, last);
+                       msginfo_list = g_slist_concat(msginfo_list, tmp_msginfo_list);
+                       first = next;
+               }
+               last = next;
+       }
+       tmp_msginfo_list = news_fetch_msginfo_from_to(session, item, first, last);
+       msginfo_list = g_slist_concat(msginfo_list, tmp_msginfo_list);
+
+       g_slist_free(tmp_msgnum_list);
+       
+       return msginfo_list;
+}
index 15062b4..c4bbb8b 100644 (file)
@@ -792,6 +792,11 @@ static PrefParam param[] = {
         &other.loglength_entry,
         prefs_set_data_from_entry, prefs_set_entry},
 
+       {"cache_max_mem_usage", "4096", &prefs_common.cache_max_mem_usage, P_INT,
+        NULL, NULL, NULL},
+       {"cache_min_keep_time", "15", &prefs_common.cache_min_keep_time, P_INT,
+        NULL, NULL, NULL},
+
        {NULL, NULL, NULL, P_OTHER, NULL, NULL, NULL}
 };
 
index e1e0a42..1593f51 100644 (file)
@@ -238,6 +238,10 @@ struct _PrefsCommon
        gboolean ask_on_clean;
        gboolean warn_queued_on_exit;
        gboolean return_receipt;
+
+       /* Memory cache*/
+       gint cache_max_mem_usage;
+       gint cache_min_keep_time;
        
        /* boolean for work offline 
           stored here for use in inc.c */
index 355c0e1..aae2381 100644 (file)
@@ -520,7 +520,7 @@ MsgInfo *procheader_parse_stream(FILE *fp, MsgFlags flags, gboolean full,
                        if (buf[0] == '\r' || buf[0] == '\n') break;
        }
 
-       msginfo = g_new0(MsgInfo, 1);
+       msginfo = procmsg_msginfo_new();
        
        if (flags.tmp_flags || flags.perm_flags) 
                msginfo->flags = flags;
index 193899d..0ae7ab6 100644 (file)
@@ -226,7 +226,7 @@ GSList *procmsg_read_cache(FolderItem *item, gboolean scan_file)
        }
 
        while (fread(&num, sizeof(num), 1, fp) == 1) {
-               msginfo = g_new0(MsgInfo, 1);
+               msginfo = procmsg_msginfo_new();
                msginfo->msgnum = num;
                READ_CACHE_DATA_INT(msginfo->size, fp);
                READ_CACHE_DATA_INT(msginfo->mtime, fp);
@@ -523,8 +523,12 @@ static GHashTable *procmsg_read_mark_file(const gchar *folder)
 
                flags = g_new0(MsgFlags, 1);
                flags->perm_flags = perm_flags;
-
-               g_hash_table_insert(mark_table, GUINT_TO_POINTER(num), flags);
+    
+               if(!MSG_IS_REALLY_DELETED(*flags)) {
+                       g_hash_table_insert(mark_table, GUINT_TO_POINTER(num), flags);
+               } else {
+                       g_hash_table_remove(mark_table, GUINT_TO_POINTER(num));
+               }
        }
 
        fclose(fp);
@@ -598,7 +602,7 @@ GNode *procmsg_get_thread_tree(GSList *mlist)
                                parent = root;
                        } else {
                                if(MSG_IS_IGNORE_THREAD(((MsgInfo *)parent->data)->flags)) {
-                                       MSG_SET_PERM_FLAGS(msginfo->flags, MSG_IGNORE_THREAD);
+                                       procmsg_msginfo_set_flags(msginfo, MSG_IGNORE_THREAD, 0);
                                }
                        }
                }
@@ -629,7 +633,7 @@ GNode *procmsg_get_thread_tree(GSList *mlist)
                                (parent, parent->children, node);
                        /* CLAWS: ignore thread */
                        if(MSG_IS_IGNORE_THREAD(((MsgInfo *)parent->data)->flags)) {
-                               MSG_SET_PERM_FLAGS(msginfo->flags, MSG_IGNORE_THREAD);
+                               procmsg_msginfo_set_flags(msginfo, MSG_IGNORE_THREAD, 0);
                        }
                }
                node = next;
@@ -660,7 +664,7 @@ GNode *procmsg_get_thread_tree(GSList *mlist)
                                g_node_append(parent, node);
                                /* CLAWS: ignore thread */
                                if(MSG_IS_IGNORE_THREAD(((MsgInfo *)parent->data)->flags)) {
-                                       MSG_SET_PERM_FLAGS(msginfo->flags, MSG_IGNORE_THREAD);
+                                       procmsg_msginfo_set_flags(msginfo, MSG_IGNORE_THREAD, 0);
                                }
                        }
                }                                       
@@ -682,10 +686,6 @@ void procmsg_move_messages(GSList *mlist)
 
        if (!mlist) return;
 
-       hash = procmsg_to_folder_hash_table_create(mlist);
-       folder_item_scan_foreach(hash);
-       g_hash_table_destroy(hash);
-
        for (cur = mlist; cur != NULL; cur = cur->next) {
                msginfo = (MsgInfo *)cur->data;
                if (!dest) {
@@ -717,9 +717,14 @@ void procmsg_copy_messages(GSList *mlist)
 
        if (!mlist) return;
 
+       /* 
+       
+       Horrible: Scanning 2 times for every copy!
+
        hash = procmsg_to_folder_hash_table_create(mlist);
        folder_item_scan_foreach(hash);
        g_hash_table_destroy(hash);
+       */
 
        for (cur = mlist; cur != NULL; cur = cur->next) {
                msginfo = (MsgInfo *)cur->data;
@@ -885,22 +890,26 @@ gint procmsg_send_queue(FolderItem *queue, gboolean save_msgs)
 {
        gint i;
        gint ret = 0;
+       GSList *list, *elem;
 
        if (!queue)
                queue = folder_get_default_queue();
        g_return_val_if_fail(queue != NULL, -1);
 
        folder_item_scan(queue);
-       if (queue->last_num < 0) return -1;
-       else if (queue->last_num == 0) return 0;
+       list = folder_item_get_msg_list(queue);
 
-       for (i = 1; i <= queue->last_num; i++) {
+
+       for(elem = list; elem != NULL; elem = elem->next) {
                gchar *file;
+               MsgInfo *msginfo;
+               
+               msginfo = (MsgInfo *)(elem->data);
 
-               file = folder_item_fetch_msg(queue, i);
+               file = folder_item_fetch_msg(queue, msginfo->msgnum);
                if (file) {
                        if (procmsg_send_message_queue(file) < 0) {
-                               g_warning(_("Sending queued message %d failed.\n"), i);
+                               g_warning(_("Sending queued message %d failed.\n"), msginfo->msgnum);
                                ret = -1;
                        } else {
                        /* CLAWS: 
@@ -913,12 +922,15 @@ gint procmsg_send_queue(FolderItem *queue, gboolean save_msgs)
                                                (queue->folder->outbox,
                                                 file, TRUE);
 */
-                               folder_item_remove_msg(queue, i);
+                               folder_item_remove_msg(queue, msginfo->msgnum);
                        }
                        g_free(file);
                }
+               procmsg_msginfo_free(msginfo);
        }
 
+       folderview_update_item(queue, FALSE);
+
        return ret;
 }
 
@@ -928,6 +940,7 @@ gint procmsg_save_to_outbox(FolderItem *outbox, const gchar *file,
        gint num;
        FILE *fp;
        MsgFlags flag = {0, 0};
+       MsgInfo *msginfo;
 
        debug_print(_("saving sent message...\n"));
 
@@ -961,18 +974,21 @@ gint procmsg_save_to_outbox(FolderItem *outbox, const gchar *file,
                Xstrdup_a(file, tmp, return -1);
        }
 
-       folder_item_scan(outbox);
        if ((num = folder_item_add_msg(outbox, file, FALSE)) < 0) {
                g_warning(_("can't save message\n"));
+               if(is_queued) {
+                       unlink(file);
+               }
                return -1;
        }
+       msginfo = folder_item_fetch_msginfo(outbox, num);
+       procmsg_msginfo_unset_flags(msginfo, ~0, ~0);
+       procmsg_msginfo_free(msginfo);
 
        if(is_queued) {
                unlink(file);
        }
 
-       procmsg_add_flags(outbox, num, flag);
-
        return 0;
 }
 
@@ -1034,6 +1050,23 @@ void procmsg_print_message(MsgInfo *msginfo, const gchar *cmdline)
        system(buf);
 }
 
+MsgInfo *procmsg_msginfo_new_ref(MsgInfo *msginfo)
+{
+       msginfo->refcnt++;
+       
+       return msginfo;
+}
+
+MsgInfo *procmsg_msginfo_new()
+{
+       MsgInfo *newmsginfo;
+
+       newmsginfo = g_new0(MsgInfo, 1);
+       newmsginfo->refcnt = 1;
+       
+       return newmsginfo;
+}
+
 MsgInfo *procmsg_msginfo_copy(MsgInfo *msginfo)
 {
        MsgInfo *newmsginfo;
@@ -1042,6 +1075,8 @@ MsgInfo *procmsg_msginfo_copy(MsgInfo *msginfo)
 
        newmsginfo = g_new0(MsgInfo, 1);
 
+       newmsginfo->refcnt = 1;
+
 #define MEMBCOPY(mmb)  newmsginfo->mmb = msginfo->mmb
 #define MEMBDUP(mmb)   newmsginfo->mmb = msginfo->mmb ? \
                        g_strdup(msginfo->mmb) : NULL
@@ -1082,6 +1117,10 @@ void procmsg_msginfo_free(MsgInfo *msginfo)
 {
        if (msginfo == NULL) return;
 
+       msginfo->refcnt--;
+       if(msginfo->refcnt > 0)
+               return;
+
        g_free(msginfo->fromspace);
        g_free(msginfo->references);
        g_free(msginfo->returnreceiptto);
@@ -1103,6 +1142,43 @@ void procmsg_msginfo_free(MsgInfo *msginfo)
        g_free(msginfo);
 }
 
+guint procmsg_msginfo_memusage(MsgInfo *msginfo)
+{
+       guint memusage = 0;
+       
+       memusage += sizeof(MsgInfo);
+       if(msginfo->fromname)
+               memusage += strlen(msginfo->fromname);
+       if(msginfo->date)
+               memusage += strlen(msginfo->date);
+       if(msginfo->from)
+               memusage += strlen(msginfo->from);
+       if(msginfo->to)
+               memusage += strlen(msginfo->to);
+       if(msginfo->cc)
+               memusage += strlen(msginfo->cc);
+       if(msginfo->newsgroups)
+               memusage += strlen(msginfo->newsgroups);
+       if(msginfo->subject)
+               memusage += strlen(msginfo->subject);
+       if(msginfo->msgid)
+               memusage += strlen(msginfo->msgid);
+       if(msginfo->inreplyto)
+               memusage += strlen(msginfo->inreplyto);
+       if(msginfo->xface)
+               memusage += strlen(msginfo->xface);
+       if(msginfo->dispositionnotificationto)
+               memusage += strlen(msginfo->dispositionnotificationto);
+       if(msginfo->returnreceiptto)
+               memusage += strlen(msginfo->returnreceiptto);
+       if(msginfo->references)
+               memusage += strlen(msginfo->references);
+       if(msginfo->fromspace)
+               memusage += strlen(msginfo->fromspace);
+
+       return memusage;
+}
+
 static gint procmsg_cmp_msgnum(gconstpointer a, gconstpointer b)
 {
        const MsgInfo *msginfo = a;
@@ -1326,3 +1402,122 @@ gint procmsg_send_message_queue(const gchar *file)
 
        return (newsval != 0 ? newsval : mailval);
 }
+
+#define CHANGE_FLAGS(msginfo) \
+{ \
+if (msginfo->folder->folder->change_flags != NULL) \
+msginfo->folder->folder->change_flags(msginfo->folder->folder, \
+                                     msginfo->folder, \
+                                     msginfo); \
+}
+
+void procmsg_msginfo_set_flags(MsgInfo *msginfo, MsgPermFlags perm_flags, MsgTmpFlags tmp_flags)
+{
+       gboolean changed = FALSE;
+       FolderItem *item = msginfo->folder;
+
+       debug_print(_("Setting flags for message %d in folder %s\n"), msginfo->msgnum, item->path);
+
+       /* if new flag is set */
+       if((perm_flags & MSG_NEW) && !MSG_IS_NEW(msginfo->flags) &&
+          !MSG_IS_IGNORE_THREAD(msginfo->flags)) {
+               item->new++;
+               changed = TRUE;
+       }
+
+       /* if unread flag is set */
+       if((perm_flags & MSG_UNREAD) && !MSG_IS_UNREAD(msginfo->flags) &&
+          !MSG_IS_IGNORE_THREAD(msginfo->flags)) {
+               item->unread++;
+               changed = TRUE;
+       }
+
+       /* if ignore thread flag is set */
+       if((perm_flags & MSG_IGNORE_THREAD) && !MSG_IS_IGNORE_THREAD(msginfo->flags)) {
+               if(MSG_IS_NEW(msginfo->flags) || (perm_flags & MSG_NEW)) {
+                       item->new--;
+                       changed = TRUE;
+               }
+               if(MSG_IS_UNREAD(msginfo->flags) || (perm_flags & MSG_UNREAD)) {
+                       item->unread--;
+                       changed = TRUE;
+               }
+       }
+
+       if (MSG_IS_IMAP(msginfo->flags))
+               imap_msg_set_perm_flags(msginfo, perm_flags);
+
+       msginfo->flags.perm_flags |= perm_flags;
+       msginfo->flags.tmp_flags |= tmp_flags;
+
+       if(changed) {
+               folderview_update_item(item, FALSE);
+       }
+       CHANGE_FLAGS(msginfo);
+       procmsg_msginfo_write_flags(msginfo);
+}
+
+void procmsg_msginfo_unset_flags(MsgInfo *msginfo, MsgPermFlags perm_flags, MsgTmpFlags tmp_flags)
+{
+       gboolean changed = FALSE;
+       FolderItem *item = msginfo->folder;
+       
+       debug_print(_("Unsetting flags for message %d in folder %s\n"), msginfo->msgnum, item->path);
+
+       /* if new flag is unset */
+       if((perm_flags & MSG_NEW) && MSG_IS_NEW(msginfo->flags) &&
+          !MSG_IS_IGNORE_THREAD(msginfo->flags)) {
+               item->new--;
+               changed = TRUE;
+       }
+
+       /* if unread flag is unset */
+       if((perm_flags & MSG_UNREAD) && MSG_IS_UNREAD(msginfo->flags) &&
+          !MSG_IS_IGNORE_THREAD(msginfo->flags)) {
+               item->unread--;
+               changed = TRUE;
+       }
+
+       /* if ignore thread flag is unset */
+       if((perm_flags & MSG_IGNORE_THREAD) && MSG_IS_IGNORE_THREAD(msginfo->flags)) {
+               if(MSG_IS_NEW(msginfo->flags) && !(perm_flags & MSG_NEW)) {
+                       item->new++;
+                       changed = TRUE;
+               }
+               if(MSG_IS_UNREAD(msginfo->flags) && !(perm_flags & MSG_UNREAD)) {
+                       item->unread++;
+                       changed = TRUE;
+               }
+       }
+
+       if (MSG_IS_IMAP(msginfo->flags))
+               imap_msg_unset_perm_flags(msginfo, perm_flags);
+
+       msginfo->flags.perm_flags &= ~perm_flags;
+       msginfo->flags.tmp_flags &= ~tmp_flags;
+
+       if(changed) {
+               folderview_update_item(item, FALSE);
+       }
+       CHANGE_FLAGS(msginfo);
+       procmsg_msginfo_write_flags(msginfo);
+}
+
+void procmsg_msginfo_write_flags(MsgInfo *msginfo)
+{
+       gchar *destdir;
+       FILE *fp;
+
+       destdir = folder_item_get_path(msginfo->folder);
+       if (!is_dir_exist(destdir))
+               make_dir_hier(destdir);
+
+       if ((fp = procmsg_open_mark_file(destdir, TRUE))) {
+               procmsg_write_flags(msginfo, fp);
+               fclose(fp);
+       } else {
+               g_warning(_("Can't open mark file.\n"));
+       }
+       
+       g_free(destdir);
+}
index f0e4b21..a7d8b2b 100644 (file)
@@ -90,13 +90,14 @@ typedef enum
        MSG_ENCRYPTED   = 1 << 18,
        MSG_IMAP        = 1 << 19,
        MSG_NEWS        = 1 << 20,
+       MSG_SIGNED      = 1 << 21,
 
        MSG_MIME        = 1 << 29,
 
        MSG_CACHED      = 1 << 31
 } MsgTmpFlags;
 
-#define MSG_CACHED_FLAG_MASK   (MSG_MIME | MSG_ENCRYPTED)
+#define MSG_CACHED_FLAG_MASK   (MSG_MIME | MSG_ENCRYPTED | MSG_SIGNED)
 
 #define MSG_SET_FLAGS(msg, flags)      { (msg) |= (flags); }
 #define MSG_UNSET_FLAGS(msg, flags)    { (msg) &= ~(flags); }
@@ -122,12 +123,16 @@ typedef enum
 #define MSG_SET_COLORLABEL_VALUE(msg, val) \
        MSG_SET_PERM_FLAGS(msg, ((((guint)(val)) & 7) << MSG_CLABEL_SBIT))
 
+#define MSG_COLORLABEL_TO_FLAGS(val) ((((guint)(val)) & 7) << MSG_CLABEL_SBIT)
+#define MSG_COLORLABEL_FROM_FLAGS(val) (val >> MSG_CLABEL_SBIT)
+
 #define MSG_IS_MOVE(msg)               (((msg).tmp_flags & MSG_MOVE) != 0)
 #define MSG_IS_COPY(msg)               (((msg).tmp_flags & MSG_COPY) != 0)
 
 #define MSG_IS_QUEUED(msg)             (((msg).tmp_flags & MSG_QUEUED) != 0)
 #define MSG_IS_DRAFT(msg)              (((msg).tmp_flags & MSG_DRAFT) != 0)
 #define MSG_IS_ENCRYPTED(msg)          (((msg).tmp_flags & MSG_ENCRYPTED) != 0)
+#define MSG_IS_SIGNED(msg)             (((msg).tmp_flags & MSG_SIGNED) != 0)
 #define MSG_IS_IMAP(msg)               (((msg).tmp_flags & MSG_IMAP) != 0)
 #define MSG_IS_NEWS(msg)               (((msg).tmp_flags & MSG_NEWS) != 0)
 #define MSG_IS_MIME(msg)               (((msg).tmp_flags & MSG_MIME) != 0)
@@ -164,6 +169,8 @@ struct _MsgFlags
 
 struct _MsgInfo
 {
+       guint refcnt;
+
        guint  msgnum;
        off_t  size;
        time_t mtime;
@@ -255,11 +262,21 @@ gint      procmsg_save_to_outbox          (FolderItem     *outbox,
 void   procmsg_print_message           (MsgInfo        *msginfo,
                                         const gchar    *cmdline);
 
+MsgInfo *procmsg_msginfo_new           ();
+MsgInfo *procmsg_msginfo_new_ref       (MsgInfo        *msginfo);
 MsgInfo *procmsg_msginfo_copy          (MsgInfo        *msginfo);
 void    procmsg_msginfo_free           (MsgInfo        *msginfo);
+guint   procmsg_msginfo_memusage       (MsgInfo        *msginfo);
 
 gint procmsg_cmp_msgnum_for_sort       (gconstpointer   a,
                                         gconstpointer   b);
 gint procmsg_send_message_queue                (const gchar *file);
 
+void procmsg_msginfo_set_flags         (MsgInfo *msginfo,
+                                        MsgPermFlags perm_flags,
+                                         MsgTmpFlags tmp_flags);
+void procmsg_msginfo_unset_flags       (MsgInfo *msginfo,
+                                        MsgPermFlags perm_flags,
+                                         MsgTmpFlags tmp_flags);
+
 #endif /* __PROCMSG_H__ */
index 6bb3f77..6304da2 100644 (file)
@@ -480,6 +480,26 @@ int rfc2015_is_encrypted (MimeInfo *mimeinfo)
     return 1;
 }
 
+gboolean rfc2015_msg_is_encrypted (gchar *file)
+{
+       FILE *fp;
+       MimeInfo *mimeinfo;
+       int ret;
+
+       if ((fp = fopen(file, "r")) == NULL)
+               return FALSE;
+
+       mimeinfo = procmime_scan_mime_header(fp);
+       if(!mimeinfo) {
+               fclose(fp);
+               return FALSE;
+       }
+
+       ret = rfc2015_is_encrypted(mimeinfo);
+       procmime_mimeinfo_free_all(mimeinfo);
+       return ret != 0 ? TRUE : FALSE;
+}
+
 static int
 name_cmp(const char *a, const char *b)
 {
index 5dd6dff..7b08751 100644 (file)
@@ -31,6 +31,7 @@ MimeInfo * rfc2015_find_signature (MimeInfo *mimeinfo);
 gboolean rfc2015_has_signature (MimeInfo *mimeinfo);
 void rfc2015_check_signature (MimeInfo *mimeinfo, FILE *fp);
 int rfc2015_is_encrypted (MimeInfo *mimeinfo);
+gboolean rfc2015_msg_is_encrypted (gchar *file);
 void rfc2015_decrypt_message (MsgInfo *msginfo, MimeInfo *mimeinfo, FILE *fp);
 GSList *rfc2015_create_signers_list (const char *keyid);
 int rfc2015_encrypt (const char *file, GSList *recp_list, gboolean ascii_armored);
index 2bc0510..bf196cd 100644 (file)
@@ -789,8 +789,15 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item,
 
        main_window_cursor_wait(summaryview->mainwin);
 
+/*
        mlist = item->folder->get_msg_list(item->folder, item, !update_cache);
 
+       !!! NEW !!!
+       USE LIST FROM CACHE, WILL NOT DISPLAY ANY MESSAGES DROPED
+       BY OTHER PROGRAMS TO THE FOLDER
+*/
+       mlist = folder_item_get_msg_list(item);
+
        summary_processing(summaryview, mlist);
 
        for(cur = mlist ; cur != NULL ; cur = g_slist_next(cur)) {
@@ -861,6 +868,12 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item,
 
        g_slist_free(mlist);
 
+       summaryview->folder_item->new    = summaryview->newmsgs;
+       summaryview->folder_item->unread = summaryview->unread;
+       summaryview->folder_item->total  = summaryview->messages;
+       folderview_update_msg_num(summaryview->folderview,
+                                 summaryview->folderview->opened);
+
        if (item->sort_key != SORT_BY_NONE)
                summary_sort(summaryview, item->sort_key, item->sort_type);
 
@@ -1678,6 +1691,10 @@ static void summary_status_show(SummaryView *summaryview)
                return;
        }
 
+       summaryview->newmsgs    = summaryview->folder_item->new;
+       summaryview->unread     = summaryview->folder_item->unread;
+       summaryview->messages   = summaryview->folder_item->total;
+
        rowlist = GTK_CLIST(summaryview->ctree)->selection;
        for (cur = rowlist; cur != NULL; cur = cur->next) {
                msginfo = gtk_ctree_node_get_row_data
@@ -1757,13 +1774,6 @@ static void summary_status_show(SummaryView *summaryview)
        }
        gtk_label_set(GTK_LABEL(summaryview->statlabel_msgs), str);
        g_free(str);
-
-       summaryview->folder_item->new    = summaryview->newmsgs;
-       summaryview->folder_item->unread = summaryview->unread;
-       summaryview->folder_item->total  = summaryview->messages;
-
-       folderview_update_msg_num(summaryview->folderview,
-                                 summaryview->folderview->opened);
 }
 
 static void summary_set_column_titles(SummaryView *summaryview)
@@ -2108,6 +2118,12 @@ gint summary_write_cache(SummaryView *summaryview)
 
        if (!summaryview->folder_item || !summaryview->folder_item->path)
                return -1;
+               
+       if (!summaryview->folder_item->cache)
+               return -1;
+       
+       folder_item_write_cache(summaryview->folder_item);
+       return 0;
 
        if (summaryview->folder_item->folder->update_mark != NULL)
                summaryview->folder_item->folder->update_mark(summaryview->folder_item->folder, summaryview->folder_item);
@@ -2338,19 +2354,16 @@ static void summary_display_msg_full(SummaryView *summaryview,
        }
        g_free(filename);
 
+/* NOT NEEDED ANYMORE
        if (MSG_IS_NEW(msginfo->flags) && !MSG_IS_IGNORE_THREAD(msginfo->flags))
                summaryview->newmsgs--;
        if (MSG_IS_UNREAD(msginfo->flags) && !MSG_IS_IGNORE_THREAD(msginfo->flags))
                summaryview->unread--;
-       if (MSG_IS_NEW(msginfo->flags) && !MSG_IS_IGNORE_THREAD(msginfo->flags) || 
-           MSG_IS_UNREAD(msginfo->flags) && !MSG_IS_IGNORE_THREAD(msginfo->flags)) {
-               MSG_UNSET_PERM_FLAGS(msginfo->flags, MSG_NEW | MSG_UNREAD);
-               if (MSG_IS_IMAP(msginfo->flags))
-                       imap_msg_unset_perm_flags(msginfo, MSG_NEW | MSG_UNREAD);
-               summary_set_row_marks(summaryview, row);
-               gtk_clist_thaw(GTK_CLIST(ctree));
-               summary_status_show(summaryview);
-       }
+*/
+       procmsg_msginfo_unset_flags(msginfo, MSG_NEW | MSG_UNREAD, 0);
+       summary_set_row_marks(summaryview, row);
+       gtk_clist_thaw(GTK_CLIST(ctree));
+       summary_status_show(summaryview);
 
        flags = msginfo->flags;
 
@@ -2378,14 +2391,6 @@ static void summary_display_msg_full(SummaryView *summaryview,
                gtkut_ctree_node_move_if_on_the_edge(ctree, row);
        }
 
-       if (MSG_IS_NEW(msginfo->flags) || MSG_IS_UNREAD(msginfo->flags) ||
-           (MSG_IS_MIME(msginfo->flags) - MSG_IS_MIME(flags) != 0)) {
-               MSG_UNSET_PERM_FLAGS(msginfo->flags, MSG_NEW | MSG_UNREAD);
-               CHANGE_FLAGS(msginfo);
-               summary_set_row_marks(summaryview, row);
-               gtk_clist_thaw(GTK_CLIST(ctree));
-               summary_status_show(summaryview);
-       }
        summary_set_menu_sensitive(summaryview);
        main_window_set_toolbar_sensitive(summaryview->mainwin);
 
@@ -2676,12 +2681,8 @@ static void summary_mark_row(SummaryView *summaryview, GtkCTreeNode *row)
                        folderview_update_item(msginfo->to_folder, 0);
        }
        msginfo->to_folder = NULL;
-       MSG_UNSET_PERM_FLAGS(msginfo->flags, MSG_DELETED);
-       MSG_UNSET_TMP_FLAGS(msginfo->flags, MSG_MOVE | MSG_COPY);
-       MSG_SET_PERM_FLAGS(msginfo->flags, MSG_MARKED);
-       if (MSG_IS_IMAP(msginfo->flags))
-               imap_msg_set_perm_flags(msginfo, MSG_MARKED);
-       CHANGE_FLAGS(msginfo);
+       procmsg_msginfo_unset_flags(msginfo, MSG_DELETED, MSG_MOVE | MSG_COPY);
+       procmsg_msginfo_set_flags(msginfo, MSG_MARKED, 0);
        summary_set_row_marks(summaryview, row);
        debug_print(_("Message %s/%d is marked\n"), msginfo->folder->path, msginfo->msgnum);
 }
@@ -2710,12 +2711,8 @@ static void summary_lock_row(SummaryView *summaryview, GtkCTreeNode *row)
                        folderview_update_item(msginfo->to_folder, 0);
        }
        msginfo->to_folder = NULL;
-       MSG_UNSET_PERM_FLAGS(msginfo->flags, MSG_DELETED);
-       MSG_UNSET_TMP_FLAGS(msginfo->flags, MSG_MOVE | MSG_COPY);
-       MSG_SET_PERM_FLAGS(msginfo->flags, MSG_LOCKED);
-       if (MSG_IS_IMAP(msginfo->flags))
-               imap_msg_set_perm_flags(msginfo, MSG_LOCKED);
-       CHANGE_FLAGS(msginfo);
+       procmsg_msginfo_unset_flags(msginfo, MSG_DELETED, MSG_MOVE | MSG_COPY);
+       procmsg_msginfo_set_flags(msginfo, MSG_LOCKED, 0);
        summary_set_row_marks(summaryview, row);
        debug_print(_("Message %d is locked\n"), msginfo->msgnum);
 }
@@ -2739,20 +2736,16 @@ static void summary_mark_row_as_read(SummaryView *summaryview,
        MsgInfo *msginfo;
 
        msginfo = gtk_ctree_node_get_row_data(ctree, row);
+/* NOT NEEDED ANYMORE
        if (MSG_IS_NEW(msginfo->flags) && !MSG_IS_IGNORE_THREAD(msginfo->flags))
                summaryview->newmsgs--;
        if (MSG_IS_UNREAD(msginfo->flags) && !MSG_IS_IGNORE_THREAD(msginfo->flags))
                summaryview->unread--;
-       if (MSG_IS_NEW(msginfo->flags) ||
-           MSG_IS_UNREAD(msginfo->flags)) {
-               MSG_UNSET_PERM_FLAGS(msginfo->flags, MSG_NEW | MSG_UNREAD);
-               if (MSG_IS_IMAP(msginfo->flags))
-                       imap_msg_unset_perm_flags(msginfo, MSG_NEW | MSG_UNREAD);
-               CHANGE_FLAGS(msginfo);
-               summary_set_row_marks(summaryview, row);
-               debug_print(_("Message %d is marked as read\n"),
-                           msginfo->msgnum);
-       }
+*/
+       procmsg_msginfo_unset_flags(msginfo, MSG_NEW | MSG_UNREAD, 0);
+       summary_set_row_marks(summaryview, row);
+       debug_print(_("Message %d is marked as read\n"),
+               msginfo->msgnum);
 }
 
 void summary_mark_as_read(SummaryView *summaryview)
@@ -2796,22 +2789,18 @@ static void summary_mark_row_as_unread(SummaryView *summaryview,
        msginfo = gtk_ctree_node_get_row_data(ctree, row);
        if (MSG_IS_DELETED(msginfo->flags)) {
                msginfo->to_folder = NULL;
-               MSG_UNSET_PERM_FLAGS(msginfo->flags, MSG_DELETED);
+               procmsg_msginfo_unset_flags(msginfo, MSG_DELETED, 0);
                summaryview->deleted--;
        }
-       MSG_UNSET_PERM_FLAGS(msginfo->flags, MSG_REPLIED | MSG_FORWARDED);
-       if (MSG_IS_IMAP(msginfo->flags))
-               imap_msg_unset_perm_flags(msginfo, MSG_REPLIED);
-       if (!MSG_IS_UNREAD(msginfo->flags)) {
-               MSG_SET_PERM_FLAGS(msginfo->flags, MSG_UNREAD);
-               if (MSG_IS_IMAP(msginfo->flags))
-                       imap_msg_set_perm_flags(msginfo, MSG_UNREAD);
+/* NOT NEEDED ANYMORE
+       if (!MSG_IS_UNREAD(msginfo->flags) && !MSG_IS_IGNORE_THREAD(msginfo->flags))
                summaryview->unread++;
-               debug_print(_("Message %d is marked as unread\n"),
-                           msginfo->msgnum);
-       }
+*/
 
-       CHANGE_FLAGS(msginfo);
+       procmsg_msginfo_unset_flags(msginfo, MSG_REPLIED | MSG_FORWARDED, 0);
+       procmsg_msginfo_set_flags(msginfo, MSG_UNREAD, 0);
+       debug_print(_("Message %d is marked as unread\n"),
+               msginfo->msgnum);
 
        summary_set_row_marks(summaryview, row);
 }
@@ -2906,12 +2895,8 @@ static void summary_delete_row(SummaryView *summaryview, GtkCTreeNode *row)
                        folderview_update_item(msginfo->to_folder, 0);
        }
        msginfo->to_folder = NULL;
-       MSG_UNSET_PERM_FLAGS(msginfo->flags, MSG_MARKED);
-       if (MSG_IS_IMAP(msginfo->flags))
-               imap_msg_unset_perm_flags(msginfo, MSG_MARKED);
-       MSG_UNSET_TMP_FLAGS(msginfo->flags, MSG_MOVE | MSG_COPY);
-       MSG_SET_PERM_FLAGS(msginfo->flags, MSG_DELETED);
-       CHANGE_FLAGS(msginfo);
+       procmsg_msginfo_unset_flags(msginfo, MSG_MARKED, MSG_MOVE | MSG_COPY);
+       procmsg_msginfo_set_flags(msginfo, MSG_DELETED, 0);
        summaryview->deleted++;
 
        if (!prefs_common.immediate_exec && 
@@ -3038,11 +3023,7 @@ static void summary_unmark_row(SummaryView *summaryview, GtkCTreeNode *row)
                        folderview_update_item(msginfo->to_folder, 0);
        }
        msginfo->to_folder = NULL;
-       MSG_UNSET_PERM_FLAGS(msginfo->flags, MSG_MARKED | MSG_DELETED);
-       if (MSG_IS_IMAP(msginfo->flags))
-               imap_msg_unset_perm_flags(msginfo, MSG_MARKED);
-       MSG_UNSET_TMP_FLAGS(msginfo->flags, MSG_MOVE | MSG_COPY);
-       CHANGE_FLAGS(msginfo);
+       procmsg_msginfo_unset_flags(msginfo, MSG_MARKED | MSG_DELETED, MSG_MOVE | MSG_COPY);
        summary_set_row_marks(summaryview, row);
 
        debug_print(_("Message %s/%d is unmarked\n"),
@@ -3087,12 +3068,9 @@ static void summary_move_row_to(SummaryView *summaryview, GtkCTreeNode *row,
                if (!prefs_common.immediate_exec)
                        msginfo->to_folder->op_count--;
        }
-       MSG_UNSET_PERM_FLAGS(msginfo->flags, MSG_MARKED | MSG_DELETED);
-       if (MSG_IS_IMAP(msginfo->flags))
-               imap_msg_unset_perm_flags(msginfo, MSG_MARKED);
-       MSG_UNSET_TMP_FLAGS(msginfo->flags, MSG_COPY);
+       procmsg_msginfo_unset_flags(msginfo, MSG_MARKED | MSG_DELETED, MSG_COPY);
        if (!MSG_IS_MOVE(msginfo->flags)) {
-               MSG_SET_TMP_FLAGS(msginfo->flags, MSG_MOVE);
+               procmsg_msginfo_set_flags(msginfo, 0, MSG_MOVE);
                summaryview->moved++;
                changed = TRUE;
        }
@@ -3179,12 +3157,9 @@ static void summary_copy_row_to(SummaryView *summaryview, GtkCTreeNode *row,
                if (!prefs_common.immediate_exec)
                        msginfo->to_folder->op_count--;
        }
-       MSG_UNSET_PERM_FLAGS(msginfo->flags, MSG_MARKED | MSG_DELETED);
-       if (MSG_IS_IMAP(msginfo->flags))
-               imap_msg_unset_perm_flags(msginfo, MSG_MARKED);
-       MSG_UNSET_TMP_FLAGS(msginfo->flags, MSG_MOVE);
+       procmsg_msginfo_unset_flags(msginfo, MSG_MARKED | MSG_DELETED, MSG_MOVE);
        if (!MSG_IS_COPY(msginfo->flags)) {
-               MSG_SET_TMP_FLAGS(msginfo->flags, MSG_COPY);
+               procmsg_msginfo_set_flags(msginfo, 0, MSG_COPY);
                summaryview->copied++;
                changed = TRUE;
        }
@@ -3422,7 +3397,6 @@ static void summary_execute_move(SummaryView *summaryview)
        if (summaryview->mlist) {
                procmsg_move_messages(summaryview->mlist);
 
-               folder_item_scan_foreach(summaryview->folder_table);
                folderview_update_item_foreach(summaryview->folder_table);
 
                for (cur = summaryview->mlist; cur != NULL; cur = cur->next)
@@ -3431,6 +3405,7 @@ static void summary_execute_move(SummaryView *summaryview)
                summaryview->mlist = NULL;
        }
 
+       folderview_update_item(summaryview->folder_item, FALSE);
        g_hash_table_destroy(summaryview->folder_table);
        summaryview->folder_table = NULL;
 }
@@ -3476,7 +3451,7 @@ static void summary_execute_copy(SummaryView *summaryview)
        if (summaryview->mlist) {
                procmsg_copy_messages(summaryview->mlist);
 
-               folder_item_scan_foreach(summaryview->folder_table);
+               /* folder_item_scan_foreach(summaryview->folder_table); */
                folderview_update_item_foreach(summaryview->folder_table);
 
                g_slist_free(summaryview->mlist);
@@ -3506,7 +3481,7 @@ static void summary_execute_copy_func(GtkCTree *ctree, GtkCTreeNode *node,
                summaryview->mlist =
                        g_slist_append(summaryview->mlist, msginfo);
 
-               MSG_UNSET_TMP_FLAGS(msginfo->flags, MSG_COPY);
+               procmsg_msginfo_unset_flags(msginfo, 0, MSG_COPY);
                summary_set_row_marks(summaryview, node);
        }
 }
@@ -3541,9 +3516,9 @@ static void summary_execute_delete(SummaryView *summaryview)
        summaryview->mlist = NULL;
 
        if ((summaryview->folder_item != trash) && (trash != NULL)) {
-               folder_item_scan(trash);
                folderview_update_item(trash, FALSE);
        }
+       folderview_update_item(summaryview->folder_item, FALSE);
 }
 
 static void summary_execute_delete_func(GtkCTree *ctree, GtkCTreeNode *node,
@@ -3795,7 +3770,7 @@ void summary_processing(SummaryView *summaryview, GSList * mlist)
                                          summaryview->folder_table);
        }
        
-       folder_item_scan_foreach(summaryview->folder_table);
+       /* folder_item_scan_foreach(summaryview->folder_table); */
        folderview_update_item_foreach(summaryview->folder_table);
        
        g_hash_table_destroy(summaryview->folder_table);
@@ -3889,7 +3864,7 @@ void summary_filter(SummaryView *summaryview)
 
                gtk_clist_thaw(GTK_CLIST(summaryview->ctree));
 
-               folder_item_scan_foreach(summaryview->folder_table);
+               /* folder_item_scan_foreach(summaryview->folder_table); */
                folderview_update_item_foreach(summaryview->folder_table);
 
                g_hash_table_destroy(summaryview->folder_table);
@@ -4173,8 +4148,8 @@ void summary_set_colorlabel_color(GtkCTree *ctree, GtkCTreeNode *node,
        gint color_index;
 
        msginfo = gtk_ctree_node_get_row_data(ctree, node);
-       MSG_UNSET_PERM_FLAGS(msginfo->flags, MSG_CLABEL_FLAG_MASK);
-       MSG_SET_COLORLABEL_VALUE(msginfo->flags, labelcolor);
+       procmsg_msginfo_unset_flags(msginfo, MSG_CLABEL_FLAG_MASK, 0);
+       procmsg_msginfo_set_flags(msginfo, MSG_COLORLABEL_TO_FLAGS(labelcolor), 0);
 
        color_index = labelcolor == 0 ? -1 : (gint)labelcolor - 1;
        ctree_style = gtk_widget_get_style(GTK_WIDGET(ctree));
@@ -4588,6 +4563,12 @@ static void summary_key_pressed(GtkWidget *widget, GdkEventKey *event,
                textview_scroll_one_line(summaryview->messageview->textview,
                                         (event->state & GDK_MOD1_MASK) != 0);
                break;
+       case GDK_asterisk:      /* Mark */
+               summary_mark(summaryview);
+               break;
+       case GDK_exclam:        /* Mark as unread */
+               summary_mark_as_unread(summaryview);
+               break;
        case GDK_Delete:
                RETURN_IF_LOCKED();
                BREAK_ON_MODIFIER_KEY();
@@ -4644,10 +4625,7 @@ static void summary_selected(GtkCTree *ctree, GtkCTreeNode *row,
        switch (column < 0 ? column : summaryview->col_state[column].type) {
        case S_COL_MARK:
                if (MSG_IS_MARKED(msginfo->flags)) {
-                       MSG_UNSET_PERM_FLAGS(msginfo->flags, MSG_MARKED);
-                       if (MSG_IS_IMAP(msginfo->flags))
-                               imap_msg_unset_perm_flags(msginfo, MSG_MARKED);
-                       CHANGE_FLAGS(msginfo);
+                       procmsg_msginfo_unset_flags(msginfo, MSG_MARKED, 0);
                        summary_set_row_marks(summaryview, row);
                } else
                        summary_mark_row(summaryview, row);
@@ -4664,8 +4642,7 @@ static void summary_selected(GtkCTree *ctree, GtkCTreeNode *row,
                break;
        case S_COL_LOCKED:
                if (MSG_IS_LOCKED(msginfo->flags)) {
-                       MSG_UNSET_PERM_FLAGS(msginfo->flags, MSG_LOCKED);
-                       CHANGE_FLAGS(msginfo);
+                       procmsg_msginfo_unset_flags(msginfo, MSG_LOCKED, 0);
                        summary_set_row_marks(summaryview, row);
                }
                else
@@ -5076,13 +5053,13 @@ static void summary_ignore_thread_func(GtkCTree *ctree, GtkCTreeNode *row, gpoin
        MsgInfo *msginfo;
 
        msginfo = gtk_ctree_node_get_row_data(ctree, row);
+/* NOT NEEDED ANYMORE
        if (MSG_IS_NEW(msginfo->flags))
                summaryview->newmsgs--;
        if (MSG_IS_UNREAD(msginfo->flags))
                summaryview->unread--;
-       MSG_SET_PERM_FLAGS(msginfo->flags, MSG_IGNORE_THREAD);
-
-       CHANGE_FLAGS(msginfo);
+*/
+       procmsg_msginfo_set_flags(msginfo, MSG_IGNORE_THREAD, 0);
 
        summary_set_row_marks(summaryview, row);
        debug_print(_("Message %d is marked as ignore thread\n"),
@@ -5108,14 +5085,14 @@ static void summary_unignore_thread_func(GtkCTree *ctree, GtkCTreeNode *row, gpo
        MsgInfo *msginfo;
 
        msginfo = gtk_ctree_node_get_row_data(ctree, row);
+/* NOT NEEDED ANYMORE
        if (MSG_IS_NEW(msginfo->flags))
                summaryview->newmsgs++;
        if (MSG_IS_UNREAD(msginfo->flags))
                summaryview->unread++;
-       MSG_UNSET_PERM_FLAGS(msginfo->flags, MSG_IGNORE_THREAD);
+*/
+       procmsg_msginfo_unset_flags(msginfo, MSG_IGNORE_THREAD, 0);
 
-       CHANGE_FLAGS(msginfo);
-               
        summary_set_row_marks(summaryview, row);
        debug_print(_("Message %d is marked as unignore thread\n"),
            msginfo->msgnum);
@@ -5148,6 +5125,7 @@ static gboolean processing_apply_func(GNode *node, gpointer data)
                return FALSE;
        processing = item->prefs->processing;
 
+
        if (processing != NULL) {
                gchar * buf;
                GSList * mlist;
@@ -5158,9 +5136,11 @@ static gboolean processing_apply_func(GNode *node, gpointer data)
                STATUSBAR_PUSH(summaryview->mainwin, buf);
                g_free(buf);
 
+/*
                mlist = item->folder->get_msg_list(item->folder, item,
                                                   TRUE);
-               
+*/             
+               mlist = folder_item_get_msg_list(item);
                for(cur = mlist ; cur != NULL ; cur = cur->next) {
                        MsgInfo * msginfo;