mutt_error (_("Recoding only affects text/plain attachments."));
mutt_error (_("Recoding only affects text attachments."));
int mutt_compose_menu (HEADER *msg,   /* structure for new message */		    char *fcc,     /* where to save a copy of the message */		    size_t fcclen,		    HEADER *cur)   /* current message */{  char helpstr[SHORT_STRING];  char buf[LONG_STRING];  char fname[_POSIX_PATH_MAX];  MUTTMENU *menu;  ATTACHPTR **idx = NULL;  short idxlen = 0;  short idxmax = 0;  int i, close = 0;  int r = -1;		/* return value */  int op = 0;  int loop = 1;  int fccSet = 0;	/* has the user edited the Fcc: field ? */  CONTEXT *ctx = NULL, *this = NULL;  /* Sort, SortAux could be changed in mutt_index_menu() */  int oldSort = Sort, oldSortAux = SortAux;  struct stat st;  char **files;  int numfiles;  idx = mutt_gen_attach_list (msg->content, -1, idx, &idxlen, &idxmax, 0, 1);  menu = mutt_new_menu ();  menu->menu = MENU_COMPOSE;  menu->offset = HDR_ATTACH;  menu->max = idxlen;  menu->make_entry = snd_entry;  menu->tag = mutt_tag_attach;  menu->title = _("Compose");  menu->data = idx;  menu->help = mutt_compile_help (helpstr, sizeof (helpstr), MENU_COMPOSE, ComposeHelp);    while (loop)  {    switch (op = mutt_menuLoop (menu))    {      case OP_REDRAW:	menu_redraw_status (menu);	draw_envelope (msg, fcc);	menu->offset = HDR_ATTACH;	menu->pagelen = LINES - HDR_ATTACH - 2;	break;      case OP_COMPOSE_EDIT_FROM:	menu->redraw = edit_address_list (HDR_FROM, &msg->env->from);	break;      case OP_COMPOSE_EDIT_TO:	menu->redraw = edit_address_list (HDR_TO, &msg->env->to);	break;      case OP_COMPOSE_EDIT_BCC:	menu->redraw = edit_address_list (HDR_BCC, &msg->env->bcc);	break;      case OP_COMPOSE_EDIT_CC:	menu->redraw = edit_address_list (HDR_CC, &msg->env->cc);	break;      case OP_COMPOSE_EDIT_SUBJECT:	if (msg->env->subject)	  strfcpy (buf, msg->env->subject, sizeof (buf));	else	  buf[0] = 0;	if (mutt_get_field ("Subject: ", buf, sizeof (buf), 0) == 0)	{	  safe_free ((void **) &msg->env->subject);	  msg->env->subject = safe_strdup (buf);	  move (HDR_SUBJECT, HDR_XOFFSET);	  clrtoeol ();	  if (msg->env->subject)	    printw ("%-*.*s", W, W, msg->env->subject);	}	break;      case OP_COMPOSE_EDIT_REPLY_TO:	menu->redraw = edit_address_list (HDR_REPLYTO, &msg->env->reply_to);	break;      case OP_COMPOSE_EDIT_FCC:	strfcpy (buf, fcc, sizeof (buf));	if (mutt_get_field ("Fcc: ", buf, sizeof (buf), M_FILE | M_CLEAR) == 0)	{	  strfcpy (fcc, buf, _POSIX_PATH_MAX);	  mutt_pretty_mailbox (fcc);	  mvprintw (HDR_FCC, HDR_XOFFSET, "%-*.*s", W, W, fcc);	  fccSet = 1;	}	MAYBE_REDRAW (menu->redraw);	break;      case OP_COMPOSE_EDIT_MESSAGE:	if (Editor && (mutt_strcmp ("builtin", Editor) != 0) && !option (OPTEDITHDRS))	{	  mutt_edit_file (Editor, msg->content->filename);	  mutt_update_encoding (msg->content);	  menu->redraw = REDRAW_CURRENT;	  break;	}	/* fall through */      case OP_COMPOSE_EDIT_HEADERS:	if (op == OP_COMPOSE_EDIT_HEADERS ||	    (op == OP_COMPOSE_EDIT_MESSAGE && option (OPTEDITHDRS)))	{	  mutt_edit_headers ((!Editor || mutt_strcmp ("builtin", Editor) == 0) ? NONULL(Visual) : NONULL(Editor),			     msg->content->filename, msg, fcc, fcclen);	}	else	{	  /* this is grouped with OP_COMPOSE_EDIT_HEADERS because the	     attachment list could change if the user invokes ~v to edit	     the message with headers, in which we need to execute the	     code below to regenerate the index array */	  mutt_builtin_editor (msg->content->filename, msg, cur);	}	mutt_update_encoding (msg->content);	/* attachments may have been added */	if (idxlen && idx[idxlen - 1]->content->next)	{	  for (i = 0; i < idxlen; i++)	    safe_free ((void **) &idx[i]);	  idxlen = 0;	  idx = mutt_gen_attach_list (msg->content, -1, idx, &idxlen, &idxmax, 0, 1);	  menu->data = idx;	  menu->max = idxlen;	}	menu->redraw = REDRAW_FULL;	break;#ifdef _PGPPATH      case OP_COMPOSE_ATTACH_KEY:	if (idxlen == idxmax)        {	  safe_realloc ((void **) &idx, sizeof (ATTACHPTR *) * (idxmax += 5));	  menu->data = idx;	}		idx[idxlen] = (ATTACHPTR *) safe_calloc (1, sizeof (ATTACHPTR));	if ((idx[idxlen]->content = 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;	  menu->redraw |= REDRAW_INDEX;	}	else	  safe_free ((void **) &idx[idxlen]);	menu->redraw |= REDRAW_STATUS;	if(option(OPTNEEDREDRAW))	{	  menu->redraw = REDRAW_FULL;	  unset_option(OPTNEEDREDRAW);	}		break;#endif      case OP_COMPOSE_ATTACH_FILE:      case OP_COMPOSE_ATTACH_MESSAGE:	fname[0] = 0;	{	  char* prompt;	  int flag;	  if (op == OP_COMPOSE_ATTACH_FILE)	  {	    prompt = _("Attach file");	    flag = 0;	    numfiles = 0;	    files = NULL;	    if (_mutt_enter_fname (prompt, fname, sizeof (fname), &menu->redraw, flag, 1, &files, &numfiles) == -1)	      break;	  }	  else	  {	    prompt = _("Open mailbox to attach message from");	    if (Context)	    {	      strfcpy (fname, NONULL (Context->path), sizeof (fname));	      mutt_pretty_mailbox (fname);	    }	    flag = 1;	    if (mutt_enter_fname (prompt, fname, sizeof (fname), &menu->redraw, flag) == -1 || !fname[0])	      break;	    mutt_expand_path (fname, sizeof (fname));	    /* check to make sure the file exists and is readable */	    if (access (fname, R_OK) == -1)	    {	      mutt_perror (fname);	      break;	    }	  }	}	if (op == OP_COMPOSE_ATTACH_MESSAGE)	{	  menu->redraw = REDRAW_FULL;	  ctx = mx_open_mailbox (fname, M_READONLY, NULL);	  if (ctx == NULL)	  {	    mutt_perror (fname);	    break;	  }	  if (!ctx->msgcount)	  {	    mx_close_mailbox (ctx);	    safe_free ((void **) &ctx);	    mutt_error _("No messages in that folder.");	    break;	  }	  	  this = Context; /* remember current folder */	  Context = ctx;	  set_option(OPTATTACHMSG);	  mutt_message _("Tag the messages you want to attach!");	  close = mutt_index_menu ();	  unset_option(OPTATTACHMSG);	  if (!Context)	  {	    /* go back to the folder we started from */	    Context = this;	    /* Restore old $sort and $sort_aux */	    Sort = oldSort;	    SortAux = oldSortAux;	    menu->redraw |= REDRAW_INDEX | REDRAW_STATUS;	    break;	  }	}        {	  int numtag = 0;	  if (op == OP_COMPOSE_ATTACH_MESSAGE)	    numtag = Context->tagged;	  else	    numtag = numfiles;	  if (idxlen + numtag >= idxmax)	  {	    safe_realloc ((void **) &idx, sizeof (ATTACHPTR *) * (idxmax += 5 + numtag));	    menu->data = idx;	  }	}	if (op == OP_COMPOSE_ATTACH_FILE)	{	  int error = 0;	  mutt_message _("Attaching selected files...");	  for (i = 0; i < numfiles; i++)	  {	    char *att = files[i];	    idx[idxlen] = (ATTACHPTR *) safe_calloc (1, sizeof (ATTACHPTR));	    idx[idxlen]->content = mutt_make_file_attach (att);	    if (idx[idxlen]->content != NULL)	      update_idx (menu, idx, idxlen++);	    else	    {	      error = 1;	      mutt_error (_("Unable to attach %s!"), att);	      safe_free ((void **) &idx[idxlen]);	    }	    FREE (&this);	  }	  FREE (&files);	  if (!error)	    mutt_clear_error ();	  menu->redraw |= REDRAW_INDEX | REDRAW_STATUS;        }	else	{	  HEADER *h;	  for (i = 0; i < Context->msgcount; i++)	  {	    h = Context->hdrs[i];	    if (h->tagged)	    {	      idx[idxlen] = (ATTACHPTR *) safe_calloc (1, sizeof (ATTACHPTR));	      idx[idxlen]->content = mutt_make_message_attach (Context, h, 1);	      if (idx[idxlen]->content != NULL)		update_idx (menu, idx, idxlen++);	      else	      {		mutt_error _("Unable to attach!");		safe_free ((void **) &idx[idxlen]);	      }	    }	  }	  menu->redraw |= REDRAW_FULL;	  if (close == OP_QUIT) 	    mx_close_mailbox (Context);	  else	    mx_fastclose_mailbox (Context);	  safe_free ((void **) &Context);	  /* go back to the folder we started from */	  Context = this;	  /* Restore old $sort and $sort_aux */	  Sort = oldSort;	  SortAux = oldSortAux;	}	break;      case OP_DELETE:	CHECK_COUNT;	if (delete_attachment (menu, &idxlen, menu->current) == -1)	  break;	mutt_update_tree (idx, idxlen);	if (idxlen)	{	  if (menu->current > idxlen - 1)	    menu->current = idxlen - 1;	}	else	  menu->current = 0;	if (menu->current == 0)	  msg->content = idx[0]->content;	break;      case OP_COMPOSE_CHANGE_CHARSET:        CHECK_COUNT;        menu->redraw = change_attachment_charset(idx[menu->current]->content);        break;      case OP_COMPOSE_NORECODE:        CHECK_COUNT;        if (idx[menu->current]->content->type != TYPETEXT)        {	  mutt_error (_("Recoding only affects text/plain attachments."));	  break;	}        idx[menu->current]->content->noconv = !idx[menu->current]->content->noconv;        if (idx[menu->current]->content->noconv)	  mutt_message (_("The current attachment won't be converted."));        else	  mutt_message (_("The current attachment will be converted."));	menu->redraw = REDRAW_CURRENT;        break;            case OP_COMPOSE_EDIT_DESCRIPTION:	CHECK_COUNT;	strfcpy (buf,		 idx[menu->current]->content->description ?		 idx[menu->current]->content->description : "",		 sizeof (buf));	/* header names should not be translated */	if (mutt_get_field ("Description: ", buf, sizeof (buf), 0) == 0)	{	  safe_free ((void **) &idx[menu->current]->content->description);	  idx[menu->current]->content->description = safe_strdup (buf);	  menu->redraw = REDRAW_CURRENT;	}	break;      case OP_COMPOSE_UPDATE_ENCODING:        CHECK_COUNT;        if(menu->tagprefix)        {	  BODY *top;	  for(top = msg->content; top; top = top->next)	  {	    if(top->tagged)	      mutt_update_encoding(top);	  }	  menu->redraw = REDRAW_FULL;	}        else        {          mutt_update_encoding(idx[menu->current]->content);	  menu->redraw = REDRAW_CURRENT;	}        break;            case OP_COMPOSE_EDIT_TYPE:	CHECK_COUNT;	snprintf (buf, sizeof (buf), "%s/%s",		  TYPE (idx[menu->current]->content),		  idx[menu->current]->content->subtype);	if (mutt_get_field ("Content-Type: ", buf, sizeof (buf), 0) == 0 && buf[0])	{	  char *s;	  PARAMETER *par;	  BODY *b;	  	  b = idx[menu->current]->content;	  	  s  = b->filename;  par = b->parameter;	  b->filename  = NULL;  b->parameter = NULL;	  	  mutt_parse_content_type (buf, b);	  safe_free ((void **) &b->filename);	  b->filename = s;	  	  if ((s = mutt_get_parameter("charset", b->parameter)))	    mutt_set_parameter("charset", s, &par);	  	  /* These are needed for "traditional" PGP.	   * Should we switch to a "negative list" instead?	   */	  if ((s = mutt_get_parameter("x-action", b->parameter)))	    mutt_set_parameter("x-action", s, &par);	  if ((s = mutt_get_parameter("format", b->parameter)))	    mutt_set_parameter("format", s, &par);	  /* ignore the other parameters for now */	  mutt_free_parameter(&b->parameter);	  b->parameter = par;	  /* this may have been a "structured" message */	  if  (b->parts)	    mutt_free_body (&b->parts);	  if (b->hdr)	  {	    b->hdr->content = NULL;	    mutt_free_header (&b->hdr);	  }	  	  menu->redraw = REDRAW_CURRENT;	}	break;      case OP_COMPOSE_EDIT_ENCODING:	CHECK_COUNT;	strfcpy (buf, ENCODING (idx[menu->current]->content->encoding),							      sizeof (buf));	if (mutt_get_field ("Content-Transfer-Encoding: ", buf,					    sizeof (buf), 0) == 0 && buf[0])	{	  if ((i = mutt_check_encoding (buf)) != ENCOTHER && i != ENCUUENCODED)	  {	    idx[menu->current]->content->encoding = i;	    menu->redraw = REDRAW_CURRENT;	    mutt_clear_error();	  }	  else	    mutt_error _("Invalid encoding.");	}	break;      case OP_COMPOSE_SEND_MESSAGE:              if(check_attachments(idx, idxlen) != 0)        {	  menu->redraw = REDRAW_FULL;	  break;	}      #ifdef MIXMASTER        if (msg->chain && mix_check_message (msg) != 0)	  break;#endif      	if (!fccSet && *fcc)	{	  if ((i = query_quadoption (OPT_COPY,				_("Save a copy of this message?"))) == -1)	    break;	  else if (i == M_NO)	    *fcc = 0;	}	loop = 0;	r = 0;	break;      case OP_COMPOSE_EDIT_FILE:	CHECK_COUNT;	mutt_edit_file ((!Editor || mutt_strcmp ("builtin", Editor) == 0) ? NONULL(Visual) : NONULL(Editor),			idx[menu->current]->content->filename);	mutt_update_encoding (idx[menu->current]->content);	menu->redraw = REDRAW_CURRENT;	break;      case OP_COMPOSE_TOGGLE_UNLINK:	CHECK_COUNT;	idx[menu->current]->content->unlink = !idx[menu->current]->content->unlink;#if 0        /* OPTRESOLVE is otherwise ignored on this menu.	 * Where's the bug?	 */        if (option (OPTRESOLVE) && menu->current + 1 < menu->max)	  menu->current++;# endif	menu->redraw = REDRAW_INDEX;	break;      case OP_COMPOSE_GET_ATTACHMENT:        CHECK_COUNT;        if(menu->tagprefix)        {	  BODY *top;	  for(top = msg->content; top; top = top->next)	  {	    if(top->tagged)	      mutt_get_tmp_attachment(top);	  }	  menu->redraw = REDRAW_FULL;	}        else if (mutt_get_tmp_attachment(idx[menu->current]->content) == 0)	  menu->redraw = REDRAW_CURRENT;        break;            case OP_COMPOSE_RENAME_FILE:	CHECK_COUNT;	strfcpy (fname, idx[menu->current]->content->filename, sizeof (fname));	mutt_pretty_mailbox (fname);	if (mutt_get_field (_("Rename to: "), fname, sizeof (fname), M_FILE)							== 0 && fname[0])	{	  if(stat(idx[menu->current]->content->filename, &st) == -1)	  {	    mutt_error (_("Can't stat: %s"), fname);	    break;	  }	  mutt_expand_path (fname, sizeof (fname));	  if(mutt_rename_file (idx[menu->current]->content->filename, fname))	    break;	  	  safe_free ((void **) &idx[menu->current]->content->filename);	  idx[menu->current]->content->filename = safe_strdup (fname);	  menu->redraw = REDRAW_CURRENT;	  if(idx[menu->current]->content->stamp >= st.st_mtime)	    mutt_stamp_attachment(idx[menu->current]->content);	  	}	break;      case OP_COMPOSE_NEW_MIME:	{	  char type[STRING];	  char *p;	  int itype;	  FILE *fp;	  CLEARLINE (LINES-1);	  fname[0] = 0;	  if (mutt_get_field (_("New file: "), fname, sizeof (fname), M_FILE)	      != 0 || !fname[0])	    continue;	  mutt_expand_path (fname, sizeof (fname));	  /* Call to lookup_mime_type () ?  maybe later */	  type[0] = 0;	  if (mutt_get_field ("Content-Type: ", type, sizeof (type), 0) != 0 	      || !type[0])	    continue;	  if (!(p = strchr (type, '/')))	  {	    mutt_error _("Content-Type is of the form base/sub");	    continue;	  }	  *p++ = 0;	  if ((itype = mutt_check_mime_type (type)) == TYPEOTHER)	  {	    mutt_error (_("Unknown Content-Type %s"), type);	    continue;	  }	  if (idxlen == idxmax)	  {	    safe_realloc ((void **) &idx, sizeof (ATTACHPTR *) * (idxmax += 5));	    menu->data = idx;	  }	  idx[idxlen] = (ATTACHPTR *) safe_calloc (1, sizeof (ATTACHPTR));	  /* Touch the file */	  if (!(fp = safe_fopen (fname, "w")))	  {	    mutt_error (_("Can't create file %s"), fname);	    safe_free ((void **) &idx[idxlen]);	    continue;	  }	  fclose (fp);	  if ((idx[idxlen]->content = mutt_make_file_attach (fname)) == NULL)	  {	    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;	  idx[menu->current]->content->type = itype;	  safe_free ((void **) &idx[menu->current]->content->subtype);	  idx[menu->current]->content->subtype = safe_strdup (p);	  idx[menu->current]->content->unlink = 1;	  menu->redraw |= REDRAW_INDEX | REDRAW_STATUS;	  if (mutt_compose_attachment (idx[menu->current]->content))	  {	    mutt_update_encoding (idx[menu->current]->content);	    menu->redraw = REDRAW_FULL;	  }	}	break;      case OP_COMPOSE_EDIT_MIME:	CHECK_COUNT;	if (mutt_edit_attachment (idx[menu->current]->content))	{	  mutt_update_encoding (idx[menu->current]->content);	  menu->redraw = REDRAW_FULL;	}	break;      case OP_VIEW_ATTACH:      case OP_DISPLAY_HEADERS:	CHECK_COUNT;	mutt_attach_display_loop (menu, op, NULL, idx);	menu->redraw = REDRAW_FULL;	mutt_clear_error ();	break;      case OP_SAVE:	CHECK_COUNT;	mutt_save_attachment_list (NULL, menu->tagprefix, menu->tagprefix ?  msg->content : idx[menu->current]->content, NULL);	MAYBE_REDRAW (menu->redraw);	break;      case OP_PRINT:	CHECK_COUNT;	mutt_print_attachment_list (NULL, menu->tagprefix, menu->tagprefix ? msg->content : idx[menu->current]->content);	break;      case OP_PIPE:      case OP_FILTER:        CHECK_COUNT;	mutt_pipe_attachment_list (NULL, menu->tagprefix, menu->tagprefix ? msg->content : idx[menu->current]->content, op == OP_FILTER);	if (op == OP_FILTER) /* cte might have changed */	  menu->redraw = menu->tagprefix ? REDRAW_FULL : REDRAW_CURRENT; 	break;      case OP_EXIT:	if ((i = query_quadoption (OPT_POSTPONE, _("Postpone this message?"))) == M_NO)	{	  while (idxlen-- > 0)	  {	    /* avoid freeing other attachments */	    idx[idxlen]->content->next = NULL;	    idx[idxlen]->content->parts = NULL;	    mutt_free_body (&idx[idxlen]->content);	    safe_free ((void **) &idx[idxlen]->tree);	    safe_free ((void **) &idx[idxlen]);	  }	  safe_free ((void **) &idx);	  idxlen = 0;	  idxmax = 0;	  r = -1;	  loop = 0;	  break;	}	else if (i == -1)	  break; /* abort */	/* fall through to postpone! */      case OP_COMPOSE_POSTPONE_MESSAGE:        if(check_attachments(idx, idxlen) != 0)        {	  menu->redraw = REDRAW_FULL;	  break;	}      	loop = 0;	r = 1;	break;      case OP_COMPOSE_ISPELL:	endwin ();	snprintf (buf, sizeof (buf), "%s -x %s", NONULL(Ispell), msg->content->filename);	mutt_system (buf);        mutt_update_encoding(msg->content);	break;      case OP_COMPOSE_WRITE_MESSAGE:       fname[0] = '\0';       if (Context)       {	 strfcpy (fname, NONULL (Context->path), sizeof (fname));	 mutt_pretty_mailbox (fname);       }       if (idxlen)         msg->content = idx[0]->content;       if (mutt_enter_fname (_("Write message to mailbox"), fname, sizeof (fname),                             &menu->redraw, 1) != -1 && fname[0])       {	 int oldhdrdate;         mutt_message (_("Writing message to %s ..."), fname);         mutt_expand_path (fname, sizeof (fname));         if (msg->content->next)           msg->content = mutt_make_multipart (msg->content);	 oldhdrdate = option(OPTUSEHEADERDATE);	 set_option(OPTUSEHEADERDATE);         if (mutt_write_fcc (NONULL (fname), msg, NULL, 1, NULL) < 0)           msg->content = mutt_remove_multipart (msg->content);         else           mutt_message _("Message written.");	 if(!oldhdrdate) unset_option(OPTUSEHEADERDATE);       }       break;#ifdef _PGPPATH      case OP_COMPOSE_PGP_MENU:	msg->pgp = pgp_send_menu (msg->pgp, &menu->redraw);	break;      case OP_FORGET_PASSPHRASE:	mutt_forget_passphrase ();	break;#endif /* _PGPPATH */#ifdef MIXMASTER      case OP_COMPOSE_MIX:            	mix_make_chain (&msg->chain, &menu->redraw);        break;#endif    }  }  mutt_menuDestroy (&menu);  if (idxlen)  {    msg->content = idx[0]->content;    for (i = 0; i < idxlen; i++)      safe_free ((void **) &idx[i]);  }  else    msg->content = NULL;  safe_free ((void **) &idx);  return (r);}