From 30555a9068aa58ce67b73d93a79e1196eb552b15 Mon Sep 17 00:00:00 2001 From: Christoph Hohmann Date: Sat, 29 Jun 2002 23:33:42 +0000 Subject: [PATCH] merge new cache branch --- ChangeLog.claws | 4 + Makefile.am | 1 + configure.in | 3 +- po/Makefile.in.in | 2 +- src/Makefile.am | 3 +- src/addressbook.c | 6 +- src/compose.c | 16 +- src/filtering.c | 2 - src/folder.c | 604 ++++++++++++++++++++++++++++++++++++++++----- src/folder.h | 25 +- src/folderview.c | 8 +- src/gtkspell.c | 12 + src/imap.c | 96 +++++++ src/import.c | 1 - src/inc.c | 13 +- src/main.c | 9 + src/mainwindow.c | 2 +- src/matcher.c | 2 +- src/mbox.c | 4 +- src/mbox_folder.c | 133 +++++++++- src/messageview.c | 20 +- src/mh.c | 277 ++++++++++++++------- src/mh.h | 45 ---- src/news.c | 264 +++++++++++++++++++- src/prefs_common.c | 5 + src/prefs_common.h | 4 + src/procheader.c | 2 +- src/procmsg.c | 233 +++++++++++++++-- src/procmsg.h | 19 +- src/rfc2015.c | 20 ++ src/rfc2015.h | 1 + src/summaryview.c | 180 ++++++-------- 32 files changed, 1645 insertions(+), 371 deletions(-) diff --git a/ChangeLog.claws b/ChangeLog.claws index 3d15ab303..5f149d34f 100644 --- a/ChangeLog.claws +++ b/ChangeLog.claws @@ -1,3 +1,7 @@ +2002-06-30 [christoph] 0.7.8claws36 + + * merge new cache branch + 2002-06-29 [paul] 0.7.8claws35 * configure.in diff --git a/Makefile.am b/Makefile.am index ec0070a50..2466c620f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -6,6 +6,7 @@ EXTRA_DIST = \ README.jp \ ChangeLog.claws \ README.claws \ + README.README \ TODO.jp \ sylpheed.desktop \ sylpheed.spec \ diff --git a/configure.in b/configure.in index 86e05afee..fb700b05e 100644 --- a/configure.in +++ b/configure.in @@ -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 diff --git a/po/Makefile.in.in b/po/Makefile.in.in index 32b737655..3077d1f43 100644 --- a/po/Makefile.in.in +++ b/po/Makefile.in.in @@ -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 \ diff --git a/src/Makefile.am b/src/Makefile.am index 4aca5c18b..3f76751bc 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 \ diff --git a/src/addressbook.c b/src/addressbook.c index 7dd057fcb..61fce2cf3 100644 --- a/src/addressbook.c +++ b/src/addressbook.c @@ -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(); } diff --git a/src/compose.c b/src/compose.c index 2534af32d..1fc1a3c3e 100644 --- a/src/compose.c +++ b/src/compose.c @@ -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; diff --git a/src/filtering.c b/src/filtering.c index 8756c5383..69eb03947 100644 --- a/src/filtering.c +++ b/src/filtering.c @@ -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)); } diff --git a/src/folder.c b/src/folder.c index 17ea90c84..554ac6e4e 100644 --- a/src/folder.c +++ b/src/folder.c @@ -26,6 +26,9 @@ #include #include #include +#include +#include +#include #include #include "intl.h" @@ -40,9 +43,11 @@ #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); } diff --git a/src/folder.h b/src/folder.h index bd22c6551..4baf398c7 100644 --- a/src/folder.h +++ b/src/folder.h @@ -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__ */ diff --git a/src/folderview.c b/src/folderview.c index 4382b8eb9..a21aad04e 100644 --- a/src/folderview.c +++ b/src/folderview.c @@ -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); diff --git a/src/gtkspell.c b/src/gtkspell.c index 5da47a818..2287435a5 100644 --- a/src/gtkspell.c +++ b/src/gtkspell.c @@ -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)"), diff --git a/src/imap.c b/src/imap.c index a4a05f5c3..edddafd5e 100644 --- a/src/imap.c +++ b/src/imap.c @@ -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; +} diff --git a/src/import.c b/src/import.c index 4518db70a..8333c45e2 100644 --- a/src/import.c +++ b/src/import.c @@ -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); } } diff --git a/src/inc.c b/src/inc.c index 7e8e23658..1411cf311 100644 --- 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); } diff --git a/src/main.c b/src/main.c index b51eeda81..b5916968f 100644 --- a/src/main.c +++ b/src/main.c @@ -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); diff --git a/src/mainwindow.c b/src/mainwindow.c index a6f4d9b9b..64decf9ec 100644 --- a/src/mainwindow.c +++ b/src/mainwindow.c @@ -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); } diff --git a/src/matcher.c b/src/matcher.c index 5d5d2d27d..5a4005f3d 100644 --- a/src/matcher.c +++ b/src/matcher.c @@ -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); } diff --git a/src/mbox.c b/src/mbox.c index 56b5c0679..a1cc501a7 100644 --- a/src/mbox.c +++ b/src/mbox.c @@ -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; diff --git a/src/mbox_folder.c b/src/mbox_folder.c index 451169e5e..9dc5651a2 100644 --- a/src/mbox_folder.c +++ b/src/mbox_folder.c @@ -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; +} + diff --git a/src/messageview.c b/src/messageview.c index 6605c6a5f..4afbb025c 100644 --- a/src/messageview.c +++ b/src/messageview.c @@ -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; diff --git a/src/mh.c b/src/mh.c index 5aa390371..a888a88e0 100644 --- 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; diff --git a/src/mh.h b/src/mh.h index a1749ce73..69e287041 100644 --- 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__ */ diff --git a/src/news.c b/src/news.c index bbb2f0332..ea87fc957 100644 --- a/src/news.c +++ b/src/news.c @@ -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; +} diff --git a/src/prefs_common.c b/src/prefs_common.c index 15062b410..c4bbb8bf5 100644 --- a/src/prefs_common.c +++ b/src/prefs_common.c @@ -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} }; diff --git a/src/prefs_common.h b/src/prefs_common.h index e1e0a4272..1593f51c8 100644 --- a/src/prefs_common.h +++ b/src/prefs_common.h @@ -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 */ diff --git a/src/procheader.c b/src/procheader.c index 355c0e1cf..aae2381ee 100644 --- a/src/procheader.c +++ b/src/procheader.c @@ -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; diff --git a/src/procmsg.c b/src/procmsg.c index 193899dc8..0ae7ab63a 100644 --- a/src/procmsg.c +++ b/src/procmsg.c @@ -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); +} diff --git a/src/procmsg.h b/src/procmsg.h index f0e4b2164..a7d8b2bf9 100644 --- a/src/procmsg.h +++ b/src/procmsg.h @@ -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__ */ diff --git a/src/rfc2015.c b/src/rfc2015.c index 6bb3f7719..6304da2fe 100644 --- a/src/rfc2015.c +++ b/src/rfc2015.c @@ -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) { diff --git a/src/rfc2015.h b/src/rfc2015.h index 5dd6dff94..7b0875120 100644 --- a/src/rfc2015.h +++ b/src/rfc2015.h @@ -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); diff --git a/src/summaryview.c b/src/summaryview.c index 2bc05101d..bf196cd56 100644 --- a/src/summaryview.c +++ b/src/summaryview.c @@ -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; -- 2.25.1