]> granicus.if.org Git - mutt/commitdiff
This patch fixes various aspects of the attachment-saving
authorThomas Roessler <roessler@does-not-exist.org>
Sat, 4 Oct 2003 20:34:59 +0000 (20:34 +0000)
committerThomas Roessler <roessler@does-not-exist.org>
Sat, 4 Oct 2003 20:34:59 +0000 (20:34 +0000)
user interface.  Changes include:

* When tagging and saving multiple attachments, you can now use the
  same target directory for multiple attachments.

* When you can't save an attachment, you get an opportunity to enter
  a new file name.

* The menu cursor will highlight the attachment that you are
  currently discussing with mutt.

* Various bug fixes.

This does, in particular, address #1619 (Debian#208430).

13 files changed:
attach.h
commands.c
compose.c
keymap.h
lib.c
lib.h
menu.c
mutt.h
mutt_menu.h
muttlib.c
pager.c
protos.h
recvattach.c

index 2147b744a23dcdb9e1d05c02352c08602500f4a8..2e17a449fe90ece906cb2c8f474b6fc399b97d16 100644 (file)
--- a/attach.h
+++ b/attach.h
@@ -24,7 +24,7 @@ int mutt_attach_display_loop (MUTTMENU *menu, int op, FILE *fp, HEADER *hdr,
                              int recv);
 
 
-void mutt_save_attachment_list (FILE *fp, int tag, BODY *top, HEADER *hdr);
+void mutt_save_attachment_list (FILE *fp, int tag, BODY *top, HEADER *hdr, MUTTMENU *menu);
 void mutt_pipe_attachment_list (FILE *fp, int tag, BODY *top, int filter);
 void mutt_print_attachment_list (FILE *fp, int tag, BODY *top);
 
