2007-08-03 [paul] 2.10.0cvs85
[claws.git] / src / mh.c
index 142e9ec5430776722b6a8e8957496a661dd0317d..2b8f9cf68d2681340c2514c9f945a8789b63e9b0 100644 (file)
--- a/src/mh.c
+++ b/src/mh.c
@@ -1,10 +1,10 @@
 /*
  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2006 Hiroyuki Yamamoto and the Sylpheed-Claws team
+ * Copyright (C) 1999-2007 Hiroyuki Yamamoto and the Claws Mail team
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation; either version 3 of the License, or
  * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
@@ -13,8 +13,8 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * 
  */
 
 #ifdef HAVE_CONFIG_H
 #include <unistd.h>
 #include <string.h>
 #include <errno.h>
-
-#undef MEASURE_TIME
-
-#ifdef MEASURE_TIME
-#  include <sys/time.h>
-#endif
+#include <time.h>
 
 #include "folder.h"
 #include "mh.h"
@@ -45,6 +40,7 @@
 #include "codeconv.h"
 #include "statusbar.h"
 #include "gtkutils.h"
+#include "timing.h"
 
 /* Define possible missing constants for Windows. */
 #ifdef G_OS_WIN32
@@ -237,7 +233,7 @@ gboolean mh_scan_required(Folder *folder, FolderItem *item)
        return FALSE;
 }
 
-void mh_get_last_num(Folder *folder, FolderItem *item)
+static void mh_get_last_num(Folder *folder, FolderItem *item)
 {
        gchar *path;
        DIR *dp;
@@ -268,6 +264,8 @@ void mh_get_last_num(Folder *folder, FolderItem *item)
                        if (max < num)
                                max = num;
                }
+               if (num % 100 == 0)
+                       GTK_EVENTS_FLUSH();
        }
        closedir(dp);
 
@@ -310,7 +308,7 @@ gint mh_get_num_list(Folder *folder, FolderItem *item, GSList **list, gboolean *
        }
        closedir(dp);
 
-       item->mtime = time(NULL);
+       mh_set_mtime(item);
        return nummsgs;
 }
 
@@ -458,6 +456,8 @@ static gint mh_copy_msgs(Folder *folder, FolderItem *dest, MsgInfoList *msglist,
                         GRelation *relation)
 {
        gboolean dest_need_scan = FALSE;
+       gboolean src_need_scan = FALSE;
+       FolderItem *src = NULL;
        gchar *srcfile;
        gchar *destfile;
        gint filemode = 0;
@@ -467,7 +467,8 @@ static gint mh_copy_msgs(Folder *folder, FolderItem *dest, MsgInfoList *msglist,
        gint curnum = 0, total = 0;
        gchar *srcpath = NULL;
        gboolean full_fetch = FALSE;
-       time_t last_mtime = (time_t)0;
+       time_t last_dest_mtime = (time_t)0;
+       time_t last_src_mtime = (time_t)0;
 
        g_return_val_if_fail(dest != NULL, -1);
        g_return_val_if_fail(msglist != NULL, -1);
@@ -483,6 +484,10 @@ static gint mh_copy_msgs(Folder *folder, FolderItem *dest, MsgInfoList *msglist,
 
        if (msginfo->folder->folder != dest->folder)
                full_fetch = TRUE;
+       
+       if (FOLDER_TYPE(msginfo->folder->folder) == F_MH) {
+               src = msginfo->folder;
+       }
 
        if (dest->last_num < 0) {
                mh_get_last_num(folder, dest);
@@ -494,7 +499,12 @@ static gint mh_copy_msgs(Folder *folder, FolderItem *dest, MsgInfoList *msglist,
        srcpath = folder_item_get_path(msginfo->folder);
 
        dest_need_scan = mh_scan_required(dest->folder, dest);
-       last_mtime = dest->mtime;
+       last_dest_mtime = dest->mtime;
+
+       if (src) {
+               src_need_scan = mh_scan_required(src->folder, src);
+               last_src_mtime = src->mtime;
+       }
 
        total = g_slist_length(msglist);
        if (total > 100) {
@@ -575,9 +585,14 @@ static gint mh_copy_msgs(Folder *folder, FolderItem *dest, MsgInfoList *msglist,
        g_free(srcpath);
        mh_write_sequences(dest, TRUE);
 
-       if (dest->mtime == last_mtime && !dest_need_scan)
-               dest->mtime = time(NULL);
-       
+       if (dest->mtime == last_dest_mtime && !dest_need_scan) {
+               mh_set_mtime(dest);
+       }
+
+       if (src && src->mtime == last_src_mtime && !src_need_scan) {
+               mh_set_mtime(src);
+       }
+
        if (total > 100) {
                statusbar_progress_all(0,0,0);
                statusbar_pop_all();
@@ -614,9 +629,9 @@ static gint mh_remove_msg(Folder *folder, FolderItem *item, gint num)
                return -1;
        }
 
-       if (item->mtime == last_mtime && !need_scan)
-               item->mtime = time(NULL);
-
+       if (item->mtime == last_mtime && !need_scan) {
+               mh_set_mtime(item);
+       }
        g_free(file);
        return 0;
 }
@@ -673,8 +688,9 @@ static gint mh_remove_msgs(Folder *folder, FolderItem *item,
                statusbar_progress_all(0,0,0);
                statusbar_pop_all();
        }
-       if (item->mtime == last_mtime && !need_scan)
-               item->mtime = time(NULL);
+       if (item->mtime == last_mtime && !need_scan) {
+               mh_set_mtime(item);
+       }
 
        g_free(path);
        return 0;
@@ -748,7 +764,7 @@ static gint mh_scan_tree(Folder *folder)
                                    "Can't create folder.", dir); \
                        return -1; \
                } \
-               if (make_dir(dir) < 0) \
+               if (make_dir_hier(dir) < 0) \
                        return -1; \
        } \
 }
@@ -1058,12 +1074,12 @@ static void mh_scan_tree_recursive(FolderItem *item)
                entry = mh_filename_from_utf8(utf8entry);
 
                if (
-#if !defined(G_OS_WIN32) && defined(HAVE_DIRENT_D_TYPE)
+#if !defined(G_OS_WIN32) && !defined(MAEMO) && defined(HAVE_DIRENT_D_TYPE)
                        d->d_type == DT_DIR ||
                        (d->d_type == DT_UNKNOWN &&
 #endif
                        g_stat(entry, &s) == 0 && S_ISDIR(s.st_mode)
-#if !defined(G_OS_WIN32) && defined(HAVE_DIRENT_D_TYPE)
+#if !defined(G_OS_WIN32) && !defined(MAEMO) && defined(HAVE_DIRENT_D_TYPE)
                        )
 #endif
                   ) {
@@ -1073,10 +1089,13 @@ static void mh_scan_tree_recursive(FolderItem *item)
                        node = item->node;
                        for (node = node->children; node != NULL; node = node->next) {
                                FolderItem *cur_item = FOLDER_ITEM(node->data);
-                               if (!strcmp2(cur_item->path, entry)) {
+                               gchar *curpath = mh_filename_from_utf8(cur_item->path);
+                               if (!strcmp2(curpath, entry)) {
                                        new_item = cur_item;
+                                       g_free(curpath);
                                        break;
                                }
+                               g_free(curpath);
                        }
                        if (!new_item) {
                                debug_print("new folder '%s' found.\n", entry);
@@ -1122,7 +1141,7 @@ static void mh_scan_tree_recursive(FolderItem *item)
        closedir(dp);
 #endif
 
-       item->mtime = time(NULL);
+       mh_set_mtime(item);
 }
 
 static gboolean mh_rename_folder_func(GNode *node, gpointer data)
@@ -1159,7 +1178,7 @@ static gchar *mh_filename_from_utf8(const gchar *path)
        gchar *real_path = g_filename_from_utf8(path, -1, NULL, NULL, NULL);
 
        if (!real_path) {
-               g_warning("mh_filename_from_utf8: faild to convert character set\n");
+               g_warning("mh_filename_from_utf8: failed to convert character set\n");
                real_path = g_strdup(path);
        }
 
@@ -1170,7 +1189,7 @@ static gchar *mh_filename_to_utf8(const gchar *path)
 {
        gchar *utf8path = g_filename_to_utf8(path, -1, NULL, NULL, NULL);
        if (!utf8path) {
-               g_warning("mh_filename_to_utf8: faild to convert character set\n");
+               g_warning("mh_filename_to_utf8: failed to convert character set\n");
                utf8path = g_strdup(path);
        }
 
@@ -1321,10 +1340,8 @@ static void mh_write_sequences(FolderItem *item, gboolean remove_unseen)
        FILE *mh_sequences_old_fp, *mh_sequences_new_fp;
        gchar buf[BUFFSIZE];
        gchar *path = NULL;
-/*
-       GTimer *timer = g_timer_new();
-       g_timer_start(timer);
-*/
+       START_TIMING("");
+
        if (!item)
                return;
        
@@ -1340,6 +1357,7 @@ static void mh_write_sequences(FolderItem *item, gboolean remove_unseen)
                MsgInfo *info = NULL;
                gint start = -1, end = -1;
                gchar *sequence = g_strdup("");
+               gint seq_len = 0;
                msglist = g_slist_sort(msglist, sort_cache_list_by_msgnum);
                cur = msglist;
                
@@ -1353,18 +1371,24 @@ static void mh_write_sequences(FolderItem *item, gboolean remove_unseen)
                                        end = info->msgnum;
                        } else {
                                if (start > 0 && end > 0) {
-                                       gchar *tmp = sequence;
+                                       gchar tmp[32];
+                                       gint tmp_len = 0;
                                        if (start != end)
-                                               sequence = g_strdup_printf("%s %d-%d ", tmp, start, end);
+                                               snprintf(tmp, 31, " %d-%d", start, end);
                                        else
-                                               sequence = g_strdup_printf("%s %d ", tmp, start);
-                                       g_free(tmp);
+                                               snprintf(tmp, 31, " %d", start);
+                                       
+                                       tmp_len = strlen(tmp);
+                                       sequence = g_realloc(sequence, seq_len+tmp_len+1);
+                                       strcpy(sequence+seq_len, tmp);
+                                       seq_len += tmp_len;
+
                                        start = end = -1;
                                }
                        }
                        cur = cur ? cur->next:NULL;
                } while (cur || (start > 0 && end > 0));
-               if (sequence && strlen(sequence)) {
+               if (sequence && *sequence) {
                        fprintf(mh_sequences_new_fp, "%s%s\n", 
                                        get_unseen_seq_name(), sequence);
                        debug_print("wrote unseen sequence: '%s%s'\n", 
@@ -1379,7 +1403,12 @@ static void mh_write_sequences(FolderItem *item, gboolean remove_unseen)
                        fclose(mh_sequences_old_fp);
                }
                
+               fflush(mh_sequences_new_fp);
+#if 0
+               fsync(fileno(mh_sequences_new_fp));
+#endif
                fclose(mh_sequences_new_fp);
+
                g_rename(mh_sequences_new, mh_sequences_old);
                g_free(sequence);
                procmsg_msg_list_free(msglist);
@@ -1387,11 +1416,8 @@ static void mh_write_sequences(FolderItem *item, gboolean remove_unseen)
        g_free(mh_sequences_old);
        g_free(mh_sequences_new);
        g_free(path);
-/*
-       g_timer_stop(timer);
-       printf("mh_get_flags: %f secs\n", g_timer_elapsed(timer, NULL));
-       g_timer_destroy(timer);
-*/
+
+       END_TIMING();
 }
 
 static int mh_item_close(Folder *folder, FolderItem *item)
@@ -1402,8 +1428,27 @@ static int mh_item_close(Folder *folder, FolderItem *item)
 
        mh_write_sequences(item, FALSE);
 
-       if (item->mtime == last_mtime && !need_scan)
-               item->mtime = time(NULL);
+       if (item->mtime == last_mtime && !need_scan) {
+               mh_set_mtime(item);
+       }
 
        return 0;
 }
+
+void mh_set_mtime(FolderItem *item)
+{
+       struct stat s;
+       gchar *path = folder_item_get_path(item);
+
+       g_return_if_fail(path != NULL);
+
+       if (stat(path, &s) < 0) {
+               FILE_OP_ERROR(path, "stat");
+               g_free(path);
+               return;
+       }
+
+       item->mtime = s.st_mtime;
+       debug_print("MH: forced mtime of %s to %ld\n", item->name, item->mtime);
+       g_free(path);
+}