NeoMutt  2018-07-16 +1783-b00bd9
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 "address/lib.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 CUR_ATTACH   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:93
#define _(a)
Definition: message.h:28
#define mutt_error(...)
Definition: logging.h:83

Definition at line 95 of file compose.c.

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

Definition at line 102 of file compose.c.

#define HDR_XOFFSET   MaxHeaderWidth

Definition at line 134 of file compose.c.

#define W   (MuttIndexWindow->cols - MaxHeaderWidth)

Definition at line 135 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 109 of file compose.c.

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

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 210 of file compose.c.

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

+ 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 229 of file compose.c.

230 {
231  static bool done = false;
232 
233  if (done)
234  return;
235  done = true;
236 
237  for (int i = 0; i <= HDR_XCOMMENTTO; i++)
238  calc_header_width_padding(i, _(Prompts[i]), true);
239 
240  /* Don't include "Sign as: " in the MaxHeaderWidth calculation. It
241  * doesn't show up by default, and so can make the indentation of
242  * the other fields look funny. */
244 
245  for (int i = 0; i <= HDR_XCOMMENTTO; i++)
246  {
248  if (HeaderPadding[i] < 0)
249  HeaderPadding[i] = 0;
250  }
251 }
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:210
int MaxHeaderWidth
Definition: compose.c:132
#define _(a)
Definition: message.h:28
"Sign as:" field (encryption/signing info)
Definition: compose.c:122
"X-Comment-To:" field
Definition: compose.c:126
int HeaderPadding[HDR_XCOMMENTTO+1]
Definition: compose.c:131
static const char *const Prompts[]
Definition: compose.c:137

+ 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 256 of file compose.c.

257 {
258  struct AttachCtx *actx = menu->data;
259 
261  attach_format_str, (unsigned long) (actx->idx[actx->v2r[line]]),
263 }
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:836
#define NONULL(x)
Definition: string2.h:36
WHERE char * C_AttachFormat
Config: printf-like format string for the attachment menu.
Definition: globals.h:98
#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 269 of file compose.c.

