NeoMutt  2020-11-20
Teaching an old dog new tricks
DOXYGEN
protos.h File Reference

Prototypes for many functions. More...

#include "config.h"
#include <stddef.h>
#include <stdbool.h>
#include <stdio.h>
#include "mutt/lib.h"
#include "mutt.h"
#include "ncrypt/lib.h"
#include "keymap.h"
+ Include dependency graph for protos.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define mutt_set_flag(m, e, flag, bf)   mutt_set_flag_update(m, e, flag, bf, true)
 

Enumerations

enum  XdgType { XDG_CONFIG_HOME, XDG_CONFIG_DIRS }
 XDG variable types. More...
 
enum  EvMessage { EVM_VIEW, EVM_EDIT }
 Edit or View a message. More...
 

Functions

int mutt_ev_message (struct Mailbox *m, struct EmailList *el, enum EvMessage action)
 Edit or view a message. More...
 
int mutt_system (const char *cmd)
 Run an external command. More...
 
int mutt_set_xdg_path (enum XdgType type, struct Buffer *buf)
 Find an XDG path or its fallback. More...
 
void mutt_help (enum MenuType menu, int wraplan)
 Display the help menu. More...
 
void mutt_set_flag_update (struct Mailbox *m, struct Email *e, int flag, bool bf, bool upd_mbox)
 Set a flag on an email. More...
 
void mutt_signal_init (void)
 Initialise the signal handling. More...
 
void mutt_emails_set_flag (struct Mailbox *m, struct EmailList *el, int flag, bool bf)
 Set flag on messages. More...
 
int mutt_change_flag (struct Mailbox *m, struct EmailList *el, bool bf)
 Change the flag on a Message. More...
 
int mutt_complete (char *buf, size_t buflen)
 Attempt to complete a partial pathname. More...
 
int mutt_prepare_template (FILE *fp, struct Mailbox *m, struct Email *e_new, struct Email *e, bool resend)
 Prepare a message template. More...
 
int mutt_enter_string (char *buf, size_t buflen, int col, CompletionFlags flags)
 Ask the user for a string. More...
 
int mutt_enter_string_full (char *buf, size_t buflen, int col, CompletionFlags flags, bool multiple, char ***files, int *numfiles, struct EnterState *state)
 Ask the user for a string. More...
 
int mutt_get_postponed (struct Context *ctx, struct Email *hdr, struct Email **cur, struct Buffer *fcc)
 Recall a postponed message. More...
 
SecurityFlags mutt_parse_crypt_hdr (const char *p, bool set_empty_signas, SecurityFlags crypt_app)
 Parse a crypto header string. More...
 
int mutt_num_postponed (struct Mailbox *m, bool force)
 Return the number of postponed messages. More...
 
int mutt_thread_set_flag (struct Email *e, int flag, bool bf, bool subthread)
 Set a flag on an entire thread. More...
 
void mutt_update_num_postponed (void)
 Force the update of the number of postponed messages. More...
 
int mutt_is_quote_line (char *buf, regmatch_t *pmatch)
 Is a line of message text a quote? More...
 
int wcscasecmp (const wchar_t *a, const wchar_t *b)
 Compare two wide-character strings, ignoring case. More...
 
int mutt_reply_observer (struct NotifyCallback *nc)
 Listen for config changes to "reply_regex" - Implements observer_t. More...
 

Detailed Description

Prototypes for many functions.

Authors
  • Michael R. Elkins
  • Karel Zak

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 protos.h.

Macro Definition Documentation

◆ mutt_set_flag

#define mutt_set_flag (   m,
  e,
  flag,
  bf 
)    mutt_set_flag_update(m, e, flag, bf, true)

Definition at line 67 of file protos.h.

Enumeration Type Documentation

◆ XdgType

enum XdgType

XDG variable types.

Enumerator
XDG_CONFIG_HOME 

XDG home dir: ~/.config.

XDG_CONFIG_DIRS 

XDG system dir: /etc/xdg.

Definition at line 45 of file protos.h.

46 {
49 };
XDG home dir: ~/.config.
Definition: protos.h:47
XDG system dir: /etc/xdg.
Definition: protos.h:48

◆ EvMessage

enum EvMessage

Edit or View a message.

Enumerator
EVM_VIEW 

View the message.

EVM_EDIT 

Edit the message.

Definition at line 54 of file protos.h.

55 {
56  EVM_VIEW,
57  EVM_EDIT,
58 };
View the message.
Definition: protos.h:56
Edit the message.
Definition: protos.h:57

Function Documentation

◆ mutt_ev_message()

int mutt_ev_message ( struct Mailbox m,
struct EmailList *  el,
enum EvMessage  action 
)

Edit or view a message.

Parameters
mMailbox
elList of Emails
actionAction to perform, e.g. EVM_EDIT
Return values
1Message not modified
0Message edited successfully
-1Error

Definition at line 279 of file editmsg.c.

280 {
281  struct EmailNode *en = NULL;
282  STAILQ_FOREACH(en, el, entries)
283  {
284  if (ev_message(action, m, en->email) == -1)
285  return -1;
286  }
287 
288  return 0;
289 }
static int ev_message(enum EvMessage action, struct Mailbox *m, struct Email *e)
Edit an email or view it in an external editor.
Definition: editmsg.c:58
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
struct Email * email
Email in the list.
Definition: email.h:127
List of Emails.
Definition: email.h:125
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_system()

int mutt_system ( const char *  cmd)

Run an external command.

