NeoMutt  2018-07-16 +1360-3df4a2
Teaching an old dog new tricks
DOXYGEN
compose.c File Reference

GUI editor for an email's headers. More...

#include "config.h"
#include <errno.h>
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "mutt/mutt.h"
#include "config/lib.h"
#include "email/lib.h"
#include "conn/conn.h"
#include "mutt.h"
#include "compose.h"
#include "alias.h"
#include "browser.h"
#include "commands.h"
#include "context.h"
#include "curs_lib.h"
#include "edit.h"
#include "format_flags.h"
#include "globals.h"
#include "hook.h"
#include "index.h"
#include "keymap.h"
#include "mailbox.h"
#include "mutt_attach.h"
#include "mutt_curses.h"
#include "mutt_header.h"
#include "mutt_logging.h"
#include "mutt_menu.h"
#include "mutt_window.h"
#include "muttlib.h"
#include "mx.h"
#include "ncrypt/ncrypt.h"
#include "opcodes.h"
#include "options.h"
#include "protos.h"
#include "recvattach.h"
#include "sendlib.h"
#include "sort.h"
#include <libintl.h>
#include "nntp/nntp.h"
#include "pop/pop.h"
#include "imap/imap.h"
+ Include dependency graph for compose.c:

Go to the source code of this file.

Data Structures

struct  ComposeRedrawData
 Keep track when the compose screen needs redrawing. More...
 

Macros

#define CHECK_COUNT
 
#define CURATTACH   actx->idx[actx->v2r[menu->current]]
 
#define HDR_XOFFSET   MaxHeaderWidth
 
#define W   (MuttIndexWindow->cols - MaxHeaderWidth)
 
#define ALTS_TAG   "Alternatives for \"%s\""
 
#define LINGUAL_TAG   "Multilingual part for \"%s\""
 

Enumerations

enum  HeaderField {
  HDR_FROM = 0, HDR_TO, HDR_CC, HDR_BCC,
  HDR_SUBJECT, HDR_REPLYTO, HDR_FCC, HDR_CRYPT,
  HDR_CRYPTINFO, HDR_NEWSGROUPS, HDR_FOLLOWUPTO, HDR_XCOMMENTTO,
  HDR_ATTACH = (HDR_FCC + 5)
}
 Ordered list of headers for the compose screen. More...
 

Functions

static void calc_header_width_padding (int idx, const char *header, bool calc_max)
 Calculate the width needed for the compose labels. More...
 
static void init_header_padding (void)
 Calculate how much padding the compose table will need. More...
 
static void snd_make_entry (char *buf, size_t buflen, struct Menu *menu, int line)
 Format a menu item for the attachment list - Implements Menu::menu_make_entry() More...
 
static void redraw_crypt_lines (struct Email *msg)
 Update the encryption info in the compose window. More...
 
static int check_attachments (struct AttachCtx *actx)
 Check if any attachments have changed or been deleted. More...
 
static void draw_envelope_addr (int line, struct Address *addr)
 Write addresses to the compose window. More...
 
static void draw_envelope (struct Email *msg, char *fcc)
 Write the email headers to the compose window. More...
 
static void edit_address_list (int line, struct Address **addr)
 Let the user edit the address list. More...
 
static int delete_attachment (struct AttachCtx *actx, int x)
 Delete an attachment. More...
 
static void mutt_gen_compose_attach_list (struct AttachCtx *actx, struct Body *m, int parent_type, int level)
 Generate the attachment list for the compose screen. More...
 
static void mutt_update_compose_menu (struct AttachCtx *actx, struct Menu *menu, bool init)
 Redraw the compose window. More...
 
static void update_idx (struct Menu *menu, struct AttachCtx *actx, struct AttachPtr *new)
 Add a new attchment to the message. More...
 
static void compose_status_line (char *buf, size_t buflen, size_t col, int cols, struct Menu *menu, const char *src)
 Compose the string for the status bar. More...
 
static void compose_custom_redraw (struct Menu *menu)
 Redraw the compose menu - Implements Menu::menu_custom_redraw() More...
 
static void compose_attach_swap (struct Body *msg, struct AttachPtr **idx, short first)
 Swap two adjacent entries in the attachment list. More...
 
static unsigned long cum_attachs_size (struct Menu *menu)
 Cumulative Attachments Size. More...
 
static const char * compose_format_str (char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, unsigned long data, MuttFormatFlags flags)
 Create the status bar string for compose mode - Implements format_t. More...
 
int mutt_compose_menu (struct Email *msg, char *fcc, size_t fcclen, struct Email *cur, int flags)
 Allow the user to edit the message envelope. More...
 

Variables

char * C_ComposeFormat
 Config: printf-like format string for the Compose panel's status bar. More...
 
char * C_Ispell
 Config: External command to perform spell-checking. More...
 
unsigned char C_Postpone
 Config: Save messages to the C_Postponed folder. More...
 
static const char * There_are_no_attachments = N_("There are no attachments")
 
int HeaderPadding [HDR_XCOMMENTTO+1] = { 0 }
 
int MaxHeaderWidth = 0
 
static const char *const Prompts []
 
static const struct Mapping ComposeHelp []
 
static struct Mapping ComposeNewsHelp []
 

Detailed Description

GUI editor for an email's headers.

Authors
  • Michael R. Elkins
  • g10 Code GmbH

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file compose.c.

Macro Definition Documentation

#define CHECK_COUNT
Value:
if (actx->idxlen == 0) \
{ \
break; \
}
static const char * There_are_no_attachments
Definition: compose.c:92
#define _(a)
Definition: message.h:28
#define mutt_error(...)
Definition: logging.h:88

Definition at line 94 of file compose.c.

#define CURATTACH   actx->idx[actx->v2r[menu->current]]

Definition at line 101 of file compose.c.

#define HDR_XOFFSET   MaxHeaderWidth

Definition at line 133 of file compose.c.

#define W   (MuttIndexWindow->cols - MaxHeaderWidth)

Definition at line 134 of file compose.c.

#define ALTS_TAG   "Alternatives for \"%s\""
#define LINGUAL_TAG   "Multilingual part for \"%s\""

Enumeration Type Documentation

Ordered list of headers for the compose screen.

The position of various fields on the compose screen.

Enumerator
HDR_FROM 

"From:" field

HDR_TO 

"To:" field

HDR_CC 

"Cc:" field

HDR_BCC 

"Bcc:" field

HDR_SUBJECT 

"Subject:" field

HDR_REPLYTO 

"Reply-To:" field

HDR_FCC 

"Fcc:" (save folder) field

HDR_CRYPT 

"Security:" field (encryption/signing info)

HDR_CRYPTINFO 

"Sign as:" field (encryption/signing info)

HDR_NEWSGROUPS 

"Newsgroups:" field

HDR_FOLLOWUPTO 

"Followup-To:" field

HDR_XCOMMENTTO 

"X-Comment-To:" field

HDR_ATTACH 

Position to start printing the attachments.

Definition at line 108 of file compose.c.

109 {
110  HDR_FROM = 0,
111  HDR_TO,
112  HDR_CC,
113  HDR_BCC,
114  HDR_SUBJECT,
115  HDR_REPLYTO,
116  HDR_FCC,
117 #ifdef MIXMASTER
118  HDR_MIX,
119 #endif
120  HDR_CRYPT,
121  HDR_CRYPTINFO,
122 #ifdef USE_NNTP
126 #endif
127  HDR_ATTACH = (HDR_FCC + 5),
128 };
"To:" field
Definition: compose.c:111
"Cc:" field
Definition: compose.c:112
"Subject:" field
Definition: compose.c:114
"Sign as:" field (encryption/signing info)
Definition: compose.c:121
"From:" field
Definition: compose.c:110
"X-Comment-To:" field
Definition: compose.c:125
"Security:" field (encryption/signing info)
Definition: compose.c:120
"Bcc:" field
Definition: compose.c:113
"Followup-To:" field
Definition: compose.c:124
Position to start printing the attachments.
Definition: compose.c:127
"Newsgroups:" field
Definition: compose.c:123
"Fcc:" (save folder) field
Definition: compose.c:116
"Reply-To:" field
Definition: compose.c:115

Function Documentation

static void calc_header_width_padding ( int  idx,
const char *  header,
bool  calc_max 
)
static

Calculate the width needed for the compose labels.

Parameters
idxStore the result at this index of HeaderPadding
headerHeader string
calc_maxIf true, calculate the maximum width

Definition at line 209 of file compose.c.

210 {
211  int width;
212 
213  HeaderPadding[idx] = mutt_str_strlen(header);
214  width = mutt_strwidth(header);
215  if (calc_max && (MaxHeaderWidth < width))
216  MaxHeaderWidth = width;
217  HeaderPadding[idx] -= width;
218 }
int MaxHeaderWidth
Definition: compose.c:131
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:662
int mutt_strwidth(const char *s)
Measure a string&#39;s width in screen cells.
Definition: curs_lib.c:1176
int HeaderPadding[HDR_XCOMMENTTO+1]
Definition: compose.c:130

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void init_header_padding ( void  )
static

Calculate how much padding the compose table will need.

The padding needed for each header is strlen() + max_width - strwidth().

calc_header_width_padding sets each entry in HeaderPadding to strlen - width. Then, afterwards, we go through and add max_width to each entry.

Definition at line 228 of file compose.c.

229 {
230  static bool done = false;
231 
232  if (done)
233  return;
234  done = true;
235 
236  for (int i = 0; i <= HDR_XCOMMENTTO; i++)
237  calc_header_width_padding(i, _(Prompts[i]), true);
238 
239  /* Don't include "Sign as: " in the MaxHeaderWidth calculation. It
240  * doesn't show up by default, and so can make the indentation of
241  * the other fields look funny. */
243 
244  for (int i = 0; i <= HDR_XCOMMENTTO; i++)
245  {
247  if (HeaderPadding[i] < 0)
248  HeaderPadding[i] = 0;
249  }
250 }
static void calc_header_width_padding(int idx, const char *header, bool calc_max)
Calculate the width needed for the compose labels.
Definition: compose.c:209
int MaxHeaderWidth
Definition: compose.c:131
#define _(a)
Definition: message.h:28
"Sign as:" field (encryption/signing info)
Definition: compose.c:121
"X-Comment-To:" field
Definition: compose.c:125
int HeaderPadding[HDR_XCOMMENTTO+1]
Definition: compose.c:130
static const char *const Prompts[]
Definition: compose.c:136

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void snd_make_entry ( char *  buf,
size_t  buflen,
struct Menu menu,
int  line 
)
static

Format a menu item for the attachment list - Implements Menu::menu_make_entry()

Definition at line 255 of file compose.c.

256 {
257  struct AttachCtx *actx = menu->data;
258 
260  attach_format_str, (unsigned long) (actx->idx[actx->v2r[line]]),
262 }
void mutt_expando_format(char *buf, size_t buflen, size_t col, int cols, const char *src, format_t *callback, unsigned long data, MuttFormatFlags flags)
Expand expandos (x) in a string.
Definition: muttlib.c:811
#define NONULL(x)
Definition: string2.h:36
WHERE char * C_AttachFormat
Config: printf-like format string for the attachment menu.
Definition: globals.h:106
#define MUTT_FORMAT_ARROWCURSOR
Reserve space for arrow_cursor.
Definition: format_flags.h:35
#define MUTT_FORMAT_STAT_FILE
Used by attach_format_str.
Definition: format_flags.h:34
const char * line
Definition: common.c:35
struct MuttWindow * MuttIndexWindow
Index Window.
Definition: mutt_window.c:39
short * v2r
mapping from virtual to real attachment
Definition: attach.h:58
const char * attach_format_str(char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, unsigned long data, MuttFormatFlags flags)
Format a string for the attachment menu - Implements format_t.
Definition: recvattach.c:209
void * data
extra data for the current menu
Definition: mutt_menu.h:86
A set of attachments.
Definition: attach.h:49
struct AttachPtr ** idx
Definition: attach.h:54

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void redraw_crypt_lines ( struct Email msg)
static

Update the encryption info in the compose window.

Parameters
msgHeader of message

Definition at line 268 of file compose.c.