270 {
273  HeaderPadding[HDR_CRYPT], _(Prompts[HDR_CRYPT]));
274  NORMAL_COLOR;
275 
277  {
278  addstr(_("Not supported"));
279  return;
280  }
281 
282  if ((msg->security & (SEC_ENCRYPT | SEC_SIGN)) == (SEC_ENCRYPT | SEC_SIGN))
283  {
285  addstr(_("Sign, Encrypt"));
286  }
287  else if (msg->security & SEC_ENCRYPT)
288  {
290  addstr(_("Encrypt"));
291  }
292  else if (msg->security & SEC_SIGN)
293  {
295  addstr(_("Sign"));
296  }
297  else
298  {
299  /* L10N: This refers to the encryption of the email, e.g. "Security: None" */
301  addstr(_("None"));
302  }
303  NORMAL_COLOR;
304 
305  if ((msg->security & (SEC_ENCRYPT | SEC_SIGN)))
306  {
307  if (((WithCrypto & APPLICATION_PGP) != 0) && (msg->security & APPLICATION_PGP))
308  {
309  if ((msg->security & SEC_INLINE))
310  addstr(_(" (inline PGP)"));
311  else
312  addstr(_(" (PGP/MIME)"));
313  }
314  else if (((WithCrypto & APPLICATION_SMIME) != 0) && (msg->security & APPLICATION_SMIME))
315  addstr(_(" (S/MIME)"));
316  }
317 
319  addstr(_(" (OppEnc mode)"));
320 
324 
325  if (((WithCrypto & APPLICATION_PGP) != 0) &&
326  (msg->security & APPLICATION_PGP) && (msg->security & SEC_SIGN))
327  {
329  printw("%*s", HeaderPadding[HDR_CRYPTINFO], _(Prompts[HDR_CRYPTINFO]));
330  NORMAL_COLOR;
331  printw("%s", C_PgpSignAs ? C_PgpSignAs : _("<default>"));
332  }
333 
334  if (((WithCrypto & APPLICATION_SMIME) != 0) &&
335  (msg->security & APPLICATION_SMIME) && (msg->security & SEC_SIGN))
336  {
338  printw("%*s", HeaderPadding[HDR_CRYPTINFO], _(Prompts[HDR_CRYPTINFO]));
339  NORMAL_COLOR;
340  printw("%s", C_SmimeSignAs ? C_SmimeSignAs : _("<default>"));
341  }
342 
343  if (((WithCrypto & APPLICATION_SMIME) != 0) && (msg->security & APPLICATION_SMIME) &&
345  {
347  mutt_window_mvprintw(MuttIndexWindow, HDR_CRYPTINFO, 40, "%s", _("Encrypt with: "));
348  NORMAL_COLOR;
349  printw("%s", NONULL(C_SmimeEncryptWith));
350  }
351 }
Header labels, e.g. From:
Definition: mutt_curses.h:168
#define NONULL(x)
Definition: string2.h:36
Mail will not be encrypted or signed.
Definition: mutt_curses.h:172
#define NORMAL_COLOR
Definition: mutt_curses.h:239
Mail will be encrypted.
Definition: mutt_curses.h:169
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:122
Mail will be signed.
Definition: mutt_curses.h:170
Mail will be encrypted and signed.
Definition: mutt_curses.h:171
#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:267
struct MuttWindow * MuttIndexWindow
Index Window.
Definition: mutt_window.c:39
WHERE char * C_SmimeEncryptWith
Config: Algorithm for encryption.
Definition: globals.h:168
int HeaderPadding[HDR_XCOMMENTTO+1]
Definition: compose.c:131
"Security:" field (encryption/signing info)
Definition: compose.c:121
static const char *const Prompts[]
Definition: compose.c:137
SecurityFlags security
bit 0-8: flags, bit 9,10: application.
Definition: email.h:39
#define SET_COLOR(X)
Definition: mutt_curses.h:224
int mutt_window_move(struct MuttWindow *win, int row, int col)
Move the cursor in a Window.
Definition: mutt_window.c:162
#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:220
WHERE char * C_PgpSignAs
Config: Use this alternative key for signing messages.
Definition: globals.h:163
WHERE char * C_SmimeSignAs
Config: Use this alternative key for signing messages.
Definition: globals.h:167
#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 400 of file compose.c.

401 {
402  struct stat st;
403  char pretty[PATH_MAX], msg[PATH_MAX + 128];
404 
405  for (int i = 0; i < actx->idxlen; i++)
406  {
407  if (actx->idx[i]->content->type == TYPE_MULTIPART)
408  continue;
409  mutt_str_strfcpy(pretty, actx->idx[i]->content->filename, sizeof(pretty));
410  if (stat(actx->idx[i]->content->filename, &st) != 0)
411  {
412  mutt_pretty_mailbox(pretty, sizeof(pretty));
413  mutt_error(_("%s [#%d] no longer exists"), pretty, i + 1);
414  return -1;
415  }
416 
417  if (actx->idx[i]->content->stamp < st.st_mtime)
418  {
419  mutt_pretty_mailbox(pretty, sizeof(pretty));
420  snprintf(msg, sizeof(msg), _("%s [#%d] modified. Update encoding?"), pretty, i + 1);
421 
422  enum QuadOption ans = mutt_yesorno(msg, MUTT_YES);
423  if (ans == MUTT_YES)
424  mutt_update_encoding(actx->idx[i]->content);
425  else if (ans == MUTT_ABORT)
426  return -1;
427  }
428  }
429 
430  return 0;
431 }
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:48
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:332
void mutt_update_encoding(struct Body *a)
Update the encoding type.
Definition: sendlib.c:1447
#define PATH_MAX
Definition: mutt.h:49
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:753
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:615
unsigned int type
content-type primary type
Definition: body.h:72
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:68
#define mutt_error(...)
Definition: logging.h:83
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 438 of file compose.c.

439 {
440  char buf[1024];
441 
442  buf[0] = '\0';
443  mutt_addr_write(buf, sizeof(buf), addr, true);
446  _(Prompts[line]));
447  NORMAL_COLOR;
448  mutt_paddstr(W, buf);
449 }
Header labels, e.g. From:
Definition: mutt_curses.h:168
#define NORMAL_COLOR
Definition: mutt_curses.h:239
#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:1146
size_t mutt_addr_write(char *buf, size_t buflen, struct Address *addr, bool display)
Write an Address to a buffer.
Definition: address.c:1184
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:131
static const char *const Prompts[]
Definition: compose.c:137
#define W
Definition: compose.c:135
#define SET_COLOR(X)
Definition: mutt_curses.h:224
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:220

+ 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 456 of file compose.c.

457 {
459 #ifdef USE_NNTP
460  if (!OptNewsSend)
461  {
462 #endif
466 #ifdef USE_NNTP
467  }
468  else
469  {
471  HeaderPadding[HDR_NEWSGROUPS], Prompts[HDR_NEWSGROUPS]);
474  HeaderPadding[HDR_FOLLOWUPTO], Prompts[HDR_FOLLOWUPTO]);
476  if (C_XCommentTo)
477  {
479  HeaderPadding[HDR_XCOMMENTTO], Prompts[HDR_XCOMMENTTO]);
481  }
482  }
483 #endif
484 
487  HeaderPadding[HDR_SUBJECT], _(Prompts[HDR_SUBJECT]));
488  NORMAL_COLOR;
489  mutt_paddstr(W, NONULL(msg->env->subject));
490 
492 
495  HeaderPadding[HDR_FCC], _(Prompts[HDR_FCC]));
496  NORMAL_COLOR;
497  mutt_paddstr(W, fcc);
498 
499  if (WithCrypto)
500  redraw_crypt_lines(msg);
501 
502 #ifdef MIXMASTER
503  redraw_mix_line(&msg->chain);
504 #endif
505 
507  mutt_window_mvaddstr(MuttIndexWindow, HDR_ATTACH - 1, 0, _("-- Attachments"));
509 
510  NORMAL_COLOR;
511 }
Header labels, e.g. From:
Definition: mutt_curses.h:168
#define NONULL(x)
Definition: string2.h:36
struct Address * to
Definition: envelope.h:42
#define NORMAL_COLOR
Definition: mutt_curses.h:239
void mutt_window_clrtoeol(struct MuttWindow *win)
Clear to the end of the line.
Definition: mutt_window.c:81
"To:" field
Definition: compose.c:112
"Cc:" field
Definition: compose.c:113
#define _(a)
Definition: message.h:28
"Subject:" field
Definition: compose.c:115
"From:" field
Definition: compose.c:111
void mutt_paddstr(int n, const char *s)
Display a string on screen, padded if necessary.
Definition: curs_lib.c:1146
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:438
struct Envelope * env
envelope information
Definition: email.h:92
"X-Comment-To:" field
Definition: compose.c:126
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:131
static const char *const Prompts[]
Definition: compose.c:137
#define SET_COLOR(X)
Definition: mutt_curses.h:224
#define W
Definition: compose.c:135
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
"Bcc:" field
Definition: compose.c:114
"Followup-To:" field
Definition: compose.c:125
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:281
char * followup_to
Definition: envelope.h:61
Status bar.
Definition: mutt_curses.h:129
Position to start printing the attachments.
Definition: compose.c:128
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:220
"Newsgroups:" field
Definition: compose.c:124
static void redraw_crypt_lines(struct Email *msg)
Update the encryption info in the compose window.
Definition: compose.c:269
WHERE bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: options.h:43
"Fcc:" (save folder) field
Definition: compose.c:117
#define WithCrypto
Definition: ncrypt.h:155
struct Address * cc
Definition: envelope.h:43
"Reply-To:" field
Definition: compose.c:116