Parameters
cmdCommand and arguments
Return values
-1Error
>=0Success (command's return code)

Fork and run an external command with arguments.

Note
This function won't return until the command finishes.

Definition at line 51 of file system.c.

52 {
53  int rc = -1;
54  struct sigaction act;
55  struct sigaction oldtstp;
56  struct sigaction oldcont;
57  pid_t pid;
58 
59  if (!cmd || (*cmd == '\0'))
60  return 0;
61 
62  /* must ignore SIGINT and SIGQUIT */
63 
65 
66  act.sa_handler = SIG_DFL;
67 /* we want to restart the waitpid() below */
68 #ifdef SA_RESTART
69  act.sa_flags = SA_RESTART;
70 #endif
71  sigemptyset(&act.sa_mask);
72  sigaction(SIGTSTP, &act, &oldtstp);
73  sigaction(SIGCONT, &act, &oldcont);
74 
75  pid = fork();
76  if (pid == 0)
77  {
78  act.sa_flags = 0;
79 
80  /* reset signals for the child; not really needed, but... */
82  act.sa_handler = SIG_DFL;
83  act.sa_flags = 0;
84  sigemptyset(&act.sa_mask);
85  sigaction(SIGTERM, &act, NULL);
86  sigaction(SIGTSTP, &act, NULL);
87  sigaction(SIGCONT, &act, NULL);
88 
89  execle(EXEC_SHELL, "sh", "-c", cmd, NULL, mutt_envlist_getlist());
90  _exit(127); /* execl error */
91  }
92  else if (pid != -1)
93  {
94 #ifdef USE_IMAP
95  rc = imap_wait_keepalive(pid);
96 #endif
97  }
98 
99  sigaction(SIGCONT, &oldcont, NULL);
100  sigaction(SIGTSTP, &oldtstp, NULL);
101 
102  /* reset SIGINT, SIGQUIT and SIGCHLD */
104 
105  rc = (pid != -1) ? (WIFEXITED(rc) ? WEXITSTATUS(rc) : -1) : -1;
106 
107  return rc;
108 }
void mutt_sig_block_system(void)
Block signals before calling exec()
Definition: signal.c:183
#define EXEC_SHELL
Definition: filter.h:27
void mutt_sig_unblock_system(bool restore)
Restore previously blocked signals.
Definition: signal.c:207
int imap_wait_keepalive(pid_t pid)
Wait for a process to change state.
Definition: util.c:1102
char ** mutt_envlist_getlist(void)
Get the private environment.
Definition: envlist.c:169
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_set_xdg_path()

int mutt_set_xdg_path ( enum XdgType  type,
struct Buffer buf 
)

Find an XDG path or its fallback.

Parameters
typeType of XDG variable, e.g. XDG_CONFIG_HOME
bufBuffer to save path
Return values
1if an entry was found that actually exists on disk and 0 otherwise

Process an XDG environment variable or its fallback.

Definition at line 1499 of file muttlib.c.

1500 {
1501  const char *xdg_env = mutt_str_getenv(xdg_env_vars[type]);
1502  char *xdg = xdg_env ? mutt_str_dup(xdg_env) : mutt_str_dup(xdg_defaults[type]);
1503  char *x = xdg; /* strsep() changes xdg, so free x instead later */
1504  char *token = NULL;
1505  int rc = 0;
1506 
1507  while ((token = strsep(&xdg, ":")))
1508  {
1509  if (mutt_buffer_printf(buf, "%s/%s/neomuttrc", token, PACKAGE) < 0)
1510  continue;
1512  if (access(mutt_b2s(buf), F_OK) == 0)
1513  {
1514  rc = 1;
1515  break;
1516  }
1517 
1518  if (mutt_buffer_printf(buf, "%s/%s/Muttrc", token, PACKAGE) < 0)
1519  continue;
1521  if (access(mutt_b2s(buf), F_OK) == 0)
1522  {
1523  rc = 1;
1524  break;
1525  }
1526  }
1527 
1528  FREE(&x);
1529  return rc;
1530 }
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
static const char * xdg_env_vars[]
Definition: muttlib.c:72
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition: string.c:991
#define mutt_b2s(buf)
Definition: buffer.h:41
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:323
#define FREE(x)
Definition: memory.h:40
static const char * xdg_defaults[]
Definition: muttlib.c:77
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_help()

void mutt_help ( enum MenuType  menu,
int  wraplen 
)

Display the help menu.

Parameters
menuCurrent Menu
wraplenWidth to wrap to

Definition at line 386 of file help.c.

387 {
388  char buf[128];
389  FILE *fp = NULL;
390 
391  /* We don't use the buffer pool because of the extended lifetime of t */
392  struct Buffer t = mutt_buffer_make(PATH_MAX);
393  mutt_buffer_mktemp(&t);
394 
395  const struct Binding *funcs = km_get_table(menu);
396  const char *desc = mutt_map_get_name(menu, Menus);
397  if (!desc)
398  desc = _("<UNKNOWN>");
399 
400  do
401  {
402  fp = mutt_file_fopen(mutt_b2s(&t), "w");
403  if (!fp)
404  {
405  mutt_perror(mutt_b2s(&t));
406  goto cleanup;
407  }
408 
409  dump_menu(fp, menu, wraplen);
410  if ((menu != MENU_EDITOR) && (menu != MENU_PAGER))
411  {
412  fprintf(fp, "\n%s\n\n", _("Generic bindings:"));
413  dump_menu(fp, MENU_GENERIC, wraplen);
414  }
415 
416  fprintf(fp, "\n%s\n\n", _("Unbound functions:"));
417  if (funcs)
418  dump_unbound(fp, funcs, &Keymaps[menu], NULL, wraplen);
419  if (menu != MENU_PAGER)
420  dump_unbound(fp, OpGeneric, &Keymaps[MENU_GENERIC], &Keymaps[menu], wraplen);
421 
422  mutt_file_fclose(&fp);
423 
424  snprintf(buf, sizeof(buf), _("Help for %s"), desc);
425  } while (mutt_do_pager(buf, mutt_b2s(&t),
427  NULL) == OP_REFORMAT_WINCH);
428 
429 cleanup:
431 }
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:77
static void dump_unbound(FILE *fp, const struct Binding *funcs, struct KeymapList *km_list, struct KeymapList *aux, int wraplen)
Write out all the operations with no key bindings.
Definition: help.c:371
#define mutt_perror(...)
Definition: logging.h:85
struct KeymapList Keymaps[MENU_MAX]
Array of Keymap keybindings, one for each Menu.
Definition: keymap.c:149
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
#define MUTT_PAGER_NOWRAP
Format for term width, ignore $wrap.
Definition: pager.h:56
Pager pager (email viewer)
Definition: keymap.h:81
const char * mutt_map_get_name(int val, const struct Mapping *map)
Lookup a string for a constant.
Definition: mapping.c:42
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
const struct Binding OpGeneric[]
Key bindings for the generic menu.
Definition: functions.c:53
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
#define MUTT_PAGER_NSKIP
Preserve whitespace with smartwrap.
Definition: pager.h:52
#define mutt_b2s(buf)
Definition: buffer.h:41
const struct Mapping Menus[]
Menu name lookup table.
Definition: keymap.c:61
#define PATH_MAX
Definition: mutt.h:44
static void dump_menu(FILE *fp, enum MenuType menu, int wraplen)
Write all the key bindings to a file.
Definition: help.c:317
#define MUTT_PAGER_RETWINCH
Need reformatting on SIGWINCH.
Definition: pager.h:54
int mutt_do_pager(const char *banner, const char *tempfile, PagerFlags do_color, struct Pager *info)
Display some page-able text to the user.
Definition: curs_lib.c:690
const struct Binding * km_get_table(enum MenuType menu)
Lookup a menu&#39;s keybindings.
Definition: keymap.c:1306
Text entry area.
Definition: keymap.h:77
#define MUTT_PAGER_MARKER
Use markers if option is set.
Definition: pager.h:53
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:588
Mapping between a user key and a function.
Definition: keymap.h:120
Generic selection list.
Definition: keymap.h:79
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_set_flag_update()

void mutt_set_flag_update ( struct Mailbox m,
struct Email e,
int  flag,
bool  bf,
bool  upd_mbox 
)

Set a flag on an email.

Parameters
mMailbox
eEmail
flagFlag to set, e.g. MUTT_DELETE
bftrue: set the flag; false: clear the flag
upd_mboxtrue: update the Mailbox

Definition at line 54 of file flags.c.

55 {
56  if (!m || !e)
57  return;
58 
59  bool changed = e->changed;
60  int deleted = m->msg_deleted;
61  int tagged = m->msg_tagged;
62  int flagged = m->msg_flagged;
63  int update = false;
64 
65  if (m->readonly && (flag != MUTT_TAG))
66  return; /* don't modify anything if we are read-only */
67 
68  switch (flag)
69  {
70  case MUTT_DELETE:
71 
72  if (!(m->rights & MUTT_ACL_DELETE))
73  return;
74 
75  if (bf)
76  {
77  if (!e->deleted && !m->readonly && (!e->flagged || !C_FlagSafe))
78  {
79  e->deleted = true;
80  update = true;
81  if (upd_mbox)
82  m->msg_deleted++;
83 #ifdef USE_IMAP
84  /* deleted messages aren't treated as changed elsewhere so that the
85  * purge-on-sync option works correctly. This isn't applicable here */
86  if (m->type == MUTT_IMAP)
87  {
88  e->changed = true;
89  if (upd_mbox)
90  m->changed = true;
91  }
92 #endif
93  }
94  }
95  else if (e->deleted)
96  {
97  e->deleted = false;
98  update = true;
99  if (upd_mbox)
100  m->msg_deleted--;
101 #ifdef USE_IMAP
102  /* see my comment above */
103  if (m->type == MUTT_IMAP)
104  {
105  e->changed = true;
106  if (upd_mbox)
107  m->changed = true;
108  }
109 #endif
110  /* If the user undeletes a message which is marked as
111  * "trash" in the maildir folder on disk, the folder has
112  * been changed, and is marked accordingly. However, we do
113  * _not_ mark the message itself changed, because trashing
114  * is checked in specific code in the maildir folder
115  * driver. */
116  if ((m->type == MUTT_MAILDIR) && upd_mbox && e->trash)
117  m->changed = true;
118  }
119  break;
120 
121  case MUTT_PURGE:
122 
123  if (!(m->rights & MUTT_ACL_DELETE))
124  return;
125 
126  if (bf)
127  {
128  if (!e->purge && !m->readonly)
129  e->purge = true;
130  }
131  else if (e->purge)
132  e->purge = false;
133  break;
134 
135  case MUTT_NEW:
136 
137  if (!(m->rights & MUTT_ACL_SEEN))
138  return;
139 
140  if (bf)
141  {
142  if (e->read || e->old)
143  {
144  update = true;
145  e->old = false;
146  if (upd_mbox)
147  m->msg_new++;
148  if (e->read)
149  {
150  e->read = false;
151  if (upd_mbox)
152  m->msg_unread++;
153  }
154  e->changed = true;
155  if (upd_mbox)
156  m->changed = true;
157  }
158  }
159  else if (!e->read)
160  {
161  update = true;
162  if (!e->old)
163  if (upd_mbox)
164  m->msg_new--;
165  e->read = true;
166  if (upd_mbox)
167  m->msg_unread--;
168  e->changed = true;
169  if (upd_mbox)
170  m->changed = true;
171  }
172  break;
173 
174  case MUTT_OLD:
175 
176  if (!(m->rights & MUTT_ACL_SEEN))
177  return;
178 
179  if (bf)
180  {
181  if (!e->old)
182  {
183  update = true;
184  e->old = true;
185  if (!e->read)
186  if (upd_mbox)
187  m->msg_new--;
188  e->changed = true;
189  if (upd_mbox)
190  m->changed = true;
191  }
192  }
193  else if (e->old)
194  {
195  update = true;
196  e->old = false;
197  if (!e->read)
198  if (upd_mbox)
199  m->msg_new++;
200  e->changed = true;
201  if (upd_mbox)
202  m->changed = true;
203  }
204  break;
205 
206  case MUTT_READ:
207 
208  if (!(m->rights & MUTT_ACL_SEEN))
209  return;
210 
211  if (bf)
212  {
213  if (!e->read)
214  {
215  update = true;
216  e->read = true;
217  if (upd_mbox)
218  m->msg_unread--;
219  if (!e->old)
220  if (upd_mbox)
221  m->msg_new--;
222  e->changed = true;
223  if (upd_mbox)
224  m->changed = true;
225  }
226  }
227  else if (e->read)
228  {
229  update = true;
230  e->read = false;
231  if (upd_mbox)
232  m->msg_unread++;
233  if (!e->old)
234  if (upd_mbox)
235  m->msg_new++;
236  e->changed = true;
237  if (upd_mbox)
238  m->changed = true;
239  }
240  break;
241 
242  case MUTT_REPLIED:
243 
244  if (!(m->rights & MUTT_ACL_WRITE))
245  return;
246 
247  if (bf)
248  {
249  if (!e->replied)
250  {
251  update = true;
252  e->replied = true;
253  if (!e->read)
254  {
255  e->read = true;
256  if (upd_mbox)
257  m->msg_unread--;
258  if (!e->old)
259  if (upd_mbox)
260  m->msg_new--;
261  }
262  e->changed = true;
263  if (upd_mbox)
264  m->changed = true;
265  }
266  }
267  else if (e->replied)
268  {
269  update = true;
270  e->replied = false;
271  e->changed = true;
272  if (upd_mbox)
273  m->changed = true;
274  }
275  break;
276 
277  case MUTT_FLAG:
278 
279  if (!(m->rights & MUTT_ACL_WRITE))
280  return;
281 
282  if (bf)
283  {
284  if (!e->flagged)
285  {
286  update = true;
287  e->flagged = bf;
288  if (upd_mbox)
289  m->msg_flagged++;
290  e->changed = true;
291  if (upd_mbox)
292  m->changed = true;
293  }
294  }
295  else if (e->flagged)
296  {
297  update = true;
298  e->flagged = false;
299  if (upd_mbox)
300  m->msg_flagged--;
301  e->changed = true;
302  if (upd_mbox)
303  m->changed = true;
304  }
305  break;
306 
307  case MUTT_TAG:
308  if (bf)
309  {
310  if (!e->tagged)
311  {
312  update = true;
313  e->tagged = true;
314  if (upd_mbox)
315  m->msg_tagged++;
316  }
317  }
318  else if (e->tagged)
319  {
320  update = true;
321  e->tagged = false;
322  if (upd_mbox)
323  m->msg_tagged--;
324  }
325  break;
326  }
327 
328  if (update)
329  {
330  mutt_set_header_color(m, e);
331  }
332 
333  /* if the message status has changed, we need to invalidate the cached
334  * search results so that any future search will match the current status
335  * of this message and not what it was at the time it was last searched. */
336  if (e->searched && ((changed != e->changed) || (deleted != m->msg_deleted) ||
337  (tagged != m->msg_tagged) || (flagged != m->msg_flagged)))
338  {
339  e->searched = false;
340  }
341 }
enum MailboxType type
Mailbox type.
Definition: mailbox.h:105
int msg_deleted
Number of deleted messages.
Definition: mailbox.h:96
int msg_unread
Number of unread messages.
Definition: mailbox.h:92
int msg_flagged
Number of flagged messages.
Definition: mailbox.h:93
Flagged messages.
Definition: mutt.h:102
bool changed
Email has been edited.
Definition: email.h:48
Messages to be purged (bypass trash)
Definition: mutt.h:100
bool searched
Email has been searched.
Definition: email.h:67
#define MUTT_ACL_DELETE
Delete a message.
Definition: mailbox.h:66
Messages that have been replied to.
Definition: mutt.h:95
bool tagged
Email is tagged.
Definition: email.h:44
bool read
Email is read.
Definition: email.h:51
bool old
Email is seen, but unread.
Definition: email.h:50
bool readonly
Don&#39;t allow changes to the mailbox.
Definition: mailbox.h:119
#define MUTT_ACL_WRITE
Write to a message (for flagging or linking threads)
Definition: mailbox.h:74
&#39;Maildir&#39; Mailbox type
Definition: mailbox.h:51
bool trash
Message is marked as trashed on disk (used by the maildir_trash option)
Definition: email.h:60
Old messages.
Definition: mutt.h:94
Messages to be deleted.
Definition: mutt.h:98
Tagged messages.
Definition: mutt.h:103
New messages.
Definition: mutt.h:93
Messages that have been read.
Definition: mutt.h:96
WHERE bool C_FlagSafe
Config: Protect flagged messages from deletion.
Definition: mutt_globals.h:146
bool purge
Skip trash folder when deleting.
Definition: email.h:46
int msg_tagged
How many messages are tagged?
Definition: mailbox.h:97
AclFlags rights
ACL bits, see AclFlags.
Definition: mailbox.h:121
void mutt_set_header_color(struct Mailbox *m, struct Email *e)
Select a colour for a message.
Definition: index.c:3956
bool flagged
Marked important?
Definition: email.h:43
int msg_new
Number of new messages.
Definition: mailbox.h:95
bool deleted
Email is deleted.
Definition: email.h:45
bool replied
Email has been replied to.
Definition: email.h:54
#define MUTT_ACL_SEEN
Change the &#39;seen&#39; status of a message.
Definition: mailbox.h:73
bool changed
Mailbox has been modified.
Definition: mailbox.h:114
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_signal_init()

void mutt_signal_init ( void  )

Initialise the signal handling.

Definition at line 132 of file mutt_signal.c.

133 {
135 
136 #ifdef USE_SLANG_CURSES
137  /* This bit of code is required because of the implementation of
138  * SLcurses_wgetch(). If a signal is received (like SIGWINCH) when we
139  * are in blocking mode, SLsys_getkey() will not return an error unless
140  * a handler function is defined and it returns -1. This is needed so
141  * that if the user resizes the screen while at a prompt, it will just
142  * abort and go back to the main-menu. */
143  SLang_getkey_intr_hook = mutt_intr_hook;
144 #endif
145 }
static void curses_signal_handler(int sig)
Catch signals and relay the info to the main program - Implements sig_handler_t.
Definition: mutt_signal.c:46
static void curses_exit_handler(int sig)
Notify the user and shutdown gracefully - Implements sig_handler_t.
Definition: mutt_signal.c:86
void mutt_sig_init(sig_handler_t sig_fn, sig_handler_t exit_fn, sig_handler_t segv_fn)
Initialise the signal handling.
Definition: signal.c:88
static void curses_segv_handler(int sig)
Catch a segfault and print a backtrace - Implements sig_handler_t.
Definition: mutt_signal.c:98
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_emails_set_flag()

void mutt_emails_set_flag ( struct Mailbox m,
struct EmailList *  el,
int  flag,
bool  bf 
)

Set flag on messages.

Parameters
mMailbox
elList of Emails to flag
flagFlag to set, e.g. MUTT_DELETE
bftrue: set the flag; false: clear the flag

Definition at line 350 of file flags.c.

351 {
352  if (!m || !el || STAILQ_EMPTY(el))
353  return;
354 
355  struct EmailNode *en = NULL;
356  STAILQ_FOREACH(en, el, entries)
357  {
358  mutt_set_flag(m, en->email, flag, bf);
359  }
360 }
#define mutt_set_flag(m, e, flag, bf)
Definition: protos.h:67
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
struct Email * email
Email in the list.
Definition: email.h:127
#define STAILQ_EMPTY(head)
Definition: queue.h:345
List of Emails.
Definition: email.h:125
+ Here is the caller graph for this function:

◆ mutt_change_flag()

int mutt_change_flag ( struct Mailbox m,
struct EmailList *  el,
bool  bf 
)

Change the flag on a Message.

Parameters
mMailbox
elList of Emails to change
bftrue: set the flag; false: clear the flag
Return values
0Success
-1Failure

Definition at line 429 of file flags.c.

430 {
431  if (!m || !el || STAILQ_EMPTY(el))
432  return -1;
433 
434  int flag;
435  struct KeyEvent event;
436 
438  "%s? (D/N/O/r/*/!): ", bf ? _("Set flag") : _("Clear flag"));
440  mutt_refresh();
441 
442  do
443  {
444  event = mutt_getch();
445  } while (event.ch == -2);
446  int i = event.ch;
447  if (i < 0)
448  {
450  return -1;
451  }
452 
454 
455  switch (i)
456  {
457  case 'd':
458  case 'D':
459  if (!bf)
460  mutt_emails_set_flag(m, el, MUTT_PURGE, bf);
461  flag = MUTT_DELETE;
462  break;
463 
464  case 'N':
465  case 'n':
466  flag = MUTT_NEW;
467  break;
468 
469  case 'o':
470  case 'O':
471  mutt_emails_set_flag(m, el, MUTT_READ, !bf);
472  flag = MUTT_OLD;
473  break;
474 
475  case 'r':
476  case 'R':
477  flag = MUTT_REPLIED;
478  break;
479 
480  case '*':
481  flag = MUTT_TAG;
482  break;
483 
484  case '!':
485  flag = MUTT_FLAG;
486  break;
487 
488  default:
489  mutt_beep(false);
490  return -1;
491  }
492 
493  mutt_emails_set_flag(m, el, flag, bf);
494  return 0;
495 }
void mutt_emails_set_flag(struct Mailbox *m, struct EmailList *el, int flag, bool bf)
Set flag on messages.
Definition: flags.c:350
void mutt_window_clrtoeol(struct MuttWindow *win)
Clear to the end of the line.
Definition: mutt_window.c:244
Flagged messages.
Definition: mutt.h:102
#define _(a)
Definition: message.h:28
Messages to be purged (bypass trash)
Definition: mutt.h:100
Messages that have been replied to.
Definition: mutt.h:95
void mutt_beep(bool force)
Irritate the user.
Definition: curs_lib.c:99
void mutt_window_clearline(struct MuttWindow *win, int row)
Clear a row of a Window.
Definition: mutt_window.c:232
Old messages.
Definition: mutt.h:94
void mutt_refresh(void)
Force a refresh of the screen.
Definition: curs_lib.c:108
struct MuttWindow * MessageWindow
Message Window, ":set", etc.
Definition: mutt_window.c:47
Messages to be deleted.
Definition: mutt.h:98
Tagged messages.
Definition: mutt.h:103
New messages.
Definition: mutt.h:93
Messages that have been read.
Definition: mutt.h:96
An event such as a keypress.
Definition: keymap.h:63
struct KeyEvent mutt_getch(void)
Read a character from the input buffer.
Definition: curs_lib.c:189
#define STAILQ_EMPTY(head)
Definition: queue.h:345
int mutt_window_mvprintw(struct MuttWindow *win, int col, int row, const char *fmt,...)
Move the cursor and write a formatted string to a Window.
Definition: mutt_window.c:415
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_complete()