269 {
272  HeaderPadding[HDR_CRYPT], _(Prompts[HDR_CRYPT]));
273  NORMAL_COLOR;
274 
276  {
277  addstr(_("Not supported"));
278  return;
279  }
280 
281  if ((msg->security & (SEC_ENCRYPT | SEC_SIGN)) == (SEC_ENCRYPT | SEC_SIGN))
282  {
284  addstr(_("Sign, Encrypt"));
285  }
286  else if (msg->security & SEC_ENCRYPT)
287  {
289  addstr(_("Encrypt"));
290  }
291  else if (msg->security & SEC_SIGN)
292  {
294  addstr(_("Sign"));
295  }
296  else
297  {
298  /* L10N: This refers to the encryption of the email, e.g. "Security: None" */
300  addstr(_("None"));
301  }
302  NORMAL_COLOR;
303 
304  if ((msg->security & (SEC_ENCRYPT | SEC_SIGN)))
305  {
306  if (((WithCrypto & APPLICATION_PGP) != 0) && (msg->security & APPLICATION_PGP))
307  {
308  if ((msg->security & SEC_INLINE))
309  addstr(_(" (inline PGP)"));
310  else
311  addstr(_(" (PGP/MIME)"));
312  }
313  else if (((WithCrypto & APPLICATION_SMIME) != 0) && (msg->security & APPLICATION_SMIME))
314  addstr(_(" (S/MIME)"));
315  }
316 
318  addstr(_(" (OppEnc mode)"));
319 
323 
324  if (((WithCrypto & APPLICATION_PGP) != 0) &&
325  (msg->security & APPLICATION_PGP) && (msg->security & SEC_SIGN))
326  {
328  printw("%*s", HeaderPadding[HDR_CRYPTINFO], _(Prompts[HDR_CRYPTINFO]));
329  NORMAL_COLOR;
330  printw("%s", C_PgpSignAs ? C_PgpSignAs : _("<default>"));
331  }
332 
333  if (((WithCrypto & APPLICATION_SMIME) != 0) &&
334  (msg->security & APPLICATION_SMIME) && (msg->security & SEC_SIGN))
335  {
337  printw("%*s", HeaderPadding[HDR_CRYPTINFO], _(Prompts[HDR_CRYPTINFO]));
338  NORMAL_COLOR;
339  printw("%s", C_SmimeSignAs ? C_SmimeSignAs : _("<default>"));
340  }
341 
342  if (((WithCrypto & APPLICATION_SMIME) != 0) && (msg->security & APPLICATION_SMIME) &&
344  {
346  mutt_window_mvprintw(MuttIndexWindow, HDR_CRYPTINFO, 40, "%s", _("Encrypt with: "));
347  NORMAL_COLOR;
348  printw("%s", NONULL(C_SmimeEncryptWith));
349  }
350 }
Header labels, e.g. From:
Definition: mutt_curses.h:167
#define NONULL(x)
Definition: string2.h:36
Mail will not be encrypted or signed.
Definition: mutt_curses.h:171
#define NORMAL_COLOR
Definition: mutt_curses.h:237
Mail will be encrypted.
Definition: mutt_curses.h:168
void mutt_window_clrtoeol(struct MuttWindow *win)
Clear to the end of the line.
Definition: mutt_window.c:81
#define _(a)
Definition: message.h:28
#define SEC_INLINE
Email has an inline signature.
Definition: ncrypt.h:127
#define SEC_ENCRYPT
Email is encrypted.
Definition: ncrypt.h:120
"Sign as:" field (encryption/signing info)
Definition: compose.c:121
Mail will be signed.
Definition: mutt_curses.h:169
Mail will be encrypted and signed.
Definition: mutt_curses.h:170
#define SEC_SIGN
Email is signed.
Definition: ncrypt.h:121
WHERE bool C_CryptOpportunisticEncrypt
Config: Enable encryption when the recipient&#39;s key is available.
Definition: globals.h:275
struct MuttWindow * MuttIndexWindow
Index Window.
Definition: mutt_window.c:39
WHERE char * C_SmimeEncryptWith
Config: Algorithm for encryption.
Definition: globals.h:176
int HeaderPadding[HDR_XCOMMENTTO+1]
Definition: compose.c:130
"Security:" field (encryption/signing info)
Definition: compose.c:120
static const char *const Prompts[]
Definition: compose.c:136
SecurityFlags security
bit 0-8: flags, bit 9,10: application.
Definition: email.h:39
int mutt_window_move(struct MuttWindow *win, int row, int col)
Move the cursor in a Window.
Definition: mutt_window.c:162
#define SETCOLOR(X)
Definition: mutt_curses.h:222
#define SEC_OPPENCRYPT
Opportunistic encrypt mode.
Definition: ncrypt.h:128
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: ncrypt.h:129
int mutt_window_mvprintw(struct MuttWindow *win, int row, int col, const char *fmt,...)
Move the cursor and write a formatted string to a Window.
Definition: mutt_window.c:205
WHERE char * C_PgpSignAs
Config: Use this alternative key for signing messages.
Definition: globals.h:171
WHERE char * C_SmimeSignAs
Config: Use this alternative key for signing messages.
Definition: globals.h:175
#define WithCrypto
Definition: ncrypt.h:155
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: ncrypt.h:130

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int check_attachments ( struct AttachCtx actx)
static

Check if any attachments have changed or been deleted.

Parameters
actxAttachment context
Return values
0Success
-1Error

Definition at line 399 of file compose.c.

400 {
401  struct stat st;
402  char pretty[PATH_MAX], msg[PATH_MAX + 128];
403 
404  for (int i = 0; i < actx->idxlen; i++)
405  {
406  if (actx->idx[i]->content->type == TYPE_MULTIPART)
407  continue;
408  mutt_str_strfcpy(pretty, actx->idx[i]->content->filename, sizeof(pretty));
409  if (stat(actx->idx[i]->content->filename, &st) != 0)
410  {
411  mutt_pretty_mailbox(pretty, sizeof(pretty));
412  mutt_error(_("%s [#%d] no longer exists"), pretty, i + 1);
413  return -1;
414  }
415 
416  if (actx->idx[i]->content->stamp < st.st_mtime)
417  {
418  mutt_pretty_mailbox(pretty, sizeof(pretty));
419  snprintf(msg, sizeof(msg), _("%s [#%d] modified. Update encoding?"), pretty, i + 1);
420 
421  enum QuadOption ans = mutt_yesorno(msg, MUTT_YES);
422  if (ans == MUTT_YES)
423  mutt_update_encoding(actx->idx[i]->content);
424  else if (ans == MUTT_ABORT)
425  return -1;
426  }
427  }
428 
429  return 0;
430 }
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:48
void mutt_pretty_mailbox(char *s, size_t buflen)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:605
User aborted the question (with Ctrl-G)
Definition: quad.h:37
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
#define _(a)
Definition: message.h:28
short idxlen
Definition: attach.h:55
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:330
void mutt_update_encoding(struct Body *a)
Update the encoding type.
Definition: sendlib.c:1428
#define PATH_MAX
Definition: mutt.h:48
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:741
unsigned int type
content-type primary type
Definition: body.h:70
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
struct Body * content
Definition: attach.h:36
time_t stamp
time stamp of last encoding update.
Definition: body.h:66
#define mutt_error(...)
Definition: logging.h:88
struct AttachPtr ** idx
Definition: attach.h:54
QuadOption
Possible values for a quad-option.
Definition: quad.h:35

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void draw_envelope_addr ( int  line,
struct Address addr 
)
static

Write addresses to the compose window.

Parameters
lineLine to write to (index into Prompts)
addrAddress list to write

Definition at line 437 of file compose.c.

438 {
439  char buf[1024];
440 
441  buf[0] = '\0';
442  mutt_addr_write(buf, sizeof(buf), addr, true);
445  _(Prompts[line]));
446  NORMAL_COLOR;
447  mutt_paddstr(W, buf);
448 }
Header labels, e.g. From:
Definition: mutt_curses.h:167
#define NORMAL_COLOR
Definition: mutt_curses.h:237
#define _(a)
Definition: message.h:28
void mutt_paddstr(int n, const char *s)
Display a string on screen, padded if necessary.
Definition: curs_lib.c:1083
size_t mutt_addr_write(char *buf, size_t buflen, struct Address *addr, bool display)
Write an Address to a buffer.
Definition: address.c:1146
const char * line
Definition: common.c:35
struct MuttWindow * MuttIndexWindow
Index Window.
Definition: mutt_window.c:39
int HeaderPadding[HDR_XCOMMENTTO+1]
Definition: compose.c:130
static const char *const Prompts[]
Definition: compose.c:136
#define W
Definition: compose.c:134
#define SETCOLOR(X)
Definition: mutt_curses.h:222
int mutt_window_mvprintw(struct MuttWindow *win, int row, int col, const char *fmt,...)
Move the cursor and write a formatted string to a Window.
Definition: mutt_window.c:205

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void draw_envelope ( struct Email msg,
char *  fcc 
)
static

Write the email headers to the compose window.

Parameters
msgHeader of the message
fccFcc field

Definition at line 455 of file compose.c.

456 {
458 #ifdef USE_NNTP
459  if (!OptNewsSend)
460  {
461 #endif
465 #ifdef USE_NNTP
466  }
467  else
468  {
470  HeaderPadding[HDR_NEWSGROUPS], Prompts[HDR_NEWSGROUPS]);
473  HeaderPadding[HDR_FOLLOWUPTO], Prompts[HDR_FOLLOWUPTO]);
475  if (C_XCommentTo)
476  {
478  HeaderPadding[HDR_XCOMMENTTO], Prompts[HDR_XCOMMENTTO]);
480  }
481  }
482 #endif
483 
486  HeaderPadding[HDR_SUBJECT], _(Prompts[HDR_SUBJECT]));
487  NORMAL_COLOR;
488  mutt_paddstr(W, NONULL(msg->env->subject));
489 
491 
494  HeaderPadding[HDR_FCC], _(Prompts[HDR_FCC]));
495  NORMAL_COLOR;
496  mutt_paddstr(W, fcc);
497 
498  if (WithCrypto)
499  redraw_crypt_lines(msg);
500 
501 #ifdef MIXMASTER
502  redraw_mix_line(&msg->chain);
503 #endif
504 
506  mutt_window_mvaddstr(MuttIndexWindow, HDR_ATTACH - 1, 0, _("-- Attachments"));
508 
509  NORMAL_COLOR;
510 }
Header labels, e.g. From:
Definition: mutt_curses.h:167
#define NONULL(x)
Definition: string2.h:36
struct Address * to
Definition: envelope.h:42
#define NORMAL_COLOR
Definition: mutt_curses.h:237
void mutt_window_clrtoeol(struct MuttWindow *win)
Clear to the end of the line.
Definition: mutt_window.c:81
"To:" field
Definition: compose.c:111
"Cc:" field
Definition: compose.c:112
#define _(a)
Definition: message.h:28
"Subject:" field
Definition: compose.c:114
"From:" field
Definition: compose.c:110
void mutt_paddstr(int n, const char *s)
Display a string on screen, padded if necessary.
Definition: curs_lib.c:1083
struct Address * reply_to
Definition: envelope.h:46
static void draw_envelope_addr(int line, struct Address *addr)
Write addresses to the compose window.
Definition: compose.c:437
struct Envelope * env
envelope information
Definition: email.h:92
"X-Comment-To:" field
Definition: compose.c:125
struct Address * from
Definition: envelope.h:41
char * x_comment_to
Definition: envelope.h:62
struct Address * bcc
Definition: envelope.h:44
struct MuttWindow * MuttIndexWindow
Index Window.
Definition: mutt_window.c:39
int HeaderPadding[HDR_XCOMMENTTO+1]
Definition: compose.c:130
static const char *const Prompts[]
Definition: compose.c:136
#define W
Definition: compose.c:134
int mutt_window_mvaddstr(struct MuttWindow *win, int row, int col, const char *str)
Move the cursor and write a fixed string to a Window.
Definition: mutt_window.c:190
#define SETCOLOR(X)
Definition: mutt_curses.h:222
"Bcc:" field
Definition: compose.c:113
"Followup-To:" field
Definition: compose.c:124
char * subject
Definition: envelope.h:50
char * newsgroups
Definition: envelope.h:59
WHERE bool C_XCommentTo
Config: (nntp) Add &#39;X-Comment-To&#39; header that contains article author.
Definition: globals.h:289
char * followup_to
Definition: envelope.h:61
Status bar.
Definition: mutt_curses.h:128
Position to start printing the attachments.
Definition: compose.c:127
int mutt_window_mvprintw(struct MuttWindow *win, int row, int col, const char *fmt,...)
Move the cursor and write a formatted string to a Window.
Definition: mutt_window.c:205
"Newsgroups:" field
Definition: compose.c:123
static void redraw_crypt_lines(struct Email *msg)
Update the encryption info in the compose window.
Definition: compose.c:268
WHERE bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: options.h:43
"Fcc:" (save folder) field
Definition: compose.c:116
#define WithCrypto
Definition: ncrypt.h:155
struct Address * cc
Definition: envelope.h:43
"Reply-To:" field
Definition: compose.c:115

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void edit_address_list ( int  line,
struct Address **  addr 
)
static

Let the user edit the address list.

Parameters
[in]lineIndex into the Prompts lists
[in,out]addrAddress list to edit

Definition at line 517 of file compose.c.

