The attached patch fixes various aspects of the attachment-saving 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). Comments welcome. -- Thomas Roessler · Personal soap box at <http://log.does-not-exist.org/>.
? err ? patch-1.5.3-CVS.tlr.idna.1 ? patch-1.5.4.nr.tag_prefix_cond ? patch-1.5.4.tlr.nodots.1 ? patch-1.5.4.tlr.pgpsmimeautoselect.1 ? patch-1.5.4.tlr.save_attachment.1 ? patch-1.5.4.tlr.tag_prefix.1 ? send.c.new ? sort.c.new ? stamp-h1 ? typescript Index: attach.h =================================================================== RCS file: /cvs/mutt/mutt/attach.h,v retrieving revision 3.1 diff -u -r3.1 attach.h --- attach.h 11 Dec 2002 11:19:39 -0000 3.1 +++ attach.h 4 Oct 2003 20:30:15 -0000 @@ -24,7 +24,7 @@ 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: commands.c =================================================================== RCS file: /cvs/mutt/mutt/commands.c,v retrieving revision 3.19 diff -u -r3.19 commands.c --- commands.c 5 Aug 2003 13:55:47 -0000 3.19 +++ commands.c 4 Oct 2003 20:30:16 -0000 @@ -761,7 +761,7 @@ 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: compose.c =================================================================== RCS file: /cvs/mutt/mutt/compose.c,v retrieving revision 3.13 diff -u -r3.13 compose.c --- compose.c 19 Sep 2003 13:03:25 -0000 3.13 +++ compose.c 4 Oct 2003 20:30:19 -0000 @@ -483,6 +483,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ { msg->content = idx[0]->content; for (i = 0; i < idxlen; i++) + { + idx[i]->content->aptr = NULL; FREE (&idx[i]); + } } else msg->content = NULL; Index: keymap.h =================================================================== RCS file: /cvs/mutt/mutt/keymap.h,v retrieving revision 3.6 diff -u -r3.6 keymap.h --- keymap.h 16 Jul 2003 11:17:31 -0000 3.6 +++ keymap.h 4 Oct 2003 20:30:20 -0000 @@ -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 Index: lib.c =================================================================== RCS file: /cvs/mutt/mutt/lib.c,v retrieving revision 3.10 diff -u -r3.10 lib.c --- lib.c 19 Sep 2003 13:03:25 -0000 3.10 +++ lib.c 4 Oct 2003 20:30:31 -0000 @@ -646,3 +646,10 @@ 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; +} Index: lib.h =================================================================== RCS file: /cvs/mutt/mutt/lib.h,v retrieving revision 3.7 diff -u -r3.7 lib.h --- lib.h 19 Sep 2003 13:03:25 -0000 3.7 +++ lib.h 4 Oct 2003 20:30:31 -0000 @@ -118,6 +118,7 @@ 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); Index: menu.c =================================================================== RCS file: /cvs/mutt/mutt/menu.c,v retrieving revision 3.9 diff -u -r3.9 menu.c --- menu.c 4 Oct 2003 16:41:04 -0000 3.9 +++ menu.c 4 Oct 2003 20:30:31 -0000 @@ -800,6 +800,34 @@ } } +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 @@ 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; Index: mutt.h =================================================================== RCS file: /cvs/mutt/mutt/mutt.h,v retrieving revision 3.20 diff -u -r3.20 mutt.h --- mutt.h 16 Jul 2003 11:17:31 -0000 3.20 +++ mutt.h 4 Oct 2003 20:30:31 -0000 @@ -598,6 +598,8 @@ 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: mutt_menu.h =================================================================== RCS file: /cvs/mutt/mutt/mutt_menu.h,v retrieving revision 3.1 diff -u -r3.1 mutt_menu.h --- mutt_menu.h 11 Dec 2002 11:19:40 -0000 3.1 +++ mutt_menu.h 4 Oct 2003 20:30:31 -0000 @@ -83,6 +83,7 @@ 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: muttlib.c =================================================================== RCS file: /cvs/mutt/mutt/muttlib.c,v retrieving revision 3.16 diff -u -r3.16 muttlib.c --- muttlib.c 24 Jul 2003 18:40:50 -0000 3.16 +++ muttlib.c 4 Oct 2003 20:30:31 -0000 @@ -814,10 +814,11 @@ } -/* 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 @@ 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 @@ (_("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 @@ 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 @@ if (magic == M_POP) { mutt_error _("Can't save message to POP mailbox."); - return 0; + return 1; } #endif @@ -1155,14 +1178,16 @@ 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 @@ 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; } } } Index: pager.c =================================================================== RCS file: /cvs/mutt/mutt/pager.c,v retrieving revision 3.11 diff -u -r3.11 pager.c --- pager.c 19 Sep 2003 13:03:25 -0000 3.11 +++ pager.c 4 Oct 2003 20:30:38 -0000 @@ -2438,7 +2438,7 @@ 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: protos.h =================================================================== RCS file: /cvs/mutt/mutt/protos.h,v retrieving revision 3.17 diff -u -r3.17 protos.h --- protos.h 5 Mar 2003 21:18:24 -0000 3.17 +++ protos.h 4 Oct 2003 20:30:38 -0000 @@ -248,7 +248,7 @@ 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: recvattach.c =================================================================== RCS file: /cvs/mutt/mutt/recvattach.c,v retrieving revision 3.11 diff -u -r3.11 recvattach.c --- recvattach.c 19 Sep 2003 13:03:26 -0000 3.11 +++ recvattach.c 4 Oct 2003 20:30:38 -0000 @@ -129,6 +129,7 @@ new = idx[(*idxlen)++]; new->content = m; + m->aptr = new; new->parent_type = parent_type; new->level = level; @@ -363,14 +364,21 @@ 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 @@ 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 @@ 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 @@ } } } - 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 @@ 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 @@ 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]); }
Attachment:
pgpkB9IXNGdXN.pgp
Description: PGP signature