int mutt_complete ( char *  buf,
size_t  buflen 
)

Attempt to complete a partial pathname.

Parameters
bufBuffer containing pathname
buflenLength of buffer
Return values
0if ok
-1if no matches

Given a partial pathname, fill in as much of the rest of the path as is unique.

Definition at line 57 of file complete.c.

58 {
59  char *p = NULL;
60  DIR *dirp = NULL;
61  struct dirent *de = NULL;
62  int init = 0;
63  size_t len;
64  struct Buffer *dirpart = NULL;
65  struct Buffer *exp_dirpart = NULL;
66  struct Buffer *filepart = NULL;
67  struct Buffer *tmp = NULL;
68 #ifdef USE_IMAP
69  struct Buffer *imap_path = NULL;
70  int rc;
71 #endif
72 
73  mutt_debug(LL_DEBUG2, "completing %s\n", buf);
74 
75 #ifdef USE_NNTP
76  if (OptNews)
77  return nntp_complete(buf, buflen);
78 #endif
79 
80 #ifdef USE_IMAP
81  imap_path = mutt_buffer_pool_get();
82  /* we can use '/' as a delimiter, imap_complete rewrites it */
83  if ((*buf == '=') || (*buf == '+') || (*buf == '!'))
84  {
85  if (*buf == '!')
86  p = NONULL(C_Spoolfile);
87  else
88  p = NONULL(C_Folder);
89 
90  mutt_buffer_concat_path(imap_path, p, buf + 1);
91  }
92  else
93  mutt_buffer_strcpy(imap_path, buf);
94 
95  if (imap_path_probe(mutt_b2s(imap_path), NULL) == MUTT_IMAP)
96  {
97  rc = imap_complete(buf, buflen, mutt_b2s(imap_path));
98  mutt_buffer_pool_release(&imap_path);
99  return rc;
100  }
101 
102  mutt_buffer_pool_release(&imap_path);
103 #endif
104 
105  dirpart = mutt_buffer_pool_get();
106  exp_dirpart = mutt_buffer_pool_get();
107  filepart = mutt_buffer_pool_get();
108  tmp = mutt_buffer_pool_get();
109 
110  if ((*buf == '=') || (*buf == '+') || (*buf == '!'))
111  {
112  mutt_buffer_addch(dirpart, *buf);
113  if (*buf == '!')
114  mutt_buffer_strcpy(exp_dirpart, NONULL(C_Spoolfile));
115  else
116  mutt_buffer_strcpy(exp_dirpart, NONULL(C_Folder));
117  p = strrchr(buf, '/');
118  if (p)
119  {
120  mutt_buffer_concatn_path(tmp, mutt_b2s(exp_dirpart), mutt_buffer_len(exp_dirpart),
121  buf + 1, (size_t)(p - buf - 1));
122  mutt_buffer_copy(exp_dirpart, tmp);
123  mutt_buffer_substrcpy(dirpart, buf, p + 1);
124  mutt_buffer_strcpy(filepart, p + 1);
125  }
126  else
127  mutt_buffer_strcpy(filepart, buf + 1);
128  dirp = opendir(mutt_b2s(exp_dirpart));
129  }
130  else
131  {
132  p = strrchr(buf, '/');
133  if (p)
134  {
135  if (p == buf) /* absolute path */
136  {
137  p = buf + 1;
138  mutt_buffer_strcpy(dirpart, "/");
139  mutt_buffer_strcpy(filepart, p);
140  dirp = opendir(mutt_b2s(dirpart));
141  }
142  else
143  {
144  mutt_buffer_substrcpy(dirpart, buf, p);
145  mutt_buffer_strcpy(filepart, p + 1);
146  mutt_buffer_copy(exp_dirpart, dirpart);
147  mutt_buffer_expand_path(exp_dirpart);
148  dirp = opendir(mutt_b2s(exp_dirpart));
149  }
150  }
151  else
152  {
153  /* no directory name, so assume current directory. */
154  mutt_buffer_strcpy(filepart, buf);
155  dirp = opendir(".");
156  }
157  }
158 
159  if (!dirp)
160  {
161  mutt_debug(LL_DEBUG1, "%s: %s (errno %d)\n", mutt_b2s(exp_dirpart),
162  strerror(errno), errno);
163  goto cleanup;
164  }
165 
166  /* special case to handle when there is no filepart yet. find the first
167  * file/directory which is not "." or ".." */
168  len = mutt_buffer_len(filepart);
169  if (len == 0)
170  {
171  while ((de = readdir(dirp)))
172  {
173  if (!mutt_str_equal(".", de->d_name) && !mutt_str_equal("..", de->d_name))
174  {
175  mutt_buffer_strcpy(filepart, de->d_name);
176  init++;
177  break;
178  }
179  }
180  }
181 
182  while ((de = readdir(dirp)))
183  {
184  if (mutt_strn_equal(de->d_name, mutt_b2s(filepart), len))
185  {
186  if (init)
187  {
188  char *cp = filepart->data;
189 
190  for (int i = 0; (*cp != '\0') && (de->d_name[i] != '\0'); i++, cp++)
191  {
192  if (*cp != de->d_name[i])
193  break;
194  }
195  *cp = '\0';
196  mutt_buffer_fix_dptr(filepart);
197  }
198  else
199  {
200  struct stat st;
201 
202  mutt_buffer_strcpy(filepart, de->d_name);
203 
204  /* check to see if it is a directory */
205  if (mutt_buffer_is_empty(dirpart))
206  {
207  mutt_buffer_reset(tmp);
208  }
209  else
210  {
211  mutt_buffer_copy(tmp, exp_dirpart);
212  mutt_buffer_addch(tmp, '/');
213  }
214  mutt_buffer_addstr(tmp, mutt_b2s(filepart));
215  if ((stat(mutt_b2s(tmp), &st) != -1) && (st.st_mode & S_IFDIR))
216  mutt_buffer_addch(filepart, '/');
217  init = 1;
218  }
219  }
220  }
221  closedir(dirp);
222 
223  if (!mutt_buffer_is_empty(dirpart))
224  {
225  mutt_str_copy(buf, mutt_b2s(dirpart), buflen);
226  if (!mutt_str_equal("/", mutt_b2s(dirpart)) &&
227  (mutt_b2s(dirpart)[0] != '=') && (mutt_b2s(dirpart)[0] != '+'))
228  {
229  mutt_str_copy(buf + strlen(buf), "/", buflen - strlen(buf));
230  }
231  mutt_str_copy(buf + strlen(buf), mutt_b2s(filepart), buflen - strlen(buf));
232  }
233  else
234  mutt_str_copy(buf, mutt_b2s(filepart), buflen);
235 
236 cleanup:
237  mutt_buffer_pool_release(&dirpart);
238  mutt_buffer_pool_release(&exp_dirpart);
239  mutt_buffer_pool_release(&filepart);
241 
242  return init ? 0 : -1;
243 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:871
#define NONULL(x)
Definition: string2.h:37
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe()
Definition: imap.c:2367
size_t mutt_buffer_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer&#39;s contents to another Buffer.
Definition: buffer.c:445
size_t mutt_buffer_substrcpy(struct Buffer *buf, const char *beg, const char *end)
Copy a partial string into a Buffer.
Definition: buffer.c:342
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
Log at debug level 2.
Definition: logging.h:41
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
void mutt_buffer_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition: buffer.c:181
#define mutt_b2s(buf)
Definition: buffer.h:41
size_t mutt_buffer_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:356
char * data
Pointer to data.
Definition: buffer.h:35
WHERE char * C_Folder
Config: Base folder for a set of mailboxes.
Definition: mutt_globals.h:96
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
size_t mutt_buffer_concatn_path(struct Buffer *buf, const char *dir, size_t dirlen, const char *fname, size_t fnamelen)
Join a directory name and a filename.
Definition: buffer.c:411
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
int nntp_complete(char *buf, size_t buflen)
Auto-complete NNTP newsgroups.
Definition: complete.c:45
bool mutt_strn_equal(const char *a, const char *b, size_t l)
Check for equality of two strings (to a maximum), safely.
Definition: string.c:593
int imap_complete(char *buf, size_t buflen, const char *path)
Try to complete an IMAP folder path.
Definition: imap.c:1316
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:323
WHERE char * C_Spoolfile
Config: Inbox.
Definition: mutt_globals.h:108
Log at debug level 1.
Definition: logging.h:40
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:716
size_t mutt_buffer_concat_path(struct Buffer *buf, const char *dir, const char *fname)
Join a directory name and a filename.
Definition: buffer.c:374
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:45
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_prepare_template()

int mutt_prepare_template ( FILE *  fp,
struct Mailbox m,
struct Email e_new,
struct Email e,
bool  resend 
)

Prepare a message template.

Parameters
fpIf not NULL, file containing the template
mIf fp is NULL, the Mailbox containing the header with the template
e_newThe template is read into this Header
eEmail to recall/resend
resendSet if resending (as opposed to recalling a postponed msg) Resent messages enable header weeding, and also discard any existing Message-ID and Mail-Followup-To
Return values
0Success
-1Error

Definition at line 655 of file postpone.c.

657 {
658  struct Message *msg = NULL;
659  struct Body *b = NULL;
660  FILE *fp_body = NULL;
661  int rc = -1;
662  struct State s = { 0 };
663  SecurityFlags sec_type;
664  struct Envelope *protected_headers = NULL;
665 
666  if (!fp && !(msg = mx_msg_open(m, e->msgno)))
667  return -1;
668 
669  if (!fp)
670  fp = msg->fp;
671 
672  fp_body = fp;
673 
674  /* parse the message header and MIME structure */
675 
676  fseeko(fp, e->offset, SEEK_SET);
677  e_new->offset = e->offset;
678  /* enable header weeding for resent messages */
679  e_new->env = mutt_rfc822_read_header(fp, e_new, true, resend);
680  e_new->body->length = e->body->length;
681  mutt_parse_part(fp, e_new->body);
682 
683  /* If resending a message, don't keep message_id or mail_followup_to.
684  * Otherwise, we are resuming a postponed message, and want to keep those
685  * headers if they exist. */
686  if (resend)
687  {
688  FREE(&e_new->env->message_id);
689  FREE(&e_new->env->mail_followup_to);
690  }
691 
692  /* decrypt pgp/mime encoded messages */
693 
694  if (((WithCrypto & APPLICATION_PGP) != 0) &&
695  (sec_type = mutt_is_multipart_encrypted(e_new->body)))
696  {
697  e_new->security |= sec_type;
698  if (!crypt_valid_passphrase(sec_type))
699  goto bail;
700 
701  mutt_message(_("Decrypting message..."));
702  if ((crypt_pgp_decrypt_mime(fp, &fp_body, e_new->body, &b) == -1) || !b)
703  {
704  goto bail;
705  }
706 
707  mutt_body_free(&e_new->body);
708  e_new->body = b;
709 
710  if (b->mime_headers)
711  {
712  protected_headers = b->mime_headers;
713  b->mime_headers = NULL;
714  }
715 
717  }
718 
719  /* remove a potential multipart/signed layer - useful when
720  * resending messages */
721  if ((WithCrypto != 0) && mutt_is_multipart_signed(e_new->body))
722  {
723  e_new->security |= SEC_SIGN;
724  if (((WithCrypto & APPLICATION_PGP) != 0) &&
725  mutt_istr_equal(mutt_param_get(&e_new->body->parameter, "protocol"),
726  "application/pgp-signature"))
727  {
728  e_new->security |= APPLICATION_PGP;
729  }
730  else if (WithCrypto & APPLICATION_SMIME)
731  e_new->security |= APPLICATION_SMIME;
732 
733  /* destroy the signature */
734  mutt_body_free(&e_new->body->parts->next);
735  e_new->body = mutt_remove_multipart(e_new->body);
736 
737  if (e_new->body->mime_headers)
738  {
739  mutt_env_free(&protected_headers);
740  protected_headers = e_new->body->mime_headers;
741  e_new->body->mime_headers = NULL;
742  }
743  }
744 
745  /* We don't need no primary multipart.
746  * Note: We _do_ preserve messages!
747  *
748  * XXX - we don't handle multipart/alternative in any
749  * smart way when sending messages. However, one may
750  * consider this a feature. */
751  if (e_new->body->type == TYPE_MULTIPART)
752  e_new->body = mutt_remove_multipart(e_new->body);
753 
754  s.fp_in = fp_body;
755 
756  struct Buffer *file = mutt_buffer_pool_get();
757 
758  /* create temporary files for all attachments */
759  for (b = e_new->body; b; b = b->next)
760  {
761  /* what follows is roughly a receive-mode variant of
762  * mutt_get_tmp_attachment () from muttlib.c */
763 
764  mutt_buffer_reset(file);
765  if (b->filename)
766  {
767  mutt_buffer_strcpy(file, b->filename);
769  }
770  else
771  {
772  /* avoid Content-Disposition: header with temporary filename */
773  b->use_disp = false;
774  }
775 
776  /* set up state flags */
777 
778  s.flags = 0;
779 
780  if (b->type == TYPE_TEXT)
781  {
782  if (mutt_istr_equal("yes",
783  mutt_param_get(&b->parameter, "x-mutt-noconv")))
784  {
785  b->noconv = true;
786  }
787  else
788  {
789  s.flags |= MUTT_CHARCONV;
790  b->noconv = false;
791  }
792 
793  mutt_param_delete(&b->parameter, "x-mutt-noconv");
794  }
795 
796  mutt_adv_mktemp(file);
797  s.fp_out = mutt_file_fopen(mutt_b2s(file), "w");
798  if (!s.fp_out)
799  goto bail;
800 
801  if (((WithCrypto & APPLICATION_PGP) != 0) &&
802  ((sec_type = mutt_is_application_pgp(b)) & (SEC_ENCRYPT | SEC_SIGN)))
803  {
804  if (sec_type & SEC_ENCRYPT)
805  {
806  if (!crypt_valid_passphrase(APPLICATION_PGP))
807  goto bail;
808  mutt_message(_("Decrypting message..."));
809  }
810 
811  if (mutt_body_handler(b, &s) < 0)
812  {
813  mutt_error(_("Decryption failed"));
814  goto bail;
815  }
816 
817  if ((b == e_new->body) && !protected_headers)
818  {
819  protected_headers = b->mime_headers;
820  b->mime_headers = NULL;
821  }
822 
823  e_new->security |= sec_type;
824  b->type = TYPE_TEXT;
825  mutt_str_replace(&b->subtype, "plain");
826  mutt_param_delete(&b->parameter, "x-action");
827  }
828  else if (((WithCrypto & APPLICATION_SMIME) != 0) &&
829  ((sec_type = mutt_is_application_smime(b)) & (SEC_ENCRYPT | SEC_SIGN)))
830  {
831  if (sec_type & SEC_ENCRYPT)
832  {
833  if (!crypt_valid_passphrase(APPLICATION_SMIME))
834  goto bail;
835  crypt_smime_getkeys(e_new->env);
836  mutt_message(_("Decrypting message..."));
837  }
838 
839  if (mutt_body_handler(b, &s) < 0)
840  {
841  mutt_error(_("Decryption failed"));
842  goto bail;
843  }
844 
845  e_new->security |= sec_type;
846  b->type = TYPE_TEXT;
847  mutt_str_replace(&b->subtype, "plain");
848  }
849  else
850  mutt_decode_attachment(b, &s);
851 
852  if (mutt_file_fclose(&s.fp_out) != 0)
853  goto bail;
854 
855  mutt_str_replace(&b->filename, mutt_b2s(file));
856  b->unlink = true;
857 
859 
860  mutt_body_free(&b->parts);
861  if (b->email)
862  b->email->body = NULL; /* avoid dangling pointer */
863  }
864 
865  if (C_CryptProtectedHeadersRead && protected_headers && protected_headers->subject &&
866  !mutt_str_equal(e_new->env->subject, protected_headers->subject))
867  {
868  mutt_str_replace(&e_new->env->subject, protected_headers->subject);
869  }
870  mutt_env_free(&protected_headers);
871 
872  /* Fix encryption flags. */
873 
874  /* No inline if multipart. */
875  if ((WithCrypto != 0) && (e_new->security & SEC_INLINE) && e_new->body->next)
876  e_new->security &= ~SEC_INLINE;
877 
878  /* Do we even support multiple mechanisms? */
879  e_new->security &= WithCrypto | ~(APPLICATION_PGP | APPLICATION_SMIME);
880 
881  /* Theoretically, both could be set. Take the one the user wants to set by default. */
882  if ((e_new->security & APPLICATION_PGP) && (e_new->security & APPLICATION_SMIME))
883  {
884  if (C_SmimeIsDefault)
885  e_new->security &= ~APPLICATION_PGP;
886  else
887  e_new->security &= ~APPLICATION_SMIME;
888  }
889 
891 
892  rc = 0;
893 
894 bail:
895 
896  /* that's it. */
898  if (fp_body != fp)
899  mutt_file_fclose(&fp_body);
900  if (msg)
901  mx_msg_close(m, &msg);
902 
903  if (rc == -1)
904  {
905  mutt_env_free(&e_new->env);
906  mutt_body_free(&e_new->body);
907  }
908 
909  return rc;
910 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:871
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email&#39;s attachment.
Definition: handler.c:1843
void mutt_stamp_attachment(struct Body *a)
Timestamp an Attachment.
Definition: sendlib.c:891
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
struct Envelope * mime_headers
Memory hole protected headers.
Definition: body.h:63
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
#define WithCrypto
Definition: lib.h:123
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
struct AddressList mail_followup_to
Email&#39;s &#39;mail-followup-to&#39;.
Definition: envelope.h:63
struct Body * body
List of MIME parts.
Definition: email.h:91
#define MUTT_CHARCONV
Do character set conversions.
Definition: state.h:36
#define mutt_message(...)
Definition: logging.h:83
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:85
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
bool noconv
Don&#39;t do character set conversion.
Definition: body.h:73
String manipulation buffer.
Definition: buffer.h:33
bool C_CryptProtectedHeadersRead
Config: Display protected headers (Memory Hole) in the pager.
Definition: config.c:58
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
#define _(a)
Definition: message.h:28
struct Body * next
next attachment in the list
Definition: body.h:53
FILE * fp_out
File to write to.
Definition: state.h:47
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition: lib.h:83
FILE * fp_in
File to read from.
Definition: state.h:46
The body of an email.
Definition: body.h:34
#define SEC_INLINE
Email has an inline signature.
Definition: lib.h:92
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1204
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:134
char * message_id
Message ID.
Definition: envelope.h:69
SecurityFlags mutt_is_multipart_encrypted(struct Body *b)
Does the message have encrypted parts?
Definition: crypt.c:447
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
struct Envelope * env
Envelope information.
Definition: email.h:90
SecurityFlags mutt_is_multipart_signed(struct Body *b)
Is a message signed?
Definition: crypt.c:407
void mutt_rfc3676_space_unstuff(struct Email *e)
Remove RFC3676 space stuffing.
Definition: rfc3676.c:492
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:113
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:883
char * subtype
content-type subtype
Definition: body.h:37
void mutt_param_delete(struct ParameterList *pl, const char *attribute)
Delete a matching Parameter.
Definition: parameter.c:142
#define mutt_b2s(buf)
Definition: buffer.h:41
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:98
bool C_SmimeIsDefault
Config: Use SMIME rather than PGP by default.
Definition: config.c:61
SecurityFlags mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
Definition: crypt.c:552
struct Body * mutt_remove_multipart(struct Body *b)
Extract the multipart body if it exists.
Definition: multipart.c:126
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:97
A local copy of an email.
Definition: mx.h:82
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
Type: &#39;text/*&#39;.
Definition: mime.h:38
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition: envelope.c:96
void crypt_smime_getkeys(struct Envelope *env)
Wrapper for CryptModuleSpecs::smime_getkeys()
Definition: cryptglue.c:455
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
SecurityFlags mutt_is_application_smime(struct Body *m)
Does the message use S/MIME?
Definition: crypt.c:610
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib...
Definition: email.h:39
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
LOFF_T offset
Where in the stream does this message begin?
Definition: email.h:84
#define SEC_SIGN
Email is signed.
Definition: lib.h:86
void mutt_parse_part(FILE *fp, struct Body *b)
Parse a MIME part.
Definition: parse.c:1657
int crypt_pgp_decrypt_mime(FILE *fp_in, FILE **fp_out, struct Body *b, struct Body **cur)
Wrapper for CryptModuleSpecs::decrypt_mime()
Definition: cryptglue.c:207
char * subject
Email&#39;s subject.
Definition: envelope.h:66
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:68
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:446
#define mutt_error(...)
Definition: logging.h:84
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition: body.h:69
FILE * fp
pointer to the message data
Definition: mx.h:84
void mutt_adv_mktemp(struct Buffer *buf)
Create a temporary file.
Definition: muttlib.c:90
#define FREE(x)
Definition: memory.h:40
char * mutt_param_get(const struct ParameterList *pl, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
Keep track when processing files.
Definition: state.h:44
int mutt_body_handler(struct Body *b, struct State *s)
Handler for the Body of an email.
Definition: handler.c:1593
char * d_filename
filename to be used for the content-disposition header.
Definition: body.h:47
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:588
struct Envelope * mutt_rfc822_read_header(FILE *fp, struct Email *e, bool user_hdrs, bool weed)
parses an RFC822 header
Definition: parse.c:1111
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
struct Email * email
header information for message/rfc822
Definition: body.h:55
struct Message * mx_msg_open(struct Mailbox *m, int msgno)
return a stream pointer for a message
Definition: mx.c:1158
The header of an Email.
Definition: envelope.h:54
int msgno
Number displayed to the user.
Definition: email.h:87
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_enter_string()

int mutt_enter_string ( char *  buf,
size_t  buflen,
int  col,
CompletionFlags  flags 
)

Ask the user for a string.

Parameters
bufBuffer to store the string
buflenBuffer length
colInitial cursor position
flagsFlags, see CompletionFlags
Return values
0if input was given
-1if abort

This function is for very basic input, currently used only by the built-in editor. It does not handle screen redrawing on resizes well, because there is no active menu for the built-in editor. Most callers should prefer mutt_get_field() instead.

Definition at line 147 of file enter.c.

148 {
149  int rc;
150  struct EnterState *es = mutt_enter_state_new();
151  do
152  {
153  if (SigWinch)
154  {
155  SigWinch = 0;
157  clearok(stdscr, true);
158  }
159  rc = mutt_enter_string_full(buf, buflen, col, flags, false, NULL, NULL, es);
160  } while (rc == 1);
162  return rc;
163 }
void mutt_resize_screen(void)
Update NeoMutt&#39;s opinion about the window size (CURSES)
Definition: resize.c:101
int mutt_enter_string_full(char *buf, size_t buflen, int col, CompletionFlags flags, bool multiple, char ***files, int *numfiles, struct EnterState *state)
Ask the user for a string.
Definition: enter.c:179
Keep our place when entering a string.
Definition: enter_state.h:32
void mutt_enter_state_free(struct EnterState **ptr)
Free an EnterState.
Definition: enter.c:841
struct EnterState * mutt_enter_state_new(void)
Create a new EnterState.
Definition: enter.c:128
WHERE SIG_ATOMIC_VOLATILE_T SigWinch
true after SIGWINCH is received
Definition: mutt_globals.h:75
+ Here is the call graph for this function:

◆ mutt_enter_string_full()

int mutt_enter_string_full ( char *  buf,
size_t  buflen,
int  col,
CompletionFlags  flags,
bool  multiple,
char ***  files,
int *  numfiles,
struct EnterState state 
)

Ask the user for a string.

Parameters
[in]bufBuffer to store the string
[in]buflenBuffer length
[in]colInitial cursor position
[in]flagsFlags, see CompletionFlags
[in]multipleAllow multiple matches
[out]filesList of files selected
[out]numfilesNumber of files selected
[out]stateCurrent state (if function is called repeatedly)
Return values
1Redraw the screen and call the function again
0Selection made
-1Aborted

Definition at line 179 of file enter.c.

182 {
183  int width = MessageWindow->state.cols - col - 1;
184  enum EnterRedrawFlags redraw = ENTER_REDRAW_NONE;
185  bool pass = (flags & MUTT_PASS);
186  bool first = true;
187  int ch;
188  wchar_t *tempbuf = NULL;
189  size_t templen = 0;
190  enum HistoryClass hclass;
191  int rc = 0;
192  mbstate_t mbstate;
193  memset(&mbstate, 0, sizeof(mbstate));
194 
195  if (state->wbuf)
196  {
197  /* Coming back after return 1 */
198  redraw = ENTER_REDRAW_LINE;
199  first = false;
200  }
201  else
202  {
203  /* Initialise wbuf from buf */
204  state->wbuflen = 0;
205  state->lastchar = mutt_mb_mbstowcs(&state->wbuf, &state->wbuflen, 0, buf);
206  redraw = ENTER_REDRAW_INIT;
207  }
208 
209  if (flags & MUTT_FILE)
210  hclass = HC_FILE;
211  else if (flags & MUTT_EFILE)
212  hclass = HC_MBOX;
213  else if (flags & MUTT_CMD)
214  hclass = HC_CMD;
215  else if (flags & MUTT_ALIAS)
216  hclass = HC_ALIAS;
217  else if (flags & MUTT_COMMAND)
218  hclass = HC_COMMAND;
219  else if (flags & MUTT_PATTERN)
220  hclass = HC_PATTERN;
221  else
222  hclass = HC_OTHER;
223 
224  while (true)
225  {
226  if (!pass)
227  {
228  if (redraw == ENTER_REDRAW_INIT)
229  {
230  /* Go to end of line */
231  state->curpos = state->lastchar;
232  state->begin = mutt_mb_width_ceiling(
233  state->wbuf, state->lastchar,
234  mutt_mb_wcswidth(state->wbuf, state->lastchar) - width + 1);
235  }
236  if ((state->curpos < state->begin) ||
237  (mutt_mb_wcswidth(state->wbuf + state->begin, state->curpos - state->begin) >= width))
238  {
239  state->begin = mutt_mb_width_ceiling(
240  state->wbuf, state->lastchar,
241  mutt_mb_wcswidth(state->wbuf, state->curpos) - (width / 2));
242  }
244  int w = 0;
245  for (size_t i = state->begin; i < state->lastchar; i++)
246  {
247  w += mutt_mb_wcwidth(state->wbuf[i]);
248  if (w > width)
249  break;
250  my_addwch(state->wbuf[i]);
251  }
254  col + mutt_mb_wcswidth(state->wbuf + state->begin,
255  state->curpos - state->begin),
256  0);
257  }
258  mutt_refresh();
259 
260  ch = km_dokey(MENU_EDITOR);
261  if (ch < 0)
262  {
263  rc = (SigWinch && (ch == -2)) ? 1 : -1;
264  goto bye;
265  }
266 
267  if (ch != OP_NULL)
268  {
269  first = false;
270  if ((ch != OP_EDITOR_COMPLETE) && (ch != OP_EDITOR_COMPLETE_QUERY))
271  state->tabs = 0;
272  redraw = ENTER_REDRAW_LINE;
273  switch (ch)
274  {
275  case OP_EDITOR_HISTORY_UP:
276  state->curpos = state->lastchar;
277  if (mutt_hist_at_scratch(hclass))
278  {
279  mutt_mb_wcstombs(buf, buflen, state->wbuf, state->curpos);
280  mutt_hist_save_scratch(hclass, buf);
281  }
282  replace_part(state, 0, mutt_hist_prev(hclass));
283  redraw = ENTER_REDRAW_INIT;
284  break;
285 
286  case OP_EDITOR_HISTORY_DOWN:
287  state->curpos = state->lastchar;
288  if (mutt_hist_at_scratch(hclass))
289  {
290  mutt_mb_wcstombs(buf, buflen, state->wbuf, state->curpos);
291  mutt_hist_save_scratch(hclass, buf);
292  }
293  replace_part(state, 0, mutt_hist_next(hclass));
294  redraw = ENTER_REDRAW_INIT;
295  break;
296 
297  case OP_EDITOR_HISTORY_SEARCH:
298  state->curpos = state->lastchar;
299  mutt_mb_wcstombs(buf, buflen, state->wbuf, state->curpos);
300  mutt_hist_complete(buf, buflen, hclass);
301  replace_part(state, 0, buf);
302  rc = 1;
303  goto bye;
304  break;
305 
306  case OP_EDITOR_BACKSPACE:
307  if (state->curpos == 0)
308  {
309  // Pressing backspace when no text is in the command prompt should exit the prompt
310  if (C_AbortBackspace && (state->lastchar == 0))
311  goto bye;
312  // Pressing backspace with text in the command prompt should just beep
313  mutt_beep(false);
314  }
315  else
316  {
317  size_t i = state->curpos;
318  while ((i > 0) && COMB_CHAR(state->wbuf[i - 1]))
319  i--;
320  if (i > 0)
321  i--;
322  memmove(state->wbuf + i, state->wbuf + state->curpos,
323  (state->lastchar - state->curpos) * sizeof(wchar_t));
324  state->lastchar -= state->curpos - i;
325  state->curpos = i;
326  }
327  break;
328 
329  case OP_EDITOR_BOL:
330  state->curpos = 0;
331  break;
332 
333  case OP_EDITOR_EOL:
334  redraw = ENTER_REDRAW_INIT;
335  break;
336 
337  case OP_EDITOR_KILL_LINE:
338  state->curpos = 0;
339  state->lastchar = 0;
340  break;
341 
342  case OP_EDITOR_KILL_EOL:
343  state->lastchar = state->curpos;
344  break;
345 
346  case OP_EDITOR_BACKWARD_CHAR:
347  if (state->curpos == 0)
348  mutt_beep(false);
349  else
350  {
351  while (state->curpos && COMB_CHAR(state->wbuf[state->curpos - 1]))
352  state->curpos--;
353  if (state->curpos)
354  state->curpos--;
355  }
356  break;
357 
358  case OP_EDITOR_FORWARD_CHAR:
359  if (state->curpos == state->lastchar)
360  mutt_beep(false);
361  else
362  {
363  state->curpos++;
364  while ((state->curpos < state->lastchar) &&
365  COMB_CHAR(state->wbuf[state->curpos]))
366  {
367  state->curpos++;
368  }
369  }
370  break;
371 
372  case OP_EDITOR_BACKWARD_WORD:
373  if (state->curpos == 0)
374  mutt_beep(false);
375  else
376  {
377  while (state->curpos && iswspace(state->wbuf[state->curpos - 1]))
378  state->curpos--;
379  while (state->curpos && !iswspace(state->wbuf[state->curpos - 1]))
380  state->curpos--;
381  }
382  break;
383 
384  case OP_EDITOR_FORWARD_WORD:
385  if (state->curpos == state->lastchar)
386  mutt_beep(false);
387  else
388  {
389  while ((state->curpos < state->lastchar) &&
390  iswspace(state->wbuf[state->curpos]))
391  {
392  state->curpos++;
393  }
394  while ((state->curpos < state->lastchar) &&
395  !iswspace(state->wbuf[state->curpos]))
396  {
397  state->curpos++;
398  }
399  }
400  break;
401 
402  case OP_EDITOR_CAPITALIZE_WORD:
403  case OP_EDITOR_UPCASE_WORD:
404  case OP_EDITOR_DOWNCASE_WORD:
405  if (state->curpos == state->lastchar)
406  {
407  mutt_beep(false);
408  break;
409  }
410  while (state->curpos && !iswspace(state->wbuf[state->curpos]))
411  state->curpos--;
412  while ((state->curpos < state->lastchar) && iswspace(state->wbuf[state->curpos]))
413  state->curpos++;
414  while ((state->curpos < state->lastchar) &&
415  !iswspace(state->wbuf[state->curpos]))
416  {
417  if (ch == OP_EDITOR_DOWNCASE_WORD)
418  state->wbuf[state->curpos] = towlower(state->wbuf[state->curpos]);
419  else
420  {
421  state->wbuf[state->curpos] = towupper(state->wbuf[state->curpos]);
422  if (ch == OP_EDITOR_CAPITALIZE_WORD)
423  ch = OP_EDITOR_DOWNCASE_WORD;
424  }
425  state->curpos++;
426  }
427  break;
428 
429  case OP_EDITOR_DELETE_CHAR:
430  if (state->curpos == state->lastchar)
431  mutt_beep(false);
432  else
433  {
434  size_t i = state->curpos;
435  while ((i < state->lastchar) && COMB_CHAR(state->wbuf[i]))
436  i++;
437  if (i < state->lastchar)
438  i++;
439  while ((i < state->lastchar) && COMB_CHAR(state->wbuf[i]))
440  i++;
441  memmove(state->wbuf + state->curpos, state->wbuf + i,
442  (state->lastchar - i) * sizeof(wchar_t));
443  state->lastchar -= i - state->curpos;
444  }
445  break;
446 
447  case OP_EDITOR_KILL_WORD:
448  /* delete to beginning of word */
449  if (state->curpos != 0)
450  {
451  size_t i = state->curpos;
452  while (i && iswspace(state->wbuf[i - 1]))
453  i--;
454  if (i > 0)
455  {
456  if (iswalnum(state->wbuf[i - 1]))
457  {
458  for (--i; (i > 0) && iswalnum(state->wbuf[i - 1]); i--)
459  ; // do nothing
460  }
461  else
462  i--;
463  }
464  memmove(state->wbuf + i, state->wbuf + state->curpos,
465  (state->lastchar - state->curpos) * sizeof(wchar_t));
466  state->lastchar += i - state->curpos;
467  state->curpos = i;
468  }
469  break;
470 
471  case OP_EDITOR_KILL_EOW:
472  {
473  /* delete to end of word */
474 
475  /* first skip over whitespace */
476  size_t i;
477  for (i = state->curpos; (i < state->lastchar) && iswspace(state->wbuf[i]); i++)
478  ; // do nothing
479 
480  /* if there are any characters left.. */
481  if (i < state->lastchar)
482  {
483  /* if the current character is alphanumeric.. */
484  if (iswalnum(state->wbuf[i]))
485  {
486  /* skip over the rest of the word consistent of only alphanumerics */
487  for (; (i < state->lastchar) && iswalnum(state->wbuf[i]); i++)
488  ; // do nothing
489  }
490  else
491  {
492  /* skip over one non-alphanumeric character */
493  i++;
494  }
495  }
496 
497  memmove(state->wbuf + state->curpos, state->wbuf + i,
498  (state->lastchar - i) * sizeof(wchar_t));
499  state->lastchar += state->curpos - i;
500  break;
501  }
502 
503  case OP_EDITOR_MAILBOX_CYCLE:
504  if (flags & MUTT_EFILE)
505  {
506  first = true; /* clear input if user types a real key later */
507  mutt_mb_wcstombs(buf, buflen, state->wbuf, state->curpos);
508 
509  struct Buffer *pool = mutt_buffer_pool_get();
510  mutt_buffer_addstr(pool, buf);
511  mutt_mailbox_next(Context ? Context->mailbox : NULL, pool);
512  mutt_str_copy(buf, mutt_b2s(pool), buflen);
514 
515  state->curpos = state->lastchar =
516  mutt_mb_mbstowcs(&state->wbuf, &state->wbuflen, 0, buf);
517  break;
518  }
519  else if (!(flags & MUTT_FILE))
520  {
521  goto self_insert;
522  }
523  /* fallthrough */
524 
525  case OP_EDITOR_COMPLETE:
526  case OP_EDITOR_COMPLETE_QUERY:
527  state->tabs++;
528  if (flags & MUTT_CMD)
529  {
530  size_t i;
531  for (i = state->curpos;
532  (i > 0) && !mutt_mb_is_shell_char(state->wbuf[i - 1]); i--)
533  {
534  }
535  mutt_mb_wcstombs(buf, buflen, state->wbuf + i, state->curpos - i);
536  if (tempbuf && (templen == (state->lastchar - i)) &&
537  (memcmp(tempbuf, state->wbuf + i, (state->lastchar - i) * sizeof(wchar_t)) == 0))
538  {
539  mutt_select_file(buf, buflen, (flags & MUTT_EFILE) ? MUTT_SEL_FOLDER : MUTT_SEL_NO_FLAGS,
540  NULL, NULL);
541  if (buf[0] != '\0')
542  replace_part(state, i, buf);
543  rc = 1;
544  goto bye;
545  }
546  if (mutt_complete(buf, buflen) == 0)
547  {
548  templen = state->lastchar - i;
549  mutt_mem_realloc(&tempbuf, templen * sizeof(wchar_t));
550  }
551  else
552  mutt_beep(false);
553 
554  replace_part(state, i, buf);
555  }
556  else if ((flags & MUTT_ALIAS) && (ch == OP_EDITOR_COMPLETE))
557  {
558  /* invoke the alias-menu to get more addresses */
559  size_t i;
560  for (i = state->curpos;
561  (i > 0) && (state->wbuf[i - 1] != ',') && (state->wbuf[i - 1] != ':'); i--)
562  {
563  }
564  for (; (i < state->lastchar) && (state->wbuf[i] == ' '); i++)
565  ; // do nothing
566 
567  mutt_mb_wcstombs(buf, buflen, state->wbuf + i, state->curpos - i);
568  int rc2 = alias_complete(buf, buflen, NeoMutt->sub);
569  replace_part(state, i, buf);
570  if (rc2 != 1)
571  {
572  rc = 1;
573  goto bye;
574  }
575  break;
576  }
577  else if ((flags & MUTT_LABEL) && (ch == OP_EDITOR_COMPLETE))
578  {
579  size_t i;
580  for (i = state->curpos;
581  (i > 0) && (state->wbuf[i - 1] != ',') && (state->wbuf[i - 1] != ':'); i--)
582  {
583  }
584  for (; (i < state->lastchar) && (state->wbuf[i] == ' '); i++)
585  ; // do nothing
586 
587  mutt_mb_wcstombs(buf, buflen, state->wbuf + i, state->curpos - i);
588  int rc2 = mutt_label_complete(buf, buflen, state->tabs);
589  replace_part(state, i, buf);
590  if (rc2 != 1)
591  {
592  rc = 1;
593  goto bye;
594  }
595  break;
596  }
597  else if ((flags & MUTT_PATTERN) && (ch == OP_EDITOR_COMPLETE))
598  {
599  size_t i = state->curpos;
600  if (i && (state->wbuf[i - 1] == '~'))
601  {
602  if (dlg_select_pattern(buf, buflen))
603  replace_part(state, i - 1, buf);
604  rc = 1;
605  goto bye;
606  }
607  for (; (i > 0) && (state->wbuf[i - 1] != '~'); i--)
608  ; // do nothing
609 
610  if ((i > 0) && (i < state->curpos) && (state->wbuf[i - 1] == '~') &&
611  (state->wbuf[i] == 'y'))
612  {
613  i++;
614  mutt_mb_wcstombs(buf, buflen, state->wbuf + i, state->curpos - i);
615  int rc2 = mutt_label_complete(buf, buflen, state->tabs);
616  replace_part(state, i, buf);
617  if (rc2 != 1)
618  {
619  rc = 1;
620  goto bye;
621  }
622  }
623  else
624  goto self_insert;
625  break;
626  }
627  else if ((flags & MUTT_ALIAS) && (ch == OP_EDITOR_COMPLETE_QUERY))
628  {
629  size_t i = state->curpos;
630  if (i != 0)
631  {
632  for (; (i > 0) && (state->wbuf[i - 1] != ','); i--)
633  ; // do nothing
634 
635  for (; (i < state->curpos) && (state->wbuf[i] == ' '); i++)
636  ; // do nothing
637  }
638 
639  mutt_mb_wcstombs(buf, buflen, state->wbuf + i, state->curpos - i);
640  query_complete(buf, buflen, NeoMutt->sub);
641  replace_part(state, i, buf);
642 
643  rc = 1;
644  goto bye;
645  }
646  else if (flags & MUTT_COMMAND)
647  {
648  mutt_mb_wcstombs(buf, buflen, state->wbuf, state->curpos);
649  size_t i = strlen(buf);
650  if ((i != 0) && (buf[i - 1] == '=') &&
651  (mutt_var_value_complete(buf, buflen, i) != 0))
652  {
653  state->tabs = 0;
654  }
655  else if (mutt_command_complete(buf, buflen, i, state->tabs) == 0)
656  mutt_beep(false);
657  replace_part(state, 0, buf);
658  }
659  else if (flags & (MUTT_FILE | MUTT_EFILE))
660  {
661  mutt_mb_wcstombs(buf, buflen, state->wbuf, state->curpos);
662 
663  /* see if the path has changed from the last time */
664  if ((!tempbuf && !state->lastchar) ||
665  (tempbuf && (templen == state->lastchar) &&
666  (memcmp(tempbuf, state->wbuf, state->lastchar * sizeof(wchar_t)) == 0)))
667  {
668  mutt_select_file(buf, buflen,
669  ((flags & MUTT_EFILE) ? MUTT_SEL_FOLDER : MUTT_SEL_NO_FLAGS) |
670  (multiple ? MUTT_SEL_MULTI : MUTT_SEL_NO_FLAGS),
671  files, numfiles);
672  if (buf[0] != '\0')
673  {
674  mutt_pretty_mailbox(buf, buflen);
675  if (!pass)
676  mutt_hist_add(hclass, buf, true);
677  rc = 0;
678  goto bye;
679  }
680 
681  /* file selection cancelled */
682  rc = 1;
683  goto bye;
684  }
685 
686  if (mutt_complete(buf, buflen) == 0)
687  {
688  templen = state->lastchar;
689  mutt_mem_realloc(&tempbuf, templen * sizeof(wchar_t));
690  memcpy(tempbuf, state->wbuf, templen * sizeof(wchar_t));
691  }
692  else
693  mutt_beep(false); /* let the user know that nothing matched */
694  replace_part(state, 0, buf);
695  }
696 #ifdef USE_NOTMUCH
697  else if (flags & MUTT_NM_QUERY)
698  {
699  mutt_mb_wcstombs(buf, buflen, state->wbuf, state->curpos);
700  size_t len = strlen(buf);
701  if (!mutt_nm_query_complete(buf, buflen, len, state->tabs))
702  mutt_beep(false);
703 
704  replace_part(state, 0, buf);
705  }
706  else if (flags & MUTT_NM_TAG)
707  {
708  mutt_mb_wcstombs(buf, buflen, state->wbuf, state->curpos);
709  if (!mutt_nm_tag_complete(buf, buflen, state->tabs))
710  mutt_beep(false);
711 
712  replace_part(state, 0, buf);
713  }
714 #endif
715  else
716  goto self_insert;
717  break;
718 
719  case OP_EDITOR_QUOTE_CHAR:
720  {
721  struct KeyEvent event;
722  do
723  {
724  event = mutt_getch();
725  } while (event.ch == -2);
726  if (event.ch >= 0)
727  {
728  LastKey = event.ch;
729  goto self_insert;
730  }
731  break;
732  }
733 
734  case OP_EDITOR_TRANSPOSE_CHARS:
735  if (state->lastchar < 2)
736  mutt_beep(false);
737  else
738  {
739  wchar_t t;
740 
741  if (state->curpos == 0)
742  state->curpos = 2;
743  else if (state->curpos < state->lastchar)
744  state->curpos++;
745 
746  t = state->wbuf[state->curpos - 2];
747  state->wbuf[state->curpos - 2] = state->wbuf[state->curpos - 1];
748  state->wbuf[state->curpos - 1] = t;
749  }
750  break;
751 
752  default:
753  mutt_beep(false);
754  }
755  }
756  else
757  {
758  self_insert:
759  state->tabs = 0;
760  wchar_t wc;
761  /* use the raw keypress */
762  ch = LastKey;
763 
764  /* quietly ignore all other function keys */
765  if (ch & ~0xff)
766  continue;
767 
768  /* gather the octets into a wide character */
769  {
770  char c = ch;
771  size_t k = mbrtowc(&wc, &c, 1, &mbstate);
772  if (k == (size_t)(-2))
773  continue;
774  else if ((k != 0) && (k != 1))
775  {
776  memset(&mbstate, 0, sizeof(mbstate));
777  continue;
778  }
779  }
780 
781  if (first && (flags & MUTT_CLEAR))
782  {
783  first = false;
784  if (IsWPrint(wc)) /* why? */
785  {
786  state->curpos = 0;
787  state->lastchar = 0;
788  }
789  }
790 
791  if ((wc == '\r') || (wc == '\n'))
792  {
793  /* Convert from wide characters */
794  mutt_mb_wcstombs(buf, buflen, state->wbuf, state->lastchar);
795  if (!pass)
796  mutt_hist_add(hclass, buf, true);
797 
798  if (multiple)
799  {
800  char **tfiles = NULL;
801  *numfiles = 1;
802  tfiles = mutt_mem_calloc(*numfiles, sizeof(char *));
803  mutt_expand_path(buf, buflen);
804  tfiles[0] = mutt_str_dup(buf);
805  *files = tfiles;
806  }
807  rc = 0;
808  goto bye;
809  }
810  else if (wc && ((wc < ' ') || IsWPrint(wc))) /* why? */
811  {
812  if (state->lastchar >= state->wbuflen)
813  {
814  state->wbuflen = state->lastchar + 20;
815  mutt_mem_realloc(&state->wbuf, state->wbuflen * sizeof(wchar_t));
816  }
817  memmove(state->wbuf + state->curpos + 1, state->wbuf + state->curpos,
818  (state->lastchar - state->curpos) * sizeof(wchar_t));
819  state->wbuf[state->curpos++] = wc;
820  state->lastchar++;
821  }
822  else
823  {
824  mutt_flushinp();
825  mutt_beep(false);
826  }
827  }
828  }
829 
830 bye:
831 
832  mutt_hist_reset_state(hclass);
833  FREE(&tempbuf);
834  return rc;
835 }
int km_dokey(enum MenuType menu)
Determine what a keypress should do.
Definition: keymap.c:658
The "current" mailbox.
Definition: context.h:38
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:522
NeoMutt commands.
Definition: lib.h:56
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
wchar_t * wbuf
Definition: enter_state.h:34
#define MUTT_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:62
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
char * mutt_hist_next(enum HistoryClass hclass)
Get the next string in a History.
Definition: history.c:500
#define MUTT_ALIAS
Do alias "completion" by calling up the alias-menu.
Definition: mutt.h:57
#define IsWPrint(wc)
Definition: mbyte.h:40
void mutt_hist_complete(char *buf, size_t buflen, enum HistoryClass hclass)
Complete a string from a history list.
Definition: mutt_history.c:42
int mutt_label_complete(char *buf, size_t buflen, int numtabs)
Complete a label name.
Definition: init.c:1308
#define MUTT_LABEL
Do label completion.
Definition: mutt.h:65
void mutt_flushinp(void)
Empty all the keyboard buffers.
Definition: curs_lib.c:919
void mutt_window_clrtoeol(struct MuttWindow *win)
Clear to the end of the line.
Definition: mutt_window.c:244
int query_complete(char *buf, size_t buflen, struct ConfigSubset *sub)
Perform auto-complete using an Address Query.
Definition: dlgquery.c:605
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
void mutt_hist_add(enum HistoryClass hclass, const char *str, bool save)
Add a string to a history.
Definition: history.c:464
size_t wbuflen
Definition: enter_state.h:35
bool mutt_nm_tag_complete(char *buf, size_t buflen, int numtabs)
Complete to the nearest notmuch tag.
Definition: init.c:1429
#define MUTT_NM_QUERY
Notmuch query mode.
Definition: mutt.h:66
String manipulation buffer.
Definition: buffer.h:33
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
int mutt_command_complete(char *buf, size_t buflen, int pos, int numtabs)
Complete a command name.
Definition: init.c:1126
int ch
raw key pressed
Definition: keymap.h:65
#define MUTT_SEL_NO_FLAGS
No flags are set.
Definition: browser.h:40
size_t mutt_mb_width_ceiling(const wchar_t *s, size_t n, int w1)
Keep the end of the string on-screen.
Definition: mbyte.c:217
struct Mailbox * mutt_mailbox_next(struct Mailbox *m_cur, struct Buffer *s)
incoming folders completion routine
Definition: mutt_mailbox.c:308
bool mutt_nm_query_complete(char *buf, size_t buflen, int pos, int numtabs)
Complete to the nearest notmuch tag.
Definition: init.c:1372
Container for Accounts, Notifications.
Definition: neomutt.h:36
#define MUTT_PATTERN
Pattern mode - only used for history classes.
Definition: mutt.h:64
int mutt_window_move(struct MuttWindow *win, int col, int row)
Move the cursor in a Window.
Definition: mutt_window.c:382
#define MUTT_SEL_FOLDER
Select a local directory.
Definition: browser.h:43
Mailboxes.
Definition: lib.h:60
void mutt_mb_wcstombs(char *dest, size_t dlen, const wchar_t *src, size_t slen)
Convert a string from wide to multibyte characters.
Definition: mbyte.c:237
void mutt_beep(bool force)
Irritate the user.
Definition: curs_lib.c:99
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:128
struct Mailbox * mailbox
Definition: context.h:50
#define MUTT_NM_TAG
Notmuch tag +/- mode.
Definition: mutt.h:67
int LastKey
contains the last key the user pressed
Definition: keymap.c:146
int mutt_mb_wcswidth(const wchar_t *s, size_t n)
Measure the screen width of a string.
Definition: mbyte.c:196
#define MUTT_COMMAND
Do command completion.
Definition: mutt.h:63
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
bool dlg_select_pattern(char *buf, size_t buflen)
Show menu to select a Pattern.
Definition: dlgpattern.c:262
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
short cols
Number of columns, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:57
#define MUTT_CMD
Do completion on previous word.
Definition: mutt.h:60
size_t begin
Definition: enter_state.h:38
#define mutt_b2s(buf)
Definition: buffer.h:41
void mutt_refresh(void)
Force a refresh of the screen.
Definition: curs_lib.c:108
Nothing to redraw.
Definition: enter.c:60
#define MUTT_PASS
Password mode (no echo)
Definition: mutt.h:61
struct WindowState state
Current state of the Window.
Definition: mutt_window.h:120
struct MuttWindow * MessageWindow
Message Window, ":set", etc.
Definition: mutt_window.c:47
bool mutt_hist_at_scratch(enum HistoryClass hclass)
Is the current History position at the &#39;scratch&#39; place?
Definition: history.c:618
External commands.
Definition: lib.h:54
void mutt_select_file(char *file, size_t filelen, SelectFileFlags flags, char ***files, int *numfiles)
Let the user select a file.
Definition: browser.c:2179
void mutt_hist_save_scratch(enum HistoryClass hclass, const char *str)
Save a temporary string to the History.
Definition: history.c:635
int alias_complete(char *buf, size_t buflen, struct ConfigSubset *sub)
alias completion routine
Definition: dlgalias.c:375
static int my_addwch(wchar_t wc)
Display one wide character on screen.
Definition: enter.c:74
WHERE bool C_AbortBackspace
Config: Hitting backspace against an empty prompt aborts the prompt.
Definition: mutt_globals.h:83
An event such as a keypress.
Definition: keymap.h:63
size_t curpos
Definition: enter_state.h:37
struct KeyEvent mutt_getch(void)
Read a character from the input buffer.
Definition: curs_lib.c:189
#define COMB_CHAR(wc)
Definition: enter.c:66
static void replace_part(struct EnterState *state, size_t from, char *buf)
Search and replace on a buffer.
Definition: enter.c:92
#define MUTT_SEL_MULTI
Multi-selection is enabled.
Definition: browser.h:42
#define MUTT_FILE
Do file completion.
Definition: mutt.h:58
char * mutt_hist_prev(enum HistoryClass hclass)
Get the previous string in a History.
Definition: history.c:527
int mutt_complete(char *buf, size_t buflen)
Attempt to complete a partial pathname.
Definition: complete.c:57
EnterRedrawFlags
redraw flags for mutt_enter_string_full()
Definition: enter.c:58
bool mutt_mb_is_shell_char(wchar_t ch)
Is character not typically part of a pathname.
Definition: mbyte.c:344
HistoryClass
Type to differentiate different histories.
Definition: lib.h:52
size_t mutt_mb_mbstowcs(wchar_t **pwbuf, size_t *pwbuflen, size_t i, char *buf)
Convert a string from multibyte to wide characters.
Definition: mbyte.c:295
Go to end of line and redraw.
Definition: enter.c:61
#define MUTT_EFILE
Do file completion, plus incoming folders.
Definition: mutt.h:59
Patterns.
Definition: lib.h:58
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:716
Redraw entire line.
Definition: enter.c:62
#define FREE(x)
Definition: memory.h:40
int mutt_mb_wcwidth(wchar_t wc)
Measure the screen width of a character.
Definition: mbyte.c:178
Aliases.
Definition: lib.h:55
Text entry area.
Definition: keymap.h:77
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
void mutt_hist_reset_state(enum HistoryClass hclass)
Move the &#39;current&#39; position to the end of the History.
Definition: history.c:554
WHERE SIG_ATOMIC_VOLATILE_T SigWinch
true after SIGWINCH is received
Definition: mutt_globals.h:75
Miscellaneous strings.
Definition: lib.h:59
size_t lastchar
Definition: enter_state.h:36
Files.
Definition: lib.h:57
int mutt_var_value_complete(char *buf, size_t buflen, int pos)
Complete a variable/value.
Definition: init.c:1482
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_get_postponed()

int mutt_get_postponed ( struct Context ctx,
struct Email hdr,
struct Email **  cur,
struct Buffer fcc 
)

Recall a postponed message.

Parameters
[in]ctxContext info, used when recalling a message to which we reply
[in]hdrenvelope/attachment info for recalled message
[out]curif message was a reply, 'cur' is set to the message which 'hdr' is in reply to
[in]fccfcc for the recalled message
Return values
-1Error/no messages
0Normal exit
SEND_REPLYRecalled message is a reply

Definition at line 315 of file postpone.c.

317 {
318  if (!C_Postponed)
319  return -1;
320 
321  struct Email *e = NULL;
322  int rc = SEND_POSTPONED;
323  int rc_close;
324  const char *p = NULL;
325  struct Context *ctx_post = NULL;
326 
327  struct Mailbox *m = mx_path_resolve(C_Postponed);
328  if (ctx && (ctx->mailbox == m))
329  ctx_post = ctx;
330  else
331  ctx_post = mx_mbox_open(m, MUTT_NOSORT);
332 
333  if (!ctx_post)
334  {
335  PostCount = 0;
336  mutt_error(_("No postponed messages"));
337  mailbox_free(&m);
338  return -1;
339  }
340 
341  /* TODO:
342  * mx_mbox_open() for IMAP leaves IMAP_REOPEN_ALLOW set. For the
343  * index this is papered-over because it calls mx_check_mailbox()
344  * every event loop(which resets that flag).
345  *
346  * For a stable-branch fix, I'm doing the same here, to prevent
347  * context changes from occuring behind the scenes and causing
348  * segvs, but probably the flag needs to be reset after downloading
349  * headers in imap_open_mailbox().
350  */
351  mx_mbox_check(ctx_post->mailbox);
352 
353  if (ctx_post->mailbox->msg_count == 0)
354  {
355  PostCount = 0;
356  if (ctx_post == ctx)
357  ctx_post = NULL;
358  else
359  mx_fastclose_mailbox(ctx_post->mailbox);
360  mutt_error(_("No postponed messages"));
361  return -1;
362  }
363 
364  if (ctx_post->mailbox->msg_count == 1)
365  {
366  /* only one message, so just use that one. */
367  e = ctx_post->mailbox->emails[0];
368  }
369  else if (!(e = dlg_select_postponed_email(ctx_post)))
370  {
371  if (ctx_post == ctx)
372  ctx_post = NULL;
373  else
374  {
375  /* messages might have been marked for deletion.
376  * try once more on reopen before giving up. */
377  rc_close = mx_mbox_close(&ctx_post);
378  if (rc_close > 0)
379  rc_close = mx_mbox_close(&ctx_post);
380  if (rc_close != 0)
381  mx_fastclose_mailbox(ctx_post->mailbox);
382  }
383  return -1;
384  }
385 
386  if (mutt_prepare_template(NULL, ctx_post->mailbox, hdr, e, false) < 0)
387  {
388  if (ctx_post != ctx)
389  {
390  mx_fastclose_mailbox(ctx_post->mailbox);
391  FREE(&ctx_post);
392  }
393  return -1;
394  }
395 
396  /* finished with this message, so delete it. */
397  mutt_set_flag(ctx_post->mailbox, e, MUTT_DELETE, true);
398  mutt_set_flag(ctx_post->mailbox, e, MUTT_PURGE, true);
399 
400  /* update the count for the status display */
401  PostCount = ctx_post->mailbox->msg_count - ctx_post->mailbox->msg_deleted;
402 
403  /* avoid the "purge deleted messages" prompt */
404  int opt_delete = C_Delete;
405  C_Delete = MUTT_YES;
406  if (ctx_post == ctx)
407  ctx_post = NULL;
408  else
409  {
410  rc_close = mx_mbox_close(&ctx_post);
411  if (rc_close > 0)
412  rc_close = mx_mbox_close(&ctx_post);
413  if (rc_close != 0)
414  mx_fastclose_mailbox(ctx_post->mailbox);
415  }
416  C_Delete = opt_delete;
417 
418  struct ListNode *np = NULL, *tmp = NULL;
419  STAILQ_FOREACH_SAFE(np, &hdr->env->userhdrs, entries, tmp)
420  {
421  size_t plen = mutt_istr_startswith(np->data, "X-Mutt-References:");
422  if (plen)
423  {
424  /* if a mailbox is currently open, look to see if the original message
425  * the user attempted to reply to is in this mailbox */
426  p = mutt_str_skip_email_wsp(np->data + plen);
427  if (!ctx->mailbox->id_hash)
429  *cur = mutt_hash_find(ctx->mailbox->id_hash, p);
430 
431  if (*cur)
432  rc |= SEND_REPLY;
433  }
434  else if ((plen = mutt_istr_startswith(np->data, "X-Mutt-Fcc:")))
435  {
436  p = mutt_str_skip_email_wsp(np->data + plen);
437  mutt_buffer_strcpy(fcc, p);
439 
440  /* note that x-mutt-fcc was present. we do this because we want to add a
441  * default fcc if the header was missing, but preserve the request of the
442  * user to not make a copy if the header field is present, but empty.
443  * see http://dev.mutt.org/trac/ticket/3653 */
444  rc |= SEND_POSTPONED_FCC;
445  }
446  else if (((WithCrypto & APPLICATION_PGP) != 0) &&
447  /* this is generated by old neomutt versions */
448  (mutt_str_startswith(np->data, "Pgp:") ||
449  /* this is the new way */
450  mutt_str_startswith(np->data, "X-Mutt-PGP:")))
451  {
452  hdr->security = mutt_parse_crypt_hdr(strchr(np->data, ':') + 1, true, APPLICATION_PGP);
453  hdr->security |= APPLICATION_PGP;
454  }
455  else if (((WithCrypto & APPLICATION_SMIME) != 0) &&
456  mutt_str_startswith(np->data, "X-Mutt-SMIME:"))
457  {
458  hdr->security = mutt_parse_crypt_hdr(strchr(np->data, ':') + 1, true, APPLICATION_SMIME);
459  hdr->security |= APPLICATION_SMIME;
460  }
461 #ifdef MIXMASTER
462  else if (mutt_str_startswith(np->data, "X-Mutt-Mix:"))
463  {
464  mutt_list_free(&hdr->chain);
465 
466  char *t = strtok(np->data + 11, " \t\n");
467  while (t)
468  {
470  t = strtok(NULL, " \t\n");
471  }
472  }
473 #endif
474  else
475  {
476  // skip header removal
477  continue;
478  }
479 
480  // remove the header
481  STAILQ_REMOVE(&hdr->env->userhdrs, np, ListNode, entries);
482  FREE(&np->data);
483  FREE(&np);
484  }
485 
488 
489  return rc;
490 }
void * mutt_hash_find(const struct HashTable *table, const char *strkey)
Find the HashElem data in a Hash Table element using a key.
Definition: hash.c:354
struct Email ** emails
Array of Emails.
Definition: mailbox.h:99
The "current" mailbox.
Definition: context.h:38
#define STAILQ_REMOVE(head, elm, type, field)
Definition: queue.h:399
int msg_count
Total number of messages.
Definition: mailbox.h:91
#define mutt_set_flag(m, e, flag, bf)
Definition: protos.h:67
#define WithCrypto
Definition: lib.h:123
#define SEND_POSTPONED_FCC
Used by mutt_get_postponed() to signal that the x-mutt-fcc header field was present.
Definition: send.h:49
The envelope/body of an email.
Definition: email.h:37
int msg_deleted
Number of deleted messages.
Definition: mailbox.h:96
int mx_mbox_close(struct Context **ptr)
Save changes and close mailbox.
Definition: mx.c:630
static size_t plen
Length of cached packet.
Definition: pgppacket.c:39
struct HashTable * mutt_make_id_hash(struct Mailbox *m)
Create a Hash Table for message-ids.
Definition: mutt_thread.c:1521
static struct Email * dlg_select_postponed_email(struct Context *ctx)
Create a Menu to select a postponed message.
Definition: postpone.c:224
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
struct ListHead userhdrs
user defined headers
Definition: envelope.h:83
#define _(a)
Definition: message.h:28
struct Context * mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:303
Messages to be purged (bypass trash)
Definition: mutt.h:100
#define SEND_POSTPONED
Recall a postponed email.
Definition: send.h:45
void mutt_buffer_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:598
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
struct Mailbox * mailbox
Definition: context.h:50
struct HashTable * id_hash
Hash Table by msg id.
Definition: mailbox.h:127
bool C_CryptOpportunisticEncrypt
Config: Enable encryption when the recipient&#39;s key is available.
Definition: config.c:56
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:63
struct Envelope * env
Envelope information.
Definition: email.h:90
void mx_fastclose_mailbox(struct Mailbox *m)
free up memory associated with the Mailbox
Definition: mx.c:445
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:359
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:64
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:98
struct ListHead chain
Mixmaster chain.
Definition: email.h:102
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:97
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:160
Messages to be deleted.
Definition: mutt.h:98
A mailbox.
Definition: mailbox.h:81
#define MUTT_NOSORT
Do not sort the mailbox after opening it.
Definition: mx.h:52
static short PostCount
Definition: postpone.c:78
char * mutt_str_skip_email_wsp(const char *s)
Skip over whitespace as defined by RFC5322.
Definition: string.c:743
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition: string.c:172
int mx_mbox_check(struct Mailbox *m)
Check for new mail - Wrapper for MxOps::mbox_check()
Definition: mx.c:1139
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib...
Definition: email.h:39
#define SEND_REPLY
Reply to sender.
Definition: send.h:41
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
SecurityFlags mutt_parse_crypt_hdr(const char *p, bool set_empty_signas, SecurityFlags crypt_app)
Parse a crypto header string.
Definition: postpone.c:499
void crypt_opportunistic_encrypt(struct Email *e)
Can all recipients be determined.
Definition: crypt.c:1021
char * data
String.
Definition: list.h:36
WHERE unsigned char C_Delete
Config: Really delete messages, when the mailbox is closed.
Definition: mutt_globals.h:125
#define mutt_error(...)
Definition: logging.h:84
#define FREE(x)
Definition: memory.h:40
struct Mailbox * mx_path_resolve(const char *path)
Get a Mailbox for a path.
Definition: mx.c:1681
A List node for strings.
Definition: list.h:34
WHERE char * C_Postponed
Config: Folder to store postponed messages.
Definition: mutt_globals.h:101
int mutt_prepare_template(FILE *fp, struct Mailbox *m, struct Email *e_new, struct Email *e, bool resend)
Prepare a message template.
Definition: postpone.c:655
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:40
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_parse_crypt_hdr()

SecurityFlags mutt_parse_crypt_hdr ( const char *  p,
bool  set_empty_signas,
SecurityFlags  crypt_app 
)

Parse a crypto header string.

Parameters
pHeader string to parse
set_empty_signasAllow an empty "Sign as"
crypt_appApp, e.g. APPLICATION_PGP
Return values
numSecurityFlags, see SecurityFlags

Definition at line 499 of file postpone.c.

500 {
501  char smime_cryptalg[1024] = { 0 };
502  char sign_as[1024] = { 0 };
503  char *q = NULL;
504  SecurityFlags flags = SEC_NO_FLAGS;
505 
506  if (!WithCrypto)
507  return SEC_NO_FLAGS;
508 
510  for (; p[0] != '\0'; p++)
511  {
512  switch (p[0])
513  {
514  case 'c':
515  case 'C':
516  q = smime_cryptalg;
517 
518  if (p[1] == '<')
519  {
520  for (p += 2; (p[0] != '\0') && (p[0] != '>') &&
521  (q < (smime_cryptalg + sizeof(smime_cryptalg) - 1));
522  *q++ = *p++)
523  {
524  }
525 
526  if (p[0] != '>')
527  {
528  mutt_error(_("Illegal S/MIME header"));
529  return SEC_NO_FLAGS;
530  }
531  }
532 
533  *q = '\0';
534  break;
535 
536  case 'e':
537  case 'E':
538  flags |= SEC_ENCRYPT;
539  break;
540 
541  case 'i':
542  case 'I':
543  flags |= SEC_INLINE;
544  break;
545 
546  /* This used to be the micalg parameter.
547  *
548  * It's no longer needed, so we just skip the parameter in order
549  * to be able to recall old messages. */
550  case 'm':
551  case 'M':
552  if (p[1] != '<')
553  break;
554 
555  for (p += 2; (p[0] != '\0') && (p[0] != '>'); p++)
556  ; // do nothing
557 
558  if (p[0] != '>')
559  {
560  mutt_error(_("Illegal crypto header"));
561  return SEC_NO_FLAGS;
562  }
563  break;
564 
565  case 'o':
566  case 'O':
567  flags |= SEC_OPPENCRYPT;
568  break;
569 
570  case 'a':
571  case 'A':
572 #ifdef USE_AUTOCRYPT
573  flags |= SEC_AUTOCRYPT;
574 #endif
575  break;
576 
577  case 'z':
578  case 'Z':
579 #ifdef USE_AUTOCRYPT
580  flags |= SEC_AUTOCRYPT_OVERRIDE;
581 #endif
582  break;
583 
584  case 's':
585  case 'S':
586  flags |= SEC_SIGN;
587  q = sign_as;
588 
589  if (p[1] == '<')
590  {
591  for (p += 2;
592  (p[0] != '\0') && (*p != '>') && (q < (sign_as + sizeof(sign_as) - 1));
593  *q++ = *p++)
594  {
595  }
596 
597  if (p[0] != '>')
598  {
599  mutt_error(_("Illegal crypto header"));
600  return SEC_NO_FLAGS;
601  }
602  }
603 
604  q[0] = '\0';
605  break;
606 
607  default:
608  mutt_error(_("Illegal crypto header"));
609  return SEC_NO_FLAGS;
610  }
611  }
612 
613  /* the cryptalg field must not be empty */
614  if (((WithCrypto & APPLICATION_SMIME) != 0) && *smime_cryptalg)
615  {
616  struct Buffer errmsg = mutt_buffer_make(0);
617  int rc = cs_subset_str_string_set(NeoMutt->sub, "smime_encrypt_with",
618  smime_cryptalg, &errmsg);
619 
620  if ((CSR_RESULT(rc) != CSR_SUCCESS) && !mutt_buffer_is_empty(&errmsg))
621  mutt_error("%s", mutt_b2s(&errmsg));
622 
623  mutt_buffer_dealloc(&errmsg);
624  }
625 
626  /* Set {Smime,Pgp}SignAs, if desired. */
627 
628  if (((WithCrypto & APPLICATION_PGP) != 0) && (crypt_app == APPLICATION_PGP) &&
629  (flags & SEC_SIGN) && (set_empty_signas || *sign_as))
630  {
631  mutt_str_replace(&C_PgpSignAs, sign_as);
632  }
633 
634  if (((WithCrypto & APPLICATION_SMIME) != 0) && (crypt_app == APPLICATION_SMIME) &&
635  (flags & SEC_SIGN) && (set_empty_signas || *sign_as))
636  {
637  mutt_str_replace(&C_SmimeSignAs, sign_as);
638  }
639 
640  return flags;
641 }
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:35
#define WithCrypto
Definition: lib.h:123
#define SEC_NO_FLAGS
No flags are set.
Definition: lib.h:84
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:85
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
#define SEC_AUTOCRYPT
(Autocrypt) Message will be, or was Autocrypt encrypt+signed
Definition: lib.h:94
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition: lib.h:83
Container for Accounts, Notifications.
Definition: neomutt.h:36
#define CSR_RESULT(x)
Definition: set.h:52
#define SEC_INLINE
Email has an inline signature.
Definition: lib.h:92
int cs_subset_str_string_set(const struct ConfigSubset *sub, const char *name, const char *value, struct Buffer *err)
Set a config item by string.
Definition: subset.c:395
char * C_PgpSignAs
Config: Use this alternative key for signing messages.
Definition: config.c:67
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
#define mutt_b2s(buf)
Definition: buffer.h:41
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:98
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:97
#define SEC_AUTOCRYPT_OVERRIDE
(Autocrypt) Indicates manual set/unset of encryption
Definition: lib.h:95
char * mutt_str_skip_email_wsp(const char *s)
Skip over whitespace as defined by RFC5322.
Definition: string.c:743
#define SEC_OPPENCRYPT
Opportunistic encrypt mode.
Definition: lib.h:93
char * C_SmimeSignAs
Config: Use this alternative key for signing messages.
Definition: config.c:70
#define SEC_SIGN
Email is signed.
Definition: lib.h:86
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:446
#define mutt_error(...)
Definition: logging.h:84
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_num_postponed()

int mutt_num_postponed ( struct Mailbox m,
bool  force 
)

Return the number of postponed messages.

Parameters
mcurrently selected mailbox
force
  • false Use a cached value if costly to get a fresh count (IMAP)
  • true Force check
Return values
numPostponed messages

Definition at line 89 of file postpone.c.

90 {
91  struct stat st;
92 
93  static time_t LastModify = 0;
94  static char *OldPostponed = NULL;
95 
97  {
98  UpdateNumPostponed = false;
99  force = true;
100  }
101 
102  if (!mutt_str_equal(C_Postponed, OldPostponed))
103  {
104  FREE(&OldPostponed);
105  OldPostponed = mutt_str_dup(C_Postponed);
106  LastModify = 0;
107  force = true;
108  }
109 
110  if (!C_Postponed)
111  return 0;
112 
113  // We currently are in the `$postponed` mailbox so just pick the current status
114  if (m && mutt_str_equal(C_Postponed, m->realpath))
115  {
116  PostCount = m->msg_count - m->msg_deleted;
117  return PostCount;
118  }
119 
120 #ifdef USE_IMAP
121  /* LastModify is useless for IMAP */
122  if (imap_path_probe(C_Postponed, NULL) == MUTT_IMAP)
123  {
124  if (force)
125  {
126  short newpc;
127 
128  newpc = imap_path_status(C_Postponed, false);
129  if (newpc >= 0)
130  {
131  PostCount = newpc;
132  mutt_debug(LL_DEBUG3, "%d postponed IMAP messages found\n", PostCount);
133  }
134  else
135  mutt_debug(LL_DEBUG3, "using old IMAP postponed count\n");
136  }
137  return PostCount;
138  }
139 #endif
140 
141  if (stat(C_Postponed, &st) == -1)
142  {
143  PostCount = 0;
144  LastModify = 0;
145  return 0;
146  }
147 
148  if (S_ISDIR(st.st_mode))
149  {
150  /* if we have a maildir mailbox, we need to stat the "new" dir */
151  struct Buffer *buf = mutt_buffer_pool_get();
152 
153  mutt_buffer_printf(buf, "%s/new", C_Postponed);
154  if ((access(mutt_b2s(buf), F_OK) == 0) && (stat(mutt_b2s(buf), &st) == -1))
155  {
156  PostCount = 0;
157  LastModify = 0;
159  return 0;
160  }
162  }
163 
164  if (LastModify < st.st_mtime)
165  {
166 #ifdef USE_NNTP
167  int optnews = OptNews;
168 #endif
169  LastModify = st.st_mtime;
170 
171  if (access(C_Postponed, R_OK | F_OK) != 0)
172  return PostCount = 0;
173 #ifdef USE_NNTP
174  if (optnews)
175  OptNews = false;
176 #endif
177  struct Mailbox *m_post = mx_path_resolve(C_Postponed);
178  struct Context *ctx = mx_mbox_open(m_post, MUTT_NOSORT | MUTT_QUIET);
179  if (ctx)
180  {
181  PostCount = ctx->mailbox->msg_count;
182  }
183  else
184  {
185  mailbox_free(&m_post);
186  PostCount = 0;
187  }
188  mx_fastclose_mailbox(m_post);
189  ctx_free(&ctx);
190 #ifdef USE_NNTP
191  if (optnews)
192  OptNews = true;
193 #endif
194  }
195 
196  return PostCount;
197 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:871
The "current" mailbox.
Definition: context.h:38
int msg_count
Total number of messages.
Definition: mailbox.h:91
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
int imap_path_status(const char *path, bool queue)
Refresh the number of total and new messages.
Definition: imap.c:1211
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe()
Definition: imap.c:2367
int msg_deleted
Number of deleted messages.
Definition: mailbox.h:96
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:84
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
struct Context * mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:303
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
struct Mailbox * mailbox
Definition: context.h:50
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:63
void mx_fastclose_mailbox(struct Mailbox *m)
free up memory associated with the Mailbox
Definition: mx.c:445
#define mutt_b2s(buf)
Definition: buffer.h:41
A mailbox.
Definition: mailbox.h:81
#define MUTT_NOSORT
Do not sort the mailbox after opening it.
Definition: mx.h:52
static short PostCount
Definition: postpone.c:78
#define MUTT_QUIET
Do not print any messages.
Definition: mx.h:55
#define FREE(x)
Definition: memory.h:40
struct Mailbox * mx_path_resolve(const char *path)
Get a Mailbox for a path.
Definition: mx.c:1681
static bool UpdateNumPostponed
Definition: postpone.c:79
void ctx_free(struct Context **ptr)
Free a Context.
Definition: context.c:50
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:45
Log at debug level 3.
Definition: logging.h:42
WHERE char * C_Postponed
Config: Folder to store postponed messages.
Definition: mutt_globals.h:101
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_thread_set_flag()

int mutt_thread_set_flag ( struct Email e,
int  flag,
bool  bf,
bool  subthread 
)

Set a flag on an entire thread.

Parameters
eEmail
flagFlag to set, e.g. MUTT_DELETE
bftrue: set the flag; false: clear the flag
subthreadIf true apply to all of the thread
Return values
0Success
-1Failure

Definition at line 371 of file flags.c.

372 {
373  struct MuttThread *start = NULL;
374  struct MuttThread *cur = e->thread;
375 
376  if ((C_Sort & SORT_MASK) != SORT_THREADS)
377  {
378  mutt_error(_("Threading is not enabled"));
379  return -1;
380  }
381 
382  if (!subthread)
383  while (cur->parent)
384  cur = cur->parent;
385  start = cur;
386 
387  if (cur->message && (cur != e->thread))
388  mutt_set_flag(Context->mailbox, cur->message, flag, bf);
389 
390  cur = cur->child;
391  if (!cur)
392  goto done;
393 
394  while (true)
395  {
396  if (cur->message && (cur != e->thread))
397  mutt_set_flag(Context->mailbox, cur->message, flag, bf);
398 
399  if (cur->child)
400  cur = cur->child;
401  else if (cur->next)
402  cur = cur->next;
403  else
404  {
405  while (!cur->next)
406  {
407  cur = cur->parent;
408  if (cur == start)
409  goto done;
410  }
411  cur = cur->next;
412  }
413  }
414 done:
415  cur = e->thread;
416  if (cur->message)
417  mutt_set_flag(Context->mailbox, cur->message, flag, bf);
418  return 0;
419 }
struct MuttThread * next
Next sibling Thread.
Definition: thread.h:47
The "current" mailbox.
Definition: context.h:38
#define mutt_set_flag(m, e, flag, bf)
Definition: protos.h:67
struct MuttThread * thread
Thread of Emails.
Definition: email.h:95
#define _(a)
Definition: message.h:28
struct MuttThread * parent
Parent of this Thread.
Definition: thread.h:45
struct Mailbox * mailbox
Definition: context.h:50
WHERE short C_Sort
Config: Sort method for the index.
Definition: sort.h:60
struct MuttThread * child
Child of this Thread.
Definition: thread.h:46
Sort by email threads.
Definition: sort2.h:51
struct Email * message
Email this Thread refers to.
Definition: thread.h:49
An Email conversation.
Definition: thread.h:34
#define mutt_error(...)
Definition: logging.h:84
#define SORT_MASK
Mask for the sort id.
Definition: sort2.h:80
+ Here is the caller graph for this function:

◆ mutt_update_num_postponed()

void mutt_update_num_postponed ( void  )

Force the update of the number of postponed messages.

Definition at line 202 of file postpone.c.

203 {
204  UpdateNumPostponed = true;
205 }
static bool UpdateNumPostponed
Definition: postpone.c:79
+ Here is the caller graph for this function:

◆ mutt_is_quote_line()

int mutt_is_quote_line ( char *  line,
regmatch_t *  pmatch 
)

Is a line of message text a quote?

Parameters
[in]lineLine to test
[out]pmatchRegex sub-matches
Return values
trueLine is quoted

Checks if line matches the $quote_regex and doesn't match $smileys. This is used by the pager for calling classify_quote.

Definition at line 964 of file pager.c.

965 {
966  bool is_quote = false;
967  regmatch_t pmatch_internal[1], smatch[1];
968 
969  if (!pmatch)
970  pmatch = pmatch_internal;
971 
972  if (mutt_regex_capture(C_QuoteRegex, line, 1, pmatch))
973  {
974  if (mutt_regex_capture(C_Smileys, line, 1, smatch))
975  {
976  if (smatch[0].rm_so > 0)
977  {
978  char c = line[smatch[0].rm_so];
979  line[smatch[0].rm_so] = 0;
980 
981  if (mutt_regex_capture(C_QuoteRegex, line, 1, pmatch))
982  is_quote = true;
983 
984  line[smatch[0].rm_so] = c;
985  }
986  }
987  else
988  is_quote = true;
989  }
990 
991  return is_quote;
992 }
struct Regex * C_Smileys
Config: Regex to match smileys to prevent mistakes when quoting text.
Definition: pager.c:92
WHERE struct Regex * C_QuoteRegex
Config: Regex to match quoted text in a reply.
Definition: mutt_globals.h:120
bool mutt_regex_capture(const struct Regex *regex, const char *str, size_t nmatch, regmatch_t matches[])
match a regex against a string, with provided options
Definition: regex.c:593
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ wcscasecmp()

int wcscasecmp ( const wchar_t *  a,
const wchar_t *  b 
)

Compare two wide-character strings, ignoring case.

Parameters
aFirst string
bSecond string
Return values
-1a precedes b
0a and b are identical
1b precedes a

Definition at line 41 of file wcscasecmp.c.

42 {
43  if (!a && !b)
44  return 0;
45  if (!a && b)
46  return -1;
47  if (a && !b)
48  return 1;
49 
50  for (; *a || *b; a++, b++)
51  {
52  int i = towlower(*a);
53  if ((i - towlower(*b)) != 0)
54  return i;
55  }
56  return 0;
57 }
+ Here is the caller graph for this function:

◆ mutt_reply_observer()

int mutt_reply_observer ( struct NotifyCallback nc)

Listen for config changes to "reply_regex" - Implements observer_t.

Definition at line 3979 of file index.c.

3980 {
3981  if (!nc->event_data)
3982  return -1;
3983  if (nc->event_type != NT_CONFIG)
3984  return 0;
3985 
3986  struct EventConfig *ec = nc->event_data;
3987 
3988  if (!mutt_str_equal(ec->name, "reply_regex"))
3989  return 0;
3990 
3991  if (!Context || !Context->mailbox)
3992  return 0;
3993 
3994  regmatch_t pmatch[1];
3995  struct Mailbox *m = Context->mailbox;
3996 
3997  for (int i = 0; i < m->msg_count; i++)
3998  {
3999  struct Email *e = m->emails[i];
4000  if (!e)
4001  break;
4002  struct Envelope *env = e->env;
4003  if (!env || !env->subject)
4004  continue;
4005 
4006  if (mutt_regex_capture(C_ReplyRegex, env->subject, 1, pmatch))
4007  {
4008  env->real_subj = env->subject + pmatch[0].rm_eo;
4009  continue;
4010  }
4011 
4012  env->real_subj = env->subject;
4013  }
4014 
4015  OptResortInit = true; /* trigger a redraw of the index */
4016  return 0;
4017 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:871
struct Email ** emails
Array of Emails.
Definition: mailbox.h:99
The "current" mailbox.
Definition: context.h:38
int msg_count
Total number of messages.
Definition: mailbox.h:91
The envelope/body of an email.
Definition: email.h:37
struct Regex * C_ReplyRegex
Config: Regex to match message reply subjects like "re: ".
Definition: globals.c:37
A config-change event.
Definition: subset.h:70
char * real_subj
Offset of the real subject.
Definition: envelope.h:67
enum NotifyType event_type
Send: Event type, e.g. NT_ACCOUNT.
Definition: observer.h:42
struct Mailbox * mailbox
Definition: context.h:50
struct Envelope * env
Envelope information.
Definition: email.h:90
A mailbox.
Definition: mailbox.h:81
WHERE bool OptResortInit
(pseudo) used to force the next resort to be from scratch
Definition: options.h:51
void * event_data
Data from notify_send()
Definition: observer.h:44
bool mutt_regex_capture(const struct Regex *regex, const char *str, size_t nmatch, regmatch_t matches[])
match a regex against a string, with provided options
Definition: regex.c:593
Config has changed, NotifyConfig, EventConfig.
Definition: notify_type.h:37
char * subject
Email&#39;s subject.
Definition: envelope.h:66
const char * name
Name of config item that changed.
Definition: subset.h:73
The header of an Email.
Definition: envelope.h:54
+ Here is the call graph for this function:
+ Here is the caller graph for this function: