Beispiel #1
0
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;
}
/* return values:
 *
 * 1	message should be postponed
 * 0	normal exit
 * -1	abort message
 */
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, oldSortAux;
  struct stat st;

  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)
	{
	  mutt_str_replace (&msg->env->subject, 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 HAVE_PGP
      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:
	{
	  char *prompt, **files;
	  int error, numfiles;

	  fname[0] = 0;
	  prompt = _("Attach file");
	  numfiles = 0;
	  files = NULL;

	  if (_mutt_enter_fname (prompt, fname, sizeof (fname), &menu->redraw, 0, 1, &files, &numfiles) == -1 ||
	      *fname == '\0')
	    break;

	  if (idxlen + numfiles >= idxmax)
	  {
	    safe_realloc ((void **) &idx, sizeof (ATTACHPTR *) * (idxmax += 5 + numfiles));
	    menu->data = idx;
	  }

	  error = 0;
	  if (numfiles > 1)
	    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 (&files);
	  if (!error) mutt_clear_error ();

	  menu->redraw |= REDRAW_INDEX | REDRAW_STATUS;
	}
	break;

      case OP_COMPOSE_ATTACH_MESSAGE:
	{
	  char *prompt;
	  HEADER *h;

	  fname[0] = 0;
	  prompt = _("Open mailbox to attach message from");

	  if (Context)
	  {
	    strfcpy (fname, NONULL (Context->path), sizeof (fname));
	    mutt_pretty_mailbox (fname);
	  }

	  if (mutt_enter_fname (prompt, fname, sizeof (fname), &menu->redraw, 1) == -1 || !fname[0])
	    break;

	  mutt_expand_path (fname, sizeof (fname));
#ifdef USE_IMAP
          if (!mx_is_imap (fname))
#endif
	  /* check to make sure the file exists and is readable */
	  if (access (fname, R_OK) == -1)
	  {
	    mutt_perror (fname);
	    break;
	  }

	  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, NULL);
	    safe_free ((void **) &ctx);
	    mutt_error _("No messages in that folder.");
	    break;
	  }

	  this = Context; /* remember current folder and sort methods*/
	  oldSort = Sort; oldSortAux = SortAux;
	  
	  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;
	  }

	  if (idxlen + Context->tagged >= idxmax)
	  {
	    safe_realloc ((void **) &idx, sizeof (ATTACHPTR *) * (idxmax += 5 + Context->tagged));
	    menu->data = idx;
	  }

	  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, NULL);
	  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;