518 {
519  char buf[8192] = ""; /* needs to be large for alias expansion */
520  char *err = NULL;
521 
522  mutt_addrlist_to_local(*addr);
523  mutt_addr_write(buf, sizeof(buf), *addr, false);
524  if (mutt_get_field(_(Prompts[line]), buf, sizeof(buf), MUTT_ALIAS) == 0)
525  {
526  mutt_addr_free(addr);
527  *addr = mutt_addr_parse_list2(*addr, buf);
528  *addr = mutt_expand_aliases(*addr);
529  }
530 
531  if (mutt_addrlist_to_intl(*addr, &err) != 0)
532  {
533  mutt_error(_("Bad IDN: '%s'"), err);
534  mutt_refresh();
535  FREE(&err);
536  }
537 
538  /* redraw the expanded list so the user can see the result */
539  buf[0] = '\0';
540  mutt_addr_write(buf, sizeof(buf), *addr, true);
542  mutt_paddstr(W, buf);
543 }
struct Address * mutt_addr_parse_list2(struct Address *p, const char *s)
Parse a list of email addresses.
Definition: address.c:630
#define MUTT_ALIAS
Do alias "completion" by calling up the alias-menu.
Definition: mutt.h:61
#define _(a)
Definition: message.h:28
#define mutt_get_field(field, buf, buflen, complete)
Definition: curs_lib.h:77
int mutt_addrlist_to_intl(struct Address *a, char **err)
Convert an Address list to Punycode.
Definition: address.c:1208
void mutt_paddstr(int n, const char *s)
Display a string on screen, padded if necessary.
Definition: curs_lib.c:1083
size_t mutt_addr_write(char *buf, size_t buflen, struct Address *addr, bool display)
Write an Address to a buffer.
Definition: address.c:1146
const char * line
Definition: common.c:35
void mutt_refresh(void)
Force a refresh of the screen.
Definition: curs_lib.c:99
int mutt_addrlist_to_local(struct Address *a)
Convert an Address list from Punycode.
Definition: address.c:1249
#define HDR_XOFFSET
Definition: compose.c:133
struct MuttWindow * MuttIndexWindow
Index Window.
Definition: mutt_window.c:39
static const char *const Prompts[]
Definition: compose.c:136
#define W
Definition: compose.c:134
int mutt_window_move(struct MuttWindow *win, int row, int col)
Move the cursor in a Window.
Definition: mutt_window.c:162
struct Address * mutt_expand_aliases(struct Address *a)
Expand aliases in a List of Addresses.
Definition: alias.c:297
#define mutt_error(...)
Definition: logging.h:88
#define FREE(x)
Definition: memory.h:40
void mutt_addr_free(struct Address **p)
Free a list of Addresses.
Definition: address.c:446

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int delete_attachment ( struct AttachCtx actx,
int  x 
)
static

Delete an attachment.

Parameters
actxAttachment context
xIndex number of attachment
Return values
0Success
-1Error

Definition at line 552 of file compose.c.

553 {
554  struct AttachPtr **idx = actx->idx;
555  int rindex = actx->v2r[x];
556 
557  if ((rindex == 0) && (actx->idxlen == 1))
558  {
559  mutt_error(_("You may not delete the only attachment"));
560  idx[rindex]->content->tagged = false;
561  return -1;
562  }
563 
564  for (int y = 0; y < actx->idxlen; y++)
565  {
566  if (idx[y]->content->next == idx[rindex]->content)
567  {
568  idx[y]->content->next = idx[rindex]->content->next;
569  break;
570  }
571  }
572 
573  idx[rindex]->content->next = NULL;
574  idx[rindex]->content->parts = NULL;
575  mutt_body_free(&(idx[rindex]->content));
576  FREE(&idx[rindex]->tree);
577  FREE(&idx[rindex]);
578  for (; rindex < actx->idxlen - 1; rindex++)
579  idx[rindex] = idx[rindex + 1];
580  idx[actx->idxlen - 1] = NULL;
581  actx->idxlen--;
582 
583  return 0;
584 }
An email to which things will be attached.
Definition: attach.h:34
#define _(a)
Definition: message.h:28
struct Body * next
next attachment in the list
Definition: body.h:58
short idxlen
Definition: attach.h:55
char * tree
Definition: attach.h:39
bool tagged
Definition: body.h:77
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:59
void mutt_body_free(struct Body **p)
Free a Body.
Definition: body.c:57
short * v2r
mapping from virtual to real attachment
Definition: attach.h:58
struct Body * content
Definition: attach.h:36
#define mutt_error(...)
Definition: logging.h:88
#define FREE(x)
Definition: memory.h:40
struct AttachPtr ** idx
Definition: attach.h:54

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void mutt_gen_compose_attach_list ( struct AttachCtx actx,
struct Body m,
int  parent_type,
int  level 
)
static

Generate the attachment list for the compose screen.

Parameters
actxAttachment context
mAttachment
parent_typeAttachment type, e.g TYPE_MULTIPART
levelNesting depth of attachment

Definition at line 593 of file compose.c.