index fe623fd466c31ce935f3ae1013189f0b1027847d..3761926d4042a76d65b06110403e8824f63c0ae3 100644 (file)
@@ -761,7 +761,7 @@ int mutt_save_message (HEADER *h, int delete,
   mutt_expand_path (buf, sizeof (buf));
 
   /* check to make sure that this file is really the one the user wants */
-  if (!mutt_save_confirm (buf, &st))
+  if (mutt_save_confirm (buf, &st) != 0)
     return -1;
 
   if (WithCrypto && need_passphrase && (decode || decrypt)
index 22ebc23c239e636c1b91d405702a1903d886a3bc..a77667c8c96f3a0afd9fabc0cf06c5ec09647524 100644 (file)
--- a/compose.c
+++ b/compose.c
@@ -483,6 +483,7 @@ static void update_idx (MUTTMENU *menu, ATTACHPTR **idx, short idxlen)
   idx[idxlen]->level = (idxlen > 0) ? idx[idxlen-1]->level : 0;
   if (idxlen)
     idx[idxlen - 1]->content->next = idx[idxlen]->content;
+  idx[idxlen]->content->aptr = idx[idxlen];
   menu->current = idxlen++;
   mutt_update_tree (idx, idxlen);
   menu->max = idxlen;
@@ -760,14 +761,7 @@ int mutt_compose_menu (HEADER *msg,   /* structure for new message */
        idx[idxlen] = (ATTACHPTR *) safe_calloc (1, sizeof (ATTACHPTR));
        if ((idx[idxlen]->content = crypt_pgp_make_key_attachment(NULL)) != NULL)
        {
-         idx[idxlen]->level = (idxlen > 0) ? idx[idxlen-1]->level : 0;
-
-         if(idxlen)
-           idx[idxlen - 1]->content->next = idx[idxlen]->content;
-         
-         menu->current = idxlen++;
-         mutt_update_tree (idx, idxlen);
-         menu->max = idxlen;
+         update_idx (menu, idx, idxlen++);
          menu->redraw |= REDRAW_INDEX;
        }
        else
@@ -1187,14 +1181,7 @@ int mutt_compose_menu (HEADER *msg,   /* structure for new message */
            mutt_error _("What we have here is a failure to make an attachment");
            continue;
          }
-         
-         idx[idxlen]->level = (idxlen > 0) ? idx[idxlen-1]->level : 0;
-         if (idxlen)
-           idx[idxlen - 1]->content->next = idx[idxlen]->content;
-         
-         menu->current = idxlen++;
-         mutt_update_tree (idx, idxlen);
-         menu->max = idxlen;
+         update_idx (menu, idx, idxlen++);
 
          idx[menu->current]->content->type = itype;
          mutt_str_replace (&idx[menu->current]->content->subtype, p);
@@ -1227,7 +1214,7 @@ int mutt_compose_menu (HEADER *msg,   /* structure for new message */
 
       case OP_SAVE:
        CHECK_COUNT;
-       mutt_save_attachment_list (NULL, menu->tagprefix, menu->tagprefix ?  msg->content : idx[menu->current]->content, NULL);
+       mutt_save_attachment_list (NULL, menu->tagprefix, menu->tagprefix ?  msg->content : idx[menu->current]->content, NULL, menu);
        MAYBE_REDRAW (menu->redraw);
        break;
 
@@ -1392,7 +1379,10 @@ int mutt_compose_menu (HEADER *msg,   /* structure for new message */
   {
     msg->content = idx[0]->content;
     for (i = 0; i < idxlen; i++)
+    {
+      idx[i]->content->aptr = NULL;
       FREE (&idx[i]);
+    }
   }
   else
     msg->content = NULL;
index bdbafae63c9f9bddc84f71d6c339099da36bcbb2..a88bbf46167a812b375297f37a608b4dbcbe69fa 100644 (file)
--- a/keymap.h
+++ b/keymap.h
@@ -19,6 +19,8 @@
 #ifndef KEYMAP_H
 #define KEYMAP_H
 
+#include "mapping.h"
+
 /* maximal length of a key binding sequence used for buffer in km_bindkey */
 #define MAX_SEQ 8
 
diff --git a/lib.c b/lib.c
index 97879c9878d098273c90c79c5d645ac92fae4f32..4c6a4b5b30ab7aea13cf205e56b2496fcc266339 100644 (file)
--- a/lib.c
+++ b/lib.c
@@ -646,3 +646,10 @@ char *mutt_concat_path (char *d, const char *dir, const char *fname, size_t l)
   snprintf (d, l, fmt, dir, fname);
   return d;
 }
+
+const char *mutt_basename (const char *f)
+{
+  const char *p = strrchr (f, '/');
+  if (p) ++p;
+  return p;
+}
diff --git a/lib.h b/lib.h
index 6e0068366eb03af975ef8113abfa7557a66c2bff..2bda25d2fa06e70b03b3b30457d60af757b8d059 100644 (file)
--- a/lib.h
+++ b/lib.h
@@ -118,6 +118,7 @@ char *mutt_substrdup (const char *, const char *);
 char *safe_strdup (const char *);
 
 const char *mutt_stristr (const char *, const char *);
+const char *mutt_basename (const char *);
 
 int mutt_copy_stream (FILE *, FILE *);
 int mutt_copy_bytes (FILE *, FILE *, size_t);
diff --git a/menu.c b/menu.c
index f64d918c33a352f7a9c55c1b2dac727d2c5d9aa1..11d8faa10f4fea5af5bef614d3afb79a57f386ae 100644 (file)
--- a/menu.c
+++ b/menu.c
@@ -800,6 +800,34 @@ static int menu_dialog_dokey (MUTTMENU *menu, int *ip)
   }
 }
 
+int menu_redraw (MUTTMENU *menu)
+{
+  /* See if all or part of the screen needs to be updated.  */
+  if (menu->redraw & REDRAW_FULL)
+  {
+    menu_redraw_full (menu);
+    /* allow the caller to do any local configuration */
+    return (OP_REDRAW);
+  }
+  
+  if (!menu->dialog)
+    menu_check_recenter (menu);
+  
+  if (menu->redraw & REDRAW_STATUS)
+    menu_redraw_status (menu);
+  if (menu->redraw & REDRAW_INDEX)
+    menu_redraw_index (menu);
+  else if (menu->redraw & (REDRAW_MOTION | REDRAW_MOTION_RESYNCH))
+    menu_redraw_motion (menu);
+  else if (menu->redraw == REDRAW_CURRENT)
+    menu_redraw_current (menu);
+  
+  if (menu->dialog)
+    menu_redraw_prompt (menu);
+  
+  return OP_NULL;
+}
+
 int mutt_menuLoop (MUTTMENU *menu)
 {
   int i = OP_NULL;
@@ -819,28 +847,8 @@ int mutt_menuLoop (MUTTMENU *menu)
     imap_keepalive ();
 #endif
 
-    /* See if all or part of the screen needs to be updated.  */
-    if (menu->redraw & REDRAW_FULL)
-    {
-      menu_redraw_full (menu);
-      /* allow the caller to do any local configuration */
-      return (OP_REDRAW);
-    }
-
-    if (!menu->dialog)
-      menu_check_recenter (menu);
-
-    if (menu->redraw & REDRAW_STATUS)
-      menu_redraw_status (menu);
-    if (menu->redraw & REDRAW_INDEX)
-      menu_redraw_index (menu);
-    else if (menu->redraw & (REDRAW_MOTION | REDRAW_MOTION_RESYNCH))
-      menu_redraw_motion (menu);
-    else if (menu->redraw == REDRAW_CURRENT)
-      menu_redraw_current (menu);
-
-    if (menu->dialog)
-      menu_redraw_prompt (menu);
+    if (menu_redraw (menu) == OP_REDRAW)
+      return OP_REDRAW;
     
     menu->oldcurrent = menu->current;
 
diff --git a/mutt.h b/mutt.h
index f708d091afe5155bc1f096d52a1f09a1a053794a..cc0d1b192b05d933e7acd4851484f619a065590c 100644 (file)
--- a/mutt.h
+++ b/mutt.h
@@ -598,6 +598,8 @@ typedef struct body
   struct body *parts;           /* parts of a multipart or message/rfc822 */
   struct header *hdr;          /* header information for message/rfc822 */
 
+  struct attachptr *aptr;      /* Menu information, used in recvattach.c */
+  
   time_t stamp;                        /* time stamp of last
                                 * encoding update.
                                 */
index 83b83cdb255a736e506c218baf339f80cd3159c1..9ed85bba79bab02bb35058b7cc2b1442db964b1c 100644 (file)
@@ -83,6 +83,7 @@ void menu_redraw_index (MUTTMENU *);
 void menu_redraw_status (MUTTMENU *);
 void menu_redraw_motion (MUTTMENU *);
 void menu_redraw_current (MUTTMENU *);
+int  menu_redraw (MUTTMENU *);
 void menu_first_entry (MUTTMENU *);
 void menu_last_entry (MUTTMENU *);
 void menu_top_page (MUTTMENU *);
index 9b75b834cf463f744325b0957993bc68848b791e..7d4120894424f25709dfeb3458e3a70753ce7ec5 100644 (file)
--- a/muttlib.c
+++ b/muttlib.c
@@ -814,10 +814,11 @@ void mutt_expand_fmt (char *dest, size_t destlen, const char *fmt, const char *s
   
 }
 
-/* return 0 on success, -1 on error */
+/* return 0 on success, -1 on abort, 1 on error */
 int mutt_check_overwrite (const char *attname, const char *path,
-                               char *fname, size_t flen, int *append) 
+                               char *fname, size_t flen, int *append, char **directory
 {
+  int rc = 0;
   char tmp[_POSIX_PATH_MAX];
   struct stat st;
 
@@ -828,18 +829,38 @@ int mutt_check_overwrite (const char *attname, const char *path,
     return -1;
   if (S_ISDIR (st.st_mode))
   {
-    if (mutt_yesorno (_("File is a directory, save under it?"), M_YES) != M_YES) 
-      return (-1);
+    if (directory)
+    {
+      switch (mutt_multi_choice
+             (_("File is a directory, save under it? [(y)es, (n)o, (a)ll]"), _("yna")))
+      {
+       case 3:         /* all */
+         mutt_str_replace (directory, fname);
+         break;
+       case 1:         /* yes */
+         FREE (directory);
+         break;
+       case -1:        /* abort */
+         FREE (directory); 
+         return -1;
+       case  2:        /* no */
+         FREE (directory);
+         return 1;
+      }
+    }
+    else if ((rc = mutt_yesorno (_("File is a directory, save under it?"), M_YES)) != M_YES)
+      return (rc == M_NO) ? 1 : -1;
+
     if (!attname || !attname[0])
     {
       tmp[0] = 0;
       if (mutt_get_field (_("File under directory: "), tmp, sizeof (tmp),
                                      M_FILE | M_CLEAR) != 0 || !tmp[0])
        return (-1);
-      snprintf (fname, flen, "%s/%s", path, tmp);
+      mutt_concat_path (fname, path, tmp, flen);
     }
     else
-      snprintf (fname, flen, "%s/%s", path, attname);
+      mutt_concat_path (fname, path, mutt_basename (attname), flen);
   }
   
   if (*append == 0 && access (fname, F_OK) == 0)
@@ -848,8 +869,9 @@ int mutt_check_overwrite (const char *attname, const char *path,
            (_("File exists, (o)verwrite, (a)ppend, or (c)ancel?"), _("oac")))
     {
       case -1: /* abort */
+        return -1;
       case 3:  /* cancel */
-       return -1;
+       return 1;
 
       case 2: /* append */
         *append = M_SAVE_APPEND;
@@ -1133,11 +1155,12 @@ FILE *mutt_open_read (const char *path, pid_t *thepid)
   return (f);
 }
 
-/* returns 1 if OK to proceed, 0 to abort */
+/* returns 0 if OK to proceed, -1 to abort, 1 to retry */
 int mutt_save_confirm (const char *s, struct stat *st)
 {
   char tmp[_POSIX_PATH_MAX];
-  int ret = 1;
+  int ret = 0;
+  int rc;
   int magic = 0;
 
   magic = mx_get_magic (s);
@@ -1146,7 +1169,7 @@ int mutt_save_confirm (const char *s, struct stat *st)
   if (magic == M_POP)
   {
     mutt_error _("Can't save message to POP mailbox.");
-    return 0;
+    return 1;
   }
 #endif
 
@@ -1155,14 +1178,16 @@ int mutt_save_confirm (const char *s, struct stat *st)
     if (magic == -1)
     {
       mutt_error (_("%s is not a mailbox!"), s);
-      return 0;
+      return 1;
     }
 
     if (option (OPTCONFIRMAPPEND))
     {
       snprintf (tmp, sizeof (tmp), _("Append messages to %s?"), s);
-      if (mutt_yesorno (tmp, M_YES) != M_YES)
-       ret = 0;
+      if ((rc = mutt_yesorno (tmp, M_YES)) == M_NO)
+       ret = 1;
+      else if (rc == -1)
+       ret = -1;
     }
   }
   else
@@ -1179,14 +1204,16 @@ int mutt_save_confirm (const char *s, struct stat *st)
        if (option (OPTCONFIRMCREATE))
        {
          snprintf (tmp, sizeof (tmp), _("Create %s?"), s);
-         if (mutt_yesorno (tmp, M_YES) != M_YES)
-           ret = 0;
+         if ((rc = mutt_yesorno (tmp, M_YES)) == M_NO)
+           ret = 1;
+         else if (rc == -1)
+           ret = -1;
        }
       }
       else
       {
        mutt_perror (s);
-       return 0;
+       return 1;
       }
     }
   }
diff --git a/pager.c b/pager.c
index 26fcf07e34225f1351b3cdd0afaf23fa6dd475cf..dd84c4f8c2a1fda6f2a1a073d42575f27b830abe 100644 (file)
--- a/pager.c
+++ b/pager.c
@@ -2438,7 +2438,7 @@ CHECK_IMAP_ACL(IMAP_ACL_WRITE);
       case OP_SAVE:
        if (IsAttach (extra))
        {
-         mutt_save_attachment_list (extra->fp, 0, extra->bdy, extra->hdr);
+         mutt_save_attachment_list (extra->fp, 0, extra->bdy, extra->hdr, NULL);
          break;
        }
        /* fall through */
index 5a0d97f363802493f1a0ad003c19d02eee85d508..8a4722cd927e5e552a9eabce663c52be03b6f271 100644 (file)
--- a/protos.h
+++ b/protos.h
@@ -248,7 +248,7 @@ int mutt_check_key (const char *);
 int mutt_check_menu (const char *);
 int mutt_check_mime_type (const char *);
 int mutt_check_month (const char *);
-int mutt_check_overwrite (const char *, const char *, char *, size_t, int *);
+int mutt_check_overwrite (const char *, const char *, char *, size_t, int *, char **);
 int mutt_check_traditional_pgp (HEADER *, int *);
 int mutt_command_complete (char *, size_t, int, int);
 int mutt_var_value_complete (char *, size_t, int);
index 09abea2d82250e8d55198fe55816951cd2244c06..aa1ce2740e2eee5881d1f473dcc39404a8057239 100644 (file)
@@ -129,6 +129,7 @@ ATTACHPTR **mutt_gen_attach_list (BODY *m,
 
       new = idx[(*idxlen)++];
       new->content = m;
+      m->aptr = new;
       new->parent_type = parent_type;
       new->level = level;
 
@@ -363,14 +364,21 @@ int mutt_is_message_type (int type, const char *subtype)
   return (ascii_strcasecmp (subtype, "rfc822") == 0 || ascii_strcasecmp (subtype, "news") == 0);
 }
 
-static int mutt_query_save_attachment (FILE *fp, BODY *body, HEADER *hdr)
+static int mutt_query_save_attachment (FILE *fp, BODY *body, HEADER *hdr, char **directory)
 {
+  char *prompt;
   char buf[_POSIX_PATH_MAX], tfile[_POSIX_PATH_MAX];
   int is_message;
   int append = 0;
-
-  if (body->filename)
-    strfcpy (buf, body->filename, sizeof (buf));
+  int rc;
+  
+  if (body->filename) 
+  {
+    if (directory && *directory)
+      mutt_concat_path (buf, *directory, mutt_basename (body->filename), sizeof (buf));
+    else
+      strfcpy (buf, body->filename, sizeof (buf));
+  }
   else if(body->hdr &&
          body->encoding != ENCBASE64 &&
          body->encoding != ENCQUOTEDPRINTABLE &&
@@ -379,45 +387,68 @@ static int mutt_query_save_attachment (FILE *fp, BODY *body, HEADER *hdr)
   else
     buf[0] = 0;
 
-  if (mutt_get_field (_("Save to file: "), buf, sizeof (buf), M_FILE | M_CLEAR) != 0
-      || !buf[0])
-    return -1;
-
-  mutt_expand_path (buf, sizeof (buf));
-
-  is_message = (fp && 
-      body->hdr && 
-      body->encoding != ENCBASE64 && 
-      body->encoding != ENCQUOTEDPRINTABLE && 
-      mutt_is_message_type (body->type, body->subtype));
-  
-  if (is_message)
+  prompt = _("Save to file: ");
+  while (prompt)
   {
-    struct stat st;
-    
-    /* check to make sure that this file is really the one the user wants */
-    if (!mutt_save_confirm (buf, &st))
-      return -1;
-    strfcpy(tfile, buf, sizeof(tfile));
-  }
-  else
-    if (mutt_check_overwrite (body->filename, buf, tfile, sizeof (tfile), &append))
+    if (mutt_get_field (prompt, buf, sizeof (buf), M_FILE | M_CLEAR) != 0
+       || !buf[0])
       return -1;
-
-  mutt_message _("Saving...");
-  if (mutt_save_attachment (fp, body, tfile, append, (hdr || !is_message) ? hdr : body->hdr) == 0)
-  {
-    mutt_message _("Attachment saved.");
-    return 0;
+    
+    prompt = NULL;
+    mutt_expand_path (buf, sizeof (buf));
+    
+    is_message = (fp && 
+                 body->hdr && 
+                 body->encoding != ENCBASE64 && 
+                 body->encoding != ENCQUOTEDPRINTABLE && 
+                 mutt_is_message_type (body->type, body->subtype));
+    
+    if (is_message)
+    {
+      struct stat st;
+      
+      /* check to make sure that this file is really the one the user wants */
+      if ((rc = mutt_save_confirm (buf, &st)) == 1)
+      {
+       prompt = _("Save to file: ");
+       continue;
+      } 
+      else if (rc == -1)
+       return -1;
+      strfcpy(tfile, buf, sizeof(tfile));
+    }
+    else
+    {
+      if ((rc = mutt_check_overwrite (body->filename, buf, tfile, sizeof (tfile), &append, directory)) == -1)
+       return -1;
+      else if (rc == 1)
+      {
+       prompt = _("Save to file: ");
+       continue;
+      }
+    }
+    
+    mutt_message _("Saving...");
+    if (mutt_save_attachment (fp, body, tfile, append, (hdr || !is_message) ? hdr : body->hdr) == 0)
+    {
+      mutt_message _("Attachment saved.");
+      return 0;
+    }
+    else
+    {
+      prompt = _("Save to file: ");
+      continue;
+    }
   }
-  else
-    return -1;
+  return 0;
 }
-
-void mutt_save_attachment_list (FILE *fp, int tag, BODY *top, HEADER *hdr)
+    
+void mutt_save_attachment_list (FILE *fp, int tag, BODY *top, HEADER *hdr, MUTTMENU *menu)
 {
   char buf[_POSIX_PATH_MAX], tfile[_POSIX_PATH_MAX];
+  char *directory = NULL;
   int rc = 1;
+  int last = menu ? menu->current : -1;
   FILE *fpout;
 
   buf[0] = 0;
@@ -438,7 +469,7 @@ void mutt_save_attachment_list (FILE *fp, int tag, BODY *top, HEADER *hdr)
            return;
          mutt_expand_path (buf, sizeof (buf));
          if (mutt_check_overwrite (top->filename, buf, tfile,
-                                   sizeof (tfile), &append))
+                                   sizeof (tfile), &append, NULL))
            return;
          rc = mutt_save_attachment (fp, top, tfile, append, hdr);
          if (rc == 0 && AttachSep && (fpout = fopen (tfile,"a")) != NULL)
@@ -457,15 +488,37 @@ void mutt_save_attachment_list (FILE *fp, int tag, BODY *top, HEADER *hdr)
          }
        }
       }
