2007-03-16 [wwp] 2.8.1cvs19
[claws.git] / src / action.c
index 96bbd40b1c208edfbc6b4ec7f8fd030504c1aaae..d807eecea39fd235d9d966689f8437d632afa89c 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2006 Hiroyuki Yamamoto & The Sylpheed Claws Team
+ * Copyright (C) 1999-2007 Hiroyuki Yamamoto & 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
@@ -54,6 +54,7 @@
 #include "textview.h"
 #include "matcher_parser.h" /* CLAWS */
 #include "filtering.h"
+#include "procheader.h"
 
 typedef struct _Children               Children;
 typedef struct _ChildInfo              ChildInfo;
@@ -101,6 +102,8 @@ struct _ChildInfo
        GString         *output;
        void (*callback)(void *data);
        void *data;
+
+       GSList          *msginfo_list;
 };
 
 static void action_update_menu         (GtkItemFactory *ifactory,
@@ -397,7 +400,7 @@ static gboolean parse_append_msgpart(GString *cmd, MsgInfo *msginfo,
        g_free(filename);
 
        if (ret < 0) {
-               alertpanel_error(_("Can't get part of multipart message"));
+               alertpanel_error(_("Can't get part of multipart message: %s"), strerror(-ret));
                g_free(part_filename);
                return FALSE;
        }
@@ -588,7 +591,14 @@ static gboolean execute_filtering_actions(gchar *action, GSList *msglist)
        GSList *action_list, *p;
        const gchar *sbegin, *send;
        gchar *action_string;
-       
+       SummaryView *summaryview = NULL;
+       MainWindow *mainwin = NULL;
+
+       if (mainwindow_get_mainwindow()) {
+               summaryview = mainwindow_get_mainwindow()->summaryview;
+               mainwin = mainwindow_get_mainwindow();
+       }
+
        if (NULL == (sbegin = strstr2(action, "%as{")))
                return FALSE;
        sbegin += sizeof "%as{" - 1;
@@ -597,15 +607,41 @@ static gboolean execute_filtering_actions(gchar *action, GSList *msglist)
        action_string = g_strndup(sbegin, send - sbegin);
        
        action_list = matcher_parser_get_action_list(action_string);
+       if (action_list == NULL) {
+               gchar *tmp = g_strdup(action_string);
+
+               g_strstrip(tmp);
+               if (*tmp == '\0')
+                       alertpanel_error(_("There is no filtering action set"));
+               else
+                       alertpanel_error(_("Invalid filtering action(s):\n%s"), tmp);
+               g_free(action_string);
+               g_free(tmp);
+               return FALSE;
+       }
        g_free(action_string);
-       if (action_list == NULL) return FALSE;
        
        /* apply actions on each message info */
        for (p = msglist; p && p->data; p = g_slist_next(p)) {
                filteringaction_apply_action_list(action_list, (MsgInfo *) p->data);
-               
        }
+
+       if (summaryview) {
+               summary_lock(summaryview);                              
+               main_window_cursor_wait(mainwin);               
+               summary_freeze(summaryview);    
+               folder_item_update_freeze();                            
+       }
+
        filtering_move_and_copy_msgs(msglist);
+
+       if (summaryview) {
+               folder_item_update_thaw();                              
+               summary_thaw(summaryview);              
+               main_window_cursor_normal(mainwin);     
+               summary_unlock(summaryview);                            
+               summary_show(summaryview, summaryview->folder_item);
+       }
        for (p = action_list; p; p = g_slist_next(p))
                if (p->data) filteringaction_free(p->data);     
        g_slist_free(action_list);              
@@ -726,6 +762,10 @@ static gboolean execute_actions(gchar *action, GSList *msg_list,
                                break;
                        }
                        if ((child_info = fork_child(cmd, msg_str, children))) {
+                               /* Pass msginfo to catch_status () */
+                               if (!(action_type & (ACTION_PIPE_OUT | ACTION_INSERT)))
+                                       child_info->msginfo_list = 
+                                               g_slist_append (NULL, msginfo);
                                children_list = g_slist_append(children_list,
                                                               child_info);
                        }
@@ -736,8 +776,11 @@ static gboolean execute_actions(gchar *action, GSList *msg_list,
                                       user_str, user_hidden_str, sel_str);
                if (cmd) {
                        if ((child_info = fork_child(cmd, msg_str, children))) {
+                               if (!(action_type & (ACTION_PIPE_OUT | ACTION_INSERT)))
+                                       child_info->msginfo_list = 
+                                               g_slist_copy (msg_list);
                                children_list = g_slist_append(children_list,
-                                                              child_info);
+                                                               child_info);
                        }
                        g_free(cmd);
                } else
@@ -879,7 +922,7 @@ static ChildInfo *fork_child(gchar *cmd, const gchar *msg_str,
                                close(chld_err[1]);
                                close(chld_status[0]);
 
-                               debug_print("Child: Waiting for grandchild\n");
+                               debug_print("Child: waiting for grandchild\n");
                                waitpid(gch_pid, NULL, 0);
                                debug_print("Child: grandchild ended\n");
                                write(chld_status[1], "0\n", 2);
@@ -997,11 +1040,8 @@ static gint wait_for_children(Children *children)
        if (children->nb)
                return FALSE;
 
-       if (!children->dialog) {
+       if (!children->dialog)
                free_children(children);
-       } else if (!children->output) {
-               gtk_widget_destroy(children->dialog);
-       }
 
        return FALSE;
 }
@@ -1014,7 +1054,6 @@ static void send_input(GtkWidget *w, gpointer data)
        child_info->tag_in = gdk_input_add(child_info->chld_in,
                                           GDK_INPUT_WRITE,
                                           catch_input, children);
-       gtk_widget_set_sensitive(children->input_hbox, FALSE);
 }
 
 static gint delete_io_dialog_cb(GtkWidget *w, GdkEvent *e, gpointer data)
