2 * Copyright notice from original mutt:
3 * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org>
4 * Copyright (C) 1999-2000 Thomas Roessler <roessler@does-not-exist.org>
6 * This file is part of mutt-ng, see http://www.muttng.org/.
7 * It's licensed under the GNU General Public License,
8 * please see the file GPL in the top level source directory.
11 #include <lib-lib/lib-lib.h>
13 #include <lib-mime/mime.h>
14 #include <lib-sys/unix.h>
16 #include <lib-ui/curses.h>
17 #include <lib-ui/enter.h>
18 #include <lib-ui/menu.h>
19 #include <lib-mx/mx.h>
20 #include <lib-crypt/crypt.h>
24 #include "recvattach.h"
28 #define SW (option(OPTMBOXPANE)?SidebarWidth:0)
30 static struct mapping_t AttachHelp[] = {
31 {N_("Exit"), OP_EXIT},
32 {N_("Save"), OP_SAVE},
33 {N_("Pipe"), OP_PIPE},
34 {N_("Print"), OP_PRINT},
35 {N_("Help"), OP_HELP},
39 void mutt_update_tree (ATTACHPTR ** idx, short idxlen)
45 for (x = 0; x < idxlen; x++) {
47 if (2 * (idx[x]->level + 2) < ssizeof (buf)) {
49 s = buf + 2 * (idx[x]->level - 1);
50 *s++ = (idx[x]->content->next) ? M_TREE_LTEE : M_TREE_LLCORNER;
60 if (m_strcmp(idx[x]->tree, buf) != 0)
61 m_strreplace(&idx[x]->tree, buf);
64 idx[x]->tree = m_strdup(buf);
66 if (2 * (idx[x]->level + 2) < ssizeof (buf) && idx[x]->level) {
67 s = buf + 2 * (idx[x]->level - 1);
68 *s++ = (idx[x]->content->next) ? '\005' : '\006';
74 ATTACHPTR **mutt_gen_attach_list (BODY * m,
78 short *idxmax, int level, int compose)
83 for (; m; m = m->next) {
84 if (*idxlen == *idxmax) {
85 p_realloc(&idx, (*idxmax) += 5);
86 for (i = *idxlen; i < *idxmax; i++)
90 if (m->type == TYPEMULTIPART && m->parts
93 && ascii_strcasecmp ("alternative", m->subtype)))
94 && (!mutt_is_multipart_encrypted (m))
97 mutt_gen_attach_list (m->parts, m->type, idx, idxlen, idxmax, level,
102 idx[*idxlen] = p_new(ATTACHPTR, 1);
104 new = idx[(*idxlen)++];
107 new->parent_type = parent_type;
110 /* We don't support multipart messages in the compose menu yet */
111 if (!compose && !m->collapsed
112 && ((m->type == TYPEMULTIPART && !mutt_is_multipart_encrypted(m))
113 || mutt_is_message_type(m)))
115 idx = mutt_gen_attach_list (m->parts, m->type, idx, idxlen, idxmax,
122 mutt_update_tree (idx, *idxlen);
127 /* %c = character set: convert?
131 * %e = MIME content-transfer-encoding
133 * %I = content-disposition, either I (inline) or A (attachment)
136 * %m = major MIME type
138 * %n = attachment number
142 const char *mutt_attach_fmt (char *dest,
147 const char *ifstring,
148 const char *elsestring,
149 unsigned long data, format_flag flags)
153 char charset[STRING];
154 ATTACHPTR *aptr = (ATTACHPTR *) data;
155 int optional = (flags & M_FORMAT_OPTIONAL);
161 if (mutt_is_text_part (aptr->content) &&
162 mutt_get_body_charset (charset, sizeof (charset), aptr->content))
163 mutt_format_s (dest, destlen, prefix, charset);
165 mutt_format_s (dest, destlen, prefix, "");
167 else if (!mutt_is_text_part (aptr->content) ||
168 !mutt_get_body_charset (charset, sizeof (charset),
175 snprintf (fmt, sizeof (fmt), "%%%sc", prefix);
176 snprintf (dest, destlen, fmt, aptr->content->type != TYPETEXT ||
177 aptr->content->noconv ? 'n' : 'c');
179 else if (aptr->content->type != TYPETEXT || aptr->content->noconv)
184 if (aptr->content->description) {
185 mutt_format_s (dest, destlen, prefix, aptr->content->description);
188 if (mutt_is_message_type(aptr->content) && MsgFmt && aptr->content->hdr)
192 _mutt_make_string (s, sizeof (s), MsgFmt, NULL, aptr->content->hdr,
193 M_FORMAT_FORCESUBJ | M_FORMAT_MAKEPRINT |
194 M_FORMAT_ARROWCURSOR);
196 mutt_format_s (dest, destlen, prefix, s);
200 if (!aptr->content->filename) {
201 mutt_format_s (dest, destlen, prefix, "<no description>");
205 else if (aptr->content->description ||
206 (mutt_is_message_type(aptr->content)
207 && MsgFmt && aptr->content->hdr))
209 /* FALLS THROUGH TO 'f' */
212 if (aptr->content->filename && *aptr->content->filename == '/') {
213 char path[_POSIX_PATH_MAX];
215 m_strcpy(path, sizeof(path), aptr->content->filename);
216 mutt_pretty_mailbox (path);
217 mutt_format_s (dest, destlen, prefix, path);
220 mutt_format_s (dest, destlen, prefix,
221 NONULL (aptr->content->filename));
223 else if (!aptr->content->filename)
228 snprintf (dest, destlen, "%c", aptr->content->deleted ? 'D' : ' ');
229 else if (!aptr->content->deleted)
234 mutt_format_s (dest, destlen, prefix,
235 ENCODING (aptr->content->encoding));
239 snprintf (dest, destlen, "%c",
240 (aptr->content->disposition == DISPINLINE) ? 'I' : 'A');
245 mutt_format_s (dest, destlen, prefix, TYPE (aptr->content));
249 mutt_format_s (dest, destlen, prefix, aptr->content->subtype);
250 else if (!aptr->content->subtype)
255 snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
256 snprintf (dest, destlen, fmt, aptr->num + 1);
261 optional = aptr->content->attach_qualifies;
263 snprintf (fmt, sizeof (fmt), "%%%sc", prefix);
264 mutt_format_s (dest, destlen, fmt, "Q");
268 if (flags & M_FORMAT_STAT_FILE) {
271 stat (aptr->content->filename, &st);
275 l = aptr->content->length;
278 mutt_pretty_size (tmp, sizeof (tmp), l);
279 mutt_format_s (dest, destlen, prefix, tmp);
287 snprintf (dest, destlen, "%c", aptr->content->tagged ? '*' : ' ');
288 else if (!aptr->content->tagged)
293 mutt_format_s_tree (dest, destlen, prefix, NONULL (aptr->tree));
294 else if (!aptr->tree)
299 snprintf (dest, destlen, "%c", aptr->content->unlink ? '-' : ' ');
300 else if (!aptr->content->unlink)
305 optional = (aptr->content->attach_count + aptr->content->attach_qualifies) != 0;
307 snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
308 snprintf (dest, destlen, fmt, aptr->content->attach_count + aptr->content->attach_qualifies);
316 mutt_FormatString (dest, destlen, ifstring, mutt_attach_fmt, data, 0);
317 else if (flags & M_FORMAT_OPTIONAL)
318 mutt_FormatString (dest, destlen, elsestring, mutt_attach_fmt, data, 0);
322 static void attach_entry (char *b, ssize_t blen, MUTTMENU * menu, int num)
324 int w=(COLS-SW)>blen?blen:(COLS-SW);
325 mutt_FormatString (b, w, NONULL (AttachFormat), mutt_attach_fmt,
326 (unsigned long) (((ATTACHPTR **) menu->data)[num]),
327 M_FORMAT_ARROWCURSOR);
330 int mutt_tag_attach (MUTTMENU * menu, int n, int m)
332 BODY *cur = ((ATTACHPTR **) menu->data)[n]->content;
333 int ot = cur->tagged;
335 cur->tagged = (m >= 0 ? m : !cur->tagged);
336 return cur->tagged - ot;
339 static int mutt_query_save_attachment (FILE * fp, BODY * body, HEADER * hdr,
343 char buf[_POSIX_PATH_MAX], tfile[_POSIX_PATH_MAX];
349 if (body->filename) {
350 if (directory && *directory)
351 mutt_concat_path(buf, sizeof(buf), *directory,
352 mutt_basename(body->filename));
354 m_strcpy(buf, sizeof(buf), body->filename);
356 else if (body->hdr &&
357 body->encoding != ENCBASE64 &&
358 body->encoding != ENCQUOTEDPRINTABLE &&
359 mutt_is_message_type(body))
360 mutt_default_save (buf, sizeof (buf), body->hdr);
364 prompt = _("Save to file ('#' for last used folder): ");
366 static char LastSaveFolder[_POSIX_PATH_MAX] = ".";
368 ret = mutt_get_field(prompt, buf, sizeof (buf),
369 M_FILE | M_CLEAR | M_LASTFOLDER);
370 if (((ret != 0) && (ret != 2)) || (!buf[0] && ret != 2))
374 char tmpbuf[_POSIX_PATH_MAX];
376 snprintf (tmpbuf, sizeof (tmpbuf), "%s/%s", LastSaveFolder, buf);
377 m_strcpy(buf, sizeof(buf), tmpbuf);
378 ret = mutt_get_field(_("Save to file: "), buf, sizeof (buf), M_FILE);
379 if ((ret != 0) || (!buf[0]))
382 m_dirname(LastSaveFolder, sizeof(LastSaveFolder), buf);
385 mutt_expand_path(buf, sizeof(buf));
387 is_message = (fp && body->hdr &&
388 body->encoding != ENCBASE64 &&
389 body->encoding != ENCQUOTEDPRINTABLE &&
390 mutt_is_message_type(body));
395 /* check to make sure that this file is really the one the user wants */
396 rc = mutt_save_confirm(buf, &st);
397 m_strcpy(tfile, sizeof(tfile), buf);
399 rc = mutt_check_overwrite(body->filename, buf, tfile, sizeof(tfile),
405 prompt = _("Save to file: ");
409 mutt_message _("Saving...");
411 if (mutt_save_attachment(fp, body, tfile, append,
412 (hdr || !is_message) ? hdr : body->hdr) == 0)
414 mutt_message _("Attachment saved.");
417 prompt = _("Save to file: ");
424 void mutt_save_attachment_list (FILE * fp, int tag, BODY * top, HEADER * hdr,
427 char buf[_POSIX_PATH_MAX], tfile[_POSIX_PATH_MAX];
428 char *directory = NULL;
430 int last = menu ? menu->current : -1;
435 for (; top; top = top->next) {
436 if (!tag || top->tagged) {
437 if (!option (OPTATTACHSPLIT)) {
441 m_strcpy(buf, sizeof(buf), NONULL(top->filename));
442 if (mutt_get_field (_("Save to file: "), buf, sizeof (buf),
443 M_FILE | M_CLEAR) != 0 || !buf[0])
445 mutt_expand_path (buf, sizeof (buf));
446 if (mutt_check_overwrite (top->filename, buf, tfile,
447 sizeof (tfile), &append, NULL))
449 rc = mutt_save_attachment (fp, top, tfile, append, hdr);
450 if (rc == 0 && AttachSep && (fpout = fopen (tfile, "a")) != NULL) {
451 fprintf (fpout, "%s", AttachSep);
456 rc = mutt_save_attachment (fp, top, tfile, M_SAVE_APPEND, hdr);
457 if (rc == 0 && AttachSep && (fpout = fopen (tfile, "a")) != NULL) {
458 fprintf (fpout, "%s", AttachSep);
463 if (tag && menu && top->aptr) {
464 menu->oldcurrent = menu->current;
465 menu->current = top->aptr->num;
466 menu_check_recenter (menu);
467 menu->redraw |= REDRAW_MOTION;
471 if (mutt_query_save_attachment (fp, top, hdr, &directory) == -1)
476 mutt_save_attachment_list (fp, 1, top->parts, hdr, menu);
481 p_delete(&directory);
484 menu->oldcurrent = menu->current;
485 menu->current = last;
486 menu_check_recenter (menu);
487 menu->redraw |= REDRAW_MOTION;
490 if (!option (OPTATTACHSPLIT) && (rc == 0))
491 mutt_message _("Attachment saved.");
495 mutt_query_pipe_attachment (char *command, FILE * fp, BODY * body, int afilter)
497 char tfile[_POSIX_PATH_MAX];
498 char warning[STRING + _POSIX_PATH_MAX];
501 snprintf (warning, sizeof (warning),
502 _("WARNING! You are about to overwrite %s, continue?"),
504 if (mutt_yesorno (warning, M_NO) != M_YES) {
505 CLEARLINE (LINES - 1);
513 if (mutt_pipe_attachment (fp, body, command, tfile)) {
515 mutt_unlink (body->filename);
516 mutt_rename_file (tfile, body->filename);
517 mutt_update_encoding (body);
518 mutt_message _("Attachment filtered.");
521 if (afilter && tfile[0])
526 static void pipe_attachment (FILE * fp, BODY * b, STATE * state)
532 mutt_decode_attachment (b, state);
534 state_puts (AttachSep, state);
536 if ((ifp = fopen (b->filename, "r")) == NULL) {
537 mutt_perror ("fopen");
540 mutt_copy_stream (ifp, state->fpout);
543 state_puts (AttachSep, state);
548 pipe_attachment_list (char *command, FILE * fp, int tag, BODY * top,
549 int afilter, STATE * state)
551 for (; top; top = top->next) {
552 if (!tag || top->tagged) {
553 if (!afilter && !option (OPTATTACHSPLIT))
554 pipe_attachment (fp, top, state);
556 mutt_query_pipe_attachment (command, fp, top, afilter);
559 pipe_attachment_list (command, fp, tag, top->parts, afilter, state);
565 void mutt_pipe_attachment_list (FILE * fp, int tag, BODY * top, int afilter)
572 afilter = 0; /* sanity check: we can't filter in the recv case yet */
577 if (mutt_get_field ((afilter ? _("Filter through: ") : _("Pipe to: ")),
578 buf, sizeof (buf), M_CMD) != 0 || !buf[0])
581 mutt_expand_path (buf, sizeof (buf));
583 if (!afilter && !option (OPTATTACHSPLIT)) {
585 thepid = mutt_create_filter (buf, &state.fpout, NULL, NULL);
586 pipe_attachment_list (buf, fp, tag, top, afilter, &state);
587 m_fclose(&state.fpout);
588 if (mutt_wait_filter (thepid) != 0 || option (OPTWAITKEY))
589 mutt_any_key_to_continue (NULL);
591 pipe_attachment_list (buf, fp, tag, top, afilter, &state);
595 static int can_print(BODY * top, int tag)
597 for (; top; top = top->next) {
599 int tok = mime_which_token(top->subtype, -1);
601 snprintf(type, sizeof(type), "%s/%s", TYPE(top), top->subtype);
603 if (!tag || top->tagged) {
604 if (!rfc1524_mailcap_lookup(top, type, NULL, M_PRINT)
605 && !(top->type == TYPETEXT && tok == MIME_PLAIN)
606 && !(top->type == TYPEAPPLICATION && tok == MIME_POSTSCRIPT)
607 && !mutt_can_decode(top))
609 mutt_error(_("I dont know how to print %s attachments!"), type);
614 return (can_print(top->parts, tag));
621 static void print_attachment_list (FILE * fp, int tag, BODY * top,
626 for (; top; top = top->next) {
627 if (!tag || top->tagged) {
628 int tok = mime_which_token(top->subtype, -1);
630 snprintf (type, sizeof (type), "%s/%s", TYPE (top), top->subtype);
631 if (!option (OPTATTACHSPLIT)
632 && !rfc1524_mailcap_lookup (top, type, NULL, M_PRINT)) {
633 if ((top->type == TYPETEXT && tok == MIME_PLAIN)
634 || (top->type == TYPEAPPLICATION && tok == MIME_POSTSCRIPT)) {
635 pipe_attachment (fp, top, state);
637 if (mutt_can_decode (top)) {
638 /* decode and print */
640 char newfile[_POSIX_PATH_MAX] = "";
643 mutt_mktemp (newfile);
644 if (mutt_decode_save_attachment (fp, top, newfile, M_PRINTING, 0) ==
646 if ((ifp = fopen (newfile, "r")) != NULL) {
647 mutt_copy_stream (ifp, state->fpout);
650 state_puts (AttachSep, state);
653 mutt_unlink (newfile);
656 mutt_print_attachment(fp, top);
660 print_attachment_list (fp, tag, top->parts, state);
666 void mutt_print_attachment_list (FILE * fp, int tag, BODY * top)
672 if (query_quadoption(OPT_PRINT,
673 tag ? _("Print tagged attachment(s)?") : _("Print attachment?")) !=
677 if (!option (OPTATTACHSPLIT)) {
678 if (!can_print (top, tag))
682 thepid = mutt_create_filter (NONULL (PrintCmd), &state.fpout, NULL, NULL);
683 print_attachment_list (fp, tag, top, &state);
684 m_fclose(&state.fpout);
685 if (mutt_wait_filter (thepid) != 0 || option (OPTWAITKEY))
686 mutt_any_key_to_continue (NULL);
689 print_attachment_list (fp, tag, top, &state);
693 mutt_update_attach_index (BODY * cur, ATTACHPTR *** idxp,
694 short *idxlen, short *idxmax, MUTTMENU * menu)
696 ATTACHPTR **idx = *idxp;
698 while (--(*idxlen) >= 0)
699 idx[(*idxlen)]->content = NULL;
702 idx = *idxp = mutt_gen_attach_list (cur, -1, idx, idxlen, idxmax, 0, 0);
707 if (menu->current >= menu->max)
708 menu->current = menu->max - 1;
709 menu_check_recenter (menu);
710 menu->redraw |= REDRAW_INDEX;
714 mutt_attach_display_loop (MUTTMENU * menu, int op, FILE * fp, HEADER * hdr,
715 BODY * cur, ATTACHPTR *** idxp, short *idxlen,
716 short *idxmax, int recv)
718 ATTACHPTR **idx = *idxp;
722 case OP_DISPLAY_HEADERS:
723 toggle_option (OPTWEED);
727 op = mutt_view_attachment (fp, idx[menu->current]->content, M_REGULAR,
732 case OP_MAIN_NEXT_UNDELETED: /* hack */
733 if (menu->current < menu->max - 1) {
741 case OP_MAIN_PREV_UNDELETED: /* hack */
742 if (menu->current > 0) {
750 /* when we edit the content-type, we should redisplay the attachment
752 mutt_edit_content_type (hdr, idx[menu->current]->content, fp);
754 mutt_update_attach_index (cur, idxp, idxlen, idxmax, menu);
759 /* functions which are passed through from the pager */
760 case OP_CHECK_TRADITIONAL:
761 if (hdr && hdr->security & PGP_TRADITIONAL_CHECKED) {
766 case OP_ATTACH_COLLAPSE:
773 while (op != OP_NULL);
778 static void attach_collapse (BODY * b, short collapse, short init,
783 for (; b; b = b->next) {
784 i = init || b->collapsed;
785 if (i && option (OPTDIGESTCOLLAPSE) && b->type == TYPEMULTIPART
786 && mime_which_token(b->subtype, -1) == MIME_DIGEST)
787 attach_collapse (b->parts, 1, 1, 0);
788 else if (b->type == TYPEMULTIPART || mutt_is_message_type(b))
789 attach_collapse (b->parts, collapse, i, 0);
790 b->collapsed = collapse;
796 void mutt_attach_init (BODY * b)
798 for (; b; b = b->next) {
802 mutt_attach_init (b->parts);
806 void mutt_view_attachments (HEADER * hdr)
809 int need_secured = 0;
811 char helpstr[STRING];
816 ATTACHPTR **idx = NULL;
822 /* make sure we have parsed this message */
823 mutt_parse_mime_message (Context, hdr);
825 mutt_message_hook (Context, hdr, M_MESSAGEHOOK);
827 if ((msg = mx_open_message (Context, hdr->msgno)) == NULL)
830 if ((hdr->security & ENCRYPT) ||
831 (mutt_is_application_smime (hdr->content) & SMIMEOPAQUE))
835 if ((hdr->security & ENCRYPT) && !crypt_valid_passphrase (hdr->security)) {
836 mx_close_message (&msg);
839 if (hdr->security & APPLICATION_SMIME) {
841 crypt_smime_getkeys (hdr->env);
843 if (mutt_is_application_smime (hdr->content)) {
844 secured = !crypt_smime_decrypt_mime (msg->fp, &fp,
848 if ((mutt_is_application_smime (cur) & SMIMEOPAQUE)) {
854 secured = !crypt_smime_decrypt_mime (_fp, &fp, _cur, &cur);
856 body_list_wipe(&_cur);
863 if (hdr->security & APPLICATION_PGP) {
864 if (mutt_is_multipart_encrypted (hdr->content))
865 secured = !crypt_pgp_decrypt_mime (msg->fp, &fp, hdr->content, &cur);
870 if (need_secured && !secured) {
871 mx_close_message (&msg);
872 mutt_error _("Can't decrypt encrypted message!");
882 menu = mutt_new_menu ();
883 menu->menu = MENU_ATTACH;
884 menu->title = _("Attachments");
885 menu->make_entry = attach_entry;
886 menu->tag = mutt_tag_attach;
888 mutt_compile_help (helpstr, sizeof (helpstr), MENU_ATTACH, AttachHelp);
890 mutt_attach_init (cur);
891 attach_collapse (cur, 0, 1, 0);
892 mutt_update_attach_index (cur, &idx, &idxlen, &idxmax, menu);
894 #define CHECK_READONLY \
895 if (Context->readonly) { \
897 mutt_error _("Mailbox is read-only."); \
901 #define CHECK_ATTACH \
902 if (option(OPTATTACHMSG)) { \
904 mutt_error _("Function not permitted in attach-message mode."); \
910 op = mutt_menuLoop(menu);
912 case OP_ATTACH_VIEW_MAILCAP:
913 mutt_view_attachment (fp, idx[menu->current]->content, M_MAILCAP,
915 menu->redraw = REDRAW_FULL;
918 case OP_ATTACH_VIEW_TEXT:
919 mutt_view_attachment (fp, idx[menu->current]->content, M_AS_TEXT,
921 menu->redraw = REDRAW_FULL;
924 case OP_DISPLAY_HEADERS:
927 mutt_attach_display_loop (menu, op, fp, hdr, cur, &idx, &idxlen,
929 menu->redraw = REDRAW_FULL;
932 case OP_ATTACH_COLLAPSE:
933 if (!idx[menu->current]->content->parts) {
934 mutt_error _("There are no subparts to show!");
938 if (!idx[menu->current]->content->collapsed)
939 attach_collapse (idx[menu->current]->content, 1, 0, 1);
941 attach_collapse (idx[menu->current]->content, 0, 1, 1);
942 mutt_update_attach_index (cur, &idx, &idxlen, &idxmax, menu);
945 case OP_FORGET_PASSPHRASE:
946 crypt_forget_passphrase ();
949 case OP_EXTRACT_KEYS:
950 crypt_pgp_extract_keys_from_attachment_list (fp, menu->tagprefix,
955 menu->redraw = REDRAW_FULL;
958 case OP_CHECK_TRADITIONAL:
959 if (crypt_pgp_check_traditional (fp, menu->tagprefix ? cur
960 : idx[menu->current]->content,
963 hdr->security = crypt_query (cur);
964 menu->redraw = REDRAW_FULL;
969 mutt_print_attachment_list (fp, menu->tagprefix,
970 menu->tagprefix ? cur : idx[menu->current]->
975 mutt_pipe_attachment_list (fp, menu->tagprefix,
976 menu->tagprefix ? cur : idx[menu->current]->
981 mutt_save_attachment_list (fp, menu->tagprefix,
982 menu->tagprefix ? cur : idx[menu->current]->
985 if (!menu->tagprefix && option (OPTRESOLVE)
986 && menu->current < menu->max - 1)
989 menu->redraw = REDRAW_MOTION_RESYNCH | REDRAW_FULL;
995 if (Context->magic == M_POP) {
997 mutt_error _("Can't delete attachment from POP server.");
1003 if (Context->magic == M_NNTP) {
1005 mutt_error _("Can't delete attachment from newsserver.");
1011 if (hdr->security & (~PGP_TRADITIONAL_CHECKED)) {
1013 _("Deletion of attachments from encrypted messages is unsupported.");
1016 if (!menu->tagprefix) {
1017 if (idx[menu->current]->parent_type == TYPEMULTIPART) {
1018 idx[menu->current]->content->deleted = 1;
1019 if (option (OPTRESOLVE) && menu->current < menu->max - 1) {
1021 menu->redraw = REDRAW_MOTION_RESYNCH;
1024 menu->redraw = REDRAW_CURRENT;
1028 _("Only deletion of multipart attachments is supported.");
1033 for (x = 0; x < menu->max; x++) {
1034 if (idx[x]->content->tagged) {
1035 if (idx[x]->parent_type == TYPEMULTIPART) {
1036 idx[x]->content->deleted = 1;
1037 menu->redraw = REDRAW_INDEX;
1041 _("Only deletion of multipart attachments is supported.");
1050 if (!menu->tagprefix) {
1051 idx[menu->current]->content->deleted = 0;
1052 if (option (OPTRESOLVE) && menu->current < menu->max - 1) {
1054 menu->redraw = REDRAW_MOTION_RESYNCH;
1057 menu->redraw = REDRAW_CURRENT;
1062 for (x = 0; x < menu->max; x++) {
1063 if (idx[x]->content->tagged) {
1064 idx[x]->content->deleted = 0;
1065 menu->redraw = REDRAW_INDEX;
1073 mutt_attach_resend (fp, hdr, idx, idxlen,
1074 menu->tagprefix ? NULL : idx[menu->current]->
1076 menu->redraw = REDRAW_FULL;
1079 case OP_BOUNCE_MESSAGE:
1081 mutt_attach_bounce (fp, hdr, idx, idxlen,
1082 menu->tagprefix ? NULL : idx[menu->current]->
1084 menu->redraw = REDRAW_FULL;
1087 case OP_FORWARD_MESSAGE:
1089 mutt_attach_forward (fp, hdr, idx, idxlen,
1090 menu->tagprefix ? NULL : idx[menu->current]->
1092 menu->redraw = REDRAW_FULL;
1096 case OP_FORWARD_TO_GROUP:
1098 mutt_attach_forward (fp, hdr, idx, idxlen,
1099 menu->tagprefix ? NULL : idx[menu->current]->
1101 menu->redraw = REDRAW_FULL;
1107 if (!idx[menu->current]->content->hdr->env->followup_to ||
1108 m_strcasecmp(idx[menu->current]->content->hdr->env->followup_to,
1110 || query_quadoption (OPT_FOLLOWUPTOPOSTER,
1111 _("Reply by mail as poster prefers?")) !=
1113 mutt_attach_reply (fp, hdr, idx, idxlen,
1114 menu->tagprefix ? NULL : idx[menu->current]->
1115 content, SENDNEWS | SENDREPLY);
1116 menu->redraw = REDRAW_FULL;
1122 case OP_GROUP_REPLY:
1128 (op == OP_GROUP_REPLY ? SENDGROUPREPLY : 0) |
1129 (op == OP_LIST_REPLY ? SENDLISTREPLY : 0);
1130 mutt_attach_reply (fp, hdr, idx, idxlen,
1131 menu->tagprefix ? NULL : idx[menu->current]->content,
1133 menu->redraw = REDRAW_FULL;
1137 mutt_edit_content_type (hdr, idx[menu->current]->content, fp);
1138 mutt_update_attach_index (cur, &idx, &idxlen, &idxmax, menu);
1142 mx_close_message (&msg);
1143 hdr->attach_del = 0;
1144 while (idxmax-- > 0) {
1147 if (idx[idxmax]->content && idx[idxmax]->content->deleted)
1148 hdr->attach_del = 1;
1149 if (idx[idxmax]->content)
1150 idx[idxmax]->content->aptr = NULL;
1151 p_delete(&idx[idxmax]->tree);
1152 p_delete(&idx[idxmax]);
1154 if (hdr->attach_del)
1159 if (need_secured && secured) {
1161 body_list_wipe(&cur);
1164 mutt_menuDestroy (&menu);