595 {
596  for (; m; m = m->next)
597  {
598  if ((m->type == TYPE_MULTIPART) && m->parts &&
600  {
602  }
603  else
604  {
605  struct AttachPtr *new = mutt_mem_calloc(1, sizeof(struct AttachPtr));
606  mutt_actx_add_attach(actx, new);
607  new->content = m;
608  m->aptr = new;
609  new->parent_type = parent_type;
610  new->level = level;
611 
612  /* We don't support multipart messages in the compose menu yet */
613  }
614  }
615 }
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:51
An email to which things will be attached.
Definition: attach.h:34
struct Body * next
next attachment in the list
Definition: body.h:58
void mutt_actx_add_attach(struct AttachCtx *actx, struct AttachPtr *attach)
Add an Attachment to an Attachment Context.
Definition: attach.c:40
static void mutt_gen_compose_attach_list(struct AttachCtx *actx, struct Body *m, int parent_type, int level)
Generate the attachment list for the compose screen.
Definition: compose.c:593
SecurityFlags mutt_is_multipart_encrypted(struct Body *b)
Does the message have encrypted parts?
Definition: crypt.c:418
int parent_type
Definition: attach.h:38
struct AttachPtr * aptr
Menu information, used in recvattach.c.
Definition: body.h:62
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:59
unsigned int type
content-type primary type
Definition: body.h:70
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: ncrypt.h:129
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
#define WithCrypto
Definition: ncrypt.h:155
int level
Definition: attach.h:40

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void mutt_update_compose_menu ( struct AttachCtx actx,
struct Menu menu,
bool  init 
)
static

Redraw the compose window.

Parameters
actxAttachment context
menuCurrent menu
initIf true, initialise the attachment list

Definition at line 623 of file compose.c.

624 {
625  if (init)
626  {
627  mutt_gen_compose_attach_list(actx, actx->email->content, -1, 0);
628  mutt_attach_init(actx);
629  menu->data = actx;
630  }
631 
632  mutt_update_tree(actx);
633 
634  menu->max = actx->vcount;
635  if (menu->max)
636  {
637  if (menu->current >= menu->max)
638  menu->current = menu->max - 1;
639  }
640  else
641  menu->current = 0;
642 
643  menu->redraw |= REDRAW_INDEX | REDRAW_STATUS;
644 }
struct Email * email
used by recvattach for updating
Definition: attach.h:51
struct Body * content
list of MIME parts
Definition: email.h:93
static void mutt_gen_compose_attach_list(struct AttachCtx *actx, struct Body *m, int parent_type, int level)
Generate the attachment list for the compose screen.
Definition: compose.c:593
#define REDRAW_STATUS
Redraw the status bar.
Definition: mutt_menu.h:46
void mutt_attach_init(struct AttachCtx *actx)
Create a new Attachment context.
Definition: recvattach.c:1243
int max
the number of entries in the menu
Definition: mutt_menu.h:88
MuttRedrawFlags redraw
when to redraw the screen
Definition: mutt_menu.h:89
#define REDRAW_INDEX
Redraw the index.
Definition: mutt_menu.h:42
void mutt_update_tree(struct AttachCtx *actx)
Refresh the list of attachments.
Definition: recvattach.c:143
void * data
extra data for the current menu
Definition: mutt_menu.h:86
int current
current entry
Definition: mutt_menu.h:87
short vcount
the number of virtual attachments
Definition: attach.h:59

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void update_idx ( struct Menu menu,
struct AttachCtx actx,
struct AttachPtr new 
)
static

Add a new attchment to the message.

Parameters
menuCurrent menu
actxAttachment context
newAttachment to add

Definition at line 652 of file compose.c.

653 {
654  new->level = (actx->idxlen > 0) ? actx->idx[actx->idxlen - 1]->level : 0;
655  if (actx->idxlen)
656  actx->idx[actx->idxlen - 1]->content->next = new->content;
657  new->content->aptr = new;
658  mutt_actx_add_attach(actx, new);
659  mutt_update_compose_menu(actx, menu, false);
660  menu->current = actx->vcount - 1;
661 }
struct Content * content
structure used to store detailed info about the content of the attachment.
Definition: body.h:54
struct Body * next
next attachment in the list
Definition: body.h:58
short idxlen
Definition: attach.h:55
void mutt_actx_add_attach(struct AttachCtx *actx, struct AttachPtr *attach)
Add an Attachment to an Attachment Context.
Definition: attach.c:40
static void mutt_update_compose_menu(struct AttachCtx *actx, struct Menu *menu, bool init)
Redraw the compose window.
Definition: compose.c:623
struct Body * content
Definition: attach.h:36
int current
current entry
Definition: mutt_menu.h:87
int level
Definition: attach.h:40
struct AttachPtr ** idx
Definition: attach.h:54
short vcount
the number of virtual attachments
Definition: attach.h:59

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void compose_status_line ( char *  buf,
size_t  buflen,
size_t  col,
int  cols,
struct Menu menu,
const char *  src 
)
static

Compose the string for the status bar.

Parameters
[out]bufBuffer in which to save string
[in]buflenBuffer length
[in]colStarting column
[in]colsNumber of screen columns
[in]menuCurrent menu
[in]srcPrintf-like format string

Definition at line 865 of file compose.c.

867 {
868  mutt_expando_format(buf, buflen, col, cols, src, compose_format_str,
869  (unsigned long) menu, 0);
870 }
void mutt_expando_format(char *buf, size_t buflen, size_t col, int cols, const char *src, format_t *callback, unsigned long data, MuttFormatFlags flags)
Expand expandos (x) in a string.
Definition: muttlib.c:811
static const char * compose_format_str(char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, unsigned long data, MuttFormatFlags flags)
Create the status bar string for compose mode - Implements format_t.
Definition: compose.c:807

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void compose_custom_redraw ( struct Menu menu)
static

Redraw the compose menu - Implements Menu::menu_custom_redraw()

Definition at line 678 of file compose.c.

679 {
680  struct ComposeRedrawData *rd = menu->redraw_data;
681 
682  if (!rd)
683  return;
684 
685  if (menu->redraw & REDRAW_FULL)
686  {
687  menu_redraw_full(menu);
688 
689  draw_envelope(rd->email, rd->fcc);
690  menu->offset = HDR_ATTACH;
692  }
693 
694  menu_check_recenter(menu);
695 
696  if (menu->redraw & REDRAW_STATUS)
697  {
698  char buf[1024];
699  compose_status_line(buf, sizeof(buf), 0, MuttStatusWindow->cols, menu,
704  NORMAL_COLOR;
705  menu->redraw &= ~REDRAW_STATUS;
706  }
707 
708 #ifdef USE_SIDEBAR
709  if (menu->redraw & REDRAW_SIDEBAR)
710  menu_redraw_sidebar(menu);
711 #endif
712 
713  if (menu->redraw & REDRAW_INDEX)
714  menu_redraw_index(menu);
715  else if (menu->redraw & (REDRAW_MOTION | REDRAW_MOTION_RESYNC))
716  menu_redraw_motion(menu);
717  else if (menu->redraw == REDRAW_CURRENT)
718  menu_redraw_current(menu);
719 }
#define REDRAW_FULL
Redraw everything.
Definition: mutt_menu.h:47
#define NONULL(x)
Definition: string2.h:36
struct MuttWindow * MuttStatusWindow
Status Window.
Definition: mutt_window.c:40
#define NORMAL_COLOR
Definition: mutt_curses.h:237
struct Email * email
Definition: compose.c:668
static void draw_envelope(struct Email *msg, char *fcc)
Write the email headers to the compose window.
Definition: compose.c:455
#define REDRAW_SIDEBAR
Redraw the sidebar.
Definition: mutt_menu.h:51
void mutt_paddstr(int n, const char *s)
Display a string on screen, padded if necessary.
Definition: curs_lib.c:1083
void * redraw_data
Definition: mutt_menu.h:151
static void compose_status_line(char *buf, size_t buflen, size_t col, int cols, struct Menu *menu, const char *p)
Compose the string for the status bar.
Definition: compose.c:865
#define REDRAW_MOTION
Redraw after moving the menu list.
Definition: mutt_menu.h:43
#define REDRAW_MOTION_RESYNC
Redraw any changing the menu selection.
Definition: mutt_menu.h:44
#define REDRAW_STATUS
Redraw the status bar.
Definition: mutt_menu.h:46
struct MuttWindow * MuttIndexWindow
Index Window.
Definition: mutt_window.c:39
int pagelen
number of entries per screen
Definition: mutt_menu.h:92
int mutt_window_move(struct MuttWindow *win, int row, int col)
Move the cursor in a Window.
Definition: mutt_window.c:162
#define SETCOLOR(X)
Definition: mutt_curses.h:222
MuttRedrawFlags redraw
when to redraw the screen
Definition: mutt_menu.h:89
int offset
row offset within the window to start the index
Definition: mutt_menu.h:91
#define REDRAW_INDEX
Redraw the index.
Definition: mutt_menu.h:42
Status bar.
Definition: mutt_curses.h:128
Position to start printing the attachments.
Definition: compose.c:127
char * C_ComposeFormat
Config: printf-like format string for the Compose panel&#39;s status bar.
Definition: compose.c:88
Keep track when the compose screen needs redrawing.
Definition: compose.c:666
#define REDRAW_CURRENT
Redraw the current line of the menu.
Definition: mutt_menu.h:45

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void compose_attach_swap ( struct Body msg,
struct AttachPtr **  idx,
short  first 
)
static

Swap two adjacent entries in the attachment list.

Parameters
[in]msgBody of email
[out]idxArray of Attachments
[in]firstIndex of first attachment to swap

Definition at line 727 of file compose.c.

728 {
729  /* Reorder Body pointers.
730  * Must traverse msg from top since Body has no previous ptr. */
731  for (struct Body *part = msg; part; part = part->next)
732  {
733  if (part->next == idx[first]->content)
734  {
735  idx[first]->content->next = idx[first + 1]->content->next;
736  idx[first + 1]->content->next = idx[first]->content;
737  part->next = idx[first + 1]->content;
738  break;
739  }
740  }
741 
742  /* Reorder index */
743  struct AttachPtr *saved = idx[first];
744  idx[first] = idx[first + 1];
745  idx[first + 1] = saved;
746 
747  /* Swap ptr->num */
748  int i = idx[first]->num;
749  idx[first]->num = idx[first + 1]->num;
750  idx[first + 1]->num = i;
751 }
An email to which things will be attached.
Definition: attach.h:34
struct Body * next
next attachment in the list
Definition: body.h:58
The body of an email.
Definition: body.h:34
int num
Definition: attach.h:41
struct Body * content
Definition: attach.h:36

+ Here is the caller graph for this function:

static unsigned long cum_attachs_size ( struct Menu menu)
static

Cumulative Attachments Size.

Parameters
menuMenu listing attachments
Return values
numBytes in attachments

Returns the total number of bytes used by the attachments in the attachment list after content-transfer-encodings have been applied.

Definition at line 761 of file compose.c.

762 {
763  size_t s = 0;
764  struct AttachCtx *actx = menu->data;
765  struct AttachPtr **idx = actx->idx;
766  struct Content *info = NULL;
767  struct Body *b = NULL;
768 
769  for (unsigned short i = 0; i < actx->idxlen; i++)
770  {
771  b = idx[i]->content;
772 
773  if (!b->content)
775 
776  info = b->content;
777  if (info)
778  {
779  switch (b->encoding)
780  {
782  s += 3 * (info->lobin + info->hibin) + info->ascii + info->crlf;
783  break;
784  case ENC_BASE64:
785  s += (4 * (info->lobin + info->hibin + info->ascii + info->crlf)) / 3;
786  break;
787  default:
788  s += info->lobin + info->hibin + info->ascii + info->crlf;
789  break;
790  }
791  }
792  }
793 
794  return s;
795 }
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:48
An email to which things will be attached.
Definition: attach.h:34
struct Content * content
structure used to store detailed info about the content of the attachment.
Definition: body.h:54
short idxlen
Definition: attach.h:55
long hibin
8-bit characters
Definition: content.h:35
The body of an email.
Definition: body.h:34
struct Content * mutt_get_content_info(const char *fname, struct Body *b)
Analyze file to determine MIME encoding to use.
Definition: sendlib.c:979
unsigned int encoding
content-transfer-encoding
Definition: body.h:71
Base-64 encoded text.
Definition: mime.h:52
Info about an attachment.
Definition: content.h:33
long ascii
number of ascii chars
Definition: content.h:39
long lobin
unprintable 7-bit chars (eg., control chars)
Definition: content.h:36
struct Body * content
Definition: attach.h:36
Quoted-printable text.
Definition: mime.h:51
long crlf
\r and \n characters
Definition: content.h:38
void * data
extra data for the current menu
Definition: mutt_menu.h:86
A set of attachments.
Definition: attach.h:49
struct AttachPtr ** idx
Definition: attach.h:54

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static const char* compose_format_str ( char *  buf,
size_t  buflen,
size_t  col,
int  cols,
char  op,
const char *  src,
const char *  prec,
const char *  if_str,
const char *  else_str,
unsigned long  data,
MuttFormatFlags  flags 
)
static

Create the status bar string for compose mode - Implements format_t.

Expando Description
%a Total number of attachments
%h Local hostname
%l Approximate size (in bytes) of the current message
%v NeoMutt version string

Definition at line 807 of file compose.c.

811 {
812  char fmt[128], tmp[128];
813  int optional = (flags & MUTT_FORMAT_OPTIONAL);
814  struct Menu *menu = (struct Menu *) data;
815 
816  *buf = '\0';
817  switch (op)
818  {
819  case 'a': /* total number of attachments */
820  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
821  snprintf(buf, buflen, fmt, menu->max);
822  break;
823 
824  case 'h': /* hostname */
825  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
826  snprintf(buf, buflen, fmt, NONULL(ShortHostname));
827  break;
828 
829  case 'l': /* approx length of current message in bytes */
830  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
831  mutt_str_pretty_size(tmp, sizeof(tmp), menu ? cum_attachs_size(menu) : 0);
832  snprintf(buf, buflen, fmt, tmp);
833  break;
834 
835  case 'v':
836  snprintf(buf, buflen, "%s", mutt_make_version());
837  break;
838 
839  case 0:
840  *buf = '\0';
841  return src;
842 
843  default:
844  snprintf(buf, buflen, "%%%s%c", prec, op);
845  break;
846  }
847 
848  if (optional)
849  compose_status_line(buf, buflen, col, cols, menu, if_str);
850  else if (flags & MUTT_FORMAT_OPTIONAL)
851  compose_status_line(buf, buflen, col, cols, menu, else_str);
852 
853  return src;
854 }
#define NONULL(x)
Definition: string2.h:36
GUI selectable list of items.
Definition: mutt_menu.h:82
int menu
menu definition for keymap entries.
Definition: mutt_menu.h:90
static void compose_status_line(char *buf, size_t buflen, size_t col, int cols, struct Menu *menu, const char *p)
Compose the string for the status bar.
Definition: compose.c:865
int max
the number of entries in the menu
Definition: mutt_menu.h:88
static unsigned long cum_attachs_size(struct Menu *menu)
Cumulative Attachments Size.
Definition: compose.c:761
WHERE char * ShortHostname
Short version of the hostname.
Definition: globals.h:49
void * data
extra data for the current menu
Definition: mutt_menu.h:86
#define MUTT_FORMAT_OPTIONAL
Allow optional field processing.
Definition: format_flags.h:33
void mutt_str_pretty_size(char *buf, size_t buflen, size_t num)
Display an abbreviated size, like 3.4K.
Definition: string.c:1014
const char * mutt_make_version(void)
Generate the NeoMutt version string.
Definition: muttlib.c:1485

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int mutt_compose_menu ( struct Email msg,
char *  fcc,
size_t  fcclen,
struct Email cur,
int  flags 
)

Allow the user to edit the message envelope.

Parameters
msgMessage to fill
fccBuffer to save FCC
fcclenLength of FCC buffer
curCurrent message
flagsFlags, e.g. MUTT_COMPOSE_NOFREEHEADER
Return values
1Message should be postponed
0Normal exit
-1Abort message

Definition at line 883 of file compose.c.

884 {
885  char helpstr[1024]; // This isn't copied by the help bar
886  char buf[PATH_MAX];
887  int op_close = OP_NULL;
888  int rc = -1;
889  bool loop = true;
890  bool fcc_set = false; /* has the user edited the Fcc: field ? */
891  struct ComposeRedrawData rd;
892 #ifdef USE_NNTP
893  bool news = OptNewsSend; /* is it a news article ? */
894 #endif
895 
897 
898  rd.email = msg;
899  rd.fcc = fcc;
900 
901  struct Menu *menu = mutt_menu_new(MENU_COMPOSE);
902  menu->offset = HDR_ATTACH;
904  menu->menu_tag = attach_tag;
905 #ifdef USE_NNTP
906  if (news)
907  menu->help = mutt_compile_help(helpstr, sizeof(helpstr), MENU_COMPOSE, ComposeNewsHelp);
908  else
909 #endif
910  menu->help = mutt_compile_help(helpstr, sizeof(helpstr), MENU_COMPOSE, ComposeHelp);
912  menu->redraw_data = &rd;
914 
915  struct AttachCtx *actx = mutt_mem_calloc(sizeof(struct AttachCtx), 1);
916  actx->email = msg;
917  mutt_update_compose_menu(actx, menu, true);
918 
919  while (loop)
920  {
921 #ifdef USE_NNTP
922  OptNews = false; /* for any case */
923 #endif
924  const int op = mutt_menu_loop(menu);
925  switch (op)
926  {
927  case OP_COMPOSE_EDIT_FROM:
930  break;
931 
932  case OP_COMPOSE_EDIT_TO:
933 #ifdef USE_NNTP
934  if (news)
935  break;
936 #endif
937  edit_address_list(HDR_TO, &msg->env->to);
939  {
941  redraw_crypt_lines(msg);
942  }
944  break;
945 
946  case OP_COMPOSE_EDIT_BCC:
947 #ifdef USE_NNTP
948  if (news)
949  break;
950 #endif
951  edit_address_list(HDR_BCC, &msg->env->bcc);
953  {
955  redraw_crypt_lines(msg);
956  }
958  break;
959 
960  case OP_COMPOSE_EDIT_CC:
961 #ifdef USE_NNTP
962  if (news)
963  break;
964 #endif
965  edit_address_list(HDR_CC, &msg->env->cc);
967  {
969  redraw_crypt_lines(msg);
970  }
972  break;
973 #ifdef USE_NNTP
974  case OP_COMPOSE_EDIT_NEWSGROUPS:
975  if (!news)
976  break;
977  if (msg->env->newsgroups)
978  mutt_str_strfcpy(buf, msg->env->newsgroups, sizeof(buf));
979  else
980  buf[0] = '\0';
981  if (mutt_get_field("Newsgroups: ", buf, sizeof(buf), 0) == 0)
982  {
983  mutt_str_replace(&msg->env->newsgroups, buf);
985  if (msg->env->newsgroups)
986  mutt_paddstr(W, msg->env->newsgroups);
987  else
988  clrtoeol();
989  }
990  break;
991 
992  case OP_COMPOSE_EDIT_FOLLOWUP_TO:
993  if (!news)
994  break;
995  if (msg->env->followup_to)
996  mutt_str_strfcpy(buf, msg->env->followup_to, sizeof(buf));
997  else
998  buf[0] = '\0';
999  if (mutt_get_field("Followup-To: ", buf, sizeof(buf), 0) == 0)
1000  {
1001  mutt_str_replace(&msg->env->followup_to, buf);
1003  if (msg->env->followup_to)
1004  mutt_paddstr(W, msg->env->followup_to);
1005  else
1006  clrtoeol();
1007  }
1008  break;
1009 
1010  case OP_COMPOSE_EDIT_X_COMMENT_TO:
1011  if (!(news && C_XCommentTo))
1012  break;
1013  if (msg->env->x_comment_to)
1014  mutt_str_strfcpy(buf, msg->env->x_comment_to, sizeof(buf));
1015  else
1016  buf[0] = '\0';
1017  if (mutt_get_field("X-Comment-To: ", buf, sizeof(buf), 0) == 0)
1018  {
1019  mutt_str_replace(&msg->env->x_comment_to, buf);
1021  if (msg->env->x_comment_to)
1022  mutt_paddstr(W, msg->env->x_comment_to);
1023  else
1024  clrtoeol();
1025  }
1026  break;
1027 #endif
1028 
1029  case OP_COMPOSE_EDIT_SUBJECT:
1030  if (msg->env->subject)
1031  mutt_str_strfcpy(buf, msg->env->subject, sizeof(buf));
1032  else
1033  buf[0] = '\0';
1034  if (mutt_get_field(_("Subject: "), buf, sizeof(buf), 0) == 0)
1035  {
1036  mutt_str_replace(&msg->env->subject, buf);
1038  if (msg->env->subject)
1039  mutt_paddstr(W, msg->env->subject);
1040  else
1042  }
1043  mutt_message_hook(NULL, msg, MUTT_SEND2_HOOK);
1044  break;
1045 
1046  case OP_COMPOSE_EDIT_REPLY_TO:
1048  mutt_message_hook(NULL, msg, MUTT_SEND2_HOOK);
1049  break;
1050 
1051  case OP_COMPOSE_EDIT_FCC:
1052  mutt_str_strfcpy(buf, fcc, sizeof(buf));
1053  if (mutt_get_field(_("Fcc: "), buf, sizeof(buf), MUTT_FILE | MUTT_CLEAR) == 0)
1054  {
1055  mutt_str_strfcpy(fcc, buf, fcclen);
1056  mutt_pretty_mailbox(fcc, fcclen);
1058  mutt_paddstr(W, fcc);
1059  fcc_set = true;
1060  }
1061  mutt_message_hook(NULL, msg, MUTT_SEND2_HOOK);
1062  break;
1063 
1064  case OP_COMPOSE_EDIT_MESSAGE:
1065  if (C_Editor && (mutt_str_strcmp("builtin", C_Editor) != 0) && !C_EditHeaders)
1066  {
1069  menu->redraw = REDRAW_FULL;
1070  mutt_message_hook(NULL, msg, MUTT_SEND2_HOOK);
1071  break;
1072  }
1073  /* fallthrough */
1074 
1075  case OP_COMPOSE_EDIT_HEADERS:
1076  if ((mutt_str_strcmp("builtin", C_Editor) != 0) &&
1077  ((op == OP_COMPOSE_EDIT_HEADERS) || ((op == OP_COMPOSE_EDIT_MESSAGE) && C_EditHeaders)))
1078  {
1079  const char *tag = NULL;
1080  char *err = NULL;
1081  mutt_env_to_local(msg->env);
1082  mutt_edit_headers(NONULL(C_Editor), msg->content->filename, msg, fcc, fcclen);
1083  if (mutt_env_to_intl(msg->env, &tag, &err))
1084  {
1085  mutt_error(_("Bad IDN in '%s': '%s'"), tag, err);
1086  FREE(&err);
1087  }
1090  }
1091  else
1092  {
1093  /* this is grouped with OP_COMPOSE_EDIT_HEADERS because the
1094  * attachment list could change if the user invokes ~v to edit
1095  * the message with headers, in which we need to execute the
1096  * code below to regenerate the index array */
1097  mutt_builtin_editor(msg->content->filename, msg, cur);
1098  }
1100 
1101  /* attachments may have been added */
1102  if (actx->idxlen && actx->idx[actx->idxlen - 1]->content->next)
1103  {
1104  mutt_actx_free_entries(actx);
1105  mutt_update_compose_menu(actx, menu, true);
1106  }
1107 
1108  menu->redraw = REDRAW_FULL;
1109  mutt_message_hook(NULL, msg, MUTT_SEND2_HOOK);
1110  break;
1111 
1112  case OP_COMPOSE_ATTACH_KEY:
1113  {
1114  if (!(WithCrypto & APPLICATION_PGP))
1115  break;
1116  struct AttachPtr *new = mutt_mem_calloc(1, sizeof(struct AttachPtr));
1117  new->content = crypt_pgp_make_key_attachment();
1118  if (new->content)
1119  {
1120  update_idx(menu, actx, new);
1121  menu->redraw |= REDRAW_INDEX;
1122  }
1123  else
1124  FREE(&new);
1125 
1126  menu->redraw |= REDRAW_STATUS;
1127 
1128  mutt_message_hook(NULL, msg, MUTT_SEND2_HOOK);
1129  break;
1130  }
1131 
1132  case OP_COMPOSE_MOVE_UP:
1133  if (menu->current == 0)
1134  {
1135  mutt_error(_("Attachment is already at top"));
1136  break;
1137  }
1138  if (menu->current == 1)
1139  {
1140  mutt_error(_("The fundamental part cannot be moved"));
1141  break;
1142  }
1143  compose_attach_swap(msg->content, actx->idx, menu->current - 1);
1144  menu->redraw = REDRAW_INDEX;
1145  menu->current--;
1146  break;
1147 
1148  case OP_COMPOSE_MOVE_DOWN:
1149  if (menu->current == (actx->idxlen - 1))
1150  {
1151  mutt_error(_("Attachment is already at bottom"));
1152  break;
1153  }
1154  if (menu->current == 0)
1155  {
1156  mutt_error(_("The fundamental part cannot be moved"));
1157  break;
1158  }
1159  compose_attach_swap(msg->content, actx->idx, menu->current);
1160  menu->redraw = REDRAW_INDEX;
1161  menu->current++;
1162  break;
1163 
1164  case OP_COMPOSE_GROUP_ALTS:
1165  {
1166  if (menu->tagged < 2)
1167  {
1168  mutt_error(
1169  _("Grouping alternatives requires at least 2 tagged messages"));
1170  break;
1171  }
1172 
1173  struct Body *group = mutt_body_new();
1174  group->type = TYPE_MULTIPART;
1175  group->subtype = mutt_str_strdup("alternative");
1176  group->disposition = DISP_INLINE;
1177 
1178  struct Body *alts = NULL;
1179  /* group tagged message into a multipart/alternative */
1180  struct Body *bptr = msg->content;
1181  for (int i = 0; bptr;)
1182  {
1183  if (bptr->tagged)
1184  {
1185  bptr->tagged = false;
1186  bptr->disposition = DISP_INLINE;
1187 
1188  /* for first match, set group desc according to match */
1189 #define ALTS_TAG "Alternatives for \"%s\""
1190  if (!group->description)
1191  {
1192  char *p = bptr->description ? bptr->description : bptr->filename;
1193  if (p)
1194  {
1195  group->description =
1196  mutt_mem_calloc(1, strlen(p) + strlen(ALTS_TAG) + 1);
1197  sprintf(group->description, ALTS_TAG, p);
1198  }
1199  }
1200 
1201  /* append bptr to the alts list,
1202  * and remove from the msg->content list */
1203  if (!alts)
1204  {
1205  group->parts = bptr;
1206  alts = bptr;
1207  bptr = bptr->next;
1208  alts->next = NULL;
1209  }
1210  else
1211  {
1212  alts->next = bptr;
1213  bptr = bptr->next;
1214  alts = alts->next;
1215  alts->next = NULL;
1216  }
1217 
1218  for (int j = i; j < actx->idxlen - 1; j++)
1219  {
1220  actx->idx[j] = actx->idx[j + 1];
1221  actx->idx[j + 1] = NULL; /* for debug reason */
1222  }
1223  actx->idxlen--;
1224  }
1225  else
1226  {
1227  bptr = bptr->next;
1228  i++;
1229  }
1230  }
1231 
1232  group->next = NULL;
1234 
1235  /* if no group desc yet, make one up */
1236  if (!group->description)
1237  group->description = mutt_str_strdup("unknown alternative group");
1238 
1239  struct AttachPtr *gptr = mutt_mem_calloc(1, sizeof(struct AttachPtr));
1240  gptr->content = group;
1241  update_idx(menu, actx, gptr);
1242  menu->redraw = REDRAW_INDEX;
1243  break;
1244  }
1245 
1246  case OP_COMPOSE_GROUP_LINGUAL:
1247  {
1248  if (menu->tagged < 2)
1249  {
1250  mutt_error(
1251  _("Grouping multilingual requires at least 2 tagged messages"));
1252  break;
1253  }
1254 
1255  /* traverse to see whether all the parts have Content-Language: set */
1256  int tagged_with_lang_num = 0;
1257  for (struct Body *b = msg->content; b; b = b->next)
1258  if (b->tagged && b->language && *b->language)
1259  tagged_with_lang_num++;
1260 
1261  if (menu->tagged != tagged_with_lang_num)
1262  {
1263  if (mutt_yesorno(
1264  _("Not all parts have Content-Language: set, continue?"), MUTT_YES) != MUTT_YES)
1265  {
1266  mutt_message(_("Not sending this message"));
1267  break;
1268  }
1269  }
1270 
1271  struct Body *group = mutt_body_new();
1272  group->type = TYPE_MULTIPART;
1273  group->subtype = mutt_str_strdup("multilingual");
1274  group->disposition = DISP_INLINE;
1275 
1276  struct Body *alts = NULL;
1277  /* group tagged message into a multipart/multilingual */
1278  struct Body *bptr = msg->content;
1279  for (int i = 0; bptr;)
1280  {
1281  if (bptr->tagged)
1282  {
1283  bptr->tagged = false;
1284  bptr->disposition = DISP_INLINE;
1285 
1286  /* for first match, set group desc according to match */
1287 #define LINGUAL_TAG "Multilingual part for \"%s\""
1288  if (!group->description)
1289  {
1290  char *p = bptr->description ? bptr->description : bptr->filename;
1291  if (p)
1292  {
1293  group->description =
1294  mutt_mem_calloc(1, strlen(p) + strlen(LINGUAL_TAG) + 1);
1295  sprintf(group->description, LINGUAL_TAG, p);
1296  }
1297  }
1298 
1299  /* append bptr to the alts list,
1300  * and remove from the msg->content list */
1301  if (!alts)
1302  {
1303  group->parts = bptr;
1304  alts = bptr;
1305  bptr = bptr->next;
1306  alts->next = NULL;
1307  }
1308  else
1309  {
1310  alts->next = bptr;
1311  bptr = bptr->next;
1312  alts = alts->next;
1313  alts->next = NULL;
1314  }
1315 
1316  for (int j = i; j < actx->idxlen - 1; j++)
1317  {
1318  actx->idx[j] = actx->idx[j + 1];
1319  actx->idx[j + 1] = NULL; /* for debug reason */
1320  }
1321  actx->idxlen--;
1322  }
1323  else
1324  {
1325  bptr = bptr->next;
1326  i++;
1327  }
1328  }
1329 
1330  group->next = NULL;
1332 
1333  /* if no group desc yet, make one up */
1334  if (!group->description)
1335  group->description = mutt_str_strdup("unknown multilingual group");
1336 
1337  struct AttachPtr *gptr = mutt_mem_calloc(1, sizeof(struct AttachPtr));
1338  gptr->content = group;
1339  update_idx(menu, actx, gptr);
1340  menu->redraw = REDRAW_INDEX;
1341  break;
1342  }
1343 
1344  case OP_COMPOSE_ATTACH_FILE:
1345  {
1346  char *prompt = _("Attach file");
1347  int numfiles = 0;
1348  char **files = NULL;
1349  buf[0] = '\0';
1350 
1351  if ((mutt_enter_fname_full(prompt, buf, sizeof(buf), false, true,
1352  &files, &numfiles, MUTT_SEL_MULTI) == -1) ||
1353  (*buf == '\0'))
1354  {
1355  break;
1356  }
1357 
1358  bool error = false;
1359  if (numfiles > 1)
1360  {
1361  mutt_message(ngettext("Attaching selected file...",
1362  "Attaching selected files...", numfiles));
1363  }
1364  for (int i = 0; i < numfiles; i++)
1365  {
1366  char *att = files[i];
1367  struct AttachPtr *new = mutt_mem_calloc(1, sizeof(struct AttachPtr));
1368  new->unowned = true;
1369  new->content = mutt_make_file_attach(att);
1370  if (new->content)
1371  update_idx(menu, actx, new);
1372  else
1373  {
1374  error = true;
1375  mutt_error(_("Unable to attach %s"), att);
1376  FREE(&new);
1377  }
1378  FREE(&files[i]);
1379  }
1380 
1381  FREE(&files);
1382  if (!error)
1383  mutt_clear_error();
1384 
1385  menu->redraw |= REDRAW_INDEX | REDRAW_STATUS;
1386  mutt_message_hook(NULL, msg, MUTT_SEND2_HOOK);
1387  break;
1388  }
1389 
1390  case OP_COMPOSE_ATTACH_MESSAGE:
1391 #ifdef USE_NNTP
1392  case OP_COMPOSE_ATTACH_NEWS_MESSAGE:
1393 #endif
1394  {
1395  char *prompt = _("Open mailbox to attach message from");
1396  buf[0] = '\0';
1397 
1398 #ifdef USE_NNTP
1399  OptNews = false;
1400  if (Context && (op == OP_COMPOSE_ATTACH_NEWS_MESSAGE))
1401  {
1403  if (!CurrentNewsSrv)
1404  break;
1405 
1406  prompt = _("Open newsgroup to attach message from");
1407  OptNews = true;
1408  }
1409 #endif
1410 
1411  if (Context)
1412 #ifdef USE_NNTP
1413  if ((op == OP_COMPOSE_ATTACH_MESSAGE) ^ (Context->mailbox->magic == MUTT_NNTP))
1414 #endif
1415  {
1416  mutt_str_strfcpy(buf, Context->mailbox->path, sizeof(buf));
1417  mutt_pretty_mailbox(buf, sizeof(buf));
1418  }
1419 
1420  if ((mutt_enter_fname(prompt, buf, sizeof(buf), 1) == -1) || (buf[0] == '\0'))
1421  break;
1422 
1423 #ifdef USE_NNTP
1424  if (OptNews)
1425  nntp_expand_path(buf, sizeof(buf), &CurrentNewsSrv->conn->account);
1426  else
1427 #endif
1428  mutt_expand_path(buf, sizeof(buf));
1429 #ifdef USE_IMAP
1430  if (imap_path_probe(buf, NULL) != MUTT_IMAP)
1431 #endif
1432 #ifdef USE_POP
1433  if (pop_path_probe(buf, NULL) != MUTT_POP)
1434 #endif
1435 #ifdef USE_NNTP
1436  if (!OptNews && (nntp_path_probe(buf, NULL) != MUTT_NNTP))
1437 #endif
1438  /* check to make sure the file exists and is readable */
1439  if (access(buf, R_OK) == -1)
1440  {
1441  mutt_perror(buf);
1442  break;
1443  }
1444 
1445  menu->redraw = REDRAW_FULL;
1446 
1447  struct Mailbox *m = mx_path_resolve(buf);
1448  struct Context *ctx = mx_mbox_open(m, MUTT_READONLY);
1449  if (!ctx)
1450  {
1451  mutt_error(_("Unable to open mailbox %s"), buf);
1452  mailbox_free(&m);
1453  break;
1454  }
1455 
1456  if (ctx->mailbox->msg_count == 0)
1457  {
1458  mx_mbox_close(&ctx);
1459  mutt_error(_("No messages in that folder"));
1460  break;
1461  }
1462 
1463  struct Context *this = Context; /* remember current folder and sort methods */
1464  int old_sort = C_Sort; /* C_Sort, SortAux could be changed in mutt_index_menu() */
1465  int old_sort_aux = C_SortAux;
1466 
1467  Context = ctx;
1468  OptAttachMsg = true;
1469  mutt_message(_("Tag the messages you want to attach"));
1470  op_close = mutt_index_menu();
1471  OptAttachMsg = false;
1472 
1473  if (!Context)
1474  {
1475  /* go back to the folder we started from */
1476  Context = this;
1477  /* Restore old $sort and $sort_aux */
1478  C_Sort = old_sort;
1479  C_SortAux = old_sort_aux;
1480  menu->redraw |= REDRAW_INDEX | REDRAW_STATUS;
1481  break;
1482  }
1483 
1484  for (int i = 0; i < Context->mailbox->msg_count; i++)
1485  {
1486  if (!message_is_tagged(Context, i))
1487  continue;
1488 
1489  struct AttachPtr *new = mutt_mem_calloc(1, sizeof(struct AttachPtr));
1490  new->content = mutt_make_message_attach(Context->mailbox,
1491  Context->mailbox->emails[i], true);
1492  if (new->content)
1493  update_idx(menu, actx, new);
1494  else
1495  {
1496  mutt_error(_("Unable to attach"));
1497  FREE(&new);
1498  }
1499  }
1500  menu->redraw |= REDRAW_FULL;
1501 
1502  if (op_close == OP_QUIT)
1504  else
1505  {
1507  ctx_free(&Context);
1508  }
1509 
1510  /* go back to the folder we started from */
1511  Context = this;
1512  /* Restore old $sort and $sort_aux */
1513  C_Sort = old_sort;
1514  C_SortAux = old_sort_aux;
1515  mutt_message_hook(NULL, msg, MUTT_SEND2_HOOK);
1516  break;
1517  }
1518 
1519  case OP_DELETE:
1520  CHECK_COUNT;
1521  if (CURATTACH->unowned)
1522  CURATTACH->content->unlink = false;
1523  if (delete_attachment(actx, menu->current) == -1)
1524  break;
1525  mutt_update_compose_menu(actx, menu, false);
1526  if (menu->current == 0)
1527  msg->content = actx->idx[0]->content;
1528 
1529  mutt_message_hook(NULL, msg, MUTT_SEND2_HOOK);
1530  break;
1531 
1532  case OP_COMPOSE_TOGGLE_RECODE:
1533  {
1534  CHECK_COUNT;
1535  if (!mutt_is_text_part(CURATTACH->content))
1536  {
1537  mutt_error(_("Recoding only affects text attachments"));
1538  break;
1539  }
1540  CURATTACH->content->noconv = !CURATTACH->content->noconv;
1541  if (CURATTACH->content->noconv)
1542  mutt_message(_("The current attachment won't be converted"));
1543  else
1544  mutt_message(_("The current attachment will be converted"));
1545  menu->redraw = REDRAW_CURRENT;
1546  mutt_message_hook(NULL, msg, MUTT_SEND2_HOOK);
1547  break;
1548  }
1549 
1550  case OP_COMPOSE_EDIT_DESCRIPTION:
1551  CHECK_COUNT;
1552  mutt_str_strfcpy(buf,
1553  CURATTACH->content->description ? CURATTACH->content->description : "",
1554  sizeof(buf));
1555  /* header names should not be translated */
1556  if (mutt_get_field("Description: ", buf, sizeof(buf), 0) == 0)
1557  {
1558  mutt_str_replace(&CURATTACH->content->description, buf);
1559  menu->redraw = REDRAW_CURRENT;
1560  }
1561  mutt_message_hook(NULL, msg, MUTT_SEND2_HOOK);
1562  break;
1563 
1564  case OP_COMPOSE_UPDATE_ENCODING:
1565  CHECK_COUNT;
1566  if (menu->tagprefix)
1567  {
1568  struct Body *top = NULL;
1569  for (top = msg->content; top; top = top->next)
1570  {
1571  if (top->tagged)
1572  mutt_update_encoding(top);
1573  }
1574  menu->redraw = REDRAW_FULL;
1575  }
1576  else
1577  {
1578  mutt_update_encoding(CURATTACH->content);
1580  }
1581  mutt_message_hook(NULL, msg, MUTT_SEND2_HOOK);
1582  break;
1583 
1584  case OP_COMPOSE_TOGGLE_DISPOSITION:
1585  /* toggle the content-disposition between inline/attachment */
1586  CURATTACH->content->disposition =
1587  (CURATTACH->content->disposition == DISP_INLINE) ? DISP_ATTACH : DISP_INLINE;
1588  menu->redraw = REDRAW_CURRENT;
1589  break;
1590 
1591  case OP_EDIT_TYPE:
1592  CHECK_COUNT;
1593  {
1594  mutt_edit_content_type(NULL, CURATTACH->content, NULL);
1595 
1596  /* this may have been a change to text/something */
1597  mutt_update_encoding(CURATTACH->content);
1598 
1599  menu->redraw = REDRAW_CURRENT;
1600  }
1601  mutt_message_hook(NULL, msg, MUTT_SEND2_HOOK);
1602  break;
1603 
1604  case OP_COMPOSE_EDIT_LANGUAGE:
1605  CHECK_COUNT;
1606  buf[0] = '\0'; /* clear buffer first */
1607  if (CURATTACH->content->language)
1608  mutt_str_strfcpy(buf, CURATTACH->content->language, sizeof(buf));
1609  if (mutt_get_field("Content-Language: ", buf, sizeof(buf), 0) == 0)
1610  {
1611  CURATTACH->content->language = mutt_str_strdup(buf);
1613  mutt_clear_error();
1614  }
1615  else
1616  mutt_warning(_("Empty Content-Language"));
1617  mutt_message_hook(NULL, msg, MUTT_SEND2_HOOK);
1618  break;
1619 
1620  case OP_COMPOSE_EDIT_ENCODING:
1621  CHECK_COUNT;
1622  mutt_str_strfcpy(buf, ENCODING(CURATTACH->content->encoding), sizeof(buf));
1623  if ((mutt_get_field("Content-Transfer-Encoding: ", buf, sizeof(buf), 0) == 0) &&
1624  (buf[0] != '\0'))
1625  {
1626  int enc = mutt_check_encoding(buf);
1627  if ((enc != ENC_OTHER) && (enc != ENC_UUENCODED))
1628  {
1629  CURATTACH->content->encoding = enc;
1631  mutt_clear_error();
1632  }
1633  else
1634  mutt_error(_("Invalid encoding"));
1635  }
1636  mutt_message_hook(NULL, msg, MUTT_SEND2_HOOK);
1637  break;
1638 
1639  case OP_COMPOSE_SEND_MESSAGE:
1640  /* Note: We don't invoke send2-hook here, since we want to leave
1641  * users an opportunity to change settings from the ":" prompt. */
1642  if (check_attachments(actx) != 0)
1643  {
1644  menu->redraw = REDRAW_FULL;
1645  break;
1646  }
1647 
1648 #ifdef MIXMASTER
1649  if (!STAILQ_EMPTY(&msg->chain) && (mix_check_message(msg) != 0))
1650  break;
1651 #endif
1652 
1653  if (!fcc_set && *fcc)
1654  {
1655  enum QuadOption ans =
1656  query_quadoption(C_Copy, _("Save a copy of this message?"));
1657  if (ans == MUTT_ABORT)
1658  break;
1659  else if (ans == MUTT_NO)
1660  *fcc = '\0';
1661  }
1662 
1663  loop = false;
1664  rc = 0;
1665  break;
1666 
1667  case OP_COMPOSE_EDIT_FILE:
1668  CHECK_COUNT;
1669  mutt_edit_file(NONULL(C_Editor), CURATTACH->content->filename);
1670  mutt_update_encoding(CURATTACH->content);
1672  mutt_message_hook(NULL, msg, MUTT_SEND2_HOOK);
1673  break;
1674 
1675  case OP_COMPOSE_TOGGLE_UNLINK:
1676  CHECK_COUNT;
1677  CURATTACH->content->unlink = !CURATTACH->content->unlink;
1678 
1679  menu->redraw = REDRAW_INDEX;
1680  /* No send2hook since this doesn't change the message. */
1681  break;
1682 
1683  case OP_COMPOSE_GET_ATTACHMENT:
1684  CHECK_COUNT;
1685  if (menu->tagprefix)
1686  {
1687  for (struct Body *top = msg->content; top; top = top->next)
1688  {
1689  if (top->tagged)
1691  }
1692  menu->redraw = REDRAW_FULL;
1693  }
1694  else if (mutt_get_tmp_attachment(CURATTACH->content) == 0)
1695  menu->redraw = REDRAW_CURRENT;
1696 
1697  /* No send2hook since this doesn't change the message. */
1698  break;
1699 
1700  case OP_COMPOSE_RENAME_ATTACHMENT:
1701  {
1702  CHECK_COUNT;
1703  char *src = NULL;
1704  if (CURATTACH->content->d_filename)
1705  src = CURATTACH->content->d_filename;
1706  else
1707  src = CURATTACH->content->filename;
1708  mutt_str_strfcpy(buf, mutt_path_basename(NONULL(src)), sizeof(buf));
1709  int ret = mutt_get_field(_("Send attachment with name: "), buf, sizeof(buf), MUTT_FILE);
1710  if (ret == 0)
1711  {
1712  /* As opposed to RENAME_FILE, we don't check buf[0] because it's
1713  * valid to set an empty string here, to erase what was set */
1714  mutt_str_replace(&CURATTACH->content->d_filename, buf);
1715  menu->redraw = REDRAW_CURRENT;
1716  }
1717  break;
1718  }
1719 
1720  case OP_COMPOSE_RENAME_FILE:
1721  CHECK_COUNT;
1722  mutt_str_strfcpy(buf, CURATTACH->content->filename, sizeof(buf));
1723  mutt_pretty_mailbox(buf, sizeof(buf));
1724  if ((mutt_get_field(_("Rename to: "), buf, sizeof(buf), MUTT_FILE) == 0) &&
1725  (buf[0] != '\0'))
1726  {
1727  struct stat st;
1728  if (stat(CURATTACH->content->filename, &st) == -1)
1729  {
1730  /* L10N: "stat" is a system call. Do "man 2 stat" for more information. */
1731  mutt_error(_("Can't stat %s: %s"), buf, strerror(errno));
1732  break;
1733  }
1734 
1735  mutt_expand_path(buf, sizeof(buf));
1736  if (mutt_file_rename(CURATTACH->content->filename, buf))
1737  break;
1738 
1739  mutt_str_replace(&CURATTACH->content->filename, buf);
1740  menu->redraw = REDRAW_CURRENT;
1741 
1742  if (CURATTACH->content->stamp >= st.st_mtime)
1743  mutt_stamp_attachment(CURATTACH->content);
1744  }
1745  mutt_message_hook(NULL, msg, MUTT_SEND2_HOOK);
1746  break;
1747 
1748  case OP_COMPOSE_NEW_MIME:
1749  {
1751  buf[0] = '\0';
1752  if ((mutt_get_field(_("New file: "), buf, sizeof(buf), MUTT_FILE) != 0) ||
1753  (buf[0] == '\0'))
1754  {
1755  continue;
1756  }
1757  mutt_expand_path(buf, sizeof(buf));
1758 
1759  /* Call to lookup_mime_type () ? maybe later */
1760  char type[256] = { 0 };
1761  if ((mutt_get_field("Content-Type: ", type, sizeof(type), 0) != 0) ||
1762  (type[0] == '\0'))
1763  {
1764  continue;
1765  }
1766 
1767  char *p = strchr(type, '/');
1768  if (!p)
1769  {
1770  mutt_error(_("Content-Type is of the form base/sub"));
1771  continue;
1772  }
1773  *p++ = 0;
1774  int itype = mutt_check_mime_type(type);
1775  if (itype == TYPE_OTHER)
1776  {
1777  mutt_error(_("Unknown Content-Type %s"), type);
1778  continue;
1779  }
1780  struct AttachPtr *new = mutt_mem_calloc(1, sizeof(struct AttachPtr));
1781  /* Touch the file */
1782  FILE *fp = mutt_file_fopen(buf, "w");
1783  if (!fp)
1784  {
1785  mutt_error(_("Can't create file %s"), buf);
1786  FREE(&new);
1787  continue;
1788  }
1789  mutt_file_fclose(&fp);
1790 
1791  new->content = mutt_make_file_attach(buf);
1792  if (!new->content)
1793  {
1794  mutt_error(_("What we have here is a failure to make an attachment"));
1795  FREE(&new);
1796  continue;
1797  }
1798  update_idx(menu, actx, new);
1799 
1800  CURATTACH->content->type = itype;
1801  mutt_str_replace(&CURATTACH->content->subtype, p);
1802  CURATTACH->content->unlink = true;
1803  menu->redraw |= REDRAW_INDEX | REDRAW_STATUS;
1804 
1805  if (mutt_compose_attachment(CURATTACH->content))
1806  {
1807  mutt_update_encoding(CURATTACH->content);
1808  menu->redraw = REDRAW_FULL;
1809  }
1810  mutt_message_hook(NULL, msg, MUTT_SEND2_HOOK);
1811  break;
1812  }
1813 
1814  case OP_COMPOSE_EDIT_MIME:
1815  CHECK_COUNT;
1816  if (mutt_edit_attachment(CURATTACH->content))
1817  {
1818  mutt_update_encoding(CURATTACH->content);
1819  menu->redraw = REDRAW_FULL;
1820  }
1821  mutt_message_hook(NULL, msg, MUTT_SEND2_HOOK);
1822  break;
1823 
1824  case OP_VIEW_ATTACH:
1825  case OP_DISPLAY_HEADERS:
1826  CHECK_COUNT;
1827  mutt_attach_display_loop(menu, op, NULL, actx, false);
1828  menu->redraw = REDRAW_FULL;
1829  /* no send2hook, since this doesn't modify the message */
1830  break;
1831 
1832  case OP_SAVE:
1833  CHECK_COUNT;
1834  mutt_save_attachment_list(actx, NULL, menu->tagprefix,
1835  CURATTACH->content, NULL, menu);
1836  /* no send2hook, since this doesn't modify the message */
1837  break;
1838 
1839  case OP_PRINT:
1840  CHECK_COUNT;
1841  mutt_print_attachment_list(actx, NULL, menu->tagprefix, CURATTACH->content);
1842  /* no send2hook, since this doesn't modify the message */
1843  break;
1844 
1845  case OP_PIPE:
1846  case OP_FILTER:
1847  CHECK_COUNT;
1848  mutt_pipe_attachment_list(actx, NULL, menu->tagprefix,
1849  CURATTACH->content, (op == OP_FILTER));
1850  if (op == OP_FILTER) /* cte might have changed */
1851  menu->redraw = menu->tagprefix ? REDRAW_FULL : REDRAW_CURRENT;
1852  menu->redraw |= REDRAW_STATUS;
1853  mutt_message_hook(NULL, msg, MUTT_SEND2_HOOK);
1854  break;
1855 
1856  case OP_EXIT:
1857  {
1858  enum QuadOption ans =
1859  query_quadoption(C_Postpone, _("Save (postpone) draft message?"));
1860  if (ans == MUTT_NO)
1861  {
1862  for (int i = 0; i < actx->idxlen; i++)
1863  if (actx->idx[i]->unowned)
1864  actx->idx[i]->content->unlink = false;
1865 
1866  if (!(flags & MUTT_COMPOSE_NOFREEHEADER))
1867  {
1868  for (int i = 0; i < actx->idxlen; i++)
1869  {
1870  /* avoid freeing other attachments */
1871  actx->idx[i]->content->next = NULL;
1872  actx->idx[i]->content->parts = NULL;
1873  mutt_body_free(&actx->idx[i]->content);
1874  }
1875  }
1876  rc = -1;
1877  loop = false;
1878  break;
1879  }
1880  else if (ans == MUTT_ABORT)
1881  break; /* abort */
1882  }
1883  /* fallthrough */
1884 
1885  case OP_COMPOSE_POSTPONE_MESSAGE:
1886  if (check_attachments(actx) != 0)
1887  {
1888  menu->redraw = REDRAW_FULL;
1889  break;
1890  }
1891 
1892  loop = false;
1893  rc = 1;
1894  break;
1895 
1896  case OP_COMPOSE_ISPELL:
1897  endwin();
1898  snprintf(buf, sizeof(buf), "%s -x %s", NONULL(C_Ispell), msg->content->filename);
1899  if (mutt_system(buf) == -1)
1900  mutt_error(_("Error running \"%s\""), buf);
1901  else
1902  {
1904  menu->redraw |= REDRAW_STATUS;
1905  }
1906  break;
1907 
1908  case OP_COMPOSE_WRITE_MESSAGE:
1909  buf[0] = '\0';
1910  if (Context)
1911  {
1912  mutt_str_strfcpy(buf, Context->mailbox->path, sizeof(buf));
1913  mutt_pretty_mailbox(buf, sizeof(buf));
1914  }
1915  if (actx->idxlen)
1916  msg->content = actx->idx[0]->content;
1917  if ((mutt_enter_fname(_("Write message to mailbox"), buf, sizeof(buf), 1) != -1) &&
1918  (buf[0] != '\0'))
1919  {
1920  mutt_message(_("Writing message to %s ..."), buf);
1921  mutt_expand_path(buf, sizeof(buf));
1922 
1923  if (msg->content->next)
1924  msg->content = mutt_make_multipart(msg->content);
1925 
1926  if (mutt_write_fcc(buf, msg, NULL, false, NULL, NULL) < 0)
1927  msg->content = mutt_remove_multipart(msg->content);
1928  else
1929  mutt_message(_("Message written"));
1930  }
1931  break;
1932 
1933  case OP_COMPOSE_PGP_MENU:
1934  if (!(WithCrypto & APPLICATION_PGP))
1935  break;
1936  if (!crypt_has_module_backend(APPLICATION_PGP))
1937  {
1938  mutt_error(_("No PGP backend configured"));
1939  break;
1940  }
1941  if (((WithCrypto & APPLICATION_SMIME) != 0) && (msg->security & APPLICATION_SMIME))
1942  {
1943  if (msg->security & (SEC_ENCRYPT | SEC_SIGN))
1944  {
1945  if (mutt_yesorno(_("S/MIME already selected. Clear and continue? "),
1946  MUTT_YES) != MUTT_YES)
1947  {
1948  mutt_clear_error();
1949  break;
1950  }
1951  msg->security &= ~(SEC_ENCRYPT | SEC_SIGN);
1952  }
1953  msg->security &= ~APPLICATION_SMIME;
1954  msg->security |= APPLICATION_PGP;
1956  redraw_crypt_lines(msg);
1957  }
1958  msg->security = crypt_pgp_send_menu(msg);
1959  redraw_crypt_lines(msg);
1960  mutt_message_hook(NULL, msg, MUTT_SEND2_HOOK);
1961  break;
1962 
1963  case OP_FORGET_PASSPHRASE:
1965  break;
1966 
1967  case OP_COMPOSE_SMIME_MENU:
1968  if (!(WithCrypto & APPLICATION_SMIME))
1969  break;
1970  if (!crypt_has_module_backend(APPLICATION_SMIME))
1971  {
1972  mutt_error(_("No S/MIME backend configured"));
1973  break;
1974  }
1975 
1976  if (((WithCrypto & APPLICATION_PGP) != 0) && (msg->security & APPLICATION_PGP))
1977  {
1978  if (msg->security & (SEC_ENCRYPT | SEC_SIGN))
1979  {
1980  if (mutt_yesorno(_("PGP already selected. Clear and continue? "), MUTT_YES) != MUTT_YES)
1981  {
1982  mutt_clear_error();
1983  break;
1984  }
1985  msg->security &= ~(SEC_ENCRYPT | SEC_SIGN);
1986  }
1987  msg->security &= ~APPLICATION_PGP;
1988  msg->security |= APPLICATION_SMIME;
1990  redraw_crypt_lines(msg);
1991  }
1992  msg->security = crypt_smime_send_menu(msg);
1993  redraw_crypt_lines(msg);
1994  mutt_message_hook(NULL, msg, MUTT_SEND2_HOOK);
1995  break;
1996 
1997 #ifdef MIXMASTER
1998  case OP_COMPOSE_MIX:
1999  mix_make_chain(&msg->chain);
2000  mutt_message_hook(NULL, msg, MUTT_SEND2_HOOK);
2001  break;
2002 #endif
2003  }
2004  }
2005 
2006  mutt_menu_pop_current(menu);
2007  mutt_menu_destroy(&menu);
2008 
2009  if (actx->idxlen)
2010  msg->content = actx->idx[0]->content;
2011  else
2012  msg->content = NULL;
2013 
2014  mutt_actx_free(&actx);
2015 
2016  return rc;
2017 }
struct Email ** emails
Definition: mailbox.h:100
#define mutt_warning(...)
Definition: logging.h:86
The "current" mailbox.
Definition: context.h:37
struct NntpAccountData * nntp_select_server(struct Mailbox *m, char *server, bool leave_lock)
Open a connection to an NNTP server.
Definition: newsrc.c:992
struct Body * mutt_make_message_attach(struct Mailbox *m, struct Email *e, bool attach_msg)
Create a message attachment.
Definition: sendlib.c:1459
static int delete_attachment(struct AttachCtx *actx, int x)
Delete an attachment.
Definition: compose.c:552
void mutt_stamp_attachment(struct Body *a)
Timestamp an Attachment.
Definition: sendlib.c:1391
Unknown Content-Type.
Definition: mime.h:31
#define REDRAW_FULL
Redraw everything.
Definition: mutt_menu.h:47
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:48
#define NONULL(x)
Definition: string2.h:36
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:51
An email to which things will be attached.
Definition: attach.h:34
int mutt_attach_display_loop(struct Menu *menu, int op, struct Email *e, struct AttachCtx *actx, bool recv)
Event loop for the Attachment menu.
Definition: recvattach.c:1057
int msg_count
total number of messages
Definition: mailbox.h:93
struct Body * mutt_remove_multipart(struct Body *b)
Extract the multipart body if it exists.
Definition: sendlib.c:1713
#define CURATTACH
Definition: compose.c:101
#define MUTT_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:66
#define mutt_perror(...)
Definition: logging.h:89
GUI selectable list of items.
Definition: mutt_menu.h:82
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP mailbox? - Implements MxOps::path_probe()
Definition: imap.c:2454
struct ConnAccount account
Definition: connection.h:36
int mx_mbox_close(struct Context **ptr)
Save changes and close mailbox.
Definition: mx.c:529
int mutt_builtin_editor(const char *path, struct Email *msg, struct Email *cur)
Show the user the built-in editor.
Definition: edit.c:399
&#39;NNTP&#39; (Usenet) Mailbox type
Definition: magic.h:41
void mutt_pretty_mailbox(char *s, size_t buflen)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:605
const char * mutt_path_basename(const char *f)
Find the last component for a pathname.
Definition: path.c:304
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
User aborted the question (with Ctrl-G)
Definition: quad.h:37
enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
Ask the user a quad-question.
Definition: init.c:3369
#define mutt_message(...)
Definition: logging.h:87
struct Address * to
Definition: envelope.h:42
struct Email * email
used by recvattach for updating
Definition: attach.h:51
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
static void compose_custom_redraw(struct Menu *menu)
Redraw the compose menu - Implements Menu::menu_custom_redraw()
Definition: compose.c:678
void mutt_save_attachment_list(struct AttachCtx *actx, FILE *fp, bool tag, struct Body *top, struct Email *e, struct Menu *menu)
Save a list of attachments.
Definition: recvattach.c:588
void mutt_window_clrtoeol(struct MuttWindow *win)
Clear to the end of the line.
Definition: mutt_window.c:81
"To:" field
Definition: compose.c:111
struct Body * content
list of MIME parts
Definition: email.h:93
void crypt_forget_passphrase(void)
Forget a passphrase and display a message.
Definition: crypt.c:102
"Cc:" field
Definition: compose.c:112
int mutt_edit_attachment(struct Body *a)
Edit an attachment.
Definition: mutt_attach.c:248
#define _(a)
Definition: message.h:28
int crypt_smime_send_menu(struct Email *msg)
Wrapper for CryptModuleSpecs::send_menu()
Definition: cryptglue.c:478
struct Body * next
next attachment in the list
Definition: body.h:58
short idxlen
Definition: attach.h:55
Compose an email.
Definition: keymap.h:70
struct Context * mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:246
WHERE unsigned char C_Copy
Config: Save outgoing emails to $record.
Definition: globals.h:189
&#39;IMAP&#39; Mailbox type
Definition: magic.h:42
char * C_Ispell
Config: External command to perform spell-checking.
Definition: compose.c:89
int menu
menu definition for keymap entries.
Definition: mutt_menu.h:90
#define MUTT_READONLY
Open in read-only mode.
Definition: mx.h:53
"Subject:" field
Definition: compose.c:114
int mutt_env_to_intl(struct Envelope *env, const char **tag, char **err)
Convert an Envelope&#39;s Address fields to Punycode format.
Definition: envelope.c:238
#define SEC_ENCRYPT
Email is encrypted.
Definition: ncrypt.h:120
static int check_attachments(struct AttachCtx *actx)
Check if any attachments have changed or been deleted.
Definition: compose.c:399
"From:" field
Definition: compose.c:110
void(* menu_make_entry)(char *buf, size_t buflen, struct Menu *menu, int line)
Format a item for a menu.
Definition: mutt_menu.h:121
#define mutt_get_field(field, buf, buflen, complete)
Definition: curs_lib.h:77
The body of an email.
Definition: body.h:34
unsigned int disposition
content-disposition
Definition: body.h:72
char * mutt_compile_help(char *buf, size_t buflen, int menu, const struct Mapping *items)
Create the text for the help menu.
Definition: help.c:115
void mutt_paddstr(int n, const char *s)
Display a string on screen, padded if necessary.
Definition: curs_lib.c:1083
struct Address * reply_to
Definition: envelope.h:46
static void snd_make_entry(char *buf, size_t buflen, struct Menu *menu, int line)
Format a menu item for the attachment list - Implements Menu::menu_make_entry()
Definition: compose.c:255
int mutt_file_rename(const char *oldfile, const char *newfile)
Rename a file.
Definition: file.c:1238
void mutt_generate_boundary(struct ParameterList *parm)
Create a unique boundary id for a MIME part.
Definition: sendlib.c:570
static void edit_address_list(int line, struct Address **addr)
Let the user edit the address list.
Definition: compose.c:517
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:157
void * redraw_data
Definition: mutt_menu.h:151
void mutt_print_attachment_list(struct AttachCtx *actx, FILE *fp, bool tag, struct Body *top)
Print a list of Attachments.
Definition: recvattach.c:940
int mutt_get_tmp_attachment(struct Body *a)
Get a temporary copy of an attachment.
Definition: mutt_attach.c:67
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:330
WHERE bool C_EditHeaders
Config: Let the user edit the email headers whilst editing an email.
Definition: globals.h:216
struct Mailbox * mailbox
Definition: context.h:51
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
int mutt_enter_fname_full(const char *prompt, char *buf, size_t buflen, bool mailbox, bool multiple, char ***files, int *numfiles, SelectFileFlags flags)
Ask the user to select a file.
Definition: curs_lib.c:608
struct Body * mutt_make_file_attach(const char *path)
Create a file attachment.
Definition: sendlib.c:1591
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:103
enum MailboxType magic
mailbox type
Definition: mailbox.h:106
void mutt_update_encoding(struct Body *a)
Update the encoding type.
Definition: sendlib.c:1428
void mutt_window_clearline(struct MuttWindow *win, int row)
Clear a row of a Window.
Definition: mutt_window.c:69
struct Envelope * env
envelope information
Definition: email.h:92
#define ENCODING(x)
Definition: mime.h:85
void mx_fastclose_mailbox(struct Mailbox *m)
free up memory associated with the Mailbox
Definition: mx.c:368
Content is attached.
Definition: mime.h:63
static void compose_attach_swap(struct Body *msg, struct AttachPtr **idx, short first)
Swap two adjacent entries in the attachment list.
Definition: compose.c:727
void(* menu_custom_redraw)(struct Menu *menu)
Redraw the menu.
Definition: mutt_menu.h:150
WHERE short C_Sort
Config: Sort method for the index.
Definition: sort.h:58
bool tagged
Definition: body.h:77
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:141
struct Address * from
Definition: envelope.h:41
void ctx_free(struct Context **ctx)
Free a Context.
Definition: context.c:47
bool unowned
don&#39;t unlink on detach
Definition: attach.h:42
struct Body * mutt_make_multipart(struct Body *b)
Create a multipart email.
Definition: sendlib.c:1687
char * subtype
content-type subtype
Definition: body.h:37
void mutt_actx_free(struct AttachCtx **pactx)
Free an Attachment Context.
Definition: attach.c:119
void crypt_opportunistic_encrypt(struct Email *msg)
Can all recipients be determined.
Definition: crypt.c:985
WHERE char * C_NewsServer
Config: (nntp) Url of the news server.
Definition: globals.h:135
static const struct Mapping ComposeHelp[]
Definition: compose.c:175
char * x_comment_to
Definition: envelope.h:62
struct Address * bcc
Definition: envelope.h:44
void mutt_actx_free_entries(struct AttachCtx *actx)
Free entries in an Attachment Context.
Definition: attach.c:94
WHERE short C_SortAux
Config: Secondary sort method for the index.
Definition: sort.h:59
#define HDR_XOFFSET
Definition: compose.c:133
#define SEC_SIGN
Email is signed.
Definition: ncrypt.h:121
WHERE struct Context * Context
Definition: globals.h:41
int attach_tag(struct Menu *menu, int sel, int act)
Tag an attachment - Implements Menu::menu_tag()
Definition: recvattach.c:444
WHERE bool C_CryptOpportunisticEncrypt
Config: Enable encryption when the recipient&#39;s key is available.
Definition: globals.h:275
WHERE bool OptAttachMsg
(pseudo) used by attach-message
Definition: options.h:31
#define REDRAW_STATUS
Redraw the status bar.
Definition: mutt_menu.h:46
int mutt_check_encoding(const char *c)
Check the encoding type.
Definition: parse.c:403
#define ALTS_TAG
A mailbox.
Definition: mailbox.h:83
#define PATH_MAX
Definition: mutt.h:48
struct MuttWindow * MuttIndexWindow
Index Window.
Definition: mutt_window.c:39
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:38
int mix_check_message(struct Email *msg)
Safety-check the message before passing it to mixmaster.
Definition: remailer.c:770
bool tagprefix
Definition: mutt_menu.h:93
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:59
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:741
FILE * fp
used in the recvattach menu.
Definition: attach.h:37
void mix_make_chain(struct ListHead *chainhead)
Create a Mixmaster chain.
Definition: remailer.c:553
static void mutt_update_compose_menu(struct AttachCtx *actx, struct Menu *menu, bool init)
Redraw the compose window.
Definition: compose.c:623
char * description
content-description
Definition: body.h:40
bool mutt_is_text_part(struct Body *b)
Is this part of an email in plain text?
Definition: muttlib.c:427
SecurityFlags security
bit 0-8: flags, bit 9,10: application.
Definition: email.h:39
#define W
Definition: compose.c:134
#define MUTT_SEL_MULTI
Multi-selection is enabled.
Definition: browser.h:43
void mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:459
static struct Mapping ComposeNewsHelp[]
Definition: compose.c:191
int tagged
number of tagged entries
Definition: mutt_menu.h:112
void nntp_expand_path(char *buf, size_t buflen, struct ConnAccount *acct)
Make fully qualified url from newsgroup name.
Definition: newsrc.c:554
#define MUTT_FILE
Do file completion.
Definition: mutt.h:62
int mutt_window_move(struct MuttWindow *win, int row, int col)
Move the cursor in a Window.
Definition: mutt_window.c:162
unsigned int type
content-type primary type
Definition: body.h:70
int(* menu_tag)(struct Menu *menu, int sel, int act)
Tag some menu items.
Definition: mutt_menu.h:138
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: ncrypt.h:129
"Bcc:" field
Definition: compose.c:113
#define LINGUAL_TAG
char path[PATH_MAX]
Definition: mailbox.h:85
MuttRedrawFlags redraw
when to redraw the screen
Definition: mutt_menu.h:89
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:546
bool crypt_has_module_backend(SecurityFlags type)
Is there a crypto backend for a given type?
Definition: cryptglue.c:151
struct Connection * conn
Definition: nntp.h:103
void mutt_pipe_attachment_list(struct AttachCtx *actx, FILE *fp, bool tag, struct Body *top, bool filter)
Pipe a list of attachments to a command.
Definition: recvattach.c:791
void mutt_env_to_local(struct Envelope *env)
Convert an Envelope&#39;s Address fields to local format.
Definition: envelope.c:203
struct Body * crypt_pgp_make_key_attachment(void)
Wrapper for CryptModuleSpecs::pgp_make_key_attachment()
Definition: cryptglue.c:259
int offset
row offset within the window to start the index
Definition: mutt_menu.h:91
void mutt_body_free(struct Body **p)
Free a Body.
Definition: body.c:57
char * subject
Definition: envelope.h:50
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
char * newsgroups
Definition: envelope.h:59
#define MUTT_SEND2_HOOK
send2-hook: when changing fields in the compose menu
Definition: hook.h:55
#define REDRAW_INDEX
Redraw the index.
Definition: mutt_menu.h:42
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:383
WHERE bool C_XCommentTo
Config: (nntp) Add &#39;X-Comment-To&#39; header that contains article author.
Definition: globals.h:289
struct Body * content
Definition: attach.h:36
void mutt_edit_headers(const char *editor, const char *body, struct Email *msg, char *fcc, size_t fcclen)
Let the user edit the message header and body.
Definition: mutt_header.c:171
unsigned char C_Postpone
Config: Save messages to the C_Postponed folder.
Definition: compose.c:90
#define mutt_error(...)
Definition: logging.h:88
enum MailboxType pop_path_probe(const char *path, const struct stat *st)
Is this a POP mailbox? - Implements MxOps::path_probe()
Definition: pop.c:1231
bool unlink
flag to indicate the file named by "filename" should be unlink()ed before free()ing this structure ...
Definition: body.h:74
char * followup_to
Definition: envelope.h:61
WHERE char * C_Editor
Config: External command to use as an email editor.
Definition: globals.h:112
#define mutt_enter_fname(prompt, buf, buflen, mailbox)
Definition: curs_lib.h:76
int mutt_check_mime_type(const char *s)
Check a MIME type string.
Definition: parse.c:294
#define FREE(x)
Definition: memory.h:40
struct Mailbox * mx_path_resolve(const char *path)
XXX.
Definition: mx.c:1506
#define MUTT_COMPOSE_NOFREEHEADER
Definition: compose.h:36
#define STAILQ_EMPTY(head)
Definition: queue.h:346
Position to start printing the attachments.
Definition: compose.c:127
static void update_idx(struct Menu *menu, struct AttachCtx *actx, struct AttachPtr *new)
Add a new attchment to the message.
Definition: compose.c:652
static void redraw_crypt_lines(struct Email *msg)
Update the encryption info in the compose window.
Definition: compose.c:268
struct MuttWindow * MuttMessageWindow
Message Window.
Definition: mutt_window.c:41
static void init_header_padding(void)
Calculate how much padding the compose table will need.
Definition: compose.c:228
void mutt_message_hook(struct Mailbox *m, struct Email *e, HookFlags type)
Perform a message hook.
Definition: hook.c:441
enum MailboxType nntp_path_probe(const char *path, const struct stat *st)
Is this an NNTP mailbox? - Implements MxOps::path_probe()
Definition: nntp.c:2847
bool mutt_edit_content_type(struct Email *e, struct Body *b, FILE *fp)
Edit the content type of an attachment.
Definition: commands.c:1175
int current
current entry
Definition: mutt_menu.h:87
WHERE bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: options.h:43
"Fcc:" (save folder) field
Definition: compose.c:116
#define CHECK_COUNT
Definition: compose.c:94
int mutt_index_menu(void)
Display a list of emails.
Definition: index.c:1017
Content is inline.
Definition: mime.h:62
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
#define WithCrypto
Definition: ncrypt.h:155
A set of attachments.
Definition: attach.h:49
Encoding unknown.
Definition: mime.h:48
struct AttachPtr ** idx
Definition: attach.h:54
void mutt_edit_file(const char *editor, const char *file)
Let the user edit a file.
Definition: curs_lib.c:308
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:42
char * help
quickref for the current menu
Definition: mutt_menu.h:85
Keep track when the compose screen needs redrawing.
Definition: compose.c:666
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:611
int mutt_system(const char *cmd)
Run an external command.
Definition: system.c:50
QuadOption
Possible values for a quad-option.
Definition: quad.h:35
UUEncoded text.
Definition: mime.h:54
bool message_is_tagged(struct Context *ctx, int index)
Is a message in the index tagged (and within limit)
Definition: context.c:311
#define REDRAW_CURRENT
Redraw the current line of the menu.
Definition: mutt_menu.h:45
int mutt_compose_attachment(struct Body *a)
Create an attachment.
Definition: mutt_attach.c:111
struct Address * cc
Definition: envelope.h:43
struct NntpAccountData * CurrentNewsSrv
Current NNTP news server.
Definition: nntp.c:79
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: ncrypt.h:130
&#39;POP3&#39; Mailbox type
Definition: magic.h:44
"Reply-To:" field
Definition: compose.c:115
int crypt_pgp_send_menu(struct Email *msg)
Wrapper for CryptModuleSpecs::send_menu()
Definition: cryptglue.c:323
int mutt_write_fcc(const char *path, struct Email *e, const char *msgid, bool post, char *fcc, char **finalpath)
Write email to FCC mailbox.
Definition: sendlib.c:3132

+ Here is the caller graph for this function:

Variable Documentation

char* C_ComposeFormat

Config: printf-like format string for the Compose panel's status bar.

Definition at line 88 of file compose.c.

char* C_Ispell

Config: External command to perform spell-checking.

Definition at line 89 of file compose.c.

unsigned char C_Postpone

Config: Save messages to the C_Postponed folder.

Definition at line 90 of file compose.c.

const char* There_are_no_attachments = N_("There are no attachments")
static

Definition at line 92 of file compose.c.

int HeaderPadding[HDR_XCOMMENTTO+1] = { 0 }

Definition at line 130 of file compose.c.

int MaxHeaderWidth = 0

Definition at line 131 of file compose.c.

const char* const Prompts[]
static

Definition at line 136 of file compose.c.

const struct Mapping ComposeHelp[]
static
Initial value:
= {
{ N_("Send"), OP_COMPOSE_SEND_MESSAGE },
{ N_("Abort"), OP_EXIT },
{ N_("To"), OP_COMPOSE_EDIT_TO },
{ N_("CC"), OP_COMPOSE_EDIT_CC },
{ N_("Subj"), OP_COMPOSE_EDIT_SUBJECT },
{ N_("Attach file"), OP_COMPOSE_ATTACH_FILE },
{ N_("Descrip"), OP_COMPOSE_EDIT_DESCRIPTION },
{ N_("Help"), OP_HELP },
{ NULL, 0 },
}
#define N_(a)
Definition: message.h:32

Definition at line 175 of file compose.c.

struct Mapping ComposeNewsHelp[]
static
Initial value:
= {
{ N_("Send"), OP_COMPOSE_SEND_MESSAGE },
{ N_("Abort"), OP_EXIT },
{ N_("Newsgroups"), OP_COMPOSE_EDIT_NEWSGROUPS },
{ N_("Subj"), OP_COMPOSE_EDIT_SUBJECT },
{ N_("Attach file"), OP_COMPOSE_ATTACH_FILE },
{ N_("Descrip"), OP_COMPOSE_EDIT_DESCRIPTION },
{ N_("Help"), OP_HELP },
{ NULL, 0 },
}
#define N_(a)
Definition: message.h:32

Definition at line 191 of file compose.c.