-      else
-       mutt_query_save_attachment (fp, top, hdr);
+      else 
+      {
+       if (tag && menu && top->aptr)
+       {
+         menu->oldcurrent = menu->current;
+         menu->current = top->aptr->num;
+         menu_check_recenter (menu);
+         menu->redraw |= REDRAW_MOTION;
+
+         menu_redraw (menu);
+       }
+       if (mutt_query_save_attachment (fp, top, hdr, &directory) == -1)
+         break;
+      }
     }
     else if (top->parts)
-      mutt_save_attachment_list (fp, 1, top->parts, hdr);
+      mutt_save_attachment_list (fp, 1, top->parts, hdr, menu);
     if (!tag)
-      return;
+      break;
   }
 
+  FREE (&directory);
+
+  if (tag && menu)
+  {
+    menu->oldcurrent = menu->current;
+    menu->current = last;
+    menu_check_recenter (menu);
+    menu->redraw |= REDRAW_MOTION;
+  }
+  
   if (!option (OPTATTACHSPLIT) && (rc == 0))
     mutt_message _("Attachment saved.");
 }
@@ -977,9 +1030,9 @@ void mutt_view_attachments (HEADER *hdr)
 
       case OP_SAVE:
        mutt_save_attachment_list (fp, menu->tagprefix, 
-                 menu->tagprefix ?  cur : idx[menu->current]->content, hdr);
+                 menu->tagprefix ?  cur : idx[menu->current]->content, hdr, menu);
 
-        if (option (OPTRESOLVE) && menu->current < menu->max - 1)
+        if (!menu->tagprefix && option (OPTRESOLVE) && menu->current < menu->max - 1)
          menu->current++;
       
         menu->redraw = REDRAW_MOTION_RESYNCH | REDRAW_FULL;
@@ -1120,6 +1173,8 @@ void mutt_view_attachments (HEADER *hdr)
            continue;
          if (idx[idxmax]->content && idx[idxmax]->content->deleted)
            hdr->attach_del = 1;
+         if (idx[idxmax]->content)
+           idx[idxmax]->content->aptr = NULL;
          FREE (&idx[idxmax]->tree);
          FREE (&idx[idxmax]);
        }