+ 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 518 of file compose.c.

519 {
520  char buf[8192] = ""; /* needs to be large for alias expansion */
521  char *err = NULL;
522 
523  mutt_addrlist_to_local(*addr);
524  mutt_addr_write(buf, sizeof(buf), *addr, false);
525  if (mutt_get_field(_(Prompts[line]), buf, sizeof(buf), MUTT_ALIAS) == 0)
526  {
527  mutt_addr_free(addr);
528  *addr = mutt_addr_parse_list2(*addr, buf);
529  *addr = mutt_expand_aliases(*addr);
530  }
531 
532  if (mutt_addrlist_to_intl(*addr, &err) != 0)
533  {
534  mutt_error(_("Bad IDN: '%s'"), err);
535  mutt_refresh();
536  FREE(&err);
537  }
538 
539  /* redraw the expanded list so the user can see the result */
540  buf[0] = '\0';
541  mutt_addr_write(buf, sizeof(buf), *addr, true);
543  mutt_paddstr(W, buf);
544 }
struct Address * mutt_addr_parse_list2(struct Address *p, const char *s)
Parse a list of email addresses.
Definition: address.c:641
#define MUTT_ALIAS
Do alias "completion" by calling up the alias-menu.
Definition: mutt.h:62
#define _(a)
Definition: message.h:28
#define mutt_get_field(field, buf, buflen, complete)
Definition: curs_lib.h:86
void mutt_paddstr(int n, const char *s)
Display a string on screen, padded if necessary.
Definition: curs_lib.c:1146
int mutt_addrlist_to_local(struct Address *a)
Convert an Address list from Punycode.
Definition: address.c:1290
size_t mutt_addr_write(char *buf, size_t buflen, struct Address *addr, bool display)
Write an Address to a buffer.
Definition: address.c:1184
void mutt_refresh(void)
Force a refresh of the screen.
Definition: curs_lib.c:99
const char * line
Definition: common.c:35
#define HDR_XOFFSET
Definition: compose.c:134
struct MuttWindow * MuttIndexWindow
Index Window.
Definition: mutt_window.c:39
int mutt_addrlist_to_intl(struct Address *a, char **err)
Convert an Address list to Punycode.
Definition: address.c:1249
static const char *const Prompts[]
Definition: compose.c:137
#define W
Definition: compose.c:135
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:298
#define mutt_error(...)
Definition: logging.h:83
#define FREE(x)
Definition: memory.h:40
void mutt_addr_free(struct Address **p)
Free a list of Addresses.
Definition: address.c:451

+ 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 553 of file compose.c.

554 {
555  struct AttachPtr **idx = actx->idx;
556  int rindex = actx->v2r[x];
557 
558  if ((rindex == 0) && (actx->idxlen == 1))
559  {
560  mutt_error(_("You may not delete the only attachment"));
561  idx[rindex]->content->tagged = false;
562  return -1;
563  }
564 
565  for (int y = 0; y < actx->idxlen; y++)
566  {
567  if (idx[y]->content->next == idx[rindex]->content)
568  {
569  idx[y]->content->next = idx[rindex]->content->next;
570  break;
571  }
572  }
573 
574  idx[rindex]->content->next = NULL;
575  idx[rindex]->content->parts = NULL;
576  mutt_body_free(&(idx[rindex]->content));
577  FREE(&idx[rindex]->tree);
578  FREE(&idx[rindex]);
579  for (; rindex < actx->idxlen - 1; rindex++)
580  idx[rindex] = idx[rindex + 1];
581  idx[actx->idxlen - 1] = NULL;
582  actx->idxlen--;
583 
584  return 0;
585 }
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:60
short idxlen
Definition: attach.h:55
char * tree
Definition: attach.h:39
bool tagged
Definition: body.h:79
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:61
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:83
#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 594 of file compose.c.