#define CURRENT idx[menu->current]->content
      
      case OP_COMPOSE_TOGGLE_RECODE:
      {      
        CHECK_COUNT;
        if (!mutt_is_text_type (CURRENT->type, CURRENT->subtype))
        {
	  mutt_error (_("Recoding only affects text attachments."));
	  break;
	}
	if (mutt_is_utf8 (mutt_get_parameter ("charset", CURRENT->parameter)))
	{
	  mutt_error (_("We currently can't encode to utf-8."));
	  break;
	}
        CURRENT->noconv = !CURRENT->noconv;
        if (CURRENT->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_RECODE:
      {
	const char *chs;
	int rv;

        CHECK_COUNT;
        if (!mutt_is_text_type (CURRENT->type, CURRENT->subtype))
        {
	  mutt_error (_("Recoding only affects text attachments."));
	  break;
	}

	if (!(chs = mutt_get_parameter ("charset", CURRENT->parameter)))
	  chs = SendCharset;

        if (CURRENT->noconv)
	  rv = mutt_recode_file (CURRENT->filename, chs, Charset);
	else
	  rv = mutt_recode_file (CURRENT->filename, Charset, chs);

	mutt_update_encoding (CURRENT);
	
	if (rv == 0)
	{
	  mutt_message (_("Recoding successful."));
	  CURRENT->noconv = !CURRENT->noconv;
	}

	menu->redraw = REDRAW_CURRENT;
	break;
      }
#undef CURRENT

      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)
	{
	  mutt_str_replace (&idx[menu->current]->content->description, 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_TOGGLE_DISPOSITION:
	/* toggle the content-disposition between inline/attachment */
	idx[menu->current]->content->disposition = (idx[menu->current]->content->disposition == DISPINLINE) ? DISPATTACH : DISPINLINE;
	menu->redraw = REDRAW_CURRENT;
	break;

      case OP_EDIT_TYPE:
	CHECK_COUNT;
        {
	  mutt_edit_content_type (NULL, idx[menu->current]->content);

	  /* this may have been a change to text/something */
	  mutt_update_encoding (idx[menu->current]->content);

	  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;
	  
	  mutt_str_replace (&idx[menu->current]->content->filename, 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;
	  mutt_str_replace (&idx[menu->current]->content->subtype, 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, NULL, idx, idxlen);
	menu->redraw = REDRAW_FULL;
	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);
	if (mutt_system (buf) == -1)
	  mutt_error (_("Error running \"%s\"!"), buf);
	else
	  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])
       {
         mutt_message (_("Writing message to %s ..."), fname);
         mutt_expand_path (fname, sizeof (fname));

         if (msg->content->next)
           msg->content = mutt_make_multipart (msg->content);

         if (mutt_write_fcc (NONULL (fname), msg, NULL, 1, NULL) < 0)
           msg->content = mutt_remove_multipart (msg->content);
         else
           mutt_message _("Message written.");
       }
       break;



#ifdef HAVE_PGP
      case OP_COMPOSE_PGP_MENU:

	msg->pgp = pgp_send_menu (msg->pgp, &menu->redraw);
	break;

      case OP_FORGET_PASSPHRASE:

	mutt_forget_passphrase ();
	break;

#endif /* HAVE_PGP */


#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);
}
Beispiel #3
0
void mix_make_chain (LIST **chainp, int *redraw)
{
  LIST *p;
  MIXCHAIN *chain;
  int c_cur = 0, c_old = 0;
  short c_redraw = 1;
  
  REMAILER **type2_list = NULL;
  size_t ttll = 0;
  
  struct coord *coords = NULL;
  
  MUTTMENU *menu;
  char helpstr[LONG_STRING];
  short loop = 1;
  int op;
  
  int i, j;
  char *t;

  if (!(type2_list = mix_type2_list (&ttll)))
  {
    mutt_error _("Can't get mixmaster's type2.list!");
    return;
  }

  *redraw = REDRAW_FULL;
  
  chain = safe_calloc (sizeof (MIXCHAIN), 1);
  for (p = *chainp; p; p = p->next)
    mix_chain_add (chain, (char *) p->data, type2_list);

  mutt_free_list (chainp);
  
  /* safety check */
  for (i = 0; i < chain->cl; i++)
  {
    if (chain->ch[i] >= ttll)
      chain->ch[i] = 0;
  }
  
  mix_screen_coordinates (type2_list, &coords, chain, 0);
  
  menu = mutt_new_menu (MENU_MIX);
  menu->max = ttll;
  menu->make_entry = mix_entry;
  menu->tag = NULL;
  menu->title = _("Select a remailer chain.");
  menu->data = type2_list;
  menu->help = mutt_compile_help (helpstr, sizeof (helpstr), MENU_MIX, RemailerHelp);
  menu->pagelen = MIX_VOFFSET - 1;
  
  while (loop) 
  {
    if (menu->pagelen != MIX_VOFFSET - 1)
    {
      menu->pagelen = MIX_VOFFSET - 1;
      menu->redraw = REDRAW_FULL;
    }
    
    if (c_redraw)
    {
      mix_redraw_head (chain);
      mix_redraw_chain (type2_list, coords, chain, c_cur);
      c_redraw = 0;
    }
    else if (c_cur != c_old)
    {
      mix_redraw_ce (type2_list, coords, chain, c_old, 0);
      mix_redraw_ce (type2_list, coords, chain, c_cur, 1);
    }
    
    c_old = c_cur;
    
    switch ((op = mutt_menuLoop (menu)))
    {
      case OP_REDRAW:
      {
	menu_redraw_status (menu);
	mix_redraw_head (chain);
	mix_screen_coordinates (type2_list, &coords, chain, 0);
	mix_redraw_chain (type2_list, coords, chain, c_cur);
	menu->pagelen = MIX_VOFFSET - 1;
	break;
      }
      
      case OP_EXIT:
      {
	chain->cl = 0;
	loop = 0;
	break;
      }

      case OP_MIX_USE:
      {
	if (!chain->cl)
	{
	  chain->cl++;
	  chain->ch[0] = menu->current;
	  mix_screen_coordinates (type2_list, &coords, chain, c_cur);
	  c_redraw = 1;
	}
	
	if (chain->cl && chain->ch[chain->cl - 1] && 
	    (type2_list[chain->ch[chain->cl-1]]->caps & MIX_CAP_MIDDLEMAN))
	{
	  mutt_error ( _("Error: %s can't be used as the final remailer of a chain."),
		    type2_list[chain->ch[chain->cl - 1]]->shortname);
	}
	else
	{
	  loop = 0;
	}
	break;
      }

      case OP_GENERIC_SELECT_ENTRY:
      case OP_MIX_APPEND:
      {
	if (chain->cl < MAXMIXES && c_cur < chain->cl)
	  c_cur++;
      }
      /* fallthrough */
      case OP_MIX_INSERT:
      {
	if (chain->cl < MAXMIXES)
	{
	  chain->cl++;
	  for (i = chain->cl - 1; i > c_cur; i--)
	    chain->ch[i] = chain->ch[i-1];
	  
	  chain->ch[c_cur] = menu->current;
	  mix_screen_coordinates (type2_list, &coords, chain, c_cur);
	  c_redraw = 1;
	}
	else
	  mutt_error ( _("Mixmaster chains are limited to %d elements."),
		    MAXMIXES);
	
	break;
      }
      
      case OP_MIX_DELETE:
      {
	if (chain->cl)
	{
	  chain->cl--;
	  
	  for (i = c_cur; i < chain->cl; i++)
	    chain->ch[i] = chain->ch[i+1];

	  if (c_cur == chain->cl && c_cur)
	    c_cur--;
	  
	  mix_screen_coordinates (type2_list, &coords, chain, c_cur);
	  c_redraw = 1;
	}
	else
	{
	  mutt_error _("The remailer chain is already empty.");
	}
	break;
      }
      
      case OP_MIX_CHAIN_PREV:
      {
	if (c_cur) 
	  c_cur--;
	else
	  mutt_error _("You already have the first chain element selected.");
	
	break;
      }
      
      case OP_MIX_CHAIN_NEXT:
      {
	if (chain->cl && c_cur < chain->cl - 1)
	  c_cur++;
	else
	  mutt_error _("You already have the last chain element selected.");
	
	break;
      }
    }
  }
  
  mutt_menuDestroy (&menu);

  /* construct the remailer list */
  
  if (chain->cl)
  {
    for (i = 0; i < chain->cl; i++)
    {
      if ((j = chain->ch[i]))
	t = type2_list[j]->shortname;
      else
	t = "*";
      
      *chainp = mutt_add_list (*chainp, t);
    }
  }
  
  mix_free_type2_list (&type2_list);
  FREE (&coords);
  FREE (&chain);
}