@@ -1040,7 +1079,8 @@ static void hide_io_dialog_cb(GtkWidget *w, gpointer data)
 static gint io_dialog_key_pressed_cb(GtkWidget *widget, GdkEventKey *event,
                                     gpointer data)
 {
-       if (event && event->keyval == GDK_Escape)
+       if (event && (event->keyval == GDK_Escape ||
+                     event->keyval == GDK_Return))
                hide_io_dialog_cb(widget, data);
        return TRUE;
 }
@@ -1104,6 +1144,7 @@ static void update_io_dialog(Children *children)
                gchar *text;
                
                gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(children->progress_bar),
+                                                 (children->initial_nb == 0) ? 0 :
                                              (gdouble) (children->initial_nb - children->nb) /
                                              (gdouble) children->initial_nb);
                text = g_strdup_printf("%s %d/%d", _("Completed"), 
@@ -1307,6 +1348,51 @@ static void catch_status(gpointer data, gint source, GdkInputCondition cond)
        childinfo_close_pipes(child_info);
        child_info->pid = 0;
 
+       if (child_info->children->action_type & (ACTION_SINGLE | ACTION_MULTIPLE)
+           && child_info->msginfo_list) {
+               /* Actions on message *files* might change size and
+               * time stamp, and thus invalidate the cache */
+               SummaryView *summaryview  = NULL;
+               GSList      *cur;
+               MsgInfo     *msginfo, *nmi;     /* newmsginfo */
+               char        *file;
+               gboolean     modified_something = FALSE;
+               FolderItem  *last_item = NULL;
+               if (mainwindow_get_mainwindow ())
+                       summaryview = mainwindow_get_mainwindow ()->summaryview;
+               for (cur = child_info->msginfo_list; cur; cur = cur->next) {
+                       msginfo = (MsgInfo *)cur->data;
+                       if (!(msginfo && /* Stuff used valid? */
+                           msginfo->folder && msginfo->folder->cache)) 
+                               continue;
+                       file = procmsg_get_message_file_path (msginfo);
+                       if (!file) 
+                               continue;
+                       nmi = procheader_parse_file (file, msginfo->flags, TRUE, FALSE);
+                       if (!nmi) 
+                               continue; /* Deleted? */
+                       if (msginfo->mtime != nmi->mtime || msginfo->size != nmi->size) {
+                               nmi->folder = msginfo->folder;
+                               nmi->msgnum = msginfo->msgnum;
+                               msgcache_update_msg (msginfo->folder->cache, nmi);
+                               modified_something = TRUE;
+                               last_item = nmi->folder;
+                       }
+                       procmsg_msginfo_free (nmi);
+                       if (summaryview && summaryview->displayed &&
+                           summaryview->folder_item == msginfo->folder &&
+                           summary_get_msgnum(summaryview, summaryview->displayed) == msginfo->msgnum)
+                               summary_redisplay_msg(summaryview);
+                                       
+               }
+               if (modified_something && last_item && 
+                   summaryview && summaryview->folder_item == last_item) {
+                       summary_show (summaryview, summaryview->folder_item);
+               }
+               g_slist_free (child_info->msginfo_list);
+               child_info->msginfo_list = NULL;
+       }
+
        wait_for_children(child_info->children);
 }
        
@@ -1322,6 +1408,9 @@ static void catch_input(gpointer data, gint source, GdkInputCondition cond)
        if (!(cond && GDK_INPUT_WRITE))
                return;
 
+       gtk_widget_set_sensitive(children->input_hbox, FALSE);
+       gtk_widget_grab_focus(children->abort_btn);
+
        gdk_input_remove(child_info->tag_in);
        child_info->tag_in = -1;
 
@@ -1348,8 +1437,6 @@ static void catch_input(gpointer data, gint source, GdkInputCondition cond)
 
        g_free(input);
 
-       gtk_entry_set_text(GTK_ENTRY(children->input_entry), "");
-       gtk_widget_set_sensitive(children->input_hbox, TRUE);
        close(child_info->chld_in);
        child_info->chld_in = -1;
        debug_print("Input to grand child sent.\n");
@@ -1389,7 +1476,7 @@ static void catch_output(gpointer data, gint source, GdkInputCondition cond)
                        if (ret_str && bytes_written > 0) {
                                gtk_text_buffer_insert
                                        (textbuf, &iter, ret_str,
-                                        bytes_written);
+                                        -1);
                                g_free(ret_str);
                        } else
                                gtk_text_buffer_insert(textbuf, &iter, buf, c);