force rfc2047_parameters to be set to yes, and non configureable.
[apps/madmutt.git] / compose.c
1 /*
2  * Copyright notice from original mutt:
3  * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org>
4  * Copyright (C) 2004 g10 Code GmbH
5  *
6  * Parts were written/modified by:
7  * Nico Golde <nico@ngolde.de>
8  *
9  * This file is part of mutt-ng, see http://www.muttng.org/.
10  * It's licensed under the GNU General Public License,
11  * please see the file GPL in the top level source directory.
12  */
13
14 #include <lib-lib/lib-lib.h>
15
16 #include <lib-sys/unix.h>
17
18 #include <lib-mime/mime.h>
19
20 #include <lib-ui/curses.h>
21 #include <lib-ui/enter.h>
22 #include <lib-ui/menu.h>
23 #include <lib-mx/mx.h>
24
25 #include "mutt.h"
26 #include "alias.h"
27 #include "mutt_idna.h"
28 #include "attach.h"
29 #include "recvattach.h"
30 #include "sort.h"
31 #include "charset.h"
32 #include "buffy.h"
33 #include "remailer.h"
34
35 #ifdef USE_NNTP
36 #include <nntp/nntp.h>
37 #endif
38
39 static const char *There_are_no_attachments = N_("There are no attachments.");
40
41 #define CHECK_COUNT if (idxlen == 0) { mutt_error _(There_are_no_attachments); break; }
42
43
44
45 enum {
46   HDR_FROM = 1,
47   HDR_TO,
48   HDR_CC,
49   HDR_BCC,
50   HDR_SUBJECT,
51   HDR_REPLYTO,
52   HDR_FCC,
53   HDR_MIX,
54
55   HDR_CRYPT,
56   HDR_CRYPTINFO,
57
58 #ifdef USE_NNTP
59   HDR_NEWSGROUPS,
60   HDR_FOLLOWUPTO,
61   HDR_XCOMMENTTO,
62 #endif
63
64 #ifndef USE_NNTP
65   HDR_ATTACH = (HDR_FCC + 5)    /* where to start printing the attachments */
66 #else
67   HDR_ATTACH = (HDR_FCC + 7)
68 #endif
69 };
70
71 #define HDR_XOFFSET     14
72 #define TITLE_FMT       "%14s"        /* Used for Prompts, which are ASCII */
73 #define SW              (option(OPTMBOXPANE)?SidebarWidth:0)
74 #define W               (COLS - HDR_XOFFSET - SW)
75
76 static const char *Prompts[] = {
77   "From: ",
78   "To: ",
79   "Cc: ",
80   "Bcc: ",
81   "Subject: ",
82   "Reply-To: ",
83   "Fcc: ",
84 #ifdef USE_NNTP
85     "",
86     "", "", "Newsgroups: ", "Followup-To: ", "X-Comment-To: "
87 #endif
88 };
89
90 static struct mapping_t ComposeHelp[] = {
91   {N_("Send"), OP_COMPOSE_SEND_MESSAGE},
92   {N_("Abort"), OP_EXIT},
93   {"To", OP_COMPOSE_EDIT_TO},
94   {"CC", OP_COMPOSE_EDIT_CC},
95   {"Subj", OP_COMPOSE_EDIT_SUBJECT},
96   {N_("Attach file"), OP_COMPOSE_ATTACH_FILE},
97   {N_("Descrip"), OP_COMPOSE_EDIT_DESCRIPTION},
98   {N_("Help"), OP_HELP},
99   {NULL, OP_NULL}
100 };
101
102 #ifdef USE_NNTP
103 static struct mapping_t ComposeNewsHelp[] = {
104   {N_("Send"), OP_COMPOSE_SEND_MESSAGE},
105   {N_("Abort"), OP_EXIT},
106   {"Newsgroups", OP_COMPOSE_EDIT_NEWSGROUPS},
107   {"Subj", OP_COMPOSE_EDIT_SUBJECT},
108   {N_("Attach file"), OP_COMPOSE_ATTACH_FILE},
109   {N_("Descrip"), OP_COMPOSE_EDIT_DESCRIPTION},
110   {N_("Help"), OP_HELP},
111   {NULL, OP_NULL}
112 };
113 #endif
114
115
116 static void snd_entry (char *b, ssize_t blen, MUTTMENU * menu, int num) {
117   int w=(COLS-SW)>blen?blen:COLS-SW;
118   mutt_FormatString (b, w, NONULL (AttachFormat), mutt_attach_fmt,
119                      (unsigned long) (((ATTACHPTR **) menu->data)[num]),
120                      M_FORMAT_STAT_FILE | M_FORMAT_ARROWCURSOR);
121 }
122
123 #include <lib-crypt/crypt.h>
124
125 static void redraw_crypt_lines (HEADER * msg)
126 {
127   int off = 0;
128
129   if (!msg->security)
130     mvaddstr (HDR_CRYPT, SW, "    Security: ");
131   else if (msg->security & APPLICATION_SMIME)
132     mvaddstr (HDR_CRYPT, SW, "      S/MIME: ");
133   else if (msg->security & APPLICATION_PGP)
134     mvaddstr (HDR_CRYPT, SW, "         PGP: ");
135
136   if ((msg->security & (ENCRYPT | SIGN)) == (ENCRYPT | SIGN))
137     addstr (_("Sign, Encrypt"));
138   else if (msg->security & ENCRYPT)
139     addstr (_("Encrypt"));
140   else if (msg->security & SIGN)
141     addstr (_("Sign"));
142   else
143     addstr (_("Clear"));
144
145   if ((msg->security & APPLICATION_PGP)
146       && (msg->security & (ENCRYPT | SIGN))) {
147     if ((msg->security & INLINE))
148       addstr (_(" (inline)"));
149     else
150       addstr (_(" (PGP/MIME)"));
151   }
152   clrtoeol ();
153
154   move (HDR_CRYPTINFO, SW);
155   clrtoeol ();
156   if (msg->security & APPLICATION_PGP && msg->security & SIGN)
157     printw ("%s%s", _("     sign as: "),
158             PgpSignAs ? PgpSignAs : _("<default>"));
159
160   if (msg->security & APPLICATION_SMIME && msg->security & SIGN) {
161     printw ("%s%s", _("     sign as: "),
162             SmimeDefaultKey ? SmimeDefaultKey : _("<default>"));
163   }
164
165   if ((msg->security & APPLICATION_SMIME)
166       && (msg->security & ENCRYPT)
167       && SmimeCryptAlg && *SmimeCryptAlg) {
168     mvprintw (HDR_CRYPTINFO, SW + 40, "%s%s", _("Encrypt with: "),
169               NONULL (SmimeCryptAlg));
170     off = 20;
171   }
172 }
173
174 static void redraw_mix_line (string_list_t * chain)
175 {
176   int c;
177   const char *t;
178
179   mvaddstr (HDR_MIX, SW, "         Mix: ");
180
181   if (!chain) {
182     addstr ("<no chain defined>");
183     clrtoeol ();
184     return;
185   }
186
187   for (c = 12; chain; chain = chain->next) {
188     t = chain->data;
189     if (t && t[0] == '0' && t[1] == '\0')
190       t = "<random>";
191
192     if (c + m_strlen(t) + 2 >= COLS - SW)
193       break;
194
195     addstr (NONULL (t));
196     if (chain->next)
197       addstr (", ");
198
199     c += m_strlen(t) + 2;
200   }
201 }
202
203 static int check_attachments (ATTACHPTR ** idx, short idxlen)
204 {
205   int i, r;
206   struct stat st;
207   char pretty[_POSIX_PATH_MAX], msg[_POSIX_PATH_MAX + SHORT_STRING];
208
209   for (i = 0; i < idxlen; i++) {
210     m_strcpy(pretty, sizeof(pretty), idx[i]->content->filename);
211     if (stat (idx[i]->content->filename, &st) != 0) {
212       mutt_pretty_mailbox (pretty);
213       mutt_error (_("%s [#%d] no longer exists!"), pretty, i + 1);
214       return -1;
215     }
216
217     if (idx[i]->content->stamp < st.st_mtime) {
218       mutt_pretty_mailbox (pretty);
219       snprintf (msg, sizeof (msg), _("%s [#%d] modified. Update encoding?"),
220                 pretty, i + 1);
221
222       if ((r = mutt_yesorno (msg, M_YES)) == M_YES)
223         mutt_update_encoding (idx[i]->content);
224       else if (r == -1)
225         return -1;
226     }
227   }
228
229   return 0;
230 }
231
232 static void draw_envelope_addr (int line, address_t * addr)
233 {
234   char buf[STRING];
235
236   buf[0] = 0;
237   rfc822_write_address (buf, sizeof (buf), addr, 1);
238   mvprintw (line, SW, TITLE_FMT, Prompts[line - 1]);
239   mutt_paddstr (W, buf);
240 }
241
242 static void draw_envelope (HEADER * msg, char *fcc)
243 {
244   draw_envelope_addr (HDR_FROM, msg->env->from);
245 #ifdef USE_NNTP
246   if (!option (OPTNEWSSEND)) {
247 #endif
248     draw_envelope_addr (HDR_TO, msg->env->to);
249     draw_envelope_addr (HDR_CC, msg->env->cc);
250     draw_envelope_addr (HDR_BCC, msg->env->bcc);
251 #ifdef USE_NNTP
252   }
253   else {
254     mvprintw (HDR_TO, SW, TITLE_FMT, Prompts[HDR_NEWSGROUPS - 1]);
255     mutt_paddstr (W, NONULL (msg->env->newsgroups));
256     mvprintw (HDR_CC, SW, TITLE_FMT, Prompts[HDR_FOLLOWUPTO - 1]);
257     mutt_paddstr (W, NONULL (msg->env->followup_to));
258     if (option (OPTXCOMMENTTO)) {
259       mvprintw (HDR_BCC, 0, TITLE_FMT, Prompts[HDR_XCOMMENTTO - 1]);
260       mutt_paddstr (W, NONULL (msg->env->x_comment_to));
261     }
262   }
263 #endif
264   mvprintw (HDR_SUBJECT, SW, TITLE_FMT, Prompts[HDR_SUBJECT - 1]);
265   mutt_paddstr (W, NONULL (msg->env->subject));
266   draw_envelope_addr (HDR_REPLYTO, msg->env->reply_to);
267   mvprintw (HDR_FCC, SW, TITLE_FMT, Prompts[HDR_FCC - 1]);
268   mutt_paddstr (W, fcc);
269
270   redraw_crypt_lines (msg);
271   redraw_mix_line (msg->chain);
272
273   SETCOLOR (MT_COLOR_STATUS);
274   mvaddstr (HDR_ATTACH - 1, SW, _("-- Attachments"));
275   BKGDSET (MT_COLOR_STATUS);
276   clrtoeol ();
277
278   BKGDSET (MT_COLOR_NORMAL);
279   SETCOLOR (MT_COLOR_NORMAL);
280 }
281
282 static int edit_address_list (int line, address_t ** addr)
283 {
284   char buf[HUGE_STRING] = "";   /* needs to be large for alias expansion */
285   char *err = NULL;
286
287   mutt_addrlist_to_local (*addr);
288   rfc822_write_address (buf, sizeof (buf), *addr, 0);
289   if (mutt_get_field (Prompts[line - 1], buf, sizeof (buf), M_ALIAS) == 0) {
290     address_list_wipe(addr);
291     *addr = mutt_parse_adrlist (*addr, buf);
292     *addr = mutt_expand_aliases (*addr);
293   }
294
295   if (option (OPTNEEDREDRAW)) {
296     unset_option (OPTNEEDREDRAW);
297     return (REDRAW_FULL);
298   }
299
300   if (mutt_addrlist_to_idna (*addr, &err) != 0) {
301     mutt_error (_("Warning: '%s' is a bad IDN."), err);
302     mutt_refresh ();
303     p_delete(&err);
304   }
305
306   /* redraw the expanded list so the user can see the result */
307   buf[0] = 0;
308   rfc822_write_address (buf, sizeof (buf), *addr, 1);
309   move (line, HDR_XOFFSET + SW);
310   mutt_paddstr (W, buf);
311
312   return 0;
313 }
314
315 static int delete_attachment (MUTTMENU * menu, short *idxlen, int x)
316 {
317   ATTACHPTR **idx = (ATTACHPTR **) menu->data;
318   int y;
319
320   menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
321
322   if (x == 0 && menu->max == 1) {
323     mutt_error _("You may not delete the only attachment.");
324
325     idx[x]->content->tagged = 0;
326     return (-1);
327   }
328
329   for (y = 0; y < *idxlen; y++) {
330     if (idx[y]->content->next == idx[x]->content) {
331       idx[y]->content->next = idx[x]->content->next;
332       break;
333     }
334   }
335
336   idx[x]->content->next = NULL;
337   idx[x]->content->parts = NULL;
338   body_list_wipe(&(idx[x]->content));
339   p_delete(&idx[x]->tree);
340   p_delete(&idx[x]);
341   for (; x < *idxlen - 1; x++)
342     idx[x] = idx[x + 1];
343   menu->max = --(*idxlen);
344
345   return (0);
346 }
347
348 static void update_idx (MUTTMENU * menu, ATTACHPTR ** idx, short idxlen)
349 {
350   idx[idxlen]->level = (idxlen > 0) ? idx[idxlen - 1]->level : 0;
351   if (idxlen)
352     idx[idxlen - 1]->content->next = idx[idxlen]->content;
353   idx[idxlen]->content->aptr = idx[idxlen];
354   menu->current = idxlen++;
355   mutt_update_tree (idx, idxlen);
356   menu->max = idxlen;
357   return;
358 }
359
360
361 /* 
362  * cum_attachs_size: Cumulative Attachments Size
363  *
364  * Returns the total number of bytes used by the attachments in the
365  * attachment list _after_ content-transfer-encodings have been
366  * applied.
367  * 
368  */
369
370 static unsigned long cum_attachs_size (MUTTMENU * menu)
371 {
372   ssize_t s;
373   unsigned short i;
374   ATTACHPTR **idx = menu->data;
375   CONTENT *info;
376   BODY *b;
377
378   for (i = 0, s = 0; i < menu->max; i++) {
379     b = idx[i]->content;
380
381     if (!b->content)
382       b->content = mutt_get_content_info (b->filename, b);
383
384     if ((info = b->content)) {
385       switch (b->encoding) {
386       case ENCQUOTEDPRINTABLE:
387         s += 3 * (info->lobin + info->hibin) + info->ascii + info->crlf;
388         break;
389       case ENCBASE64:
390         s += (4 * (info->lobin + info->hibin + info->ascii + info->crlf)) / 3;
391         break;
392       default:
393         s += info->lobin + info->hibin + info->ascii + info->crlf;
394         break;
395       }
396     }
397   }
398
399   return s;
400 }
401
402 /*
403  * compose_format_str()
404  *
405  * %a = total number of attachments 
406  * %h = hostname  [option]
407  * %l = approx. length of current message (in bytes) 
408  * %v = Mutt version 
409  *
410  * This function is similar to status_format_str().  Look at that function for
411  * help when modifying this function.
412  */
413
414 static void compose_status_line (char *buf, ssize_t buflen, MUTTMENU * menu,
415                                  const char *p);
416
417 static const char *compose_format_str (char *buf, ssize_t buflen, char op,
418                                        const char *src, const char *prefix,
419                                        const char *ifstring,
420                                        const char *elsestring,
421                                        unsigned long data, format_flag flags)
422 {
423   char fmt[SHORT_STRING], tmp[SHORT_STRING];
424   int optional = (flags & M_FORMAT_OPTIONAL);
425   MUTTMENU *menu = (MUTTMENU *) data;
426
427   *buf = 0;
428   switch (op) {
429   case 'a':                    /* total number of attachments */
430     snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
431     snprintf (buf, buflen, fmt, menu->max);
432     break;
433
434   case 'h':                    /* hostname */
435     snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
436     snprintf (buf, buflen, fmt, NONULL (Hostname));
437     break;
438
439   case 'l':                    /* approx length of current message in bytes */
440     snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
441     mutt_pretty_size (tmp, sizeof (tmp), menu ? cum_attachs_size (menu) : 0);
442     snprintf (buf, buflen, fmt, tmp);
443     break;
444
445   case 'v':
446     m_strcpy(buf, buflen, mutt_make_version (0));
447     break;
448
449   case 0:
450     *buf = 0;
451     return (src);
452
453   default:
454     snprintf (buf, buflen, "%%%s%c", prefix, op);
455     break;
456   }
457
458   if (optional)
459     compose_status_line (buf, buflen, menu, ifstring);
460   else if (flags & M_FORMAT_OPTIONAL)
461     compose_status_line (buf, buflen, menu, elsestring);
462
463   return (src);
464 }
465
466 static void compose_status_line (char *buf, ssize_t buflen, MUTTMENU * menu,
467                                  const char *p)
468 {
469   int w=(COLS-SW)>buflen?buflen:(COLS-SW);
470   mutt_FormatString (buf, w, p, compose_format_str,
471                      (unsigned long) menu, 0);
472 }
473
474
475 /* return values:
476  *
477  * 1    message should be postponed
478  * 0    normal exit
479  * -1   abort message
480  */
481 int mutt_compose_menu (HEADER * msg,    /* structure for new message */
482                        char *fcc,       /* where to save a copy of the message */
483                        ssize_t fcclen,
484                        HEADER * cur __attribute__ ((unused)))
485 {                               /* current message */
486   char helpstr[SHORT_STRING];
487   char buf[LONG_STRING];
488   char fname[_POSIX_PATH_MAX];
489   MUTTMENU *menu;
490   ATTACHPTR **idx = NULL;
491   short idxlen = 0;
492   short idxmax = 0;
493   int i, closed = 0;
494   int r = -1;                   /* return value */
495   int op = 0;
496   int loop = 1;
497   int fccSet = 0;               /* has the user edited the Fcc: field ? */
498   CONTEXT *ctx = NULL, *this = NULL;
499
500   /* Sort, SortAux could be changed in mutt_index_menu() */
501   int oldSort, oldSortAux;
502   struct stat st;
503
504 #ifdef USE_NNTP
505   int news = 0;                 /* is it a news article ? */
506
507   if (option (OPTNEWSSEND))
508     news++;
509 #endif
510
511   mutt_attach_init (msg->content);
512   idx = mutt_gen_attach_list (msg->content, -1, idx, &idxlen, &idxmax, 0, 1);
513
514   menu = mutt_new_menu ();
515   menu->menu = MENU_COMPOSE;
516   menu->offset = HDR_ATTACH;
517   menu->max = idxlen;
518   menu->make_entry = snd_entry;
519   menu->tag = mutt_tag_attach;
520   menu->data = idx;
521 #ifdef USE_NNTP
522   if (news)
523     menu->help =
524       mutt_compile_help (helpstr, sizeof (helpstr), MENU_COMPOSE,
525                          ComposeNewsHelp);
526   else
527 #endif
528     menu->help =
529       mutt_compile_help (helpstr, sizeof (helpstr), MENU_COMPOSE,
530                          ComposeHelp);
531
532   if (option (OPTMBOXPANE))
533     buffy_check (0);
534   while (loop) {
535 #ifdef USE_NNTP
536     unset_option (OPTNEWS);     /* for any case */
537 #endif
538     switch (op = mutt_menuLoop (menu)) {
539     case OP_REDRAW:
540       draw_envelope (msg, fcc);
541       menu->offset = HDR_ATTACH;
542       menu->pagelen = LINES - HDR_ATTACH - 2;
543       break;
544     case OP_COMPOSE_EDIT_FROM:
545       menu->redraw = edit_address_list (HDR_FROM, &msg->env->from);
546       mutt_message_hook (NULL, msg, M_SEND2HOOK);
547       break;
548     case OP_COMPOSE_EDIT_TO:
549 #ifdef USE_NNTP
550       if (!news) {
551 #endif
552         menu->redraw = edit_address_list (HDR_TO, &msg->env->to);
553         mutt_message_hook (NULL, msg, M_SEND2HOOK);
554 #ifdef USE_NNTP
555       }
556 #endif
557       break;
558     case OP_COMPOSE_EDIT_BCC:
559 #ifdef USE_NNTP
560       if (!news) {
561 #endif
562         menu->redraw = edit_address_list (HDR_BCC, &msg->env->bcc);
563         mutt_message_hook (NULL, msg, M_SEND2HOOK);
564 #ifdef USE_NNTP
565       }
566 #endif
567       break;
568     case OP_COMPOSE_EDIT_CC:
569 #ifdef USE_NNTP
570       if (!news) {
571 #endif
572         menu->redraw = edit_address_list (HDR_CC, &msg->env->cc);
573         mutt_message_hook (NULL, msg, M_SEND2HOOK);
574 #ifdef USE_NNTP
575       }
576 #endif
577       break;
578 #ifdef USE_NNTP
579     case OP_COMPOSE_EDIT_NEWSGROUPS:
580       if (news) {
581         if (msg->env->newsgroups)
582           m_strcpy(buf, sizeof(buf), msg->env->newsgroups);
583         else
584           buf[0] = 0;
585         if (mutt_get_field ("Newsgroups: ", buf, sizeof (buf), 0) == 0
586             && buf[0]) {
587           p_delete(&msg->env->newsgroups);
588           m_strrtrim(buf);
589           msg->env->newsgroups = m_strdup(skipspaces(buf));
590           move (HDR_TO, HDR_XOFFSET);
591           clrtoeol ();
592           if (msg->env->newsgroups)
593             printw ("%-*.*s", W, W, msg->env->newsgroups);
594         }
595       }
596       break;
597
598     case OP_COMPOSE_EDIT_FOLLOWUP_TO:
599       if (news) {
600         buf[0] = 0;
601         if (msg->env->followup_to)
602           m_strcpy(buf, sizeof(buf), msg->env->followup_to);
603         if (mutt_get_field ("Followup-To: ", buf, sizeof (buf), 0) == 0
604             && buf[0]) {
605           p_delete(&msg->env->followup_to);
606           m_strrtrim(buf);
607           msg->env->followup_to = m_strdup(skipspaces(buf));
608           move (HDR_CC, HDR_XOFFSET);
609           clrtoeol ();
610           if (msg->env->followup_to)
611             printw ("%-*.*s", W, W, msg->env->followup_to);
612         }
613       }
614       break;
615
616     case OP_COMPOSE_EDIT_X_COMMENT_TO:
617       if (news && option (OPTXCOMMENTTO)) {
618         buf[0] = 0;
619         if (msg->env->x_comment_to)
620           m_strcpy(buf, sizeof(buf), msg->env->x_comment_to);
621         if (mutt_get_field ("X-Comment-To: ", buf, sizeof (buf), 0) == 0
622             && buf[0]) {
623           p_delete(&msg->env->x_comment_to);
624           msg->env->x_comment_to = m_strdup(buf);
625           move (HDR_BCC, HDR_XOFFSET);
626           clrtoeol ();
627           if (msg->env->x_comment_to)
628             printw ("%-*.*s", W, W, msg->env->x_comment_to);
629         }
630       }
631       break;
632 #endif
633     case OP_COMPOSE_EDIT_SUBJECT:
634       if (msg->env->subject)
635         m_strcpy(buf, sizeof(buf), msg->env->subject);
636       else
637         buf[0] = 0;
638       if (mutt_get_field ("Subject: ", buf, sizeof (buf), 0) == 0) {
639         m_strreplace(&msg->env->subject, buf);
640         move (HDR_SUBJECT, HDR_XOFFSET + SW);
641         clrtoeol ();
642         if (msg->env->subject)
643           mutt_paddstr (W, msg->env->subject);
644       }
645       mutt_message_hook (NULL, msg, M_SEND2HOOK);
646       break;
647     case OP_COMPOSE_EDIT_REPLY_TO:
648       menu->redraw = edit_address_list (HDR_REPLYTO, &msg->env->reply_to);
649       mutt_message_hook (NULL, msg, M_SEND2HOOK);
650       break;
651     case OP_COMPOSE_EDIT_FCC:
652       m_strcpy(buf, sizeof(buf), fcc);
653       if (mutt_get_field ("Fcc: ", buf, sizeof (buf), M_FILE | M_CLEAR) == 0) {
654         m_strcpy(fcc, _POSIX_PATH_MAX, buf);
655         mutt_pretty_mailbox (fcc);
656         move (HDR_FCC, HDR_XOFFSET + SW);
657         mutt_paddstr (W, fcc);
658         fccSet = 1;
659       }
660       MAYBE_REDRAW (menu->redraw);
661       mutt_message_hook (NULL, msg, M_SEND2HOOK);
662       break;
663     case OP_COMPOSE_EDIT_MESSAGE:
664       if (Editor && !option (OPTEDITHDRS)) {
665         mutt_edit_file (Editor, msg->content->filename);
666         mutt_update_encoding (msg->content);
667         menu->redraw = REDRAW_CURRENT | REDRAW_STATUS;
668         mutt_message_hook (NULL, msg, M_SEND2HOOK);
669         break;
670       }
671       /* fall through */
672     case OP_COMPOSE_EDIT_HEADERS:
673       if ((op == OP_COMPOSE_EDIT_HEADERS ||
674            (op == OP_COMPOSE_EDIT_MESSAGE && option (OPTEDITHDRS)))) {
675         const char *tag = NULL;
676         char *err = NULL;
677
678         mutt_env_to_local (msg->env);
679         mutt_edit_headers (NONULL (Editor), msg->content->filename, msg,
680                            fcc, fcclen);
681         if (mutt_env_to_idna (msg->env, &tag, &err)) {
682           mutt_error (_("Bad IDN in \"%s\": '%s'"), tag, err);
683           p_delete(&err);
684         }
685       }
686       mutt_update_encoding (msg->content);
687
688       /* attachments may have been added */
689       if (idxlen && idx[idxlen - 1]->content->next) {
690         for (i = 0; i < idxlen; i++)
691           p_delete(&idx[i]);
692         idxlen = 0;
693         idx =
694           mutt_gen_attach_list (msg->content, -1, idx, &idxlen, &idxmax, 0,
695                                 1);
696         menu->data = idx;
697         menu->max = idxlen;
698       }
699
700       menu->redraw = REDRAW_FULL;
701       mutt_message_hook (NULL, msg, M_SEND2HOOK);
702       break;
703
704
705
706     case OP_COMPOSE_ATTACH_KEY:
707       if (idxlen == idxmax) {
708         p_realloc(&idx, idxmax += 5);
709         menu->data = idx;
710       }
711
712       idx[idxlen] = p_new(ATTACHPTR, 1);
713       if ((idx[idxlen]->content =
714            crypt_pgp_make_key_attachment (NULL)) != NULL) {
715         update_idx (menu, idx, idxlen++);
716         menu->redraw |= REDRAW_INDEX;
717       }
718       else
719         p_delete(&idx[idxlen]);
720
721       menu->redraw |= REDRAW_STATUS;
722
723       if (option (OPTNEEDREDRAW)) {
724         menu->redraw = REDRAW_FULL;
725         unset_option (OPTNEEDREDRAW);
726       }
727
728       mutt_message_hook (NULL, msg, M_SEND2HOOK);
729       break;
730
731
732     case OP_COMPOSE_ATTACH_FILE:
733       {
734         char *prompt, **files;
735         int error, numfiles;
736
737         fname[0] = 0;
738         prompt = _("Attach file");
739         numfiles = 0;
740         files = NULL;
741
742         if (_mutt_enter_fname
743             (prompt, fname, sizeof (fname), &menu->redraw, 0, 1, &files,
744              &numfiles) == -1 || *fname == '\0')
745           break;
746
747         if (idxlen + numfiles >= idxmax) {
748           p_realloc(&idx, idxmax += 5 + numfiles);
749           menu->data = idx;
750         }
751
752         error = 0;
753         if (numfiles > 1)
754           mutt_message _("Attaching selected files...");
755
756         for (i = 0; i < numfiles; i++) {
757           char *att = files[i];
758
759           idx[idxlen] = p_new(ATTACHPTR, 1);
760           idx[idxlen]->unowned = 1;
761           idx[idxlen]->content = mutt_make_file_attach (att);
762           if (idx[idxlen]->content != NULL)
763             update_idx (menu, idx, idxlen++);
764           else {
765             error = 1;
766             mutt_error (_("Unable to attach %s!"), att);
767             p_delete(&idx[idxlen]);
768           }
769         }
770
771         p_delete(&files);
772         if (!error)
773           mutt_clear_error ();
774
775         menu->redraw |= REDRAW_INDEX | REDRAW_STATUS;
776       }
777       mutt_message_hook (NULL, msg, M_SEND2HOOK);
778       break;
779
780     case OP_COMPOSE_ATTACH_MESSAGE:
781 #ifdef USE_NNTP
782     case OP_COMPOSE_ATTACH_NEWS_MESSAGE:
783 #endif
784       {
785         char *prompt;
786         HEADER *h;
787
788         fname[0] = 0;
789         prompt = _("Open mailbox to attach message from");
790
791 #ifdef USE_NNTP
792         unset_option (OPTNEWS);
793         if (op == OP_COMPOSE_ATTACH_NEWS_MESSAGE) {
794           if (!(CurrentNewsSrv = mutt_select_newsserver (NewsServer)))
795             break;
796
797           prompt = _("Open newsgroup to attach message from");
798           set_option (OPTNEWS);
799         }
800 #endif
801
802         if (Context)
803 #ifdef USE_NNTP
804           if ((op == OP_COMPOSE_ATTACH_MESSAGE) ^ (Context->magic == M_NNTP))
805 #endif
806           {
807             m_strcpy(fname, sizeof(fname), NONULL(Context->path));
808             mutt_pretty_mailbox (fname);
809           }
810
811         if (mutt_enter_fname (prompt, fname, sizeof (fname), &menu->redraw, 1)
812             == -1 || !fname[0])
813           break;
814
815 #ifdef USE_NNTP
816         if (option (OPTNEWS))
817           nntp_expand_path (fname, sizeof (fname),
818                             &CurrentNewsSrv->conn->account);
819         else
820 #endif
821           mutt_expand_path (fname, sizeof (fname));
822         if (mx_get_magic (fname) != M_IMAP)
823           if (mx_get_magic (fname) != M_POP)
824 #ifdef USE_NNTP
825             if (mx_get_magic (fname) != M_NNTP && !option (OPTNEWS))
826 #endif
827               /* check to make sure the file exists and is readable */
828               if (access (fname, R_OK) == -1) {
829                 mutt_perror (fname);
830                 break;
831               }
832
833         menu->redraw = REDRAW_FULL;
834
835         ctx = mx_open_mailbox (fname, M_READONLY, NULL);
836         if (ctx == NULL) {
837           mutt_perror (fname);
838           break;
839         }
840
841         if (!ctx->msgcount) {
842           mx_close_mailbox (ctx, NULL);
843           p_delete(&ctx);
844           mutt_error _("No messages in that folder.");
845
846           break;
847         }
848
849         this = Context;         /* remember current folder and sort methods */
850         oldSort = Sort;
851         oldSortAux = SortAux;
852
853         Context = ctx;
854         set_option (OPTATTACHMSG);
855         mutt_message _("Tag the messages you want to attach!");
856
857         closed = mutt_index_menu ();
858         unset_option (OPTATTACHMSG);
859
860         if (!Context) {
861           /* go back to the folder we started from */
862           Context = this;
863           /* Restore old $sort and $sort_aux */
864           Sort = oldSort;
865           SortAux = oldSortAux;
866           menu->redraw |= REDRAW_INDEX | REDRAW_STATUS;
867           break;
868         }
869
870         if (idxlen + Context->tagged >= idxmax) {
871           p_realloc(&idx, idxmax += 5 + Context->tagged);
872           menu->data = idx;
873         }
874
875         for (i = 0; i < Context->msgcount; i++) {
876           h = Context->hdrs[i];
877           if (h->tagged) {
878             idx[idxlen] = p_new(ATTACHPTR, 1);
879             idx[idxlen]->content = mutt_make_message_attach (Context, h, 1);
880             if (idx[idxlen]->content != NULL)
881               update_idx (menu, idx, idxlen++);
882             else {
883               mutt_error _("Unable to attach!");
884
885               p_delete(&idx[idxlen]);
886             }
887           }
888         }
889         menu->redraw |= REDRAW_FULL;
890
891         if (closed == OP_QUIT)
892           mx_close_mailbox (Context, NULL);
893         else
894           mx_fastclose_mailbox (Context);
895         p_delete(&Context);
896
897         /* go back to the folder we started from */
898         Context = this;
899         /* Restore old $sort and $sort_aux */
900         Sort = oldSort;
901         SortAux = oldSortAux;
902       }
903       mutt_message_hook (NULL, msg, M_SEND2HOOK);
904       break;
905
906     case OP_DELETE:
907       CHECK_COUNT;
908       if (idx[menu->current]->unowned)
909         idx[menu->current]->content->unlink = 0;
910       if (delete_attachment (menu, &idxlen, menu->current) == -1)
911         break;
912       mutt_update_tree (idx, idxlen);
913       if (idxlen) {
914         if (menu->current > idxlen - 1)
915           menu->current = idxlen - 1;
916       }
917       else
918         menu->current = 0;
919
920       if (menu->current == 0)
921         msg->content = idx[0]->content;
922
923       menu->redraw |= REDRAW_STATUS;
924       mutt_message_hook (NULL, msg, M_SEND2HOOK);
925       break;
926
927 #define CURRENT idx[menu->current]->content
928
929     case OP_COMPOSE_TOGGLE_RECODE:
930       {
931         CHECK_COUNT;
932         if (!mutt_is_text_part (CURRENT)) {
933           mutt_error (_("Recoding only affects text attachments."));
934           break;
935         }
936         CURRENT->noconv = !CURRENT->noconv;
937         if (CURRENT->noconv)
938           mutt_message (_("The current attachment won't be converted."));
939         else
940           mutt_message (_("The current attachment will be converted."));
941         menu->redraw = REDRAW_CURRENT;
942         mutt_message_hook (NULL, msg, M_SEND2HOOK);
943         break;
944       }
945 #undef CURRENT
946
947     case OP_COMPOSE_EDIT_DESCRIPTION:
948       CHECK_COUNT;
949       m_strcpy(buf, sizeof(buf),
950                NONULL(idx[menu->current]->content->description));
951       /* header names should not be translated */
952       if (mutt_get_field ("Description: ", buf, sizeof (buf), 0) == 0) {
953         m_strreplace(&idx[menu->current]->content->description, buf);
954         menu->redraw = REDRAW_CURRENT;
955       }
956       mutt_message_hook (NULL, msg, M_SEND2HOOK);
957       break;
958
959     case OP_COMPOSE_UPDATE_ENCODING:
960       CHECK_COUNT;
961       if (menu->tagprefix) {
962         BODY *top;
963
964         for (top = msg->content; top; top = top->next) {
965           if (top->tagged)
966             mutt_update_encoding (top);
967         }
968         menu->redraw = REDRAW_FULL;
969       }
970       else {
971         mutt_update_encoding (idx[menu->current]->content);
972         menu->redraw = REDRAW_CURRENT | REDRAW_STATUS;
973       }
974       mutt_message_hook (NULL, msg, M_SEND2HOOK);
975       break;
976
977     case OP_COMPOSE_TOGGLE_DISPOSITION:
978       /* toggle the content-disposition between inline/attachment */
979       idx[menu->current]->content->disposition =
980         (idx[menu->current]->content->disposition ==
981          DISPINLINE) ? DISPATTACH : DISPINLINE;
982       menu->redraw = REDRAW_CURRENT;
983       break;
984
985     case OP_EDIT_TYPE:
986       CHECK_COUNT;
987       {
988         mutt_edit_content_type (NULL, idx[menu->current]->content, NULL);
989
990         /* this may have been a change to text/something */
991         mutt_update_encoding (idx[menu->current]->content);
992
993         menu->redraw = REDRAW_CURRENT;
994       }
995       mutt_message_hook (NULL, msg, M_SEND2HOOK);
996       break;
997
998     case OP_COMPOSE_EDIT_ENCODING:
999       CHECK_COUNT;
1000       m_strcpy(buf, sizeof(buf),
1001                ENCODING(idx[menu->current]->content->encoding));
1002       if (mutt_get_field ("Content-Transfer-Encoding: ", buf,
1003                           sizeof (buf), 0) == 0 && buf[0]) {
1004         if ((i = mutt_check_encoding (buf)) != ENCOTHER && i != ENCUUENCODED) {
1005           idx[menu->current]->content->encoding = i;
1006           menu->redraw = REDRAW_CURRENT | REDRAW_STATUS;
1007           mutt_clear_error ();
1008         }
1009         else
1010           mutt_error _("Invalid encoding.");
1011       }
1012       mutt_message_hook (NULL, msg, M_SEND2HOOK);
1013       break;
1014
1015     case OP_COMPOSE_SEND_MESSAGE:
1016
1017       /* Note: We don't invoke send2-hook here, since we want to leave
1018        * users an opportunity to change settings from the ":" prompt.
1019        */
1020
1021       if (check_attachments (idx, idxlen) != 0) {
1022         menu->redraw = REDRAW_FULL;
1023         break;
1024       }
1025
1026       if (msg->chain && mix_check_message (msg) != 0)
1027         break;
1028
1029       if (!fccSet && *fcc) {
1030         if ((i = query_quadoption (OPT_COPY,
1031                                    _("Save a copy of this message?"))) == -1)
1032           break;
1033         else if (i == M_NO)
1034           *fcc = 0;
1035       }
1036
1037       loop = 0;
1038       r = 0;
1039       break;
1040
1041     case OP_COMPOSE_EDIT_FILE:
1042       CHECK_COUNT;
1043       mutt_edit_file (NONULL (Editor), idx[menu->current]->content->filename);
1044       mutt_update_encoding (idx[menu->current]->content);
1045       menu->redraw = REDRAW_CURRENT | REDRAW_STATUS;
1046       mutt_message_hook (NULL, msg, M_SEND2HOOK);
1047       break;
1048
1049     case OP_COMPOSE_TOGGLE_UNLINK:
1050       CHECK_COUNT;
1051       idx[menu->current]->content->unlink =
1052         !idx[menu->current]->content->unlink;
1053
1054       menu->redraw = REDRAW_INDEX;
1055       /* No send2hook since this doesn't change the message. */
1056       break;
1057
1058     case OP_COMPOSE_GET_ATTACHMENT:
1059       CHECK_COUNT;
1060       if (menu->tagprefix) {
1061         BODY *top;
1062
1063         for (top = msg->content; top; top = top->next) {
1064           if (top->tagged)
1065             mutt_get_tmp_attachment (top);
1066         }
1067         menu->redraw = REDRAW_FULL;
1068       }
1069       else if (mutt_get_tmp_attachment (idx[menu->current]->content) == 0)
1070         menu->redraw = REDRAW_CURRENT;
1071
1072       /* No send2hook since this doesn't change the message. */
1073       break;
1074
1075     case OP_COMPOSE_RENAME_FILE:
1076       CHECK_COUNT;
1077       m_strcpy(fname, sizeof(fname), idx[menu->current]->content->filename);
1078       mutt_pretty_mailbox (fname);
1079       if (mutt_get_field (_("Rename to: "), fname, sizeof (fname), M_FILE)
1080           == 0 && fname[0]) {
1081         if (stat (idx[menu->current]->content->filename, &st) == -1) {
1082           mutt_error (_("Can't stat %s: %s"), fname, strerror (errno));
1083           break;
1084         }
1085
1086         mutt_expand_path (fname, sizeof (fname));
1087         if (mutt_rename_file (idx[menu->current]->content->filename, fname))
1088           break;
1089
1090         m_strreplace(&idx[menu->current]->content->filename, fname);
1091         menu->redraw = REDRAW_CURRENT;
1092
1093         if (idx[menu->current]->content->stamp >= st.st_mtime)
1094           mutt_stamp_attachment (idx[menu->current]->content);
1095
1096       }
1097       mutt_message_hook (NULL, msg, M_SEND2HOOK);
1098       break;
1099
1100     case OP_COMPOSE_NEW_MIME:
1101       {
1102         char type[STRING];
1103         char *p;
1104         int itype;
1105         FILE *fp;
1106
1107         CLEARLINE (LINES - 1);
1108         fname[0] = 0;
1109         if (mutt_get_field (_("New file: "), fname, sizeof (fname), M_FILE)
1110             != 0 || !fname[0])
1111           continue;
1112         mutt_expand_path (fname, sizeof (fname));
1113
1114         /* Call to lookup_mime_type () ?  maybe later */
1115         type[0] = 0;
1116         if (mutt_get_field ("Content-Type: ", type, sizeof (type), 0) != 0
1117             || !type[0])
1118           continue;
1119
1120         if (!(p = strchr (type, '/'))) {
1121           mutt_error _("Content-Type is of the form base/sub");
1122
1123           continue;
1124         }
1125         *p++ = 0;
1126         if ((itype = mutt_check_mime_type (type)) == TYPEOTHER) {
1127           mutt_error (_("Unknown Content-Type %s"), type);
1128           continue;
1129         }
1130         if (idxlen == idxmax) {
1131           p_realloc(&idx, idxmax += 5);
1132           menu->data = idx;
1133         }
1134
1135         idx[idxlen] = p_new(ATTACHPTR, 1);
1136         /* Touch the file */
1137         if (!(fp = safe_fopen (fname, "w"))) {
1138           mutt_error (_("Can't create file %s"), fname);
1139           p_delete(&idx[idxlen]);
1140           continue;
1141         }
1142         m_fclose(&fp);
1143
1144         if ((idx[idxlen]->content = mutt_make_file_attach (fname)) == NULL) {
1145           mutt_error
1146             _("What we have here is a failure to make an attachment");
1147           continue;
1148         }
1149         update_idx (menu, idx, idxlen++);
1150
1151         idx[menu->current]->content->type = itype;
1152         m_strreplace(&idx[menu->current]->content->subtype, p);
1153         idx[menu->current]->content->unlink = 1;
1154         menu->redraw |= REDRAW_INDEX | REDRAW_STATUS;
1155
1156         if (mutt_compose_attachment (idx[menu->current]->content)) {
1157           mutt_update_encoding (idx[menu->current]->content);
1158           menu->redraw = REDRAW_FULL;
1159         }
1160       }
1161       mutt_message_hook (NULL, msg, M_SEND2HOOK);
1162       break;
1163
1164     case OP_COMPOSE_EDIT_MIME:
1165       CHECK_COUNT;
1166       if (mutt_edit_attachment (idx[menu->current]->content)) {
1167         mutt_update_encoding (idx[menu->current]->content);
1168         menu->redraw = REDRAW_FULL;
1169       }
1170       mutt_message_hook (NULL, msg, M_SEND2HOOK);
1171       break;
1172
1173     case OP_VIEW_ATTACH:
1174     case OP_DISPLAY_HEADERS:
1175       CHECK_COUNT;
1176       mutt_attach_display_loop (menu, op, NULL, NULL, NULL, &idx, &idxlen,
1177                                 NULL, 0);
1178       menu->redraw = REDRAW_FULL;
1179       /* no send2hook, since this doesn't modify the message */
1180       break;
1181
1182     case OP_SAVE:
1183       CHECK_COUNT;
1184       mutt_save_attachment_list (NULL, menu->tagprefix,
1185                                  menu->tagprefix ? msg->content : idx[menu->
1186                                                                       current]->
1187                                  content, NULL, menu);
1188       MAYBE_REDRAW (menu->redraw);
1189       /* no send2hook, since this doesn't modify the message */
1190       break;
1191
1192     case OP_PRINT:
1193       CHECK_COUNT;
1194       mutt_print_attachment_list (NULL, menu->tagprefix,
1195                                   menu->tagprefix ? msg->content : idx[menu->
1196                                                                        current]->
1197                                   content);
1198       /* no send2hook, since this doesn't modify the message */
1199       break;
1200
1201     case OP_PIPE:
1202     case OP_FILTER:
1203       CHECK_COUNT;
1204       mutt_pipe_attachment_list (NULL, menu->tagprefix,
1205                                  menu->tagprefix ? msg->content : idx[menu->
1206                                                                       current]->
1207                                  content, op == OP_FILTER);
1208       if (op == OP_FILTER)      /* cte might have changed */
1209         menu->redraw = menu->tagprefix ? REDRAW_FULL : REDRAW_CURRENT;
1210       menu->redraw |= REDRAW_STATUS;
1211       mutt_message_hook (NULL, msg, M_SEND2HOOK);
1212       break;
1213
1214     case OP_EXIT:
1215       if ((i =
1216            query_quadoption (OPT_POSTPONE,
1217                              _("Postpone this message?"))) == M_NO) {
1218         while (idxlen-- > 0) {
1219           /* avoid freeing other attachments */
1220           idx[idxlen]->content->next = NULL;
1221           idx[idxlen]->content->parts = NULL;
1222           if (idx[idxlen]->unowned)
1223             idx[idxlen]->content->unlink = 0;
1224           body_list_wipe(&idx[idxlen]->content);
1225           p_delete(&idx[idxlen]->tree);
1226           p_delete(&idx[idxlen]);
1227         }
1228         p_delete(&idx);
1229         idxlen = 0;
1230         idxmax = 0;
1231         r = -1;
1232         loop = 0;
1233         break;
1234       }
1235       else if (i == -1)
1236         break;                  /* abort */
1237
1238       /* fall through to postpone! */
1239
1240     case OP_COMPOSE_POSTPONE_MESSAGE:
1241
1242       if (check_attachments (idx, idxlen) != 0) {
1243         menu->redraw = REDRAW_FULL;
1244         break;
1245       }
1246
1247       loop = 0;
1248       r = 1;
1249       break;
1250
1251     case OP_COMPOSE_ISPELL:
1252       endwin ();
1253       snprintf (buf, sizeof (buf), "%s -x %s", NONULL (Ispell),
1254                 msg->content->filename);
1255       if (mutt_system (buf) == -1)
1256         mutt_error (_("Error running \"%s\"!"), buf);
1257       else {
1258         mutt_update_encoding (msg->content);
1259         menu->redraw |= REDRAW_STATUS;
1260       }
1261       break;
1262
1263     case OP_COMPOSE_WRITE_MESSAGE:
1264
1265       fname[0] = '\0';
1266       if (Context) {
1267         m_strcpy(fname, sizeof(fname), NONULL(Context->path));
1268         mutt_pretty_mailbox (fname);
1269       }
1270       if (idxlen)
1271         msg->content = idx[0]->content;
1272       if (mutt_enter_fname
1273           (_("Write message to mailbox"), fname, sizeof (fname),
1274            &menu->redraw, 1) != -1 && fname[0]) {
1275         mutt_message (_("Writing message to %s ..."), fname);
1276         mutt_expand_path (fname, sizeof (fname));
1277
1278         if (msg->content->next)
1279           msg->content = mutt_make_multipart (msg->content);
1280
1281         if (mutt_write_fcc (NONULL (fname), msg, NULL, 1, NULL) < 0)
1282           msg->content = mutt_remove_multipart (msg->content);
1283         else
1284           mutt_message _("Message written.");
1285       }
1286       break;
1287
1288
1289
1290     case OP_COMPOSE_PGP_MENU:
1291       if (msg->security & APPLICATION_SMIME) {
1292         if (mutt_yesorno (_("S/MIME already selected. Clear & continue ? "),
1293                           M_YES) != M_YES) {
1294           mutt_clear_error ();
1295           break;
1296         }
1297         msg->security = 0;
1298       }
1299       msg->security = crypt_pgp_send_menu (msg, &menu->redraw);
1300       redraw_crypt_lines (msg);
1301       mutt_message_hook (NULL, msg, M_SEND2HOOK);
1302       break;
1303
1304
1305     case OP_FORGET_PASSPHRASE:
1306       crypt_forget_passphrase ();
1307       break;
1308
1309
1310     case OP_COMPOSE_SMIME_MENU:
1311       if (msg->security & APPLICATION_PGP) {
1312         if (mutt_yesorno (_("PGP already selected. Clear & continue ? "),
1313                           M_YES) != M_YES) {
1314           mutt_clear_error ();
1315           break;
1316         }
1317         msg->security = 0;
1318       }
1319       msg->security = crypt_smime_send_menu (msg, &menu->redraw);
1320       redraw_crypt_lines (msg);
1321       mutt_message_hook (NULL, msg, M_SEND2HOOK);
1322       break;
1323
1324     case OP_COMPOSE_MIX:
1325       mix_make_chain (&msg->chain, &menu->redraw);
1326       mutt_message_hook (NULL, msg, M_SEND2HOOK);
1327       break;
1328     }
1329
1330     /* Draw formated compose status line */
1331     if (menu->redraw & REDRAW_STATUS) {
1332       compose_status_line (buf, sizeof (buf), menu, NONULL (ComposeFormat));
1333       CLEARLINE (option (OPTSTATUSONTOP) ? 0 : LINES - 2);
1334       SETCOLOR (MT_COLOR_STATUS);
1335       move (option (OPTSTATUSONTOP) ? 0 : LINES - 2, SW);
1336       printw ("%-*.*s", COLS-SW, COLS-SW, buf);
1337       SETCOLOR (MT_COLOR_NORMAL);
1338       menu->redraw &= ~REDRAW_STATUS;
1339     }
1340   }
1341
1342   mutt_menuDestroy (&menu);
1343
1344   if (idxlen) {
1345     msg->content = idx[0]->content;
1346     for (i = 0; i < idxlen; i++) {
1347       idx[i]->content->aptr = NULL;
1348       p_delete(&idx[i]);
1349     }
1350   }
1351   else
1352     msg->content = NULL;
1353
1354   p_delete(&idx);
1355
1356   return (r);
1357 }