596 {
597  for (; m; m = m->next)
598  {
599  if ((m->type == TYPE_MULTIPART) && m->parts &&
601  {
603  }
604  else
605  {
606  struct AttachPtr *new = mutt_mem_calloc(1, sizeof(struct AttachPtr));
607  mutt_actx_add_attach(actx, new);
608  new->content = m;
609  m->aptr = new;
610  new->parent_type = parent_type;
611  new->level = level;
612 
613  /* We don't support multipart messages in the compose menu yet */
614  }
615  }
616 }
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:60
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:594
SecurityFlags mutt_is_multipart_encrypted(struct Body *b)
Does the message have encrypted parts?
Definition: crypt.c:417
int parent_type
Definition: attach.h:38
struct AttachPtr * aptr
Menu information, used in recvattach.c.
Definition: body.h:64
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:61
unsigned int type
content-type primary type
Definition: body.h:72
#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 624 of file compose.c.

625 {
626  if (init)
627  {
628  mutt_gen_compose_attach_list(actx, actx->email->content, -1, 0);
629  mutt_attach_init(actx);
630  menu->data = actx;
631  }
632 
633  mutt_update_tree(actx);
634 
635  menu->max = actx->vcount;
636  if (menu->max)
637  {
638  if (menu->current >= menu->max)
639  menu->current = menu->max - 1;
640  }
641  else
642  menu->current = 0;
643 
644  menu->redraw |= REDRAW_INDEX | REDRAW_STATUS;
645 }
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:594
#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:1248
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 653 of file compose.c.

654 {
655  new->level = (actx->idxlen > 0) ? actx->idx[actx->idxlen - 1]->level : 0;
656  if (actx->idxlen)
657  actx->idx[actx->idxlen - 1]->content->next = new->content;
658  new->content->aptr = new;
659  mutt_actx_add_attach(actx, new);
660  mutt_update_compose_menu(actx, menu, false);
661  menu->current = actx->vcount - 1;
662 }
struct Content * content
structure used to store detailed info about the content of the attachment.
Definition: body.h:56
struct Body * next
next attachment in the list
Definition: body.h:60
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:624
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 866 of file compose.c.

868 {
869  mutt_expando_format(buf, buflen, col, cols, src, compose_format_str,
870  (unsigned long) menu, MUTT_FORMAT_NO_FLAGS);
871 }
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:836
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:808
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: format_flags.h:30

+ 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 679 of file compose.c.

680 {
681  struct ComposeRedrawData *rd = menu->redraw_data;
682 
683  if (!rd)
684  return;
685 
686  if (menu->redraw & REDRAW_FULL)
687  {
688  menu_redraw_full(menu);
689 
690  draw_envelope(rd->email, rd->fcc);
691  menu->offset = HDR_ATTACH;
693  }
694 
695  menu_check_recenter(menu);
696 
697  if (menu->redraw & REDRAW_STATUS)
698  {
699  char buf[1024];
700  compose_status_line(buf, sizeof(buf), 0, MuttStatusWindow->cols, menu,
705  NORMAL_COLOR;
706  menu->redraw &= ~REDRAW_STATUS;
707  }
708 
709 #ifdef USE_SIDEBAR
710  if (menu->redraw & REDRAW_SIDEBAR)
711  menu_redraw_sidebar(menu);
712 #endif
713 
714  if (menu->redraw & REDRAW_INDEX)
715  menu_redraw_index(menu);
716  else if (menu->redraw & (REDRAW_MOTION | REDRAW_MOTION_RESYNC))
717  menu_redraw_motion(menu);
718  else if (menu->redraw == REDRAW_CURRENT)
719  menu_redraw_current(menu);
720 }
#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:239
struct Email * email
Definition: compose.c:669
static void draw_envelope(struct Email *msg, char *fcc)
Write the email headers to the compose window.
Definition: compose.c:456
#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:1146
void * redraw_data
Definition: mutt_menu.h:152
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:866
#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
#define SET_COLOR(X)
Definition: mutt_curses.h:224
int mutt_window_move(struct MuttWindow *win, int row, int col)
Move the cursor in a Window.
Definition: mutt_window.c:162
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:129
Position to start printing the attachments.
Definition: compose.c:128
char * C_ComposeFormat
Config: printf-like format string for the Compose panel&#39;s status bar.
Definition: compose.c:89
Keep track when the compose screen needs redrawing.
Definition: compose.c:667
#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 728 of file compose.c.

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

763 {
764  size_t s = 0;
765  struct AttachCtx *actx = menu->data;
766  struct AttachPtr **idx = actx->idx;
767  struct Content *info = NULL;
768  struct Body *b = NULL;
769 
770  for (unsigned short i = 0; i < actx->idxlen; i++)
771  {
772  b = idx[i]->content;
773 
774  if (!b->content)
776 
777  info = b->content;
778  if (info)
779  {
780  switch (b->encoding)
781  {
783  s += 3 * (info->lobin + info->hibin) + info->ascii + info->crlf;
784  break;
785  case ENC_BASE64:
786  s += (4 * (info->lobin + info->hibin + info->ascii + info->crlf)) / 3;
787  break;
788  default:
789  s += info->lobin + info->hibin + info->ascii + info->crlf;
790  break;
791  }
792  }
793  }
794 
795  return s;
796 }
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:56
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:998
unsigned int encoding
content-transfer-encoding
Definition: body.h:73
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 808 of file compose.c.

812 {
813  char fmt[128], tmp[128];
814  int optional = (flags & MUTT_FORMAT_OPTIONAL);
815  struct Menu *menu = (struct Menu *) data;
816 
817  *buf = '\0';
818  switch (op)
819  {
820  case 'a': /* total number of attachments */
821  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
822  snprintf(buf, buflen, fmt, menu->max);
823  break;
824 
825  case 'h': /* hostname */
826  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
827  snprintf(buf, buflen, fmt, NONULL(ShortHostname));
828  break;
829 
830  case 'l': /* approx length of current message in bytes */
831  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
832  mutt_str_pretty_size(tmp, sizeof(tmp), menu ? cum_attachs_size(menu) : 0);
833  snprintf(buf, buflen, fmt, tmp);
834  break;
835 
836  case 'v':
837  snprintf(buf, buflen, "%s", mutt_make_version());
838  break;
839 
840  case 0:
841  *buf = '\0';
842  return src;
843 
844  default:
845  snprintf(buf, buflen, "%%%s%c", prec, op);
846  break;
847  }
848 
849  if (optional)
850  compose_status_line(buf, buflen, col, cols, menu, if_str);
851  else if (flags & MUTT_FORMAT_OPTIONAL)
852  compose_status_line(buf, buflen, col, cols, menu, else_str);
853 
854  return src;
855 }
#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:866
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:762
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:1049
const char * mutt_make_version(void)
Generate the NeoMutt version string.
Definition: muttlib.c:1512

+ 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 884 of file compose.c.

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

+ 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 89 of file compose.c.

char* C_Ispell

Config: External command to perform spell-checking.

Definition at line 90 of file compose.c.

unsigned char C_Postpone

Config: Save messages to the C_Postponed folder.

Definition at line 91 of file compose.c.

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

Definition at line 93 of file compose.c.

int HeaderPadding[HDR_XCOMMENTTO+1] = { 0 }

Definition at line 131 of file compose.c.

int MaxHeaderWidth = 0

Definition at line 132 of file compose.c.

const char* const Prompts[]
static

Definition at line 137 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 176 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 192 of file compose.c.