NeoMutt  2018-07-16 +2388-bcedc8
Teaching an old dog new tricks
DOXYGEN
index.c File Reference

GUI manage the main index (list of emails) More...

#include "config.h"
#include <assert.h>
#include <ctype.h>
#include <limits.h>
#include <regex.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "mutt/mutt.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "conn/conn.h"
#include "mutt.h"
#include "index.h"
#include "alias.h"
#include "browser.h"
#include "commands.h"
#include "context.h"
#include "curs_lib.h"
#include "format_flags.h"
#include "globals.h"
#include "hdrline.h"
#include "hook.h"
#include "keymap.h"
#include "mutt_curses.h"
#include "mutt_header.h"
#include "mutt_logging.h"
#include "mutt_mailbox.h"
#include "mutt_menu.h"
#include "mutt_thread.h"
#include "mutt_window.h"
#include "muttlib.h"
#include "mx.h"
#include "ncrypt/ncrypt.h"
#include "opcodes.h"
#include "options.h"
#include "pager.h"
#include "pattern.h"
#include "progress.h"
#include "protos.h"
#include "query.h"
#include "recvattach.h"
#include "score.h"
#include "send.h"
#include "sort.h"
#include "status.h"
#include "terminal.h"
#include "sidebar.h"
#include "pop/pop.h"
#include "imap/imap.h"
#include "notmuch/mutt_notmuch.h"
#include "nntp/nntp.h"
#include <libintl.h>
#include "autocrypt/autocrypt.h"

Go to the source code of this file.

Macros

#define CUR_EMAIL   Context->mailbox->emails[Context->mailbox->v2r[menu->current]]
 
#define UNREAD(email)   mutt_thread_contains_unread(Context, email)
 
#define FLAGGED(email)   mutt_thread_contains_flagged(Context, email)
 
#define CAN_COLLAPSE(email)   ((C_CollapseUnread || !UNREAD(email)) && (C_CollapseFlagged || !FLAGGED(email)))
 
#define CHECK_NO_FLAGS   0
 No flags are set. More...
 
#define CHECK_IN_MAILBOX   (1 << 0)
 Is there a mailbox open? More...
 
#define CHECK_MSGCOUNT   (1 << 1)
 Are there any messages? More...
 
#define CHECK_VISIBLE   (1 << 2)
 Is the selected message visible in the index? More...
 
#define CHECK_READONLY   (1 << 3)
 Is the mailbox readonly? More...
 
#define CHECK_ATTACH   (1 << 4)
 Is the user in message-attach mode? More...
 

Typedefs

typedef uint8_t CheckFlags
 typedef CheckFlags - Checks to perform before running a function More...
 

Functions

static bool prereq (struct Context *ctx, struct Menu *menu, CheckFlags checks)
 Check the pre-requisites for a function. More...
 
static bool check_acl (struct Context *ctx, AclFlags acl, const char *msg)
 Check the ACLs for a function. More...
 
static void collapse_all (struct Menu *menu, int toggle)
 Collapse/uncollapse all threads. More...
 
static int ci_next_undeleted (int msgno)
 Find the next undeleted email. More...
 
static int ci_previous_undeleted (int msgno)
 Find the previous undeleted email. More...
 
static int ci_first_message (void)
 Get index of first new message. More...
 
static int mx_toggle_write (struct Mailbox *m)
 Toggle the mailbox's readonly flag. More...
 
static void resort_index (struct Menu *menu)
 Resort the index. More...
 
static void update_index_threaded (struct Context *ctx, int check, int oldcount)
 Update the index (if threaded) More...
 
static void update_index_unthreaded (struct Context *ctx, int check, int oldcount)
 Update the index (if unthreaded) More...
 
void update_index (struct Menu *menu, struct Context *ctx, int check, int oldcount, int index_hint)
 Update the index. More...
 
static int main_change_folder (struct Menu *menu, int op, struct Mailbox *m, char *buf, size_t buflen, int *oldcount, int *index_hint)
 Change to a different mailbox. More...
 
void index_make_entry (char *buf, size_t buflen, struct Menu *menu, int line)
 Format a menu item for the index list - Implements Menu::menu_make_entry() More...
 
int index_color (int line)
 Calculate the colour for a line of the index - Implements Menu::menu_color() More...
 
void mutt_draw_statusline (int cols, const char *buf, size_t buflen)
 Draw a highlighted status bar. More...
 
static void index_custom_redraw (struct Menu *menu)
 Redraw the index - Implements Menu::menu_custom_redraw() More...
 
int mutt_index_menu (void)
 Display a list of emails. More...
 
void mutt_set_header_color (struct Mailbox *m, struct Email *e)
 Select a colour for a message. More...
 
int mutt_reply_observer (struct NotifyCallback *nc)
 Listen for config changes to "reply_regex" - Implements observer_t() More...
 

Variables

bool C_ChangeFolderNext
 Config: Suggest the next folder, rather than the first when using '<change-folder>'. More...
 
bool C_CollapseAll
 Config: Collapse all threads when entering a folder. More...
 
bool C_CollapseFlagged
 Config: Prevent the collapse of threads with flagged emails. More...
 
bool C_CollapseUnread
 Config: Prevent the collapse of threads with unread emails. More...
 
char * C_MarkMacroPrefix
 Config: Prefix for macros using '<mark-message>'. More...
 
bool C_PgpAutoDecode
 Config: Automatically decrypt PGP messages. More...
 
bool C_UncollapseJump
 Config: When opening a thread, jump to the next unread message. More...
 
bool C_UncollapseNew
 Config: Open collapsed threads when new mail arrives. More...
 
static const struct Mapping IndexHelp []
 
struct Mapping IndexNewsHelp []
 

Detailed Description

GUI manage the main index (list of emails)

Authors
  • Michael R. Elkins

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 index.c.

Macro Definition Documentation

#define CUR_EMAIL   Context->mailbox->emails[Context->mailbox->v2r[menu->current]]

Definition at line 139 of file index.c.

#define UNREAD (   email)    mutt_thread_contains_unread(Context, email)

Definition at line 140 of file index.c.

#define FLAGGED (   email)    mutt_thread_contains_flagged(Context, email)

Definition at line 141 of file index.c.

#define CAN_COLLAPSE (   email)    ((C_CollapseUnread || !UNREAD(email)) && (C_CollapseFlagged || !FLAGGED(email)))

Definition at line 143 of file index.c.

#define CHECK_NO_FLAGS   0

No flags are set.

Definition at line 151 of file index.c.

#define CHECK_IN_MAILBOX   (1 << 0)

Is there a mailbox open?

Definition at line 152 of file index.c.

#define CHECK_MSGCOUNT   (1 << 1)

Are there any messages?

Definition at line 153 of file index.c.

#define CHECK_VISIBLE   (1 << 2)

Is the selected message visible in the index?

Definition at line 154 of file index.c.

#define CHECK_READONLY   (1 << 3)

Is the mailbox readonly?

Definition at line 155 of file index.c.

#define CHECK_ATTACH   (1 << 4)

Is the user in message-attach mode?

Definition at line 156 of file index.c.

Typedef Documentation

typedef uint8_t CheckFlags

typedef CheckFlags - Checks to perform before running a function

Flags, e.g. CHECK_IN_MAILBOX

Definition at line 150 of file index.c.

Function Documentation

static bool prereq ( struct Context ctx,
struct Menu menu,
CheckFlags  checks 
)
static

Check the pre-requisites for a function.

Parameters
ctxMailbox
menuCurrent Menu
checksChecks to perform, see CheckFlags
Return values
booltrue if the checks pass successfully

Definition at line 166 of file index.c.

167 {
168  bool result = true;
169 
170  if (checks & (CHECK_MSGCOUNT | CHECK_VISIBLE | CHECK_READONLY))
171  checks |= CHECK_IN_MAILBOX;
172 
173  if ((checks & CHECK_IN_MAILBOX) && (!ctx || !ctx->mailbox))
174  {
175  mutt_error(_("No mailbox is open"));
176  result = false;
177  }
178 
179  if (result && (checks & CHECK_MSGCOUNT) && (ctx->mailbox->msg_count == 0))
180  {
181  mutt_error(_("There are no messages"));
182  result = false;
183  }
184 
185  if (result && (checks & CHECK_VISIBLE) && (menu->current >= ctx->mailbox->vcount))
186  {
187  mutt_error(_("No visible messages"));
188  result = false;
189  }
190 
191  if (result && (checks & CHECK_READONLY) && ctx->mailbox->readonly)
192  {
193  mutt_error(_("Mailbox is read-only"));
194  result = false;
195  }
196 
197  if (result && (checks & CHECK_ATTACH) && OptAttachMsg)
198  {
199  mutt_error(_("Function not permitted in attach-message mode"));
200  result = false;
201  }
202 
203  if (!result)
204  mutt_flushinp();
205 
206  return result;
207 }
int msg_count
Total number of messages.
Definition: mailbox.h:102
void mutt_flushinp(void)
Empty all the keyboard buffers.
Definition: curs_lib.c:800
#define CHECK_ATTACH
Is the user in message-attach mode?
Definition: index.c:156
#define _(a)
Definition: message.h:28
int vcount
The number of virtual messages.
Definition: mailbox.h:113
#define CHECK_VISIBLE
Is the selected message visible in the index?
Definition: index.c:154
struct Mailbox * mailbox
Definition: context.h:50
#define CHECK_IN_MAILBOX
Is there a mailbox open?
Definition: index.c:152
bool readonly
Don&#39;t allow changes to the mailbox.
Definition: mailbox.h:130
WHERE bool OptAttachMsg
(pseudo) used by attach-message
Definition: options.h:31
#define CHECK_READONLY
Is the mailbox readonly?
Definition: index.c:155
#define mutt_error(...)
Definition: logging.h:84
#define CHECK_MSGCOUNT
Are there any messages?
Definition: index.c:153
int current
current entry
Definition: mutt_menu.h:87

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static bool check_acl ( struct Context ctx,
AclFlags  acl,
const char *  msg 
)
static

Check the ACLs for a function.

Parameters
ctxMailbox
aclACL, see AclFlags
msgError message for failure
Return values
booltrue if the function is permitted

Definition at line 216 of file index.c.

217 {
218  if (!ctx || !ctx->mailbox)
219  return false;
220 
221  if (!(ctx->mailbox->rights & acl))
222  {
223  /* L10N: %s is one of the CHECK_ACL entries below. */
224  mutt_error(_("%s: Operation not permitted by ACL"), msg);
225  return false;
226  }
227 
228  return true;
229 }
#define _(a)
Definition: message.h:28
struct Mailbox * mailbox
Definition: context.h:50
AclFlags rights
ACL bits, see AclFlags.
Definition: mailbox.h:132
#define mutt_error(...)
Definition: logging.h:84

+ Here is the caller graph for this function:

static void collapse_all ( struct Menu menu,
int  toggle 
)
static

Collapse/uncollapse all threads.

Parameters
menucurrent menu
toggletoggle collapsed state

This function is called by the OP_MAIN_COLLAPSE_ALL command and on folder enter if the C_CollapseAll option is set. In the first case, the toggle parameter is 1 to actually toggle collapsed/uncollapsed state on all threads. In the second case, the toggle parameter is 0, actually turning this function into a one-way collapse.

Definition at line 242 of file index.c.

243 {
244  struct Email *e = NULL, *base = NULL;
245  struct MuttThread *thread = NULL, *top = NULL;
246  int final;
247 
248  if (!Context || !Context->mailbox || (Context->mailbox->msg_count == 0))
249  return;
250 
251  /* Figure out what the current message would be after folding / unfolding,
252  * so that we can restore the cursor in a sane way afterwards. */
253  if (CUR_EMAIL->collapsed && toggle)
255  else if (CAN_COLLAPSE(CUR_EMAIL))
257  else
258  final = CUR_EMAIL->vnum;
259 
260  if (final == -1)
261  return;
262 
263  base = Context->mailbox->emails[Context->mailbox->v2r[final]];
264 
265  /* Iterate all threads, perform collapse/uncollapse as needed */
266  top = Context->tree;
267  Context->collapsed = toggle ? !Context->collapsed : true;
268  while ((thread = top))
269  {
270  while (!thread->message)
271  thread = thread->child;
272  e = thread->message;
273 
274  if (e->collapsed != Context->collapsed)
275  {
276  if (e->collapsed)
278  else if (CAN_COLLAPSE(e))
280  }
281  top = top->next;
282  }
283 
284  /* Restore the cursor */
286  for (int j = 0; j < Context->mailbox->vcount; j++)
287  {
288  if (Context->mailbox->emails[Context->mailbox->v2r[j]]->index == base->index)
289  {
290  menu->current = j;
291  break;
292  }
293  }
294 
296 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:110
The "current" mailbox.
Definition: context.h:36
int msg_count
Total number of messages.
Definition: mailbox.h:102
The envelope/body of an email.
Definition: email.h:39
void mutt_set_vnum(struct Context *ctx)
Set the virtual index number of all the messages in a mailbox.
Definition: mutt_thread.c:1186
struct MuttThread * tree
Top of thread tree.
Definition: context.h:42
#define mutt_collapse_thread(ctx, e)
Definition: mutt_thread.h:57
int vcount
The number of virtual messages.
Definition: mailbox.h:113
struct Mailbox * mailbox
Definition: context.h:50
#define CUR_EMAIL
Definition: index.c:139
struct MuttThread * child
Child of this Thread.
Definition: thread.h:46
#define CAN_COLLAPSE(email)
Definition: index.c:143
#define REDRAW_STATUS
Redraw the status bar.
Definition: mutt_menu.h:46
bool collapsed
Is this message part of a collapsed thread?
Definition: email.h:75
struct Email * message
Email this Thread refers to.
Definition: thread.h:49
MuttRedrawFlags redraw
when to redraw the screen
Definition: mutt_menu.h:89
An Email conversation.
Definition: thread.h:34
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:112
#define REDRAW_INDEX
Redraw the index.
Definition: mutt_menu.h:42
bool collapsed
Are all threads collapsed?
Definition: context.h:48
int index
The absolute (unsorted) message number.
Definition: email.h:87
int current
current entry
Definition: mutt_menu.h:87
#define mutt_uncollapse_thread(ctx, e)
Definition: mutt_thread.h:58

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int ci_next_undeleted ( int  msgno)
static

Find the next undeleted email.

Parameters
msgnoMessage number to start at
Return values
>=0Message number of next undeleted email
-1No more undeleted messages

Definition at line 304 of file index.c.

305 {
306  if (!Context || !Context->mailbox)
307  return -1;
308 
309  for (int i = msgno + 1; i < Context->mailbox->vcount; i++)
311  return i;
312  return -1;
313 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:110
The "current" mailbox.
Definition: context.h:36
int vcount
The number of virtual messages.
Definition: mailbox.h:113
struct Mailbox * mailbox
Definition: context.h:50
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:112
bool deleted
Email is deleted.
Definition: email.h:47

+ Here is the caller graph for this function:

static int ci_previous_undeleted ( int  msgno)
static

Find the previous undeleted email.

Parameters
msgnoMessage number to start at
Return values
>=0Message number of next undeleted email
-1No more undeleted messages

Definition at line 321 of file index.c.

322 {
323  if (!Context || !Context->mailbox)
324  return -1;
325 
326  for (int i = msgno - 1; i >= 0; i--)
328  return i;
329  return -1;
330 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:110
The "current" mailbox.
Definition: context.h:36
struct Mailbox * mailbox
Definition: context.h:50
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:112
bool deleted
Email is deleted.
Definition: email.h:47

+ Here is the caller graph for this function:

static int ci_first_message ( void  )
static

Get index of first new message.

Return values
numIndex of first new message

Return the index of the first new message, or failing that, the first unread message.

Definition at line 339 of file index.c.

340 {
341  if (!Context || !Context->mailbox || (Context->mailbox->msg_count == 0))
342  return 0;
343 
344  int old = -1;
345  for (int i = 0; i < Context->mailbox->vcount; i++)
346  {
347  if (!Context->mailbox->emails[Context->mailbox->v2r[i]]->read &&
349  {
350  if (!Context->mailbox->emails[Context->mailbox->v2r[i]]->old)
351  return i;
352  else if (old == -1)
353  old = i;
354  }
355  }
356  if (old != -1)
357  return old;
358 
359  /* If C_Sort is reverse and not threaded, the latest message is first.
360  * If C_Sort is threaded, the latest message is first if exactly one
361  * of C_Sort and C_SortAux are reverse. */
362  if (((C_Sort & SORT_REVERSE) && ((C_Sort & SORT_MASK) != SORT_THREADS)) ||
363  (((C_Sort & SORT_MASK) == SORT_THREADS) && ((C_Sort ^ C_SortAux) & SORT_REVERSE)))
364  {
365  return 0;
366  }
367  else
368  {
369  return Context->mailbox->vcount ? Context->mailbox->vcount - 1 : 0;
370  }
371 
372  return 0;
373 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:110
The "current" mailbox.
Definition: context.h:36
int msg_count
Total number of messages.
Definition: mailbox.h:102
int vcount
The number of virtual messages.
Definition: mailbox.h:113
bool read
Email is read.
Definition: email.h:53
struct Mailbox * mailbox
Definition: context.h:50
bool old
Email is seen, but unread.
Definition: email.h:52
WHERE short C_Sort
Config: Sort method for the index.
Definition: sort.h:58
WHERE short C_SortAux
Config: Secondary sort method for the index.
Definition: sort.h:59
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:112
bool deleted
Email is deleted.
Definition: email.h:47
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort.h:86
Sort by email threads.
Definition: sort.h:56
#define SORT_MASK
Mask for the sort id.
Definition: sort.h:85

+ Here is the caller graph for this function:

static int mx_toggle_write ( struct Mailbox m)
static

Toggle the mailbox's readonly flag.

Parameters
mMailbox
Return values
0Success
-1Error

This should be in mx.c, but it only gets used here.

Definition at line 383 of file index.c.

384 {
385  if (!m)
386  return -1;
387 
388  if (m->readonly)
389  {
390  mutt_error(_("Can't toggle write on a readonly mailbox"));
391  return -1;
392  }
393 
394  if (m->dontwrite)
395  {
396  m->dontwrite = false;
397  mutt_message(_("Changes to folder will be written on folder exit"));
398  }
399  else
400  {
401  m->dontwrite = true;
402  mutt_message(_("Changes to folder will not be written"));
403  }
404 
405  return 0;
406 }
#define mutt_message(...)
Definition: logging.h:83
#define _(a)
Definition: message.h:28
bool readonly
Don&#39;t allow changes to the mailbox.
Definition: mailbox.h:130
bool dontwrite
Don&#39;t write the mailbox on close.
Definition: mailbox.h:126
#define mutt_error(...)
Definition: logging.h:84

+ Here is the caller graph for this function:

static void resort_index ( struct Menu menu)
static

Resort the index.

Parameters
menuCurrent Menu

Definition at line 412 of file index.c.

413 {
414  if (!Context || !Context->mailbox)
415  return;
416 
417  struct Email *e = CUR_EMAIL;
418 
419  menu->current = -1;
420  mutt_sort_headers(Context, false);
421  /* Restore the current message */
422 
423  for (int i = 0; i < Context->mailbox->vcount; i++)
424  {
425  if (Context->mailbox->emails[Context->mailbox->v2r[i]] == e)
426  {
427  menu->current = i;
428  break;
429  }
430  }
431 
432  if (((C_Sort & SORT_MASK) == SORT_THREADS) && (menu->current < 0))
433  menu->current = mutt_parent_message(Context, e, false);
434 
435  if (menu->current < 0)
436  menu->current = ci_first_message();
437 
438  menu->redraw |= REDRAW_INDEX | REDRAW_STATUS;
439 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:110
The "current" mailbox.
Definition: context.h:36
The envelope/body of an email.
Definition: email.h:39
int vcount
The number of virtual messages.
Definition: mailbox.h:113
struct Mailbox * mailbox
Definition: context.h:50
int mutt_parent_message(struct Context *ctx, struct Email *e, bool find_root)
Find the parent of a message.
Definition: mutt_thread.c:1140
#define CUR_EMAIL
Definition: index.c:139
WHERE short C_Sort
Config: Sort method for the index.
Definition: sort.h:58
static int ci_first_message(void)
Get index of first new message.
Definition: index.c:339
void mutt_sort_headers(struct Context *ctx, bool init)
Sort emails by their headers.
Definition: sort.c:362
#define REDRAW_STATUS
Redraw the status bar.
Definition: mutt_menu.h:46
MuttRedrawFlags redraw
when to redraw the screen
Definition: mutt_menu.h:89
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:112
#define REDRAW_INDEX
Redraw the index.
Definition: mutt_menu.h:42
int current
current entry
Definition: mutt_menu.h:87
Sort by email threads.
Definition: sort.h:56
#define SORT_MASK
Mask for the sort id.
Definition: sort.h:85

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void update_index_threaded ( struct Context ctx,
int  check,
int  oldcount 
)
static

Update the index (if threaded)

Parameters
ctxMailbox
checkFlags, e.g. MUTT_REOPENED
oldcountHow many items are currently in the index

Definition at line 447 of file index.c.

448 {
449  struct Email **save_new = NULL;
450 
451  /* save the list of new messages */
452  if ((check != MUTT_REOPENED) && oldcount && (ctx->pattern || C_UncollapseNew))
453  {
454  save_new = mutt_mem_malloc(sizeof(struct Email *) * (ctx->mailbox->msg_count - oldcount));
455  for (int i = oldcount; i < ctx->mailbox->msg_count; i++)
456  save_new[i - oldcount] = ctx->mailbox->emails[i];
457  }
458 
459  /* Sort first to thread the new messages, because some patterns
460  * require the threading information.
461  *
462  * If the mailbox was reopened, need to rethread from scratch. */
463  mutt_sort_headers(ctx, (check == MUTT_REOPENED));
464 
465  if (ctx->pattern)
466  {
467  for (int i = (check == MUTT_REOPENED) ? 0 : oldcount; i < ctx->mailbox->msg_count; i++)
468  {
469  struct Email *e = NULL;
470 
471  if ((check != MUTT_REOPENED) && oldcount)
472  e = save_new[i - oldcount];
473  else
474  e = ctx->mailbox->emails[i];
475 
477  MUTT_MATCH_FULL_ADDRESS, ctx->mailbox, e, NULL))
478  {
479  /* vnum will get properly set by mutt_set_vnum(), which
480  * is called by mutt_sort_headers() just below. */
481  e->vnum = 1;
482  e->limited = true;
483  }
484  }
485  /* Need a second sort to set virtual numbers and redraw the tree */
486  mutt_sort_headers(ctx, false);
487  }
488 
489  /* uncollapse threads with new mail */
490  if (C_UncollapseNew)
491  {
492  if (check == MUTT_REOPENED)
493  {
494  ctx->collapsed = false;
495 
496  for (struct MuttThread *h = ctx->tree; h; h = h->next)
497  {
498  struct MuttThread *j = h;
499  for (; !j->message; j = j->child)
500  ;
502  }
503  mutt_set_vnum(ctx);
504  }
505  else if (oldcount)
506  {
507  for (int j = 0; j < (ctx->mailbox->msg_count - oldcount); j++)
508  {
509  if (!ctx->pattern || save_new[j]->limited)
510  {
511  mutt_uncollapse_thread(ctx, save_new[j]);
512  }
513  }
514  mutt_set_vnum(ctx);
515  }
516  }
517 
518  FREE(&save_new);
519 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:110
struct MuttThread * next
Next sibling Thread.
Definition: thread.h:47
int msg_count
Total number of messages.
Definition: mailbox.h:102
The envelope/body of an email.
Definition: email.h:39
void mutt_set_vnum(struct Context *ctx)
Set the virtual index number of all the messages in a mailbox.
Definition: mutt_thread.c:1186
struct MuttThread * tree
Top of thread tree.
Definition: context.h:42
struct PatternHead * limit_pattern
Compiled limit pattern.
Definition: context.h:40
struct Mailbox * mailbox
Definition: context.h:50
bool limited
Is this message in a limited view?
Definition: email.h:76
int mutt_pattern_exec(struct Pattern *pat, PatternExecFlags flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
Match a pattern against an email header.
Definition: pattern.c:2002
struct MuttThread * child
Child of this Thread.
Definition: thread.h:46
void mutt_sort_headers(struct Context *ctx, bool init)
Sort emails by their headers.
Definition: sort.c:362
#define SLIST_FIRST(head)
Definition: queue.h:229
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
int vnum
Virtual message number.
Definition: email.h:89
struct Email * message
Email this Thread refers to.
Definition: thread.h:49
#define MUTT_MATCH_FULL_ADDRESS
Match the full address.
Definition: pattern.h:75
An Email conversation.
Definition: thread.h:34
bool collapsed
Are all threads collapsed?
Definition: context.h:48
#define FREE(x)
Definition: memory.h:40
Mailbox was reopened.
Definition: mx.h:74
char * pattern
Limit pattern string.
Definition: context.h:39
bool C_UncollapseNew
Config: Open collapsed threads when new mail arrives.
Definition: index.c:111
#define mutt_uncollapse_thread(ctx, e)
Definition: mutt_thread.h:58

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void update_index_unthreaded ( struct Context ctx,
int  check,
int  oldcount 
)
static

Update the index (if unthreaded)

Parameters
ctxMailbox
checkFlags, e.g. MUTT_REOPENED
oldcountHow many items are currently in the index

Definition at line 527 of file index.c.

528 {
529  /* We are in a limited view. Check if the new message(s) satisfy
530  * the limit criteria. If they do, set their virtual msgno so that
531  * they will be visible in the limited view */
532  if (ctx->pattern)
533  {
534  int padding = mx_msg_padding_size(ctx->mailbox);
535  for (int i = (check == MUTT_REOPENED) ? 0 : oldcount; i < ctx->mailbox->msg_count; i++)
536  {
537  if (i == 0)
538  {
539  ctx->mailbox->vcount = 0;
540  ctx->vsize = 0;
541  }
542 
544  ctx->mailbox, ctx->mailbox->emails[i], NULL))
545  {
546  assert(ctx->mailbox->vcount < ctx->mailbox->msg_count);
547  ctx->mailbox->emails[i]->vnum = ctx->mailbox->vcount;
548  ctx->mailbox->v2r[ctx->mailbox->vcount] = i;
549  ctx->mailbox->emails[i]->limited = true;
550  ctx->mailbox->vcount++;
551  struct Body *b = ctx->mailbox->emails[i]->content;
552  ctx->vsize += b->length + b->offset - b->hdr_offset + padding;
553  }
554  }
555  }
556 
557  /* if the mailbox was reopened, need to rethread from scratch */
558  mutt_sort_headers(ctx, (check == MUTT_REOPENED));
559 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:110
int msg_count
Total number of messages.
Definition: mailbox.h:102
struct Body * content
List of MIME parts.
Definition: email.h:92
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
int vcount
The number of virtual messages.
Definition: mailbox.h:113
The body of an email.
Definition: body.h:34
struct PatternHead * limit_pattern
Compiled limit pattern.
Definition: context.h:40
struct Mailbox * mailbox
Definition: context.h:50
bool limited
Is this message in a limited view?
Definition: email.h:76
off_t vsize
Definition: context.h:38
int mutt_pattern_exec(struct Pattern *pat, PatternExecFlags flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
Match a pattern against an email header.
Definition: pattern.c:2002
void mutt_sort_headers(struct Context *ctx, bool init)
Sort emails by their headers.
Definition: sort.c:362
#define SLIST_FIRST(head)
Definition: queue.h:229
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
int vnum
Virtual message number.
Definition: email.h:89
#define MUTT_MATCH_FULL_ADDRESS
Match the full address.
Definition: pattern.h:75
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:112
int mx_msg_padding_size(struct Mailbox *m)
Bytes of padding between messages - Wrapper for MxOps::msg_padding_size.
Definition: mx.c:1464
long hdr_offset
Offset in stream where the headers begin.
Definition: body.h:42
Mailbox was reopened.
Definition: mx.h:74
char * pattern
Limit pattern string.
Definition: context.h:39

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void update_index ( struct Menu menu,
struct Context ctx,
int  check,
int  oldcount,
int  index_hint 
)

Update the index.

Parameters
menuCurrent Menu
ctxMailbox
checkFlags, e.g. MUTT_REOPENED
oldcountHow many items are currently in the index
index_hintRemember our place in the index

Definition at line 569 of file index.c.

570 {
571  if (!menu || !ctx)
572  return;
573 
574  /* take note of the current message */
575  if (oldcount)
576  {
577  if (menu->current < ctx->mailbox->vcount)
578  menu->oldcurrent = index_hint;
579  else
580  oldcount = 0; /* invalid message number! */
581  }
582 
583  if ((C_Sort & SORT_MASK) == SORT_THREADS)
584  update_index_threaded(ctx, check, oldcount);
585  else
586  update_index_unthreaded(ctx, check, oldcount);
587 
588  menu->current = -1;
589  if (oldcount)
590  {
591  /* restore the current message to the message it was pointing to */
592  for (int i = 0; i < ctx->mailbox->vcount; i++)
593  {
594  if (ctx->mailbox->emails[ctx->mailbox->v2r[i]]->index == menu->oldcurrent)
595  {
596  menu->current = i;
597  break;
598  }
599  }
600  }
601 
602  if (menu->current < 0)
603  menu->current = ci_first_message();
604 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:110
int oldcurrent
for driver use only
Definition: mutt_menu.h:111
static void update_index_unthreaded(struct Context *ctx, int check, int oldcount)
Update the index (if unthreaded)
Definition: index.c:527
int vcount
The number of virtual messages.
Definition: mailbox.h:113
struct Mailbox * mailbox
Definition: context.h:50
WHERE short C_Sort
Config: Sort method for the index.
Definition: sort.h:58
static int ci_first_message(void)
Get index of first new message.
Definition: index.c:339
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:112
int index
The absolute (unsorted) message number.
Definition: email.h:87
static void update_index_threaded(struct Context *ctx, int check, int oldcount)
Update the index (if threaded)
Definition: index.c:447
int current
current entry
Definition: mutt_menu.h:87
Sort by email threads.
Definition: sort.h:56
#define SORT_MASK
Mask for the sort id.
Definition: sort.h:85

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int main_change_folder ( struct Menu menu,
int  op,
struct Mailbox m,
char *  buf,
size_t  buflen,
int *  oldcount,
int *  index_hint 
)
static

Change to a different mailbox.

Parameters
menuCurrent Menu
mMailbox
opOperation, e.g. OP_MAIN_CHANGE_FOLDER_READONLY
bufFolder to change to
buflenLength of buffer
oldcountHow many items are currently in the index
index_hintRemember our place in the index
Return values
0Success
-1Error

Definition at line 618 of file index.c.

620 {
621 #ifdef USE_NNTP
622  if (OptNews)
623  {
624  OptNews = false;
625  nntp_expand_path(buf, buflen, &CurrentNewsSrv->conn->account);
626  }
627  else
628 #endif
629  {
630  mx_path_canon(buf, buflen, C_Folder, NULL);
631  }
632 
633  enum MailboxType magic = mx_path_probe(buf, NULL);
634  if ((magic == MUTT_MAILBOX_ERROR) || (magic == MUTT_UNKNOWN))
635  {
636  // Try to see if the buffer matches a description before we bail.
637  // We'll receive a non-null pointer if there is a corresponding mailbox.
638  m = mailbox_find_name(buf);
639  if (m)
640  {
641  mutt_str_strfcpy(buf, mutt_b2s(m->pathbuf), buflen);
642  }
643  else
644  {
645  // Bail.
646  mutt_error(_("%s is not a mailbox"), buf);
647  return -1;
648  }
649  }
650 
651  /* keepalive failure in mutt_enter_fname may kill connection. #3028 */
653  ctx_free(&Context);
654 
655  if (Context && Context->mailbox)
656  {
657  char *new_last_folder = NULL;
658 #ifdef USE_INOTIFY
659  int monitor_remove_rc = mutt_monitor_remove(NULL);
660 #endif
661 #ifdef USE_COMPRESSED
662  if (Context->mailbox->compress_info && (Context->mailbox->realpath[0] != '\0'))
663  new_last_folder = mutt_str_strdup(Context->mailbox->realpath);
664  else
665 #endif
666  new_last_folder = mutt_str_strdup(mutt_b2s(Context->mailbox->pathbuf));
667  *oldcount = Context->mailbox->msg_count;
668 
669  int check = mx_mbox_close(&Context);
670  if (check != 0)
671  {
672 #ifdef USE_INOTIFY
673  if (monitor_remove_rc == 0)
674  mutt_monitor_add(NULL);
675 #endif
676  if ((check == MUTT_NEW_MAIL) || (check == MUTT_REOPENED))
677  update_index(menu, Context, check, *oldcount, *index_hint);
678 
679  FREE(&new_last_folder);
680  OptSearchInvalid = true;
681  menu->redraw |= REDRAW_INDEX | REDRAW_STATUS;
682  return 0;
683  }
684  FREE(&LastFolder);
685  LastFolder = new_last_folder;
686  }
688 
689  mutt_sleep(0);
690 
691  /* Note that menu->menu may be MENU_PAGER if the change folder
692  * operation originated from the pager.
693  *
694  * However, exec commands currently use CurrentMenu to determine what
695  * functions are available, which is automatically set by the
696  * mutt_push/pop_current_menu() functions. If that changes, the menu
697  * would need to be reset here, and the pager cleanup code after the
698  * switch statement would need to be run. */
699  mutt_folder_hook(buf, m ? m->name : NULL);
700 
701  int flags = MUTT_OPEN_NO_FLAGS;
702  if (C_ReadOnly || (op == OP_MAIN_CHANGE_FOLDER_READONLY))
703  flags = MUTT_READONLY;
704 #ifdef USE_NOTMUCH
705  if (op == OP_MAIN_VFOLDER_FROM_QUERY_READONLY)
706  flags = MUTT_READONLY;
707 #endif
708 
709  bool free_m = false;
710  if (!m)
711  {
712  m = mx_path_resolve(buf);
713  free_m = true;
714  }
715  Context = mx_mbox_open(m, flags);
716  if (Context)
717  {
718  menu->current = ci_first_message();
719 #ifdef USE_INOTIFY
720  mutt_monitor_add(NULL);
721 #endif
722  }
723  else
724  {
725  menu->current = 0;
726  if (free_m)
727  mailbox_free(&m);
728  }
729 
730  if (((C_Sort & SORT_MASK) == SORT_THREADS) && C_CollapseAll)
731  collapse_all(menu, 0);
732 
733 #ifdef USE_SIDEBAR
735 #endif
736 
738  mutt_mailbox_check(Context ? Context->mailbox : NULL, MUTT_MAILBOX_CHECK_FORCE); /* force the mailbox check after we have changed the folder */
739  menu->redraw = REDRAW_FULL;
740  OptSearchInvalid = true;
741 
742  return 0;
743 }
#define MUTT_OPEN_NO_FLAGS
No flags are set.
Definition: mx.h:50
The "current" mailbox.
Definition: context.h:36
#define REDRAW_FULL
Redraw everything.
Definition: mutt_menu.h:47
int msg_count
Total number of messages.
Definition: mailbox.h:102
struct ConnAccount account
Definition: connection.h:36
int mx_mbox_close(struct Context **ptr)
Save changes and close mailbox.
Definition: mx.c:558
int mx_path_canon(char *buf, size_t buflen, const char *folder, enum MailboxType *magic)
Canonicalise a mailbox path - Wrapper for MxOps::path_canon.
Definition: mx.c:1297
int mutt_monitor_remove(struct Mailbox *m)
Remove a watch for a mailbox.
Definition: monitor.c:508
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:95
#define _(a)
Definition: message.h:28
Mailbox wasn&#39;t recognised.
Definition: mailbox.h:46
Error occurred examining Mailbox.
Definition: mailbox.h:45
struct Context * mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:254
WHERE char * LastFolder
Previously selected mailbox.
Definition: globals.h:54
bool C_CollapseAll
Config: Collapse all threads when entering a folder.
Definition: index.c:105
#define MUTT_READONLY
Open in read-only mode.
Definition: mx.h:53
int mutt_monitor_add(struct Mailbox *m)
Add a watch for a mailbox.
Definition: monitor.c:463
static void collapse_all(struct Menu *menu, int toggle)
Collapse/uncollapse all threads.
Definition: index.c:242
void mutt_folder_hook(const char *path, const char *desc)
Perform a folder hook.
Definition: hook.c:516
char * name
A short name for the Mailbox.
Definition: mailbox.h:96
void mutt_sleep(short s)
Sleep for a while.
Definition: muttlib.c:1502
struct Mailbox * mailbox
Definition: context.h:50
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:55
WHERE char * CurrentFolder
Currently selected mailbox.
Definition: globals.h:53
WHERE short C_Sort
Config: Sort method for the index.
Definition: sort.h:58
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:143
WHERE bool C_ReadOnly
Config: Open folders in read-only mode.
Definition: globals.h:256
#define mutt_b2s(buf)
Definition: buffer.h:41
static int ci_first_message(void)
Get index of first new message.
Definition: index.c:339
#define REDRAW_STATUS
Redraw the status bar.
Definition: mutt_menu.h:46
WHERE char * C_Folder
Config: Base folder for a set of mailboxes.
Definition: globals.h:123
struct Mailbox * mailbox_find_name(const char *name)
Find the mailbox with a given name.
Definition: mailbox.c:115
int mutt_mailbox_check(struct Mailbox *m_cur, int force)
Check all all Mailboxes for new mail.
Definition: mutt_mailbox.c:126
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:750
WHERE bool OptSearchInvalid
(pseudo) used to invalidate the search pat
Definition: options.h:50
void update_index(struct Menu *menu, struct Context *ctx, int check, int oldcount, int index_hint)
Update the index.
Definition: index.c:569
void mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:453
void nntp_expand_path(char *buf, size_t buflen, struct ConnAccount *acct)
Make fully qualified url from newsgroup name.
Definition: newsrc.c:549
#define MUTT_MAILBOX_CHECK_FORCE
Definition: mutt_mailbox.h:17
struct Buffer * pathbuf
Definition: mailbox.h:94
MuttRedrawFlags redraw
when to redraw the screen
Definition: mutt_menu.h:89
struct Connection * conn
Definition: nntp.h:102
MailboxType
Supported mailbox formats.
Definition: mailbox.h:42
#define REDRAW_INDEX
Redraw the index.
Definition: mutt_menu.h:42
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
#define mutt_error(...)
Definition: logging.h:84
void * compress_info
Compressed mbox module private data.
Definition: mailbox.h:135
#define FREE(x)
Definition: memory.h:40
struct Mailbox * mx_path_resolve(const char *path)
XXX.
Definition: mx.c:1541
void ctx_free(struct Context **ptr)
Free a Context.
Definition: context.c:48
New mail received in Mailbox.
Definition: mx.h:72
int current
current entry
Definition: mutt_menu.h:87
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:283
enum MailboxType mx_path_probe(const char *path, struct stat *st)
Find a mailbox that understands a path.
Definition: mx.c:1238
Mailbox was reopened.
Definition: mx.h:74
Sort by email threads.
Definition: sort.h:56
#define SORT_MASK
Mask for the sort id.
Definition: sort.h:85
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:43
struct NntpAccountData * CurrentNewsSrv
Current NNTP news server.
Definition: nntp.c:75

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

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

Definition at line 748 of file index.c.

749 {
750  if (!Context || !Context->mailbox || !menu || (line < 0) ||
751  (line >= Context->mailbox->email_max))
752  return;
753 
754  struct Email *e = Context->mailbox->emails[Context->mailbox->v2r[line]];
755  if (!e)
756  return;
757 
759  struct MuttThread *tmp = NULL;
760 
761  if (((C_Sort & SORT_MASK) == SORT_THREADS) && e->tree)
762  {
763  flags |= MUTT_FORMAT_TREE; /* display the thread tree */
764  if (e->display_subject)
765  flags |= MUTT_FORMAT_FORCESUBJ;
766  else
767  {
768  const int reverse = C_Sort & SORT_REVERSE;
769  int edgemsgno;
770  if (reverse)
771  {
772  if (menu->top + menu->pagelen > menu->max)
773  edgemsgno = Context->mailbox->v2r[menu->max - 1];
774  else
775  edgemsgno = Context->mailbox->v2r[menu->top + menu->pagelen - 1];
776  }
777  else
778  edgemsgno = Context->mailbox->v2r[menu->top];
779 
780  for (tmp = e->thread->parent; tmp; tmp = tmp->parent)
781  {
782  if (!tmp->message)
783  continue;
784 
785  /* if no ancestor is visible on current screen, provisionally force
786  * subject... */
787  if (reverse ? (tmp->message->msgno > edgemsgno) : (tmp->message->msgno < edgemsgno))
788  {
789  flags |= MUTT_FORMAT_FORCESUBJ;
790  break;
791  }
792  else if (tmp->message->vnum >= 0)
793  break;
794  }
795  if (flags & MUTT_FORMAT_FORCESUBJ)
796  {
797  for (tmp = e->thread->prev; tmp; tmp = tmp->prev)
798  {
799  if (!tmp->message)
800  continue;
801 
802  /* ...but if a previous sibling is available, don't force it */
803  if (reverse ? (tmp->message->msgno > edgemsgno) : (tmp->message->msgno < edgemsgno))
804  break;
805  else if (tmp->message->vnum >= 0)
806  {
807  flags &= ~MUTT_FORMAT_FORCESUBJ;
808  break;
809  }
810  }
811  }
812  }
813  }
814 
816  Context->mailbox, e, flags);
817 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:110
The "current" mailbox.
Definition: context.h:36
uint8_t MuttFormatFlags
Flags for mutt_expando_format(), e.g. MUTT_FORMAT_FORCESUBJ.
Definition: format_flags.h:29
#define NONULL(x)
Definition: string2.h:37
The envelope/body of an email.
Definition: email.h:39
#define MUTT_FORMAT_FORCESUBJ
Print the subject even if unchanged.
Definition: format_flags.h:31
struct MuttThread * thread
Thread of Emails.
Definition: email.h:96
#define MUTT_FORMAT_ARROWCURSOR
Reserve space for arrow_cursor.
Definition: format_flags.h:35
bool display_subject
Used for threading.
Definition: email.h:59
struct MuttThread * parent
Parent of this Thread.
Definition: thread.h:45
struct MuttThread * prev
Previous sibling Thread.
Definition: thread.h:48
struct Mailbox * mailbox
Definition: context.h:50
#define MUTT_FORMAT_TREE
Draw the thread tree.
Definition: format_flags.h:32
void mutt_make_string_flags(char *buf, size_t buflen, const char *s, struct Context *ctx, struct Mailbox *m, struct Email *e, MuttFormatFlags flags)
Create formatted strings using mailbox expandos.
Definition: hdrline.c:1500
WHERE short C_Sort
Config: Sort method for the index.
Definition: sort.h:58
const char * line
Definition: common.c:36
int email_max
Number of pointers in emails.
Definition: mailbox.h:111
WHERE char * C_IndexFormat
Config: printf-like format string for the index menu (emails)
Definition: globals.h:116
int top
entry that is the top of the current page
Definition: mutt_menu.h:110
int vnum
Virtual message number.
Definition: email.h:89
int pagelen
number of entries per screen
Definition: mutt_menu.h:92
char * tree
Character string to print thread tree.
Definition: email.h:95
struct Email * message
Email this Thread refers to.
Definition: thread.h:49
int max
the number of entries in the menu
Definition: mutt_menu.h:88
An Email conversation.
Definition: thread.h:34
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:112
#define MUTT_FORMAT_INDEX
This is a main index entry.
Definition: format_flags.h:36
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort.h:86
Sort by email threads.
Definition: sort.h:56
#define SORT_MASK
Mask for the sort id.
Definition: sort.h:85
int msgno
Number displayed to the user.
Definition: email.h:88

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int index_color ( int  line)

Calculate the colour for a line of the index - Implements Menu::menu_color()

Definition at line 822 of file index.c.

823 {
824  if (!Context || !Context->mailbox || (line < 0))
825  return 0;
826 
827  struct Email *e = Context->mailbox->emails[Context->mailbox->v2r[line]];
828 
829  if (e && e->pair)
830  return e->pair;
831 
833  if (e)
834  return e->pair;
835 
836  return 0;
837 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:110
The "current" mailbox.
Definition: context.h:36
The envelope/body of an email.
Definition: email.h:39
struct Mailbox * mailbox
Definition: context.h:50
const char * line
Definition: common.c:36
void mutt_set_header_color(struct Mailbox *m, struct Email *e)
Select a colour for a message.
Definition: index.c:3672
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:112
int pair
Color-pair to use when displaying in the index.
Definition: email.h:81

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void mutt_draw_statusline ( int  cols,
const char *  buf,
size_t  buflen 
)

Draw a highlighted status bar.

Parameters
colsMaximum number of screen columns
bufMessage to be displayed
buflenLength of the buffer

Users configure the highlighting of the status bar, e.g. color status red default "[0-9][0-9]:[0-9][0-9]"

Where regexes overlap, the one nearest the start will be used. If two regexes start at the same place, the longer match will be used.

Definition at line 851 of file index.c.

852 {
853  size_t i = 0;
854  size_t offset = 0;
855  bool found = false;
856  size_t chunks = 0;
857  size_t len = 0;
858 
859  struct Syntax
860  {
861  int color;
862  int first;
863  int last;
864  } *syntax = NULL;
865 
866  if (!buf || !stdscr)
867  return;
868 
869  do
870  {
871  struct ColorLine *cl = NULL;
872  found = false;
873 
874  if (!buf[offset])
875  break;
876 
877  /* loop through each "color status regex" */
878  STAILQ_FOREACH(cl, &ColorStatusList, entries)
879  {
880  regmatch_t pmatch[cl->match + 1];
881 
882  if (regexec(&cl->regex, buf + offset, cl->match + 1, pmatch, 0) != 0)
883  continue; /* regex doesn't match the status bar */
884 
885  int first = pmatch[cl->match].rm_so + offset;
886  int last = pmatch[cl->match].rm_eo + offset;
887 
888  if (first == last)
889  continue; /* ignore an empty regex */
890 
891  if (!found)
892  {
893  chunks++;
894  mutt_mem_realloc(&syntax, chunks * sizeof(struct Syntax));
895  }
896 
897  i = chunks - 1;
898  if (!found || (first < syntax[i].first) ||
899  ((first == syntax[i].first) && (last > syntax[i].last)))
900  {
901  syntax[i].color = cl->pair;
902  syntax[i].first = first;
903  syntax[i].last = last;
904  }
905  found = true;
906  }
907 
908  if (syntax)
909  {
910  offset = syntax[i].last;
911  }
912  } while (found);
913 
914  /* Only 'len' bytes will fit into 'cols' screen columns */
915  len = mutt_wstr_trunc(buf, buflen, cols, NULL);
916 
917  offset = 0;
918 
919  if ((chunks > 0) && (syntax[0].first > 0))
920  {
921  /* Text before the first highlight */
922  addnstr(buf, MIN(len, syntax[0].first));
923  attrset(ColorDefs[MT_COLOR_STATUS]);
924  if (len <= syntax[0].first)
925  goto dsl_finish; /* no more room */
926 
927  offset = syntax[0].first;
928  }
929 
930  for (i = 0; i < chunks; i++)
931  {
932  /* Highlighted text */
933  attrset(syntax[i].color);
934  addnstr(buf + offset, MIN(len, syntax[i].last) - offset);
935  if (len <= syntax[i].last)
936  goto dsl_finish; /* no more room */
937 
938  size_t next;
939  if ((i + 1) == chunks)
940  {
941  next = len;
942  }
943  else
944  {
945  next = MIN(len, syntax[i + 1].first);
946  }
947 
948  attrset(ColorDefs[MT_COLOR_STATUS]);
949  offset = syntax[i].last;
950  addnstr(buf + offset, next - offset);
951 
952  offset = next;
953  if (offset >= len)
954  goto dsl_finish; /* no more room */
955  }
956 
957  attrset(ColorDefs[MT_COLOR_STATUS]);
958  if (offset < len)
959  {
960  /* Text after the last highlight */
961  addnstr(buf + offset, len - offset);
962  }
963 
964  int width = mutt_strwidth(buf);
965  if (width < cols)
966  {
967  /* Pad the rest of the line with whitespace */
968  mutt_paddstr(cols - width, "");
969  }
970 dsl_finish:
971  FREE(&syntax);
972 }
int first
Definition: pager.c:130
#define MIN(a, b)
Definition: memory.h:31
int last
Definition: pager.c:131
Highlighting for a line of text.
Definition: pager.c:127
int color
Definition: pager.c:129
void mutt_paddstr(int n, const char *s)
Display a string on screen, padded if necessary.
Definition: curs_lib.c:1169
int match
which substringmap 0 for old behaviour
Definition: mutt_curses.h:183
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
int mutt_strwidth(const char *s)
Measure a string&#39;s width in screen cells.
Definition: curs_lib.c:1262
size_t mutt_wstr_trunc(const char *src, size_t maxlen, size_t maxwid, size_t *width)
Work out how to truncate a widechar string.
Definition: curs_lib.c:1212
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
int ColorDefs[MT_COLOR_MAX]
Array of all fixed colours, see enum ColorId.
Definition: color.c:55
LOFF_T offset
Where in the stream does this message begin?
Definition: email.h:85
regex_t regex
Definition: mutt_curses.h:182
#define FREE(x)
Definition: memory.h:40
Status bar.
Definition: mutt_curses.h:129
struct ColorLineHead ColorStatusList
List of colours applied to the status bar.
Definition: color.c:64
A regular expression and a color to highlight a line.
Definition: mutt_curses.h:180

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void index_custom_redraw ( struct Menu menu)
static

Redraw the index - Implements Menu::menu_custom_redraw()

Definition at line 977 of file index.c.

978 {
979  if (menu->redraw & REDRAW_FULL)
980  {
981  menu_redraw_full(menu);
982  mutt_show_error();
983  }
984 
985 #ifdef USE_SIDEBAR
986  if (menu->redraw & REDRAW_SIDEBAR)
987  menu_redraw_sidebar(menu);
988 #endif
989 
990  if (Context && Context->mailbox && Context->mailbox->emails &&
991  !(menu->current >= Context->mailbox->vcount))
992  {
993  menu_check_recenter(menu);
994 
995  if (menu->redraw & REDRAW_INDEX)
996  {
997  menu_redraw_index(menu);
998  menu->redraw |= REDRAW_STATUS;
999  }
1000  else if (menu->redraw & (REDRAW_MOTION_RESYNC | REDRAW_MOTION))
1001  menu_redraw_motion(menu);
1002  else if (menu->redraw & REDRAW_CURRENT)
1003  menu_redraw_current(menu);
1004  }
1005 
1006  if (menu->redraw & REDRAW_STATUS)
1007  {
1008  char buf[1024];
1009  menu_status_line(buf, sizeof(buf), menu, NONULL(C_StatusFormat));
1012  mutt_draw_statusline(MuttStatusWindow->cols, buf, sizeof(buf));
1013  NORMAL_COLOR;
1014  menu->redraw &= ~REDRAW_STATUS;
1015  if (C_TsEnabled && TsSupported)
1016  {
1017  menu_status_line(buf, sizeof(buf), menu, NONULL(C_TsStatusFormat));
1018  mutt_ts_status(buf);
1019  menu_status_line(buf, sizeof(buf), menu, NONULL(C_TsIconFormat));
1020  mutt_ts_icon(buf);
1021  }
1022  }
1023 
1024  menu->redraw = 0;
1025 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:110
The "current" mailbox.
Definition: context.h:36
WHERE char * C_TsIconFormat
Config: printf-like format string for the terminal&#39;s icon title.
Definition: globals.h:154
#define REDRAW_FULL
Redraw everything.
Definition: mutt_menu.h:47
#define NONULL(x)
Definition: string2.h:37
struct MuttWindow * MuttStatusWindow
Status Window.
Definition: mutt_window.c:41
#define NORMAL_COLOR
Definition: mutt_curses.h:239
void menu_status_line(char *buf, size_t buflen, struct Menu *menu, const char *p)
Create the status line.
Definition: status.c:408
WHERE char * C_StatusFormat
Config: printf-like format string for the index&#39;s status line.
Definition: globals.h:152
WHERE bool C_TsEnabled
Config: Allow NeoMutt to set the terminal status line and icon.
Definition: globals.h:273
int vcount
The number of virtual messages.
Definition: mailbox.h:113
#define REDRAW_SIDEBAR
Redraw the sidebar.
Definition: mutt_menu.h:51
struct Mailbox * mailbox
Definition: context.h:50
#define REDRAW_MOTION
Redraw after moving the menu list.
Definition: mutt_menu.h:43
#define REDRAW_MOTION_RESYNC
Redraw any changing the menu selection.
Definition: mutt_menu.h:44
#define REDRAW_STATUS
Redraw the status bar.
Definition: mutt_menu.h:46
bool TsSupported
Terminal Setting is supported.
Definition: terminal.c:42
#define SET_COLOR(X)
Definition: mutt_curses.h:224
int mutt_window_move(struct MuttWindow *win, int row, int col)
Move the cursor in a Window.
Definition: mutt_window.c:188
WHERE char * C_TsStatusFormat
Config: printf-like format string for the terminal&#39;s status (window title)
Definition: globals.h:153
MuttRedrawFlags redraw
when to redraw the screen
Definition: mutt_menu.h:89
#define REDRAW_INDEX
Redraw the index.
Definition: mutt_menu.h:42
Status bar.
Definition: mutt_curses.h:129
void mutt_ts_icon(char *str)
Set the icon in the terminal title bar.
Definition: terminal.c:117
void mutt_show_error(void)
Show the user an error message.
Definition: curs_lib.c:485
void mutt_ts_status(char *str)
Set the text of the terminal title bar.
Definition: terminal.c:103
int current
current entry
Definition: mutt_menu.h:87
void mutt_draw_statusline(int cols, const char *buf, size_t buflen)
Draw a highlighted status bar.
Definition: index.c:851
#define REDRAW_CURRENT
Redraw the current line of the menu.
Definition: mutt_menu.h:45

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int mutt_index_menu ( void  )

Display a list of emails.

Return values
numHow the menu was finished, e.g. OP_QUIT, OP_EXIT

This function handles the message index window as well as commands returned from the pager (MENU_PAGER).

Definition at line 1034 of file index.c.

1035 {
1036  char buf[PATH_MAX], helpstr[1024];
1037  OpenMailboxFlags flags;
1038  int op = OP_NULL;
1039  bool done = false; /* controls when to exit the "event" loop */
1040  bool tag = false; /* has the tag-prefix command been pressed? */
1041  int newcount = -1;
1042  int oldcount = -1;
1043  int index_hint = 0; /* used to restore cursor position */
1044  bool do_mailbox_notify = true;
1045  int close = 0; /* did we OP_QUIT or OP_EXIT out of this menu? */
1046  int attach_msg = OptAttachMsg;
1047 
1048  struct Menu *menu = mutt_menu_new(MENU_MAIN);
1050  menu->menu_color = index_color;
1051  menu->current = ci_first_message();
1052  menu->help = mutt_compile_help(
1053  helpstr, sizeof(helpstr), MENU_MAIN,
1054 #ifdef USE_NNTP
1056  IndexNewsHelp :
1057 #endif
1058  IndexHelp);
1060  mutt_menu_push_current(menu);
1062 
1063  if (!attach_msg)
1064  {
1065  /* force the mailbox check after we enter the folder */
1067  }
1068 #ifdef USE_INOTIFY
1069  mutt_monitor_add(NULL);
1070 #endif
1071 
1072  if (((C_Sort & SORT_MASK) == SORT_THREADS) && C_CollapseAll)
1073  {
1074  collapse_all(menu, 0);
1075  menu->redraw = REDRAW_FULL;
1076  }
1077 
1078  while (true)
1079  {
1080  /* Clear the tag prefix unless we just started it. Don't clear
1081  * the prefix on a timeout (op==-2), but do clear on an abort (op==-1) */
1082  if (tag && (op != OP_TAG_PREFIX) && (op != OP_TAG_PREFIX_COND) && (op != -2))
1083  tag = false;
1084 
1085  /* check if we need to resort the index because just about
1086  * any 'op' below could do mutt_enter_command(), either here or
1087  * from any new menu launched, and change $sort/$sort_aux */
1088  if (OptNeedResort && Context && Context->mailbox &&
1089  (Context->mailbox->msg_count != 0) && (menu->current >= 0))
1090  resort_index(menu);
1091 
1092  menu->max = (Context && Context->mailbox) ? Context->mailbox->vcount : 0;
1093  oldcount = (Context && Context->mailbox) ? Context->mailbox->msg_count : 0;
1094 
1095  if (OptRedrawTree && Context && Context->mailbox &&
1096  (Context->mailbox->msg_count != 0) && ((C_Sort & SORT_MASK) == SORT_THREADS))
1097  {
1099  menu->redraw |= REDRAW_STATUS;
1100  OptRedrawTree = false;
1101  }
1102 
1103  if (Context)
1104  Context->menu = menu;
1105 
1106  if (Context && Context->mailbox && !attach_msg)
1107  {
1108  int check;
1109  /* check for new mail in the mailbox. If nonzero, then something has
1110  * changed about the file (either we got new mail or the file was
1111  * modified underneath us.) */
1112 
1113  index_hint = ((Context->mailbox->vcount != 0) && (menu->current >= 0) &&
1114  (menu->current < Context->mailbox->vcount)) ?
1115  CUR_EMAIL->index :
1116  0;
1117 
1118  check = mx_mbox_check(Context->mailbox, &index_hint);
1119  if (check < 0)
1120  {
1122  {
1123  /* fatal error occurred */
1124  ctx_free(&Context);
1125  menu->redraw = REDRAW_FULL;
1126  }
1127 
1128  OptSearchInvalid = true;
1129  }
1130  else if ((check == MUTT_NEW_MAIL) || (check == MUTT_REOPENED) || (check == MUTT_FLAGS))
1131  {
1132  /* notify the user of new mail */
1133  if (check == MUTT_REOPENED)
1134  {
1135  mutt_error(
1136  _("Mailbox was externally modified. Flags may be wrong."));
1137  }
1138  else if (check == MUTT_NEW_MAIL)
1139  {
1140  for (size_t i = oldcount; i < Context->mailbox->msg_count; i++)
1141  {
1142  if (!Context->mailbox->emails[i]->read)
1143  {
1144  mutt_message(_("New mail in this mailbox"));
1145  if (C_BeepNew)
1146  beep();
1147  if (C_NewMailCommand)
1148  {
1149  char cmd[1024];
1150  menu_status_line(cmd, sizeof(cmd), menu, NONULL(C_NewMailCommand));
1151  if (mutt_system(cmd) != 0)
1152  mutt_error(_("Error running \"%s\""), cmd);
1153  }
1154  break;
1155  }
1156  }
1157  }
1158  else if (check == MUTT_FLAGS)
1159  mutt_message(_("Mailbox was externally modified"));
1160 
1161  /* avoid the message being overwritten by mailbox */
1162  do_mailbox_notify = false;
1163 
1164  bool q = Context->mailbox->quiet;
1165  Context->mailbox->quiet = true;
1166  update_index(menu, Context, check, oldcount, index_hint);
1167  Context->mailbox->quiet = q;
1168 
1169  menu->redraw = REDRAW_FULL;
1170  menu->max = Context->mailbox->vcount;
1171 
1172  OptSearchInvalid = true;
1173  }
1174  }
1175 
1176  if (!attach_msg)
1177  {
1178  /* check for new mail in the incoming folders */
1179  oldcount = newcount;
1180  newcount = mutt_mailbox_check(Context ? Context->mailbox : NULL, 0);
1181  if (newcount != oldcount)
1182  menu->redraw |= REDRAW_STATUS;
1183  if (do_mailbox_notify)
1184  {
1185  if (mutt_mailbox_notify(Context ? Context->mailbox : NULL))
1186  {
1187  menu->redraw |= REDRAW_STATUS;
1188  if (C_BeepNew)
1189  beep();
1190  if (C_NewMailCommand)
1191  {
1192  char cmd[1024];
1193  menu_status_line(cmd, sizeof(cmd), menu, NONULL(C_NewMailCommand));
1194  if (mutt_system(cmd) != 0)
1195  mutt_error(_("Error running \"%s\""), cmd);
1196  }
1197  }
1198  }
1199  else
1200  do_mailbox_notify = true;
1201  }
1202 
1203  if (op >= 0)
1204  mutt_curs_set(0);
1205 
1206  if (menu->menu == MENU_MAIN)
1207  {
1208  index_custom_redraw(menu);
1209 
1210  /* give visual indication that the next command is a tag- command */
1211  if (tag)
1212  {
1213  mutt_window_mvaddstr(MuttMessageWindow, 0, 0, "tag-");
1215  }
1216 
1217  if (menu->current < menu->max)
1218  menu->oldcurrent = menu->current;
1219  else
1220  menu->oldcurrent = -1;
1221 
1222  if (C_ArrowCursor)
1223  mutt_window_move(MuttIndexWindow, menu->current - menu->top + menu->offset, 2);
1224  else if (C_BrailleFriendly)
1225  mutt_window_move(MuttIndexWindow, menu->current - menu->top + menu->offset, 0);
1226  else
1227  {
1228  mutt_window_move(MuttIndexWindow, menu->current - menu->top + menu->offset,
1229  MuttIndexWindow->cols - 1);
1230  }
1231  mutt_refresh();
1232 
1233  if (SigWinch)
1234  {
1235  mutt_flushinp();
1237  SigWinch = 0;
1238  menu->top = 0; /* so we scroll the right amount */
1239  /* force a real complete redraw. clrtobot() doesn't seem to be able
1240  * to handle every case without this. */
1241  clearok(stdscr, true);
1242  continue;
1243  }
1244 
1245  op = km_dokey(MENU_MAIN);
1246 
1247  mutt_debug(LL_DEBUG3, "[%d]: Got op %d\n", __LINE__, op);
1248 
1249  /* either user abort or timeout */
1250  if (op < 0)
1251  {
1253  if (tag)
1255  continue;
1256  }
1257 
1258  mutt_curs_set(1);
1259 
1260  /* special handling for the tag-prefix function */
1261  if ((op == OP_TAG_PREFIX) || (op == OP_TAG_PREFIX_COND))
1262  {
1263  /* A second tag-prefix command aborts */
1264  if (tag)
1265  {
1266  tag = false;
1268  continue;
1269  }
1270 
1271  if (!Context || !Context->mailbox)
1272  {
1273  mutt_error(_("No mailbox is open"));
1274  continue;
1275  }
1276 
1277  if (Context->mailbox->msg_tagged == 0)
1278  {
1279  if (op == OP_TAG_PREFIX)
1280  mutt_error(_("No tagged messages"));
1281  else if (op == OP_TAG_PREFIX_COND)
1282  {
1284  mutt_message(_("Nothing to do"));
1285  }
1286  continue;
1287  }
1288 
1289  /* get the real command */
1290  tag = true;
1291  continue;
1292  }
1293  else if (C_AutoTag && Context && Context->mailbox &&
1294  (Context->mailbox->msg_tagged != 0))
1295  tag = true;
1296 
1297  mutt_clear_error();
1298  }
1299  else
1300  {
1301  if (menu->current < menu->max)
1302  menu->oldcurrent = menu->current;
1303  else
1304  menu->oldcurrent = -1;
1305 
1306  mutt_curs_set(1); /* fallback from the pager */
1307  }
1308 
1309 #ifdef USE_NNTP
1310  OptNews = false; /* for any case */
1311 #endif
1312 
1313 #ifdef USE_NOTMUCH
1314  if (Context)
1316 #endif
1317 
1318  switch (op)
1319  {
1320  /* ----------------------------------------------------------------------
1321  * movement commands
1322  */
1323 
1324  case OP_BOTTOM_PAGE:
1325  menu_bottom_page(menu);
1326  break;
1327  case OP_CURRENT_BOTTOM:
1328  menu_current_bottom(menu);
1329  break;
1330  case OP_CURRENT_MIDDLE:
1331  menu_current_middle(menu);
1332  break;
1333  case OP_CURRENT_TOP:
1334  menu_current_top(menu);
1335  break;
1336  case OP_FIRST_ENTRY:
1337  menu_first_entry(menu);
1338  break;
1339  case OP_HALF_DOWN:
1340  menu_half_down(menu);
1341  break;
1342  case OP_HALF_UP:
1343  menu_half_up(menu);
1344  break;
1345  case OP_LAST_ENTRY:
1346  menu_last_entry(menu);
1347  break;
1348  case OP_MIDDLE_PAGE:
1349  menu_middle_page(menu);
1350  break;
1351  case OP_NEXT_LINE:
1352  menu_next_line(menu);
1353  break;
1354  case OP_NEXT_PAGE:
1355  menu_next_page(menu);
1356  break;
1357  case OP_PREV_LINE:
1358  menu_prev_line(menu);
1359  break;
1360  case OP_PREV_PAGE:
1361  menu_prev_page(menu);
1362  break;
1363  case OP_TOP_PAGE:
1364  menu_top_page(menu);
1365  break;
1366 
1367 #ifdef USE_NNTP
1368  case OP_GET_PARENT:
1370  break;
1371  /* fallthrough */
1372 
1373  case OP_GET_MESSAGE:
1375  break;
1376  if (Context->mailbox->magic == MUTT_NNTP)
1377  {
1378  struct Email *e = NULL;
1379 
1380  if (op == OP_GET_MESSAGE)
1381  {
1382  buf[0] = '\0';
1383  if ((mutt_get_field(_("Enter Message-Id: "), buf, sizeof(buf), 0) != 0) ||
1384  !buf[0])
1385  {
1386  break;
1387  }
1388  }
1389  else
1390  {
1391  if (STAILQ_EMPTY(&CUR_EMAIL->env->references))
1392  {
1393  mutt_error(_("Article has no parent reference"));
1394  break;
1395  }
1396  mutt_str_strfcpy(buf, STAILQ_FIRST(&CUR_EMAIL->env->references)->data,
1397  sizeof(buf));
1398  }
1399  if (!Context->mailbox->id_hash)
1401  e = mutt_hash_find(Context->mailbox->id_hash, buf);
1402  if (e)
1403  {
1404  if (e->vnum != -1)
1405  {
1406  menu->current = e->vnum;
1407  menu->redraw = REDRAW_MOTION_RESYNC;
1408  }
1409  else if (e->collapsed)
1410  {
1413  menu->current = e->vnum;
1414  menu->redraw = REDRAW_MOTION_RESYNC;
1415  }
1416  else
1417  mutt_error(_("Message is not visible in limited view"));
1418  }
1419  else
1420  {
1421  mutt_message(_("Fetching %s from server..."), buf);
1422  int rc = nntp_check_msgid(Context->mailbox, buf);
1423  if (rc == 0)
1424  {
1426  mutt_sort_headers(Context, false);
1427  menu->current = e->vnum;
1428  menu->redraw = REDRAW_FULL;
1429  }
1430  else if (rc > 0)
1431  mutt_error(_("Article %s not found on the server"), buf);
1432  }
1433  }
1434  break;
1435 
1436  case OP_GET_CHILDREN:
1437  case OP_RECONSTRUCT_THREAD:
1438  if (!prereq(Context, menu,
1440  {
1441  break;
1442  }
1443  if (Context->mailbox->magic == MUTT_NNTP)
1444  {
1445  int oldmsgcount = Context->mailbox->msg_count;
1446  int oldindex = CUR_EMAIL->index;
1447  int rc = 0;
1448 
1449  if (!CUR_EMAIL->env->message_id)
1450  {
1451  mutt_error(_("No Message-Id. Unable to perform operation."));
1452  break;
1453  }
1454 
1455  mutt_message(_("Fetching message headers..."));
1456  if (!Context->mailbox->id_hash)
1458  mutt_str_strfcpy(buf, CUR_EMAIL->env->message_id, sizeof(buf));
1459 
1460  /* trying to find msgid of the root message */
1461  if (op == OP_RECONSTRUCT_THREAD)
1462  {
1463  struct ListNode *ref = NULL;
1464  STAILQ_FOREACH(ref, &CUR_EMAIL->env->references, entries)
1465  {
1466  if (!mutt_hash_find(Context->mailbox->id_hash, ref->data))
1467  {
1468  rc = nntp_check_msgid(Context->mailbox, ref->data);
1469  if (rc < 0)
1470  break;
1471  }
1472 
1473  /* the last msgid in References is the root message */
1474  if (!STAILQ_NEXT(ref, entries))
1475  mutt_str_strfcpy(buf, ref->data, sizeof(buf));
1476  }
1477  }
1478 
1479  /* fetching all child messages */
1480  if (rc >= 0)
1481  rc = nntp_check_children(Context->mailbox, buf);
1482 
1483  /* at least one message has been loaded */
1484  if (Context->mailbox->msg_count > oldmsgcount)
1485  {
1486  struct Email *e_oldcur = CUR_EMAIL;
1487  struct Email *e = NULL;
1488  bool quiet = Context->mailbox->quiet;
1489 
1490  if (rc < 0)
1491  Context->mailbox->quiet = true;
1492  mutt_sort_headers(Context, (op == OP_RECONSTRUCT_THREAD));
1493  Context->mailbox->quiet = quiet;
1494 
1495  /* Similar to OP_MAIN_ENTIRE_THREAD, keep displaying the old message, but
1496  * update the index */
1497  if (menu->menu == MENU_PAGER)
1498  {
1499  menu->current = e_oldcur->vnum;
1500  menu->redraw = REDRAW_STATUS | REDRAW_INDEX;
1501  op = OP_DISPLAY_MESSAGE;
1502  continue;
1503  }
1504 
1505  /* if the root message was retrieved, move to it */
1506  e = mutt_hash_find(Context->mailbox->id_hash, buf);
1507  if (e)
1508  menu->current = e->vnum;
1509 
1510  /* try to restore old position */
1511  else
1512  {
1513  for (int i = 0; i < Context->mailbox->msg_count; i++)
1514  {
1515  if (Context->mailbox->emails[i]->index == oldindex)
1516  {
1517  menu->current = Context->mailbox->emails[i]->vnum;
1518  /* as an added courtesy, recenter the menu
1519  * with the current entry at the middle of the screen */
1520  menu_check_recenter(menu);
1521  menu_current_middle(menu);
1522  }
1523  }
1524  }
1525  menu->redraw = REDRAW_FULL;
1526  }
1527  else if (rc >= 0)
1528  {
1529  mutt_error(_("No deleted messages found in the thread"));
1530  /* Similar to OP_MAIN_ENTIRE_THREAD, keep displaying the old message, but
1531  * update the index */
1532  if (menu->menu == MENU_PAGER)
1533  {
1534  op = OP_DISPLAY_MESSAGE;
1535  continue;
1536  }
1537  }
1538  }
1539  break;
1540 #endif
1541 
1542  case OP_JUMP:
1543  {
1544  int msg_num = 0;
1546  break;
1547  if (isdigit(LastKey))
1549  buf[0] = '\0';
1550  if ((mutt_get_field(_("Jump to message: "), buf, sizeof(buf), 0) != 0) ||
1551  (buf[0] == '\0'))
1552  {
1553  mutt_error(_("Nothing to do"));
1554  }
1555  else if (mutt_str_atoi(buf, &msg_num) < 0)
1556  mutt_error(_("Argument must be a message number"));
1557  else if ((msg_num < 1) || (msg_num > Context->mailbox->msg_count))
1558  mutt_error(_("Invalid message number"));
1559  else if (!message_is_visible(Context, msg_num - 1))
1560  mutt_error(_("That message is not visible"));
1561  else
1562  {
1563  struct Email *e = Context->mailbox->emails[msg_num - 1];
1564 
1565  if (mutt_messages_in_thread(Context->mailbox, e, 1) > 1)
1566  {
1569  }
1570  menu->current = e->vnum;
1571  }
1572 
1573  if (menu->menu == MENU_PAGER)
1574  {
1575  op = OP_DISPLAY_MESSAGE;
1576  continue;
1577  }
1578  else
1579  menu->redraw = REDRAW_FULL;
1580 
1581  break;
1582  }
1583 
1584  /* --------------------------------------------------------------------
1585  * 'index' specific commands
1586  */
1587 
1588  case OP_MAIN_DELETE_PATTERN:
1589  if (!prereq(Context, menu,
1591  {
1592  break;
1593  }
1594  /* L10N: CHECK_ACL */
1595  /* L10N: Due to the implementation details we do not know whether we
1596  delete zero, 1, 12, ... messages. So in English we use
1597  "messages". Your language might have other means to express this. */
1598  if (!check_acl(Context, MUTT_ACL_DELETE, _("Can't delete messages")))
1599  break;
1600 
1601  mutt_pattern_func(MUTT_DELETE, _("Delete messages matching: "));
1602  menu->redraw |= REDRAW_INDEX | REDRAW_STATUS;
1603  break;
1604 
1605 #ifdef USE_POP
1606  case OP_MAIN_FETCH_MAIL:
1607  if (!prereq(Context, menu, CHECK_ATTACH))
1608  break;
1609  pop_fetch_mail();
1610  menu->redraw = REDRAW_FULL;
1611  break;
1612 #endif /* USE_POP */
1613 
1614  case OP_SHOW_LOG_MESSAGES:
1615  {
1616  char tempfile[PATH_MAX];
1617  mutt_mktemp(tempfile, sizeof(tempfile));
1618 
1619  FILE *fp = mutt_file_fopen(tempfile, "a+");
1620  if (!fp)
1621  {
1622  mutt_perror("fopen");
1623  break;
1624  }
1625 
1626  log_queue_save(fp);
1627  mutt_file_fclose(&fp);
1628 
1629  mutt_do_pager("messages", tempfile, MUTT_PAGER_LOGS, NULL);
1630  break;
1631  }
1632 
1633  case OP_HELP:
1635  menu->redraw = REDRAW_FULL;
1636  break;
1637 
1638  case OP_MAIN_SHOW_LIMIT:
1639  if (!prereq(Context, menu, CHECK_IN_MAILBOX))
1640  break;
1641  if (!Context->pattern)
1642  mutt_message(_("No limit pattern is in effect"));
1643  else
1644  {
1645  char buf2[256];
1646  /* L10N: ask for a limit to apply */
1647  snprintf(buf2, sizeof(buf2), _("Limit: %s"), Context->pattern);
1648  mutt_message("%s", buf2);
1649  }
1650  break;
1651 
1652  case OP_LIMIT_CURRENT_THREAD:
1653  case OP_MAIN_LIMIT:
1654  case OP_TOGGLE_READ:
1655  if (!prereq(Context, menu, CHECK_IN_MAILBOX))
1656  break;
1657  menu->oldcurrent = ((Context->mailbox->vcount != 0) && (menu->current >= 0) &&
1658  (menu->current < Context->mailbox->vcount)) ?
1659  CUR_EMAIL->index :
1660  -1;
1661  if (op == OP_TOGGLE_READ)
1662  {
1663  char buf2[1024];
1664 
1665  if (!Context->pattern || (strncmp(Context->pattern, "!~R!~D~s", 8) != 0))
1666  {
1667  snprintf(buf2, sizeof(buf2), "!~R!~D~s%s",
1668  Context->pattern ? Context->pattern : ".*");
1669  }
1670  else
1671  {
1672  mutt_str_strfcpy(buf2, Context->pattern + 8, sizeof(buf2));
1673  if (!*buf2 || (strncmp(buf2, ".*", 2) == 0))
1674  snprintf(buf2, sizeof(buf2), "~A");
1675  }
1676  FREE(&Context->pattern);
1677  Context->pattern = mutt_str_strdup(buf2);
1679  }
1680 
1681  if (((op == OP_LIMIT_CURRENT_THREAD) && mutt_limit_current_thread(CUR_EMAIL)) ||
1682  (op == OP_TOGGLE_READ) ||
1683  ((op == OP_MAIN_LIMIT) &&
1685  _("Limit to messages matching: ")) == 0)))
1686  {
1687  if (menu->oldcurrent >= 0)
1688  {
1689  /* try to find what used to be the current message */
1690  menu->current = -1;
1691  for (size_t i = 0; i < Context->mailbox->vcount; i++)
1692  {
1693  if (Context->mailbox->emails[Context->mailbox->v2r[i]]->index == menu->oldcurrent)
1694  {
1695  menu->current = i;
1696  break;
1697  }
1698  }
1699  if (menu->current < 0)
1700  menu->current = 0;
1701  }
1702  else
1703  menu->current = 0;
1704  if ((Context->mailbox->msg_count != 0) && ((C_Sort & SORT_MASK) == SORT_THREADS))
1705  {
1706  if (C_CollapseAll)
1707  collapse_all(menu, 0);
1709  }
1710  menu->redraw = REDRAW_FULL;
1711  }
1712  if (Context->pattern)
1713  mutt_message(_("To view all messages, limit to \"all\""));
1714  break;
1715 
1716  case OP_QUIT:
1717  close = op;
1718  if (attach_msg)
1719  {
1720  done = true;
1721  break;
1722  }
1723 
1724  if (query_quadoption(C_Quit, _("Quit NeoMutt?")) == MUTT_YES)
1725  {
1726  int check;
1727 
1728  oldcount = (Context && Context->mailbox) ? Context->mailbox->msg_count : 0;
1729 
1732 
1733  if (!Context || ((check = mx_mbox_close(&Context)) == 0))
1734  done = true;
1735  else
1736  {
1737  if ((check == MUTT_NEW_MAIL) || (check == MUTT_REOPENED))
1738  update_index(menu, Context, check, oldcount, index_hint);
1739 
1740  menu->redraw = REDRAW_FULL; /* new mail arrived? */
1741  OptSearchInvalid = true;
1742  }
1743  }
1744  break;
1745 
1746  case OP_REDRAW:
1747  clearok(stdscr, true);
1748  menu->redraw = REDRAW_FULL;
1749  break;
1750 
1751  case OP_SEARCH:
1752  case OP_SEARCH_REVERSE:
1753  case OP_SEARCH_NEXT:
1754  case OP_SEARCH_OPPOSITE:
1756  break;
1757  menu->current = mutt_search_command(menu->current, op);
1758  if (menu->current == -1)
1759  menu->current = menu->oldcurrent;
1760  else
1761  menu->redraw = REDRAW_MOTION;
1762  break;
1763 
1764  case OP_SORT:
1765  case OP_SORT_REVERSE:
1766  if (mutt_select_sort((op == OP_SORT_REVERSE)) == 0)
1767  {
1768  if (Context && Context->mailbox && (Context->mailbox->msg_count != 0))
1769  {
1770  resort_index(menu);
1771  OptSearchInvalid = true;
1772  }
1773  if (menu->menu == MENU_PAGER)
1774  {
1775  op = OP_DISPLAY_MESSAGE;
1776  continue;
1777  }
1778  menu->redraw |= REDRAW_STATUS;
1779  }
1780  break;
1781 
1782  case OP_TAG:
1784  break;
1785  if (tag && !C_AutoTag)
1786  {
1787  for (size_t i = 0; i < Context->mailbox->msg_count; i++)
1788  if (message_is_visible(Context, i))
1790  menu->redraw |= REDRAW_STATUS | REDRAW_INDEX;
1791  }
1792  else
1793  {
1795 
1796  Context->last_tag =
1797  CUR_EMAIL->tagged ?
1798  CUR_EMAIL :
1799  (((Context->last_tag == CUR_EMAIL) && !CUR_EMAIL->tagged) ?
1800  NULL :
1801  Context->last_tag);
1802 
1803  menu->redraw |= REDRAW_STATUS;
1804  if (C_Resolve && (menu->current < Context->mailbox->vcount - 1))
1805  {
1806  menu->current++;
1807  menu->redraw |= REDRAW_MOTION_RESYNC;
1808  }
1809  else
1810  menu->redraw |= REDRAW_CURRENT;
1811  }
1812  break;
1813 
1814  case OP_MAIN_TAG_PATTERN:
1816  break;
1817  mutt_pattern_func(MUTT_TAG, _("Tag messages matching: "));
1818  menu->redraw |= REDRAW_INDEX | REDRAW_STATUS;
1819  break;
1820 
1821  case OP_MAIN_UNDELETE_PATTERN:
1823  break;
1824  /* L10N: CHECK_ACL */
1825  /* L10N: Due to the implementation details we do not know whether we
1826  undelete zero, 1, 12, ... messages. So in English we use
1827  "messages". Your language might have other means to express this. */
1828  if (!check_acl(Context, MUTT_ACL_DELETE, _("Can't undelete messages")))
1829  break;
1830 
1832  _("Undelete messages matching: ")) == 0)
1833  {
1834  menu->redraw |= REDRAW_INDEX | REDRAW_STATUS;
1835  }
1836  break;
1837 
1838  case OP_MAIN_UNTAG_PATTERN:
1840  break;
1841  if (mutt_pattern_func(MUTT_UNTAG, _("Untag messages matching: ")) == 0)
1842  menu->redraw |= REDRAW_INDEX | REDRAW_STATUS;
1843  break;
1844 
1845  case OP_COMPOSE_TO_SENDER:
1846  {
1848  break;
1849  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
1850  el_add_tagged(&el, Context, CUR_EMAIL, tag);
1851  ci_send_message(SEND_TO_SENDER, NULL, NULL, Context, &el);
1852  emaillist_clear(&el);
1853  menu->redraw = REDRAW_FULL;
1854  break;
1855  }
1856 
1857  /* --------------------------------------------------------------------
1858  * The following operations can be performed inside of the pager.
1859  */
1860 
1861 #ifdef USE_IMAP
1862  case OP_MAIN_IMAP_FETCH:
1863  if (Context && Context->mailbox && (Context->mailbox->magic == MUTT_IMAP))
1865  break;
1866 
1867  case OP_MAIN_IMAP_LOGOUT_ALL:
1868  if (Context && Context->mailbox && (Context->mailbox->magic == MUTT_IMAP))
1869  {
1870  int check = mx_mbox_close(&Context);
1871  if (check != 0)
1872  {
1873  if ((check == MUTT_NEW_MAIL) || (check == MUTT_REOPENED))
1874  update_index(menu, Context, check, oldcount, index_hint);
1875  OptSearchInvalid = true;
1876  menu->redraw = REDRAW_FULL;
1877  break;
1878  }
1879  }
1880  imap_logout_all();
1881  mutt_message(_("Logged out of IMAP servers"));
1882  OptSearchInvalid = true;
1883  menu->redraw = REDRAW_FULL;
1884  break;
1885 #endif
1886 
1887  case OP_MAIN_SYNC_FOLDER:
1888  if (!Context || !Context->mailbox || (Context->mailbox->msg_count == 0))
1889  break;
1890 
1892  break;
1893  {
1894  int ovc = Context->mailbox->vcount;
1895  int oc = Context->mailbox->msg_count;
1896  struct Email *e = NULL;
1897 
1898  /* don't attempt to move the cursor if there are no visible messages in the current limit */
1899  if (menu->current < Context->mailbox->vcount)
1900  {
1901  /* threads may be reordered, so figure out what header the cursor
1902  * should be on. #3092 */
1903  int newidx = menu->current;
1904  if (CUR_EMAIL->deleted)
1905  newidx = ci_next_undeleted(menu->current);
1906  if (newidx < 0)
1907  newidx = ci_previous_undeleted(menu->current);
1908  if (newidx >= 0)
1909  e = Context->mailbox->emails[Context->mailbox->v2r[newidx]];
1910  }
1911 
1912  int check = mx_mbox_sync(Context->mailbox, &index_hint);
1913  if (check == 0)
1914  {
1915  if (e && (Context->mailbox->vcount != ovc))
1916  {
1917  for (size_t i = 0; i < Context->mailbox->vcount; i++)
1918  {
1919  if (Context->mailbox->emails[Context->mailbox->v2r[i]] == e)
1920  {
1921  menu->current = i;
1922  break;
1923  }
1924  }
1925  }
1926  OptSearchInvalid = true;
1927  }
1928  else if ((check == MUTT_NEW_MAIL) || (check == MUTT_REOPENED))
1929  update_index(menu, Context, check, oc, index_hint);
1930 
1931  /* do a sanity check even if mx_mbox_sync failed. */
1932 
1933  if ((menu->current < 0) || (Context && Context->mailbox &&
1934  (menu->current >= Context->mailbox->vcount)))
1935  {
1936  menu->current = ci_first_message();
1937  }
1938  }
1939 
1940  /* check for a fatal error, or all messages deleted */
1942  ctx_free(&Context);
1943 
1944  /* if we were in the pager, redisplay the message */
1945  if (menu->menu == MENU_PAGER)
1946  {
1947  op = OP_DISPLAY_MESSAGE;
1948  continue;
1949  }
1950  else
1951  menu->redraw = REDRAW_FULL;
1952  break;
1953 
1954  case OP_MAIN_QUASI_DELETE:
1956  break;
1957  if (tag)
1958  {
1959  for (size_t i = 0; i < Context->mailbox->msg_count; i++)
1960  {
1961  if (message_is_tagged(Context, i))
1962  {
1963  Context->mailbox->emails[i]->quasi_deleted = true;
1964  Context->mailbox->changed = true;
1965  }
1966  }
1967  }
1968  else
1969  {
1970  CUR_EMAIL->quasi_deleted = true;
1971  Context->mailbox->changed = true;
1972  }
1973  break;
1974 
1975 #ifdef USE_NOTMUCH
1976  case OP_MAIN_ENTIRE_THREAD:
1977  {
1979  break;
1980  if (Context->mailbox->magic != MUTT_NOTMUCH)
1981  {
1982  if (!CUR_EMAIL || !CUR_EMAIL->env || !CUR_EMAIL->env->message_id)
1983  {
1984  mutt_message(_("No virtual folder and no Message-Id, aborting"));
1985  break;
1986  } // no virtual folder, but we have message-id, reconstruct thread on-the-fly
1987  strncpy(buf, "id:", sizeof(buf));
1988  int msg_id_offset = 0;
1989  if ((CUR_EMAIL->env->message_id)[0] == '<')
1990  msg_id_offset = 1;
1991  mutt_str_strcat(buf, sizeof(buf), (CUR_EMAIL->env->message_id) + msg_id_offset);
1992  if (buf[strlen(buf) - 1] == '>')
1993  buf[strlen(buf) - 1] = '\0';
1994  if (!nm_uri_from_query(Context->mailbox, buf, sizeof(buf)))
1995  {
1996  mutt_message(_("Failed to create query, aborting"));
1997  break;
1998  }
1999  else
2000  main_change_folder(menu, op, NULL, buf, sizeof(buf), &oldcount, &index_hint);
2001  }
2002  oldcount = Context->mailbox->msg_count;
2003  struct Email *e_oldcur = CUR_EMAIL;
2005  {
2006  mutt_message(_("Failed to read thread, aborting"));
2007  break;
2008  }
2009  if (oldcount < Context->mailbox->msg_count)
2010  {
2011  /* nm_read_entire_thread() triggers mutt_sort_headers() if necessary */
2012  menu->current = e_oldcur->vnum;
2013  menu->redraw = REDRAW_STATUS | REDRAW_INDEX;
2014 
2015  if (e_oldcur->collapsed || Context->collapsed)
2016  {
2019  }
2020  }
2021  if (menu->menu == MENU_PAGER)
2022  {
2023  op = OP_DISPLAY_MESSAGE;
2024  continue;
2025  }
2026  break;
2027  }
2028 
2029 #endif
2030  case OP_MAIN_MODIFY_TAGS:
2031  case OP_MAIN_MODIFY_TAGS_THEN_HIDE:
2032  {
2033  if (!Context || !Context->mailbox)
2034  break;
2036  {
2037  mutt_message(_("Folder doesn't support tagging, aborting"));
2038  break;
2039  }
2041  break;
2042  char *tags = NULL;
2043  if (!tag)
2044  tags = driver_tags_get_with_hidden(&CUR_EMAIL->tags);
2045  int rc = mx_tags_edit(Context->mailbox, tags, buf, sizeof(buf));
2046  FREE(&tags);
2047  if (rc < 0)
2048  break;
2049  else if (rc == 0)
2050  {
2051  mutt_message(_("No tag specified, aborting"));
2052  break;
2053  }
2054 
2055  if (tag)
2056  {
2057  struct Progress progress;
2058 
2059  if (!Context->mailbox->quiet)
2060  {
2061  char msgbuf[256];
2062  snprintf(msgbuf, sizeof(msgbuf), _("Update tags..."));
2063  mutt_progress_init(&progress, msgbuf, MUTT_PROGRESS_MSG, 1,
2065  }
2066 
2067 #ifdef USE_NOTMUCH
2068  if (Context->mailbox->magic == MUTT_NOTMUCH)
2070 #endif
2071  for (int px = 0, i = 0; i < Context->mailbox->msg_count; i++)
2072  {
2073  if (!message_is_tagged(Context, i))
2074  continue;
2075 
2076  if (!Context->mailbox->quiet)
2077  mutt_progress_update(&progress, ++px, -1);
2079  if (op == OP_MAIN_MODIFY_TAGS_THEN_HIDE)
2080  {
2081  bool still_queried = false;
2082 #ifdef USE_NOTMUCH
2083  if (Context->mailbox->magic == MUTT_NOTMUCH)
2084  still_queried = nm_message_is_still_queried(
2086 #endif
2087  Context->mailbox->emails[i]->quasi_deleted = !still_queried;
2088  Context->mailbox->changed = true;
2089  }
2090  }
2091 #ifdef USE_NOTMUCH
2092  if (Context->mailbox->magic == MUTT_NOTMUCH)
2094 #endif
2095  menu->redraw = REDRAW_STATUS | REDRAW_INDEX;
2096  }
2097  else
2098  {
2100  {
2101  mutt_message(_("Failed to modify tags, aborting"));
2102  break;
2103  }
2104  if (op == OP_MAIN_MODIFY_TAGS_THEN_HIDE)
2105  {
2106  bool still_queried = false;
2107 #ifdef USE_NOTMUCH
2108  if (Context->mailbox->magic == MUTT_NOTMUCH)
2110 #endif
2111  CUR_EMAIL->quasi_deleted = !still_queried;
2112  Context->mailbox->changed = true;
2113  }
2114  if (menu->menu == MENU_PAGER)
2115  {
2116  op = OP_DISPLAY_MESSAGE;
2117  continue;
2118  }
2119  if (C_Resolve)
2120  {
2121  menu->current = ci_next_undeleted(menu->current);
2122  if (menu->current == -1)
2123  {
2124  menu->current = menu->oldcurrent;
2125  menu->redraw = REDRAW_CURRENT;
2126  }
2127  else
2128  menu->redraw = REDRAW_MOTION_RESYNC;
2129  }
2130  else
2131  menu->redraw = REDRAW_CURRENT;
2132  }
2133  menu->redraw |= REDRAW_STATUS;
2134  break;
2135  }
2136 
2137  case OP_CHECK_STATS:
2138  mutt_check_stats();
2139  break;
2140 
2141 #ifdef USE_NOTMUCH
2142  case OP_MAIN_VFOLDER_FROM_QUERY:
2143  case OP_MAIN_VFOLDER_FROM_QUERY_READONLY:
2144  buf[0] = '\0';
2145  if ((mutt_get_field("Query: ", buf, sizeof(buf), MUTT_NM_QUERY) != 0) || !buf[0])
2146  {
2147  mutt_message(_("No query, aborting"));
2148  break;
2149  }
2150  if (!nm_uri_from_query(NULL, buf, sizeof(buf)))
2151  mutt_message(_("Failed to create query, aborting"));
2152  else
2153  main_change_folder(menu, op, NULL, buf, sizeof(buf), &oldcount, &index_hint);
2154  break;
2155 
2156  case OP_MAIN_WINDOWED_VFOLDER_BACKWARD:
2157  if (!prereq(Context, menu, CHECK_IN_MAILBOX))
2158  break;
2159  mutt_debug(LL_DEBUG2, "OP_MAIN_WINDOWED_VFOLDER_BACKWARD\n");
2160  if (C_NmQueryWindowDuration <= 0)
2161  {
2162  mutt_message(_("Windowed queries disabled"));
2163  break;
2164  }
2166  {
2167  mutt_message(_("No notmuch vfolder currently loaded"));
2168  break;
2169  }
2172  if (!nm_uri_from_query(Context->mailbox, buf, sizeof(buf)))
2173  mutt_message(_("Failed to create query, aborting"));
2174  else
2175  main_change_folder(menu, op, NULL, buf, sizeof(buf), &oldcount, &index_hint);
2176  break;
2177 
2178  case OP_MAIN_WINDOWED_VFOLDER_FORWARD:
2179  if (!prereq(Context, menu, CHECK_IN_MAILBOX))
2180  break;
2181  if (C_NmQueryWindowDuration <= 0)
2182  {
2183  mutt_message(_("Windowed queries disabled"));
2184  break;
2185  }
2187  {
2188  mutt_message(_("No notmuch vfolder currently loaded"));
2189  break;
2190  }
2193  if (!nm_uri_from_query(Context->mailbox, buf, sizeof(buf)))
2194  mutt_message(_("Failed to create query, aborting"));
2195  else
2196  {
2197  mutt_debug(LL_DEBUG2, "nm: + windowed query (%s)\n", buf);
2198  main_change_folder(menu, op, NULL, buf, sizeof(buf), &oldcount, &index_hint);
2199  }
2200  break;
2201 
2202  case OP_MAIN_CHANGE_VFOLDER:
2203 #endif
2204 
2205 #ifdef USE_SIDEBAR
2206  case OP_SIDEBAR_OPEN:
2207 #endif
2208  case OP_MAIN_CHANGE_FOLDER:
2209  case OP_MAIN_NEXT_UNREAD_MAILBOX:
2210  case OP_MAIN_CHANGE_FOLDER_READONLY:
2211 #ifdef USE_NNTP
2212  case OP_MAIN_CHANGE_GROUP:
2213  case OP_MAIN_CHANGE_GROUP_READONLY:
2214 #endif
2215  {
2216  bool cont = false; /* Set if we want to continue instead of break */
2217 
2218  struct Buffer *folderbuf = mutt_buffer_pool_get();
2219  mutt_buffer_increase_size(folderbuf, PATH_MAX);
2220  struct Mailbox *m = NULL;
2221  char *cp = NULL;
2222 #ifdef USE_NNTP
2223  OptNews = false;
2224 #endif
2225  if (attach_msg || C_ReadOnly ||
2226 #ifdef USE_NNTP
2227  (op == OP_MAIN_CHANGE_GROUP_READONLY) ||
2228 #endif
2229  (op == OP_MAIN_CHANGE_FOLDER_READONLY))
2230  {
2231  flags = MUTT_READONLY;
2232  }
2233  else
2234  flags = MUTT_OPEN_NO_FLAGS;
2235 
2236  if (flags)
2237  cp = _("Open mailbox in read-only mode");
2238  else
2239  cp = _("Open mailbox");
2240 
2241  if ((op == OP_MAIN_NEXT_UNREAD_MAILBOX) && Context &&
2243  {
2245  mutt_buffer_pretty_mailbox(folderbuf);
2246  mutt_mailbox_next_buffer(Context ? Context->mailbox : NULL, folderbuf);
2247  if (mutt_buffer_is_empty(folderbuf))
2248  {
2249  mutt_error(_("No mailboxes have new mail"));
2250  goto changefoldercleanup;
2251  }
2252  }
2253 #ifdef USE_SIDEBAR
2254  else if (op == OP_SIDEBAR_OPEN)
2255  {
2256  m = mutt_sb_get_highlight();
2257  if (!m)
2258  goto changefoldercleanup;
2259  mutt_buffer_strcpy(folderbuf, mutt_b2s(m->pathbuf));
2260 
2261  /* Mark the selected dir for the neomutt browser */
2263  }
2264 #endif
2265  else
2266  {
2269  {
2271  mutt_buffer_pretty_mailbox(folderbuf);
2272  }
2273 #ifdef USE_NNTP
2274  if ((op == OP_MAIN_CHANGE_GROUP) || (op == OP_MAIN_CHANGE_GROUP_READONLY))
2275  {
2276  OptNews = true;
2278  C_NewsServer, false);
2279  if (!CurrentNewsSrv)
2280  break;
2281  if (flags)
2282  cp = _("Open newsgroup in read-only mode");
2283  else
2284  cp = _("Open newsgroup");
2285  nntp_mailbox(Context ? Context->mailbox : NULL, folderbuf->data,
2286  folderbuf->dsize);
2287  }
2288  else
2289 #endif
2290  {
2291  /* By default, fill buf with the next mailbox that contains unread
2292  * mail */
2293  mutt_mailbox_next_buffer(Context ? Context->mailbox : NULL, folderbuf);
2294  }
2295 
2296  if (mutt_buffer_enter_fname(cp, folderbuf, true) == -1)
2297  {
2298  if (menu->menu == MENU_PAGER)
2299  {
2300  op = OP_DISPLAY_MESSAGE;
2301  cont = true;
2302  }
2303  goto changefoldercleanup;
2304  }
2305 
2306  /* Selected directory is okay, let's save it. */
2307  mutt_browser_select_dir(mutt_b2s(folderbuf));
2308 
2309  if (mutt_buffer_is_empty(folderbuf))
2310  {
2312  goto changefoldercleanup;
2313  }
2314  }
2315 
2316  if (!m)
2317  m = mx_mbox_find2(mutt_b2s(folderbuf));
2318 
2319  main_change_folder(menu, op, m, folderbuf->data, folderbuf->dsize,
2320  &oldcount, &index_hint);
2321 #ifdef USE_NNTP
2322  /* mutt_mailbox_check() must be done with mail-reader mode! */
2323  menu->help = mutt_compile_help(helpstr, sizeof(helpstr), MENU_MAIN,
2324  (Context && Context->mailbox &&
2325  (Context->mailbox->magic == MUTT_NNTP)) ?
2326  IndexNewsHelp :
2327  IndexHelp);
2328 #endif
2329  mutt_buffer_expand_path(folderbuf);
2330 #ifdef USE_SIDEBAR
2332 #endif
2333  goto changefoldercleanup;
2334 
2335  changefoldercleanup:
2336  mutt_buffer_pool_release(&folderbuf);
2337  if (cont)
2338  continue;
2339  else
2340  break;
2341  }
2342 
2343  case OP_DISPLAY_MESSAGE:
2344  case OP_DISPLAY_HEADERS: /* don't weed the headers */
2346  break;
2347  /* toggle the weeding of headers so that a user can press the key
2348  * again while reading the message. */
2349  if (op == OP_DISPLAY_HEADERS)
2350  bool_str_toggle(Config, "weed", NULL);
2351 
2352  OptNeedResort = false;
2353 
2354  if (((C_Sort & SORT_MASK) == SORT_THREADS) && CUR_EMAIL->collapsed)
2355  {
2358  if (C_UncollapseJump)
2360  }
2361 
2362  if (C_PgpAutoDecode && (tag || !(CUR_EMAIL->security & PGP_TRADITIONAL_CHECKED)))
2363  {
2364  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
2365  el_add_tagged(&el, Context, CUR_EMAIL, tag);
2366  mutt_check_traditional_pgp(&el, &menu->redraw);
2367  emaillist_clear(&el);
2368  }
2369  int hint =
2371 
2372  /* If we are returning to the pager via an index menu redirection, we
2373  * need to reset the menu->menu. Otherwise mutt_menu_pop_current() will
2374  * set CurrentMenu incorrectly when we return back to the index menu. */
2375  menu->menu = MENU_MAIN;
2376 
2378  if (op < 0)
2379  {
2380  OptNeedResort = false;
2381  break;
2382  }
2383 
2384  /* This is used to redirect a single operation back here afterwards. If
2385  * mutt_display_message() returns 0, then the menu and pager state will
2386  * be cleaned up after this switch statement. */
2387  menu->menu = MENU_PAGER;
2388  menu->oldcurrent = menu->current;
2390  continue;
2391 
2392  case OP_EXIT:
2393  close = op;
2394  if ((menu->menu == MENU_MAIN) && attach_msg)
2395  {
2396  done = true;
2397  break;
2398  }
2399 
2400  if ((menu->menu == MENU_MAIN) &&
2401  (query_quadoption(C_Quit, _("Exit NeoMutt without saving?")) == MUTT_YES))
2402  {
2403  if (Context)
2404  {
2406  ctx_free(&Context);
2407  }
2408  done = true;
2409  }
2410  break;
2411 
2412  case OP_MAIN_BREAK_THREAD:
2414  break;
2415  /* L10N: CHECK_ACL */
2416  if (!check_acl(Context, MUTT_ACL_WRITE, _("Can't break thread")))
2417  break;
2418 
2419  if ((C_Sort & SORT_MASK) != SORT_THREADS)
2420  mutt_error(_("Threading is not enabled"));
2421  else if (!STAILQ_EMPTY(&CUR_EMAIL->env->in_reply_to) ||
2422  !STAILQ_EMPTY(&CUR_EMAIL->env->references))
2423  {
2424  {
2425  struct Email *e_oldcur = CUR_EMAIL;
2426 
2428  mutt_sort_headers(Context, true);
2429  menu->current = e_oldcur->vnum;
2430  }
2431 
2432  Context->mailbox->changed = true;
2433  mutt_message(_("Thread broken"));
2434 
2435  if (menu->menu == MENU_PAGER)
2436  {
2437  op = OP_DISPLAY_MESSAGE;
2438  continue;
2439  }
2440  else
2441  menu->redraw |= REDRAW_INDEX;
2442  }
2443  else
2444  {
2445  mutt_error(
2446  _("Thread can't be broken, message is not part of a thread"));
2447  }
2448 
2449  break;
2450 
2451  case OP_MAIN_LINK_THREADS:
2453  break;
2454  /* L10N: CHECK_ACL */
2455  if (!check_acl(Context, MUTT_ACL_WRITE, _("Can't link threads")))
2456  break;
2457 
2458  if ((C_Sort & SORT_MASK) != SORT_THREADS)
2459  mutt_error(_("Threading is not enabled"));
2460  else if (!CUR_EMAIL->env->message_id)
2461  mutt_error(_("No Message-ID: header available to link thread"));
2462  else if (!tag && (!Context->last_tag || !Context->last_tag->tagged))
2463  mutt_error(_("First, please tag a message to be linked here"));
2464  else
2465  {
2466  struct Email *e_oldcur = CUR_EMAIL;
2467  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
2468  el_add_tagged(&el, Context, Context->last_tag, tag);
2469 
2471  {
2472  mutt_sort_headers(Context, true);
2473  menu->current = e_oldcur->vnum;
2474 
2475  Context->mailbox->changed = true;
2476  mutt_message(_("Threads linked"));
2477  }
2478  else
2479  mutt_error(_("No thread linked"));
2480 
2481  emaillist_clear(&el);
2482  }
2483 
2484  if (menu->menu == MENU_PAGER)
2485  {
2486  op = OP_DISPLAY_MESSAGE;
2487  continue;
2488  }
2489  else
2490  menu->redraw |= REDRAW_STATUS | REDRAW_INDEX;
2491 
2492  break;
2493 
2494  case OP_EDIT_TYPE:
2496  break;
2497  mutt_edit_content_type(CUR_EMAIL, CUR_EMAIL->content, NULL);
2498  /* if we were in the pager, redisplay the message */
2499  if (menu->menu == MENU_PAGER)
2500  {
2501  op = OP_DISPLAY_MESSAGE;
2502  continue;
2503  }
2504  else
2505  menu->redraw = REDRAW_CURRENT;
2506  break;
2507 
2508  case OP_MAIN_NEXT_UNDELETED:
2510  break;
2511  if (menu->current >= (Context->mailbox->vcount - 1))
2512  {
2513  if (menu->menu == MENU_MAIN)
2514  mutt_message(_("You are on the last message"));
2515  break;
2516  }
2517  menu->current = ci_next_undeleted(menu->current);
2518  if (menu->current == -1)
2519  {
2520  menu->current = menu->oldcurrent;
2521  if (menu->menu == MENU_MAIN)
2522  mutt_error(_("No undeleted messages"));
2523  }
2524  else if (menu->menu == MENU_PAGER)
2525  {
2526  op = OP_DISPLAY_MESSAGE;
2527  continue;
2528  }
2529  else
2530  menu->redraw = REDRAW_MOTION;
2531  break;
2532 
2533  case OP_NEXT_ENTRY:
2535  break;
2536  if (menu->current >= (Context->mailbox->vcount - 1))
2537  {
2538  if (menu->menu == MENU_MAIN)
2539  mutt_message(_("You are on the last message"));
2540  break;
2541  }
2542  menu->current++;
2543  if (menu->menu == MENU_PAGER)
2544  {
2545  op = OP_DISPLAY_MESSAGE;
2546  continue;
2547  }
2548  else
2549  menu->redraw = REDRAW_MOTION;
2550  break;
2551 
2552  case OP_MAIN_PREV_UNDELETED:
2554  break;
2555  if (menu->current < 1)
2556  {
2557  mutt_message(_("You are on the first message"));
2558  break;
2559  }
2560  menu->current = ci_previous_undeleted(menu->current);
2561  if (menu->current == -1)
2562  {
2563  menu->current = menu->oldcurrent;
2564  if (menu->menu == MENU_MAIN)
2565  mutt_error(_("No undeleted messages"));
2566  }
2567  else if (menu->menu == MENU_PAGER)
2568  {
2569  op = OP_DISPLAY_MESSAGE;
2570  continue;
2571  }
2572  else
2573  menu->redraw = REDRAW_MOTION;
2574  break;
2575 
2576  case OP_PREV_ENTRY:
2578  break;
2579  if (menu->current < 1)
2580  {
2581  if (menu->menu == MENU_MAIN)
2582  mutt_message(_("You are on the first message"));
2583  break;
2584  }
2585  menu->current--;
2586  if (menu->menu == MENU_PAGER)
2587  {
2588  op = OP_DISPLAY_MESSAGE;
2589  continue;
2590  }
2591  else
2592  menu->redraw = REDRAW_MOTION;
2593  break;
2594 
2595  case OP_DECRYPT_COPY:
2596  case OP_DECRYPT_SAVE:
2597  if (!WithCrypto)
2598  break;
2599  /* fallthrough */
2600  case OP_COPY_MESSAGE:
2601  case OP_SAVE:
2602  case OP_DECODE_COPY:
2603  case OP_DECODE_SAVE:
2604  {
2606  break;
2607  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
2608  el_add_tagged(&el, Context, CUR_EMAIL, tag);
2609  if ((mutt_save_message(Context->mailbox, &el,
2610  (op == OP_DECRYPT_SAVE) || (op == OP_SAVE) || (op == OP_DECODE_SAVE),
2611  (op == OP_DECODE_SAVE) || (op == OP_DECODE_COPY),
2612  (op == OP_DECRYPT_SAVE) || (op == OP_DECRYPT_COPY)) == 0) &&
2613  ((op == OP_SAVE) || (op == OP_DECODE_SAVE) || (op == OP_DECRYPT_SAVE)))
2614  {
2615  menu->redraw |= REDRAW_STATUS;
2616  if (tag)
2617  menu->redraw |= REDRAW_INDEX;
2618  else if (C_Resolve)
2619  {
2620  menu->current = ci_next_undeleted(menu->current);
2621  if (menu->current == -1)
2622  {
2623  menu->current = menu->oldcurrent;
2624  menu->redraw |= REDRAW_CURRENT;
2625  }
2626  else
2627  menu->redraw |= REDRAW_MOTION_RESYNC;
2628  }
2629  else
2630  menu->redraw |= REDRAW_CURRENT;
2631  }
2632  emaillist_clear(&el);
2633  break;
2634  }
2635 
2636  case OP_MAIN_NEXT_NEW:
2637  case OP_MAIN_NEXT_UNREAD:
2638  case OP_MAIN_PREV_NEW:
2639  case OP_MAIN_PREV_UNREAD:
2640  case OP_MAIN_NEXT_NEW_THEN_UNREAD:
2641  case OP_MAIN_PREV_NEW_THEN_UNREAD:
2642  {
2644  break;
2645 
2646  int first_unread = -1;
2647  int first_new = -1;
2648 
2649  const int saved_current = menu->current;
2650  int cur = menu->current;
2651  menu->current = -1;
2652  for (size_t i = 0; i != Context->mailbox->vcount; i++)
2653  {
2654  if ((op == OP_MAIN_NEXT_NEW) || (op == OP_MAIN_NEXT_UNREAD) ||
2655  (op == OP_MAIN_NEXT_NEW_THEN_UNREAD))
2656  {
2657  cur++;
2658  if (cur > (Context->mailbox->vcount - 1))
2659  {
2660  cur = 0;
2661  }
2662  }
2663  else
2664  {
2665  cur--;
2666  if (cur < 0)
2667  {
2668  cur = Context->mailbox->vcount - 1;
2669  }
2670  }
2671 
2672  struct Email *e = Context->mailbox->emails[Context->mailbox->v2r[cur]];
2673  if (e->collapsed && ((C_Sort & SORT_MASK) == SORT_THREADS))
2674  {
2675  if ((UNREAD(e) != 0) && (first_unread == -1))
2676  first_unread = cur;
2677  if ((UNREAD(e) == 1) && (first_new == -1))
2678  first_new = cur;
2679  }
2680  else if (!e->deleted && !e->read)
2681  {
2682  if (first_unread == -1)
2683  first_unread = cur;
2684  if (!e->old && (first_new == -1))
2685  first_new = cur;
2686  }
2687 
2688  if (((op == OP_MAIN_NEXT_UNREAD) || (op == OP_MAIN_PREV_UNREAD)) &&
2689  (first_unread != -1))
2690  break;
2691  if (((op == OP_MAIN_NEXT_NEW) || (op == OP_MAIN_PREV_NEW) ||
2692  (op == OP_MAIN_NEXT_NEW_THEN_UNREAD) || (op == OP_MAIN_PREV_NEW_THEN_UNREAD)) &&
2693  (first_new != -1))
2694  {
2695  break;
2696  }
2697  }
2698  if (((op == OP_MAIN_NEXT_NEW) || (op == OP_MAIN_PREV_NEW) ||
2699  (op == OP_MAIN_NEXT_NEW_THEN_UNREAD) || (op == OP_MAIN_PREV_NEW_THEN_UNREAD)) &&
2700  (first_new != -1))
2701  {
2702  menu->current = first_new;
2703  }
2704  else if (((op == OP_MAIN_NEXT_UNREAD) || (op == OP_MAIN_PREV_UNREAD) ||
2705  (op == OP_MAIN_NEXT_NEW_THEN_UNREAD) || (op == OP_MAIN_PREV_NEW_THEN_UNREAD)) &&
2706  (first_unread != -1))
2707  {
2708  menu->current = first_unread;
2709  }
2710 
2711  if (menu->current == -1)
2712  {
2713  menu->current = menu->oldcurrent;
2714  if ((op == OP_MAIN_NEXT_NEW) || (op == OP_MAIN_PREV_NEW))
2715  {
2716  if (Context->pattern)
2717  mutt_error(_("No new messages in this limited view"));
2718  else
2719  mutt_error(_("No new messages"));
2720  }
2721  else
2722  {
2723  if (Context->pattern)
2724  mutt_error(_("No unread messages in this limited view"));
2725  else
2726  mutt_error(_("No unread messages"));
2727  }
2728  break;
2729  }
2730 
2731  if ((op == OP_MAIN_NEXT_NEW) || (op == OP_MAIN_NEXT_UNREAD) ||
2732  (op == OP_MAIN_NEXT_NEW_THEN_UNREAD))
2733  {
2734  if (saved_current > menu->current)
2735  {
2736  mutt_message(_("Search wrapped to top"));
2737  }
2738  }
2739  else if (saved_current < menu->current)
2740  {
2741  mutt_message(_("Search wrapped to bottom"));
2742  }
2743 
2744  if (menu->menu == MENU_PAGER)
2745  {
2746  op = OP_DISPLAY_MESSAGE;
2747  continue;
2748  }
2749  else
2750  menu->redraw = REDRAW_MOTION;
2751  break;
2752  }
2753  case OP_FLAG_MESSAGE:
2755  break;
2756  /* L10N: CHECK_ACL */
2757  if (!check_acl(Context, MUTT_ACL_WRITE, _("Can't flag message")))
2758  break;
2759 
2760  if (tag)
2761  {
2762  for (size_t i = 0; i < Context->mailbox->msg_count; i++)
2763  {
2764  if (message_is_tagged(Context, i))
2765  {
2768  }
2769  }
2770 
2771  menu->redraw |= REDRAW_INDEX;
2772  }
2773  else
2774  {
2776  if (C_Resolve)
2777  {
2778  menu->current = ci_next_undeleted(menu->current);
2779  if (menu->current == -1)
2780  {
2781  menu->current = menu->oldcurrent;
2782  menu->redraw |= REDRAW_CURRENT;
2783  }
2784  else
2785  menu->redraw |= REDRAW_MOTION_RESYNC;
2786  }
2787  else
2788  menu->redraw |= REDRAW_CURRENT;
2789  }
2790  menu->redraw |= REDRAW_STATUS;
2791  break;
2792 
2793  case OP_TOGGLE_NEW:
2795  break;
2796  /* L10N: CHECK_ACL */
2797  if (!check_acl(Context, MUTT_ACL_SEEN, _("Can't toggle new")))
2798  break;
2799 
2800  if (tag)
2801  {
2802  for (size_t i = 0; i < Context->mailbox->msg_count; i++)
2803  {
2804  if (!message_is_tagged(Context, i))
2805  continue;
2806 
2807  if (Context->mailbox->emails[i]->read || Context->mailbox->emails[i]->old)
2809  else
2811  }
2812  menu->redraw |= REDRAW_STATUS | REDRAW_INDEX;
2813  }
2814  else
2815  {
2816  if (CUR_EMAIL->read || CUR_EMAIL->old)
2818  else
2820 
2821  if (C_Resolve)
2822  {
2823  menu->current = ci_next_undeleted(menu->current);
2824  if (menu->current == -1)
2825  {
2826  menu->current = menu->oldcurrent;
2827  menu->redraw |= REDRAW_CURRENT;
2828  }
2829  else
2830  menu->redraw |= REDRAW_MOTION_RESYNC;
2831  }
2832  else
2833  menu->redraw |= REDRAW_CURRENT;
2834  menu->redraw |= REDRAW_STATUS;
2835  }
2836  break;
2837 
2838  case OP_TOGGLE_WRITE:
2839  if (!prereq(Context, menu, CHECK_IN_MAILBOX))
2840  break;
2841  if (mx_toggle_write(Context->mailbox) == 0)
2842  {
2843  if (menu->menu == MENU_PAGER)
2844  {
2845  op = OP_DISPLAY_MESSAGE;
2846  continue;
2847  }
2848  else
2849  menu->redraw |= REDRAW_STATUS;
2850  }
2851  break;
2852 
2853  case OP_MAIN_NEXT_THREAD:
2854  case OP_MAIN_NEXT_SUBTHREAD:
2855  case OP_MAIN_PREV_THREAD:
2856  case OP_MAIN_PREV_SUBTHREAD:
2858  break;
2859 
2860  switch (op)
2861  {
2862  case OP_MAIN_NEXT_THREAD:
2864  break;
2865 
2866  case OP_MAIN_NEXT_SUBTHREAD:
2868  break;
2869 
2870  case OP_MAIN_PREV_THREAD:
2872  break;
2873 
2874  case OP_MAIN_PREV_SUBTHREAD:
2876  break;
2877  }
2878 
2879  if (menu->current < 0)
2880  {
2881  menu->current = menu->oldcurrent;
2882  if ((op == OP_MAIN_NEXT_THREAD) || (op == OP_MAIN_NEXT_SUBTHREAD))
2883  mutt_error(_("No more threads"));
2884  else
2885  mutt_error(_("You are on the first thread"));
2886  }
2887  else if (menu->menu == MENU_PAGER)
2888  {
2889  op = OP_DISPLAY_MESSAGE;
2890  continue;
2891  }
2892  else
2893  menu->redraw = REDRAW_MOTION;
2894  break;
2895 
2896  case OP_MAIN_ROOT_MESSAGE:
2897  case OP_MAIN_PARENT_MESSAGE:
2899  break;
2900 
2901  menu->current = mutt_parent_message(Context, CUR_EMAIL, op == OP_MAIN_ROOT_MESSAGE);
2902  if (menu->current < 0)
2903  {
2904  menu->current = menu->oldcurrent;
2905  }
2906  else if (menu->menu == MENU_PAGER)
2907  {
2908  op = OP_DISPLAY_MESSAGE;
2909  continue;
2910  }
2911  else
2912  menu->redraw = REDRAW_MOTION;
2913  break;
2914 
2915  case OP_MAIN_SET_FLAG:
2916  case OP_MAIN_CLEAR_FLAG:
2917  {
2919  break;
2920  /* check_acl(MUTT_ACL_WRITE); */
2921 
2922  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
2923  el_add_tagged(&el, Context, CUR_EMAIL, tag);
2924 
2925  if (mutt_change_flag(Context->mailbox, &el, (op == OP_MAIN_SET_FLAG)) == 0)
2926  {
2927  menu->redraw |= REDRAW_STATUS;
2928  if (tag)
2929  menu->redraw |= REDRAW_INDEX;
2930  else if (C_Resolve)
2931  {
2932  menu->current = ci_next_undeleted(menu->current);
2933  if (menu->current == -1)
2934  {
2935  menu->current = menu->oldcurrent;
2936  menu->redraw |= REDRAW_CURRENT;
2937  }
2938  else
2939  menu->redraw |= REDRAW_MOTION_RESYNC;
2940  }
2941  else
2942  menu->redraw |= REDRAW_CURRENT;
2943  }
2944  emaillist_clear(&el);
2945  break;
2946  }
2947 
2948  case OP_MAIN_COLLAPSE_THREAD:
2950  break;
2951 
2952  if ((C_Sort & SORT_MASK) != SORT_THREADS)
2953  {
2954  mutt_error(_("Threading is not enabled"));
2955  break;
2956  }
2957 
2958  if (CUR_EMAIL->collapsed)
2959  {
2962  if (C_UncollapseJump)
2964  }
2965  else if (CAN_COLLAPSE(CUR_EMAIL))
2966  {
2969  }
2970  else
2971  {
2972  mutt_error(_("Thread contains unread or flagged messages"));
2973  break;
2974  }
2975 
2976  menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
2977 
2978  break;
2979 
2980  case OP_MAIN_COLLAPSE_ALL:
2982  break;
2983 
2984  if ((C_Sort & SORT_MASK) != SORT_THREADS)
2985  {
2986  mutt_error(_("Threading is not enabled"));
2987  break;
2988  }
2989  collapse_all(menu, 1);
2990  break;
2991 
2992  /* --------------------------------------------------------------------
2993  * These functions are invoked directly from the internal-pager
2994  */
2995 
2996  case OP_BOUNCE_MESSAGE:
2997  {
2999  break;
3000 
3001  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3002  el_add_tagged(&el, Context, CUR_EMAIL, tag);
3004  emaillist_clear(&el);
3005  break;
3006  }
3007 
3008  case OP_CREATE_ALIAS:
3010  CUR_EMAIL->env :
3011  NULL,
3012  NULL);
3013  menu->redraw |= REDRAW_CURRENT;
3014  break;
3015 
3016  case OP_QUERY:
3017  if (!prereq(Context, menu, CHECK_ATTACH))
3018  break;
3019  mutt_query_menu(NULL, 0);
3020  break;
3021 
3022  case OP_PURGE_MESSAGE:
3023  case OP_DELETE:
3024  {
3026  break;
3027  /* L10N: CHECK_ACL */
3028  if (!check_acl(Context, MUTT_ACL_DELETE, _("Can't delete message")))
3029  break;
3030 
3031  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3032  el_add_tagged(&el, Context, CUR_EMAIL, tag);
3033 
3035  mutt_emails_set_flag(Context->mailbox, &el, MUTT_PURGE, (op == OP_PURGE_MESSAGE));
3036  if (C_DeleteUntag)
3038  emaillist_clear(&el);
3039 
3040  if (tag)
3041  {
3042  menu->redraw |= REDRAW_INDEX;
3043  }
3044  else
3045  {
3046  if (C_Resolve)
3047  {
3048  menu->current = ci_next_undeleted(menu->current);
3049  if (menu->current == -1)
3050  {
3051  menu->current = menu->oldcurrent;
3052  menu->redraw |= REDRAW_CURRENT;
3053  }
3054  else if (menu->menu == MENU_PAGER)
3055  {
3056  op = OP_DISPLAY_MESSAGE;
3057  continue;
3058  }
3059  else
3060  menu->redraw |= REDRAW_MOTION_RESYNC;
3061  }
3062  else
3063  menu->redraw |= REDRAW_CURRENT;
3064  }
3065  menu->redraw |= REDRAW_STATUS;
3066  break;
3067  }
3068 
3069  case OP_DELETE_THREAD:
3070  case OP_DELETE_SUBTHREAD:
3071  case OP_PURGE_THREAD:
3072  {
3074  break;
3075  /* L10N: CHECK_ACL */
3076  /* L10N: Due to the implementation details we do not know whether we
3077  delete zero, 1, 12, ... messages. So in English we use
3078  "messages". Your language might have other means to express this. */
3079  if (!check_acl(Context, MUTT_ACL_DELETE, _("Can't delete messages")))
3080  break;
3081 
3082  int subthread = (op == OP_DELETE_SUBTHREAD);
3083  int rc = mutt_thread_set_flag(CUR_EMAIL, MUTT_DELETE, true, subthread);
3084  if (rc == -1)
3085  break;
3086  if (op == OP_PURGE_THREAD)
3087  {
3088  rc = mutt_thread_set_flag(CUR_EMAIL, MUTT_PURGE, true, subthread);
3089  if (rc == -1)
3090  break;
3091  }
3092 
3093  if (C_DeleteUntag)
3094  mutt_thread_set_flag(CUR_EMAIL, MUTT_TAG, false, subthread);
3095  if (C_Resolve)
3096  {
3097  menu->current = ci_next_undeleted(menu->current);
3098  if (menu->current == -1)
3099  menu->current = menu->oldcurrent;
3100  }
3101  menu->redraw |= REDRAW_INDEX | REDRAW_STATUS;
3102  break;
3103  }
3104 
3105 #ifdef USE_NNTP
3106  case OP_CATCHUP:
3108  break;
3109  if (Context && (Context->mailbox->magic == MUTT_NNTP))
3110  {
3111  struct NntpMboxData *mdata = Context->mailbox->mdata;
3112  if (mutt_newsgroup_catchup(Context->mailbox, mdata->adata, mdata->group))
3113  menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
3114  }
3115  break;
3116 #endif
3117 
3118  case OP_DISPLAY_ADDRESS:
3120  break;
3122  break;
3123 
3124  case OP_ENTER_COMMAND:
3126  if (Context)
3128  break;
3129 
3130  case OP_EDIT_OR_VIEW_RAW_MESSAGE:
3131  case OP_EDIT_RAW_MESSAGE:
3132  case OP_VIEW_RAW_MESSAGE:
3133  {
3134  /* TODO split this into 3 cases? */
3136  break;
3137  bool edit;
3138  if (op == OP_EDIT_RAW_MESSAGE)
3139  {
3140  if (!prereq(Context, menu, CHECK_READONLY))
3141  break;
3142  /* L10N: CHECK_ACL */
3143  if (!check_acl(Context, MUTT_ACL_INSERT, _("Can't edit message")))
3144  break;
3145  edit = true;
3146  }
3147  else if (op == OP_EDIT_OR_VIEW_RAW_MESSAGE)
3149  else
3150  edit = false;
3151 
3152  if (C_PgpAutoDecode && (tag || !(CUR_EMAIL->security & PGP_TRADITIONAL_CHECKED)))
3153  {
3154  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3155  el_add_tagged(&el, Context, CUR_EMAIL, tag);
3156  mutt_check_traditional_pgp(&el, &menu->redraw);
3157  emaillist_clear(&el);
3158  }
3159  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3160  el_add_tagged(&el, Context, CUR_EMAIL, tag);
3161  mutt_ev_message(Context->mailbox, &el, edit ? EVM_EDIT : EVM_VIEW);
3162  emaillist_clear(&el);
3163  menu->redraw = REDRAW_FULL;
3164 
3165  break;
3166  }
3167 
3168  case OP_FORWARD_MESSAGE:
3169  {
3171  break;
3172  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3173  el_add_tagged(&el, Context, CUR_EMAIL, tag);
3174  if (C_PgpAutoDecode && (tag || !(CUR_EMAIL->security & PGP_TRADITIONAL_CHECKED)))
3175  {
3176  mutt_check_traditional_pgp(&el, &menu->redraw);
3177  }
3178  ci_send_message(SEND_FORWARD, NULL, NULL, Context, &el);
3179  emaillist_clear(&el);
3180  menu->redraw = REDRAW_FULL;
3181  break;
3182  }
3183 
3184  case OP_FORGET_PASSPHRASE:
3186  break;
3187 
3188  case OP_GROUP_REPLY:
3189  case OP_GROUP_CHAT_REPLY:
3190  {
3191  SendFlags replyflags = SEND_REPLY;
3192  if (op == OP_GROUP_REPLY)
3193  replyflags |= SEND_GROUP_REPLY;
3194  else
3195  replyflags |= SEND_GROUP_CHAT_REPLY;
3197  break;
3198  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3199  el_add_tagged(&el, Context, CUR_EMAIL, tag);
3200  if (C_PgpAutoDecode && (tag || !(CUR_EMAIL->security & PGP_TRADITIONAL_CHECKED)))
3201  {
3202  mutt_check_traditional_pgp(&el, &menu->redraw);
3203  }
3204  ci_send_message(replyflags, NULL, NULL, Context, &el);
3205  emaillist_clear(&el);
3206  menu->redraw = REDRAW_FULL;
3207  break;
3208  }
3209 
3210  case OP_EDIT_LABEL:
3211  {
3213  break;
3214 
3215  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3216  el_add_tagged(&el, Context, CUR_EMAIL, tag);
3217  int num_changed = mutt_label_message(Context->mailbox, &el);
3218  emaillist_clear(&el);
3219 
3220  if (num_changed > 0)
3221  {
3222  Context->mailbox->changed = true;
3223  menu->redraw = REDRAW_FULL;
3224  /* L10N: This is displayed when the x-label on one or more
3225  messages is edited. */
3226  mutt_message(ngettext("%d label changed", "%d labels changed", num_changed),
3227  num_changed);
3228  }
3229  else
3230  {
3231  /* L10N: This is displayed when editing an x-label, but no messages
3232  were updated. Possibly due to canceling at the prompt or if the new
3233  label is the same as the old label. */
3234  mutt_message(_("No labels changed"));
3235  }
3236  break;
3237  }
3238 
3239  case OP_LIST_REPLY:
3240  {
3242  break;
3243  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3244  el_add_tagged(&el, Context, CUR_EMAIL, tag);
3245  if (C_PgpAutoDecode && (tag || !(CUR_EMAIL->security & PGP_TRADITIONAL_CHECKED)))
3246  {
3247  mutt_check_traditional_pgp(&el, &menu->redraw);
3248  }
3249  ci_send_message(SEND_REPLY | SEND_LIST_REPLY, NULL, NULL, Context, &el);
3250  emaillist_clear(&el);
3251  menu->redraw = REDRAW_FULL;
3252  break;
3253  }
3254 
3255  case OP_MAIL:
3256  if (!prereq(Context, menu, CHECK_ATTACH))
3257  break;
3258  ci_send_message(SEND_NO_FLAGS, NULL, NULL, Context, NULL);
3259  menu->redraw = REDRAW_FULL;
3260  break;
3261 
3262  case OP_MAIL_KEY:
3263  if (!(WithCrypto & APPLICATION_PGP))
3264  break;
3265  if (!prereq(Context, menu, CHECK_ATTACH))
3266  break;
3267  ci_send_message(SEND_KEY, NULL, NULL, NULL, NULL);
3268  menu->redraw = REDRAW_FULL;
3269  break;
3270 
3271  case OP_EXTRACT_KEYS:
3272  {
3273  if (!WithCrypto)
3274  break;
3276  break;
3277  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3278  el_add_tagged(&el, Context, CUR_EMAIL, tag);
3280  emaillist_clear(&el);
3281  menu->redraw = REDRAW_FULL;
3282  break;
3283  }
3284 
3285  case OP_CHECK_TRADITIONAL:
3286  {
3287  if (!(WithCrypto & APPLICATION_PGP))
3288  break;
3290  break;
3291  if (tag || !(CUR_EMAIL->security & PGP_TRADITIONAL_CHECKED))
3292  {
3293  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3294  el_add_tagged(&el, Context, CUR_EMAIL, tag);
3295  mutt_check_traditional_pgp(&el, &menu->redraw);
3296  emaillist_clear(&el);
3297  }
3298 
3299  if (menu->menu == MENU_PAGER)
3300  {
3301  op = OP_DISPLAY_MESSAGE;
3302  continue;
3303  }
3304  break;
3305  }
3306 
3307  case OP_PIPE:
3308  {
3310  break;
3311  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3312  el_add_tagged(&el, Context, CUR_EMAIL, tag);
3314  emaillist_clear(&el);
3315 
3316 #ifdef USE_IMAP
3317  /* in an IMAP folder index with imap_peek=no, piping could change
3318  * new or old messages status to read. Redraw what's needed. */
3319  if ((Context->mailbox->magic == MUTT_IMAP) && !C_ImapPeek)
3320  {
3321  menu->redraw |= (tag ? REDRAW_INDEX : REDRAW_CURRENT) | REDRAW_STATUS;
3322  }
3323 #endif
3324  break;
3325  }
3326 
3327  case OP_PRINT:
3328  {
3330  break;
3331  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3332  el_add_tagged(&el, Context, CUR_EMAIL, tag);
3334  emaillist_clear(&el);
3335 
3336 #ifdef USE_IMAP
3337  /* in an IMAP folder index with imap_peek=no, printing could change
3338  * new or old messages status to read. Redraw what's needed. */
3339  if ((Context->mailbox->magic == MUTT_IMAP) && !C_ImapPeek)
3340  {
3341  menu->redraw |= (tag ? REDRAW_INDEX : REDRAW_CURRENT) | REDRAW_STATUS;
3342  }
3343 #endif
3344  break;
3345  }
3346 
3347  case OP_MAIN_READ_THREAD:
3348  case OP_MAIN_READ_SUBTHREAD:
3349  {
3351  break;
3352  /* L10N: CHECK_ACL */
3353  /* L10N: Due to the implementation details we do not know whether we
3354  mark zero, 1, 12, ... messages as read. So in English we use
3355  "messages". Your language might have other means to express this. */
3356  if (!check_acl(Context, MUTT_ACL_SEEN, _("Can't mark messages as read")))
3357  break;
3358 
3359  int rc = mutt_thread_set_flag(CUR_EMAIL, MUTT_READ, true, (op != OP_MAIN_READ_THREAD));
3360  if (rc != -1)
3361  {
3362  if (C_Resolve)
3363  {
3364  menu->current =
3365  ((op == OP_MAIN_READ_THREAD) ? mutt_next_thread(CUR_EMAIL) :
3367  if (menu->current == -1)
3368  {
3369  menu->current = menu->oldcurrent;
3370  }
3371  else if (menu->menu == MENU_PAGER)
3372  {
3373  op = OP_DISPLAY_MESSAGE;
3374  continue;
3375  }
3376  }
3377  menu->redraw |= REDRAW_INDEX | REDRAW_STATUS;
3378  }
3379  break;
3380  }
3381 
3382  case OP_MARK_MSG:
3384  break;
3385  if (CUR_EMAIL->env->message_id)
3386  {
3387  char buf2[128];
3388 
3389  buf2[0] = '\0';
3390  /* L10N: This is the prompt for <mark-message>. Whatever they
3391  enter will be prefixed by $mark_macro_prefix and will become
3392  a macro hotkey to jump to the currently selected message. */
3393  if (!mutt_get_field(_("Enter macro stroke: "), buf2, sizeof(buf2), MUTT_CLEAR) &&
3394  buf2[0])
3395  {
3396  char str[256], macro[256];
3397  snprintf(str, sizeof(str), "%s%s", C_MarkMacroPrefix, buf2);
3398  snprintf(macro, sizeof(macro), "<search>~i \"%s\"\n", CUR_EMAIL->env->message_id);
3399  /* L10N: "message hotkey" is the key bindings menu description of a
3400  macro created by <mark-message>. */
3401  km_bind(str, MENU_MAIN, OP_MACRO, macro, _("message hotkey"));
3402 
3403  /* L10N: This is echoed after <mark-message> creates a new hotkey
3404  macro. %s is the hotkey string ($mark_macro_prefix followed
3405  by whatever they typed at the prompt.) */
3406  snprintf(buf2, sizeof(buf2), _("Message bound to %s"), str);
3407  mutt_message(buf2);
3408  mutt_debug(LL_DEBUG1, "Mark: %s => %s\n", str, macro);
3409  }
3410  }
3411  else
3412  {
3413  /* L10N: This error is printed if <mark-message> can't find a
3414  Message-ID for the currently selected message in the index. */
3415  mutt_error(_("No message ID to macro"));
3416  }
3417  break;
3418 
3419  case OP_RECALL_MESSAGE:
3420  if (!prereq(Context, menu, CHECK_ATTACH))
3421  break;
3422  ci_send_message(SEND_POSTPONED, NULL, NULL, Context, NULL);
3423  menu->redraw = REDRAW_FULL;
3424  break;
3425 
3426  case OP_RESEND:
3428  break;
3429 
3430  if (tag)
3431  {
3432  for (size_t i = 0; i < Context->mailbox->msg_count; i++)
3433  {
3434  if (message_is_tagged(Context, i))
3436  }
3437  }
3438  else
3440 
3441  menu->redraw = REDRAW_FULL;
3442  break;
3443 
3444 #ifdef USE_NNTP
3445  case OP_FOLLOWUP:
3446  case OP_FORWARD_TO_GROUP:
3448  break;
3449  /* fallthrough */
3450 
3451  case OP_POST:
3453  break;
3454  if ((op != OP_FOLLOWUP) || !CUR_EMAIL->env->followup_to ||
3455  (mutt_str_strcasecmp(CUR_EMAIL->env->followup_to, "poster") != 0) ||
3457  _("Reply by mail as poster prefers?")) != MUTT_YES))
3458  {
3459  if (Context && (Context->mailbox->magic == MUTT_NNTP) &&
3460  !((struct NntpMboxData *) Context->mailbox->mdata)->allowed && (query_quadoption(C_PostModerated, _("Posting to this group not allowed, may be moderated. Continue?")) != MUTT_YES))
3461  {
3462  break;
3463  }
3464  if (op == OP_POST)
3465  ci_send_message(SEND_NEWS, NULL, NULL, Context, NULL);
3466  else
3467  {
3469  break;
3470  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3471  el_add_tagged(&el, Context, CUR_EMAIL, tag);
3472  ci_send_message(((op == OP_FOLLOWUP) ? SEND_REPLY : SEND_FORWARD) | SEND_NEWS,
3473  NULL, NULL, Context, &el);
3474  emaillist_clear(&el);
3475  }
3476  menu->redraw = REDRAW_FULL;
3477  break;
3478  }
3479 #endif
3480  /* fallthrough */
3481  case OP_REPLY:
3482  {
3484  break;
3485  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3486  el_add_tagged(&el, Context, CUR_EMAIL, tag);
3487  if (C_PgpAutoDecode && (tag || !(CUR_EMAIL->security & PGP_TRADITIONAL_CHECKED)))
3488  {
3489  mutt_check_traditional_pgp(&el, &menu->redraw);
3490  }
3491  ci_send_message(SEND_REPLY, NULL, NULL, Context, &el);
3492  emaillist_clear(&el);
3493  menu->redraw = REDRAW_FULL;
3494  break;
3495  }
3496 
3497  case OP_SHELL_ESCAPE:
3499  break;
3500 
3501  case OP_TAG_THREAD:
3502  case OP_TAG_SUBTHREAD:
3503  {
3505  break;
3506 
3507  int rc = mutt_thread_set_flag(CUR_EMAIL, MUTT_TAG, !CUR_EMAIL->tagged,
3508  (op != OP_TAG_THREAD));
3509  if (rc != -1)
3510  {
3511  if (C_Resolve)
3512  {
3513  if (op == OP_TAG_THREAD)
3515  else
3517 
3518  if (menu->current == -1)
3519  menu->current = menu->oldcurrent;
3520  }
3521  menu->redraw |= REDRAW_INDEX | REDRAW_STATUS;
3522  }
3523  break;
3524  }
3525 
3526  case OP_UNDELETE:
3527  {
3529  break;
3530  /* L10N: CHECK_ACL */
3531  if (!check_acl(Context, MUTT_ACL_DELETE, _("Can't undelete message")))
3532  break;
3533 
3534  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3535  el_add_tagged(&el, Context, CUR_EMAIL, tag);
3536 
3539  emaillist_clear(&el);
3540 
3541  if (tag)
3542  {
3543  menu->redraw |= REDRAW_INDEX;
3544  }
3545  else
3546  {
3547  if (C_Resolve && (menu->current < (Context->mailbox->vcount - 1)))
3548  {
3549  menu->current++;
3550  menu->redraw |= REDRAW_MOTION_RESYNC;
3551  }
3552  else
3553  menu->redraw |= REDRAW_CURRENT;
3554  }
3555 
3556  menu->redraw |= REDRAW_STATUS;
3557  break;
3558  }
3559 
3560  case OP_UNDELETE_THREAD:
3561  case OP_UNDELETE_SUBTHREAD:
3562  {
3564  break;
3565  /* L10N: CHECK_ACL */
3566  /* L10N: Due to the implementation details we do not know whether we
3567  undelete zero, 1, 12, ... messages. So in English we use
3568  "messages". Your language might have other means to express this. */
3569  if (!check_acl(Context, MUTT_ACL_DELETE, _("Can't undelete messages")))
3570  break;
3571 
3572  int rc = mutt_thread_set_flag(CUR_EMAIL, MUTT_DELETE, false,
3573  (op != OP_UNDELETE_THREAD));
3574  if (rc != -1)
3575  {
3576  rc = mutt_thread_set_flag(CUR_EMAIL, MUTT_PURGE, false, (op != OP_UNDELETE_THREAD));
3577  }
3578  if (rc != -1)
3579  {
3580  if (C_Resolve)
3581  {
3582  if (op == OP_UNDELETE_THREAD)
3584  else
3586 
3587  if (menu->current == -1)
3588  menu->current = menu->oldcurrent;
3589  }
3590  menu->redraw |= REDRAW_INDEX | REDRAW_STATUS;
3591  }
3592  break;
3593  }
3594 
3595  case OP_VERSION:
3597  break;
3598 
3599  case OP_MAILBOX_LIST:
3601  break;
3602 
3603  case OP_VIEW_ATTACHMENTS:
3605  break;
3607  if (CUR_EMAIL->attach_del)
3608  Context->mailbox->changed = true;
3609  menu->redraw = REDRAW_FULL;
3610  break;
3611 
3612  case OP_END_COND:
3613  break;
3614 
3615  case OP_WHAT_KEY:
3616  mutt_what_key();
3617  break;
3618 
3619 #ifdef USE_SIDEBAR
3620  case OP_SIDEBAR_NEXT:
3621  case OP_SIDEBAR_NEXT_NEW:
3622  case OP_SIDEBAR_PAGE_DOWN:
3623  case OP_SIDEBAR_PAGE_UP:
3624  case OP_SIDEBAR_PREV:
3625  case OP_SIDEBAR_PREV_NEW:
3627  break;
3628 
3629  case OP_SIDEBAR_TOGGLE_VISIBLE:
3630  bool_str_toggle(Config, "sidebar_visible", NULL);
3632  break;
3633 #endif
3634 
3635 #ifdef USE_AUTOCRYPT
3636  case OP_AUTOCRYPT_ACCT_MENU:
3638  break;
3639 #endif
3640 
3641  default:
3642  if (menu->menu == MENU_MAIN)
3644  }
3645 
3646 #ifdef USE_NOTMUCH
3647  if (Context)
3649 #endif
3650 
3651  if (menu->menu == MENU_PAGER)
3652  {
3654  menu->menu = MENU_MAIN;
3655  menu->redraw = REDRAW_FULL;
3656  }
3657 
3658  if (done)
3659  break;
3660  }
3661 
3662  mutt_menu_pop_current(menu);
3663  mutt_menu_free(&menu);
3664  return close;
3665 }
void mutt_mailbox_next_buffer(struct Mailbox *m_cur, struct Buffer *s)
incoming folders completion routine
Definition: mutt_mailbox.c:291
struct Email ** emails
Array of Emails.
Definition: mailbox.h:110
#define MUTT_OPEN_NO_FLAGS
No flags are set.
Definition: mx.h:50
int mutt_save_message(struct Mailbox *m, struct EmailList *el, bool delete_original, bool decode, bool decrypt)
Save an email.
Definition: commands.c:998
enum CommandResult km_bind(char *s, int menu, int op, char *macro, char *desc)
Bind a key to a macro.
Definition: keymap.c:392
The "current" mailbox.
Definition: context.h:36
struct NntpAccountData * nntp_select_server(struct Mailbox *m, char *server, bool leave_lock)
Open a connection to an NNTP server.
Definition: newsrc.c:982
int mutt_pattern_func(int op, char *prompt)
Perform some Pattern matching.
Definition: pattern.c:2416
#define MUTT_PROGRESS_MSG
message-based progress
Definition: progress.h:32
int mutt_thread_set_flag(struct Email *e, int flag, bool bf, bool subthread)
Set a flag on an entire thread.
Definition: flags.c:375
#define REDRAW_FULL
Redraw everything.
Definition: mutt_menu.h:47
bool mutt_mailbox_list(void)
List the mailboxes with new mail.
Definition: mutt_mailbox.c:201
#define NONULL(x)
Definition: string2.h:37
int msg_count
Total number of messages.
Definition: mailbox.h:102
#define mutt_set_flag(m, e, flag, bf)
Definition: protos.h:68
int mutt_str_atoi(const char *str, int *dst)
Convert ASCII string to an integer.
Definition: string.c:262
#define SEND_TO_SENDER
Compose new email to sender.
Definition: send.h:99
void mutt_pipe_message(struct Mailbox *m, struct EmailList *el)
Pipe a message.
Definition: commands.c:674
The envelope/body of an email.
Definition: email.h:39
#define MUTT_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:69
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:75
#define mutt_perror(...)
Definition: logging.h:85
#define MUTT_SHUTDOWN_HOOK
shutdown-hook: run when leaving NeoMutt
Definition: hook.h:65
void mutt_set_vnum(struct Context *ctx)
Set the virtual index number of all the messages in a mailbox.
Definition: mutt_thread.c:1186
struct NntpMboxData * mutt_newsgroup_catchup(struct Mailbox *m, struct NntpAccountData *adata, char *group)
Catchup newsgroup.
Definition: newsrc.c:1263
GUI selectable list of items.
Definition: mutt_menu.h:82
WHERE bool C_BeepNew
Config: Make a noise when new mail arrives.
Definition: globals.h:215
int km_dokey(int menu)
Determine what a keypress should do.
Definition: keymap.c:570
int mx_mbox_check(struct Mailbox *m, int *index_hint)
Check for new mail - Wrapper for MxOps::mbox_check()
Definition: mx.c:1022
void mutt_buffer_increase_size(struct Buffer *buf, size_t new_size)
Increase the allocated size of a buffer.
Definition: buffer.c:339
&#39;NNTP&#39; (Usenet) Mailbox type
Definition: mailbox.h:51
int mx_mbox_close(struct Context **ptr)
Save changes and close mailbox.
Definition: mx.c:558
void nm_query_window_backward(void)
Function to move the current search window backward in time.
bool C_UncollapseJump
Config: When opening a thread, jump to the next unread message.
Definition: index.c:110
enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
Ask the user a quad-question.
Definition: init.c:3322
#define mutt_message(...)
Definition: logging.h:83
void mutt_check_rescore(struct Mailbox *m)
Do the emails need to have their scores recalculated?
Definition: score.c:70
int oldcurrent
for driver use only
Definition: mutt_menu.h:111
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
WHERE unsigned char C_Quit
Config: Prompt before exiting NeoMutt.
Definition: globals.h:195
void mutt_display_address(struct Envelope *env)
Display the address of a message.
Definition: commands.c:881
struct NntpAccountData * adata
Definition: nntp.h:153
void mutt_emails_set_flag(struct Mailbox *m, struct EmailList *el, int flag, bool bf)
Set flag on messages.
Definition: flags.c:354
static void index_custom_redraw(struct Menu *menu)
Redraw the index - Implements Menu::menu_custom_redraw()
Definition: index.c:977
#define mutt_thread_next_unread(ctx, e)
Definition: mutt_thread.h:62
Messages in limited view.
Definition: mutt.h:110
WHERE unsigned char C_FollowupToPoster
Config: (nntp) Reply to the poster if &#39;poster&#39; is in the &#39;Followup-To&#39; header.
Definition: globals.h:201
void mutt_view_attachments(struct Email *e)
Show the attachments in a Menu.
Definition: recvattach.c:1402
void mutt_flushinp(void)
Empty all the keyboard buffers.
Definition: curs_lib.c:800
bool mutt_limit_current_thread(struct Email *e)
Limit the email view to the current thread.
Definition: pattern.c:2375
#define SEND_FORWARD
Forward email.
Definition: send.h:90
void mutt_window_clrtoeol(struct MuttWindow *win)
Clear to the end of the line.
Definition: mutt_window.c:107
void mutt_resize_screen(void)
Update NeoMutt&#39;s opinion about the window size (CURSES)
Definition: resize.c:98
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:86
#define CHECK_ATTACH
Is the user in message-attach mode?
Definition: index.c:156
WHERE bool OptNeedResort
(pseudo) used to force a re-sort
Definition: options.h:41
void index_make_entry(char *buf, size_t buflen, struct Menu *menu, int line)
Format a menu item for the index list - Implements Menu::menu_make_entry()
Definition: index.c:748
void mutt_check_stats(void)
Forcibly update mailbox stats.
Definition: commands.c:1356
#define mutt_next_subthread(e)
Definition: mutt_thread.h:67
void * mutt_hash_find(const struct Hash *table, const char *strkey)
Find the HashElem data in a Hash table element using a key.
Definition: hash.c:379
void crypt_forget_passphrase(void)
Forget a passphrase and display a message.
Definition: crypt.c:105
bool mutt_link_threads(struct Email *parent, struct EmailList *children, struct Mailbox *m)
Forcibly link threads together.
Definition: mutt_thread.c:1479
WHERE char * C_NmQueryWindowCurrentSearch
Config: (notmuch) Current search parameters.
Definition: globals.h:181
static bool check_acl(struct Context *ctx, AclFlags acl, const char *msg)
Check the ACLs for a function.
Definition: index.c:216
void mutt_progress_update(struct Progress *progress, long pos, int percent)
Update the state of the progress bar.
Definition: progress.c:172
void mutt_progress_init(struct Progress *progress, const char *msg, unsigned short flags, unsigned short inc, size_t size)
Set up a progress bar.
Definition: progress.c:115
#define MUTT_NM_QUERY
Notmuch query mode.
Definition: mutt.h:73
void mutt_enter_command(void)
enter a neomutt command
Definition: commands.c:837
String manipulation buffer.
Definition: buffer.h:33
#define MUTT_ACL_INSERT
Add/copy into the mailbox (used when editing a message)
Definition: mailbox.h:80
Messages to be un-deleted.
Definition: mutt.h:104
Flagged messages.
Definition: mutt.h:107
#define PGP_TRADITIONAL_CHECKED
Email has a traditional (inline) signature.
Definition: ncrypt.h:136
void mutt_unget_event(int ch, int op)
Return a keystroke to the input buffer.
Definition: curs_lib.c:715
WHERE bool C_ImapPeek
Config: (imap) Don&#39;t mark messages as read when fetching them from the server.
Definition: globals.h:237
#define _(a)
Definition: message.h:28
WHERE struct ConfigSet * Config
Wrapper around the user&#39;s config settings.
Definition: globals.h:39
WHERE bool C_BrailleFriendly
Config: Move the cursor to the beginning of the line.
Definition: globals.h:216
int index_color(int line)
Calculate the colour for a line of the index - Implements Menu::menu_color()
Definition: index.c:822
void mutt_autocrypt_account_menu(void)
Display the Autocrypt account Menu.
void menu_status_line(char *buf, size_t buflen, struct Menu *menu, const char *p)
Create the status line.
Definition: status.c:408
bool mutt_check_traditional_pgp(struct EmailList *el, MuttRedrawFlags *redraw)
Check if a message has inline PGP content.
Definition: commands.c:1340
Messages to be purged (bypass trash)
Definition: mutt.h:105
struct TagHead tags
For drivers that support server tagging.
Definition: email.h:108
void pop_fetch_mail(void)
Fetch messages and save them in $spoolfile.
Definition: pop.c:573
char * C_MarkMacroPrefix
Config: Prefix for macros using &#39;<mark-message>&#39;.
Definition: index.c:108
bool C_CollapseAll
Config: Collapse all threads when entering a folder.
Definition: index.c:105
Index panel (list of emails)
Definition: keymap.h:77
uint8_t OpenMailboxFlags
Flags for mutt_open_mailbox(), e.g. MUTT_NOSORT.
Definition: mx.h:49
int menu
menu definition for keymap entries.
Definition: mutt_menu.h:90
static void resort_index(struct Menu *menu)
Resort the index.
Definition: index.c:412
#define MUTT_READONLY
Open in read-only mode.
Definition: mx.h:53
uint16_t SendFlags
Flags for ci_send_message(), e.g. SEND_REPLY.
Definition: send.h:85
int mutt_monitor_add(struct Mailbox *m)
Add a watch for a mailbox.
Definition: monitor.c:463
struct Mailbox * mx_mbox_find2(const char *path)
XXX.
Definition: mx.c:1518
#define SEND_POSTPONED
Recall a postponed email.
Definition: send.h:91
Container for Accounts, Notifications.
Definition: neomutt.h:35
A progress bar.
Definition: progress.h:37
void mutt_buffer_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:688
void(* menu_make_entry)(char *buf, size_t buflen, struct Menu *menu, int line)
Format a item for a menu.
Definition: mutt_menu.h:122
void km_error_key(int menu)
Handle an unbound key sequence.
Definition: keymap.c:1050
#define MUTT_ACL_DELETE
Delete a message.
Definition: mailbox.h:77
struct Mapping IndexNewsHelp[]
Definition: index.c:126
#define mutt_get_field(field, buf, buflen, complete)
Definition: curs_lib.h:86
#define mutt_collapse_thread(ctx, e)
Definition: mutt_thread.h:57
int vcount
The number of virtual messages.
Definition: mailbox.h:113
char * mutt_compile_help(char *buf, size_t buflen, int menu, const struct Mapping *items)
Create the text for the help menu.
Definition: help.c:115
void imap_logout_all(void)
close all open connections
Definition: imap.c:687
static void collapse_all(struct Menu *menu, int toggle)
Collapse/uncollapse all threads.
Definition: index.c:242
void mutt_print_message(struct Mailbox *m, struct EmailList *el)
Print a message.
Definition: commands.c:696
#define SEND_NO_FLAGS
No flags are set.
Definition: send.h:86
static int ci_previous_undeleted(int msgno)
Find the previous undeleted email.
Definition: index.c:321
Pager pager (email viewer)
Definition: keymap.h:78
#define mutt_previous_thread(e)
Definition: mutt_thread.h:66
size_t dsize
Length of data.
Definition: buffer.h:37
bool tagged
Email is tagged.
Definition: email.h:46
#define CHECK_VISIBLE
Is the selected message visible in the index?
Definition: index.c:154
bool read
Email is read.
Definition: email.h:53
void mutt_startup_shutdown_hook(HookFlags type)
Execute any startup/shutdown hooks.
Definition: hook.c:845
struct Mailbox * mailbox
Definition: context.h:50
Log at debug level 2.
Definition: logging.h:57
#define CHECK_IN_MAILBOX
Is there a mailbox open?
Definition: index.c:152
bool old
Email is seen, but unread.
Definition: email.h:52
static bool prereq(struct Context *ctx, struct Menu *menu, CheckFlags checks)
Check the pre-requisites for a function.
Definition: index.c:166
void mutt_flush_macro_to_endcond(void)
Drop a macro from the input buffer.
Definition: curs_lib.c:771
enum MailboxType magic
Mailbox type.
Definition: mailbox.h:116
bool message_is_visible(struct Context *ctx, int index)
Is a message in the index within limit.
Definition: context.c:327
bool readonly
Don&#39;t allow changes to the mailbox.
Definition: mailbox.h:130
void mutt_window_clearline(struct MuttWindow *win, int row)
Clear a row of a Window.
Definition: mutt_window.c:95
void emaillist_clear(struct EmailList *el)
Drop a private list of Emails.
Definition: email.c:127
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
int mutt_parent_message(struct Context *ctx, struct Email *e, bool find_root)
Find the parent of a message.
Definition: mutt_thread.c:1140
void mutt_what_key(void)
Ask the user to press a key.
Definition: keymap.c:1572
int LastKey
contains the last key the user pressed
Definition: keymap.c:145
int mx_tags_commit(struct Mailbox *m, struct Email *e, char *tags)
Save tags to the Mailbox - Wrapper for MxOps::tags_commit()
Definition: mx.c:1210
bool mutt_mailbox_notify(struct Mailbox *m_cur)
Notify the user if there&#39;s new mail.
Definition: mutt_mailbox.c:188
void mx_fastclose_mailbox(struct Mailbox *m)
free up memory associated with the Mailbox
Definition: mx.c:392
void mutt_shell_escape(void)
invoke a command in a subshell
Definition: commands.c:809
char * group
Definition: nntp.h:140
WHERE SIG_ATOMIC_VOLATILE_T SigWinch
true after SIGWINCH is received
Definition: globals.h:84
bool nm_message_is_still_queried(struct Mailbox *m, struct Email *e)
Is a message still visible in the query?
struct Menu * menu
Needed for pattern compilation.
Definition: context.h:46
void mutt_break_thread(struct Email *e)
Break the email Thread.
Definition: thread.c:225
WHERE int C_NmQueryWindowDuration
Config: (notmuch) Time duration of the current search window.
Definition: globals.h:180
void(* menu_custom_redraw)(struct Menu *menu)
Redraw the menu.
Definition: mutt_menu.h:151
WHERE unsigned char C_PostModerated
Config: (nntp) Allow posting to moderated newsgroups.
Definition: globals.h:200
#define SEND_LIST_REPLY
Reply to mailing list.
Definition: send.h:89
#define CUR_EMAIL
Definition: index.c:139
WHERE short C_Sort
Config: Sort method for the index.
Definition: sort.h:58
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:143
static int mx_toggle_write(struct Mailbox *m)
Toggle the mailbox&#39;s readonly flag.
Definition: index.c:383
WHERE bool C_ReadOnly
Config: Open folders in read-only mode.
Definition: globals.h:256
void * mdata
Driver specific data.
Definition: mailbox.h:147
#define MUTT_ACL_WRITE
Write to a message (for flagging or linking threads)
Definition: mailbox.h:85
#define REDRAW_MOTION
Redraw after moving the menu list.
Definition: mutt_menu.h:43
char * nm_uri_from_query(struct Mailbox *m, char *buf, size_t buflen)
Turn a query into a URI.
void mutt_window_reflow(void)
Resize the Windows to fit the screen.
Definition: mutt_window.c:234
bool quasi_deleted
Deleted from neomutt, but not modified on disk.
Definition: email.h:49
#define SEND_KEY
Mail a PGP public key.
Definition: send.h:94
static int ci_next_undeleted(int msgno)
Find the next undeleted email.
Definition: index.c:304
#define REDRAW_MOTION_RESYNC
Redraw any changing the menu selection.
Definition: mutt_menu.h:44
#define mutt_b2s(buf)
Definition: buffer.h:41
WHERE char * C_NewsServer
Config: (nntp) Url of the news server.
Definition: globals.h:136
View the message.
Definition: protos.h:56
void mutt_alias_create(struct Envelope *cur, struct AddressList *al)
Create a new Alias from an Envelope or an Address.
Definition: alias.c:361
void mutt_refresh(void)
Force a refresh of the screen.
Definition: curs_lib.c:94
void nm_db_longrun_done(struct Mailbox *m)
Finish a long transaction.
Definition: nm_db.c:305
Edit the message.
Definition: protos.h:57
static int ci_first_message(void)
Get index of first new message.
Definition: index.c:339
void mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:314
#define mutt_mktemp(buf, buflen)
Definition: muttlib.h:76
void mutt_sort_headers(struct Context *ctx, bool init)
Sort emails by their headers.
Definition: sort.c:362
#define CAN_COLLAPSE(email)
Definition: index.c:143
WHERE bool OptAttachMsg
(pseudo) used by attach-message
Definition: options.h:31
#define REDRAW_STATUS
Redraw the status bar.
Definition: mutt_menu.h:46
Messages to be deleted.
Definition: mutt.h:103
A mailbox.
Definition: mailbox.h:92
#define PATH_MAX
Definition: mutt.h:51
struct MuttWindow * MuttIndexWindow
Index Window.
Definition: mutt_window.c:40
int mutt_mailbox_check(struct Mailbox *m_cur, int force)
Check all all Mailboxes for new mail.
Definition: mutt_mailbox.c:126
int top
entry that is the top of the current page
Definition: mutt_menu.h:110
Nondestructive flags change (IMAP)
Definition: mx.h:75
int log_queue_save(FILE *fp)
Save the contents of the queue to a temporary file.
Definition: logging.c:377
#define UNREAD(email)
Definition: index.c:140
int nntp_check_msgid(struct Mailbox *m, const char *msgid)
Fetch article by Message-ID.
Definition: nntp.c:2222
WHERE bool C_Resolve
Config: Move to the next email whenever a command modifies an email.
Definition: globals.h:257
void nm_query_window_forward(void)
Function to move the current search window forward in time.
Tagged messages.
Definition: mutt.h:108
char * data
Pointer to data.
Definition: buffer.h:35
WHERE char * C_NewMailCommand
Config: External command to run when new mail arrives.
Definition: globals.h:144
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:750
#define mutt_next_thread(e)
Definition: mutt_thread.h:65
New messages.
Definition: mutt.h:98
Messages that have been read.
Definition: mutt.h:101
Not object-related.
Definition: notify_type.h:32
bool collapsed
Is this message part of a collapsed thread?
Definition: email.h:75
bool quiet
Inhibit status messages?
Definition: mailbox.h:129
int mx_tags_edit(struct Mailbox *m, const char *tags, char *buf, size_t buflen)
start the tag editor of the mailbox
Definition: mx.c:1190
int msg_tagged
How many messages are tagged?
Definition: mailbox.h:108
#define CHECK_READONLY
Is the mailbox readonly?
Definition: index.c:155
int vnum
Virtual message number.
Definition: email.h:89
#define SEND_NEWS
Reply to a news article.
Definition: send.h:101
int ci_send_message(SendFlags flags, struct Email *e_templ, const char *tempfile, struct Context *ctx, struct EmailList *el)
Send an email.
Definition: send.c:1837
void nntp_mailbox(struct Mailbox *m, char *buf, size_t buflen)
Get first newsgroup with new messages.
Definition: newsrc.c:1335
WHERE bool OptSearchInvalid
(pseudo) used to invalidate the search pat
Definition: options.h:50
AclFlags rights
ACL bits, see AclFlags.
Definition: mailbox.h:132
int mutt_messages_in_thread(struct Mailbox *m, struct Email *e, int flag)
Count the messages in a thread.
Definition: mutt_thread.c:1395
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
void update_index(struct Menu *menu, struct Context *ctx, int check, int oldcount, int index_hint)
Update the index.
Definition: index.c:569
struct Notify * notify
Notifications handler.
Definition: neomutt.h:37
WHERE bool OptRedrawTree
(pseudo) redraw the thread tree
Definition: options.h:48
#define STAILQ_NEXT(elm, field)
Definition: queue.h:398
#define SEND_REPLY
Reply to sender.
Definition: send.h:87
#define MUTT_PAGER_LOGS
Logview mode.
Definition: pager.h:57
struct Hash * mutt_make_id_hash(struct Mailbox *m)
Create a Hash Table for message-ids.
Definition: mutt_thread.c:1437
NNTP-specific Mailbox data -.
Definition: nntp.h:138
int mutt_window_mvaddstr(struct MuttWindow *win, int row, int col, const char *str)
Move the cursor and write a fixed string to a Window.
Definition: mutt_window.c:202
char * driver_tags_get_with_hidden(struct TagHead *head)
Get tags with hiddens.
Definition: tags.c:154
int mutt_window_move(struct MuttWindow *win, int row, int col)
Move the cursor in a Window.
Definition: mutt_window.c:188
void mutt_help(int menu)
Display the help menu.
Definition: help.c:438
void mutt_clear_pager_position(void)
Reset the pager&#39;s viewing position.
Definition: pager.c:1926
int(* menu_color)(int line)
Calculate the colour for a line of the menu.
Definition: mutt_menu.h:146
#define MUTT_MAILBOX_CHECK_FORCE
Definition: mutt_mailbox.h:17
int max
the number of entries in the menu
Definition: mutt_menu.h:88
&#39;Notmuch&#39; (virtual) Mailbox type
Definition: mailbox.h:53
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: ncrypt.h:134
WHERE bool C_DeleteUntag
Config: Untag messages when they are marked for deletion.
Definition: globals.h:220
struct Buffer * pathbuf
Definition: mailbox.h:94
MuttRedrawFlags redraw
when to redraw the screen
Definition: mutt_menu.h:89
static int main_change_folder(struct Menu *menu, int op, struct Mailbox *m, char *buf, size_t buflen, int *oldcount, int *index_hint)
Change to a different mailbox.
Definition: index.c:618
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:112
char * mutt_str_strcat(char *buf, size_t buflen, const char *s)
Concatenate two strings.
Definition: string.c:395
void ci_bounce_message(struct Mailbox *m, struct EmailList *el)
Bounce an email.
Definition: commands.c:389
int imap_check_mailbox(struct Mailbox *m, bool force)
use the NOOP or IDLE command to poll for new mail
Definition: imap.c:1186
int offset
row offset within the window to start the index
Definition: mutt_menu.h:91
#define SEND_GROUP_REPLY
Reply to all.
Definition: send.h:88
char * data
Definition: list.h:35
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:323
int mutt_label_message(struct Mailbox *m, struct EmailList *el)
Let the user label a message.
Definition: mutt_header.c:124
Log at debug level 1.
Definition: logging.h:56
bool flagged
Marked important?
Definition: email.h:45
void mutt_browser_select_dir(const char *f)
Remember the last directory selected.
Definition: browser.c:1112
#define mutt_curs_set(x)
Definition: mutt_curses.h:94
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:582
int mx_mbox_sync(struct Mailbox *m, int *index_hint)
Save changes to mailbox.
Definition: mx.c:826
#define REDRAW_INDEX
Redraw the index.
Definition: mutt_menu.h:42
int nntp_check_children(struct Mailbox *m, const char *msgid)
Fetch children of article with the Message-ID.
Definition: nntp.c:2292
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
bool collapsed
Are all threads collapsed?
Definition: context.h:48
bool deleted
Email is deleted.
Definition: email.h:47
#define mutt_error(...)
Definition: logging.h:84
static const struct Mapping IndexHelp[]
Definition: index.c:113
void mutt_query_menu(char *buf, size_t buflen)
Show the user the results of a Query.
Definition: query.c:650
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:628
NeoMutt is about to close.
Definition: neomutt.h:50
void mutt_timeout_hook(void)
Execute any timeout hooks.
Definition: hook.c:806
int mutt_select_sort(bool reverse)
Ask the user for a sort method.
Definition: commands.c:735
int index
The absolute (unsorted) message number.
Definition: email.h:87
#define FREE(x)
Definition: memory.h:40
int mutt_display_message(struct Mailbox *m, struct Email *e)
Display a message in the pager.
Definition: commands.c:195
void crypt_extract_keys_from_messages(struct Mailbox *m, struct EmailList *el)
Extract keys from a message.
Definition: crypt.c:855
#define MUTT_ACL_SEEN
Change the &#39;seen&#39; status of a message.
Definition: mailbox.h:84
#define STAILQ_EMPTY(head)
Definition: queue.h:346
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:322
WHERE bool C_AutoTag
Config: Automatically apply actions to all tagged messages.
Definition: globals.h:213
bool C_PgpAutoDecode
Config: Automatically decrypt PGP messages.
Definition: index.c:109
struct MuttWindow * MuttMessageWindow
Message Window.
Definition: mutt_window.c:42
int nm_read_entire_thread(struct Mailbox *m, struct Email *e)
Get the entire thread of an email.
bool C_ChangeFolderNext
Config: Suggest the next folder, rather than the first when using &#39;<change-folder>&#39;.
Definition: index.c:104
Messages to be un-tagged.
Definition: mutt.h:109
bool changed
Mailbox has been modified.
Definition: mailbox.h:125
void nm_db_longrun_init(struct Mailbox *m, bool writable)
Start a long transaction.
Definition: nm_db.c:290
int mutt_change_flag(struct Mailbox *m, struct EmailList *el, bool bf)
Change the flag on a Message.
Definition: flags.c:433
void ctx_free(struct Context **ptr)
Free a Context.
Definition: context.c:48
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
int bool_str_toggle(struct ConfigSet *cs, const char *name, struct Buffer *err)
Toggle the value of a bool.
Definition: bool.c:240
New mail received in Mailbox.
Definition: mx.h:72
bool mx_tags_is_supported(struct Mailbox *m)
return true if mailbox support tagging
Definition: mx.c:1227
#define CHECK_MSGCOUNT
Are there any messages?
Definition: index.c:153
#define SEND_GROUP_CHAT_REPLY
Reply to all recipients preserving To/Cc.
Definition: send.h:100
bool mutt_edit_content_type(struct Email *e, struct Body *b, FILE *fp)
Edit the content type of an attachment.
Definition: commands.c:1203
int current
current entry
Definition: mutt_menu.h:87
int el_add_tagged(struct EmailList *el, struct Context *ctx, struct Email *e, bool use_tagged)
Get a list of the tagged Emails.
Definition: context.c:357
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:584
A List node for strings.
Definition: list.h:33
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:283
Mailbox was reopened.
Definition: mx.h:74
int mutt_resend_message(FILE *fp, struct Context *ctx, struct Email *e_cur)
Resend an email.
Definition: send.c:1467
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:52
bool notify_send(struct Notify *notify, int type, int subtype, intptr_t data)
Send out a notification message.
Definition: notify.c:145
char * pattern
Limit pattern string.
Definition: context.h:39
Sort by email threads.
Definition: sort.h:56
int mutt_search_command(int cur, int op)
Perform a search.
Definition: pattern.c:2559
#define STAILQ_FIRST(head)
Definition: queue.h:348
#define WithCrypto
Definition: ncrypt.h:160
#define SORT_MASK
Mask for the sort id.
Definition: sort.h:85
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:43
char * help
quickref for the current menu
Definition: mutt_menu.h:85
int mutt_ev_message(struct Mailbox *m, struct EmailList *el, enum EvMessage action)
Edit or view a message.
Definition: editmsg.c:262
int mutt_system(const char *cmd)
Run an external command.
Definition: system.c:51
#define mutt_buffer_enter_fname(prompt, fname, mailbox)
Definition: curs_lib.h:82
#define mutt_uncollapse_thread(ctx, e)
Definition: mutt_thread.h:58
Log at debug level 3.
Definition: logging.h:58
struct Hash * id_hash
Hash table by msg id.
Definition: mailbox.h:138
bool message_is_tagged(struct Context *ctx, int index)
Is a message in the index tagged (and within limit)
Definition: context.c:343
#define REDRAW_CURRENT
Redraw the current line of the menu.
Definition: mutt_menu.h:45
struct Email * last_tag
Last tagged msg (used to link threads)
Definition: context.h:41
void mutt_draw_tree(struct Context *ctx)
Draw a tree of threaded emails.
Definition: mutt_thread.c:288
void nm_db_debug_check(struct Mailbox *m)
Check if the database is open.
Definition: nm_db.c:323
#define mutt_previous_subthread(e)
Definition: mutt_thread.h:68
struct NntpAccountData * CurrentNewsSrv
Current NNTP news server.
Definition: nntp.c:75
const char * mutt_make_version(void)
Generate the NeoMutt version string.
Definition: muttlib.c:1516
WHERE bool C_ArrowCursor
Config: Use an arrow &#39;->&#39; instead of highlighting in the index.
Definition: globals.h:204

+ Here is the caller graph for this function:

void mutt_set_header_color ( struct Mailbox m,
struct Email e 
)

Select a colour for a message.

Parameters
mMailbox
eCurrent Email

Definition at line 3672 of file index.c.

3673 {
3674  if (!e)
3675  return;
3676 
3677  struct ColorLine *color = NULL;
3678  struct PatternCache cache = { 0 };
3679 
3680  STAILQ_FOREACH(color, &ColorIndexList, entries)
3681  {
3683  MUTT_MATCH_FULL_ADDRESS, m, e, &cache))
3684  {
3685  e->pair = color->pair;
3686  return;
3687  }
3688  }
3690 }
Plain text.
Definition: mutt_curses.h:131
int mutt_pattern_exec(struct Pattern *pat, PatternExecFlags flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
Match a pattern against an email header.
Definition: pattern.c:2002
#define SLIST_FIRST(head)
Definition: queue.h:229
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
int ColorDefs[MT_COLOR_MAX]
Array of all fixed colours, see enum ColorId.
Definition: color.c:55
#define MUTT_MATCH_FULL_ADDRESS
Match the full address.
Definition: pattern.h:75
Cache commonly-used patterns.
Definition: pattern.h:85
struct ColorLineHead ColorIndexList
List of default colours applied to the index.
Definition: color.c:61
int pair
Color-pair to use when displaying in the index.
Definition: email.h:81
A regular expression and a color to highlight a line.
Definition: mutt_curses.h:180
struct PatternHead * color_pattern
compiled pattern to speed up index color calculation
Definition: mutt_curses.h:185

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int mutt_reply_observer ( struct NotifyCallback nc)

Listen for config changes to "reply_regex" - Implements observer_t()

Definition at line 3695 of file index.c.

3696 {
3697  if (!nc)
3698  return -1;
3699 
3700  struct EventConfig *ec = (struct EventConfig *) nc->event;
3701 
3702  if (mutt_str_strcmp(ec->name, "reply_regex") != 0)
3703  return 0;
3704 
3705  if (!Context || !Context->mailbox)
3706  return 0;
3707 
3708  regmatch_t pmatch[1];
3709 
3710  for (int i = 0; i < Context->mailbox->msg_count; i++)
3711  {
3712  struct Envelope *e = Context->mailbox->emails[i]->env;
3713  if (!e || !e->subject)
3714  continue;
3715 
3716  if (mutt_regex_capture(C_ReplyRegex, e->subject, 1, pmatch))
3717  {
3718  e->real_subj = e->subject + pmatch[0].rm_eo;
3719  continue;
3720  }
3721 
3722  e->real_subj = e->subject;
3723  }
3724 
3725  OptResortInit = true; /* trigger a redraw of the index */
3726  return 0;
3727 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:110
The "current" mailbox.
Definition: context.h:36
int msg_count
Total number of messages.
Definition: mailbox.h:102
A config-change event.
Definition: set.h:199
char * real_subj
Offset of the real subject.
Definition: envelope.h:67
intptr_t event
Send: event data.
Definition: observer.h:46
struct Mailbox * mailbox
Definition: context.h:50
struct Envelope * env
Envelope information.
Definition: email.h:91
struct Regex * C_ReplyRegex
Config: Regex to match message reply subjects like "re: ".
Definition: email_globals.c:37
WHERE bool OptResortInit
(pseudo) used to force the next resort to be from scratch
Definition: options.h:49
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:594
char * subject
Email&#39;s subject.
Definition: envelope.h:66
const char * name
Name of config item that changed.
Definition: set.h:203
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:615
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:

Variable Documentation

bool C_ChangeFolderNext

Config: Suggest the next folder, rather than the first when using '<change-folder>'.

Definition at line 104 of file index.c.

bool C_CollapseAll

Config: Collapse all threads when entering a folder.

Definition at line 105 of file index.c.

bool C_CollapseFlagged

Config: Prevent the collapse of threads with flagged emails.

Definition at line 106 of file index.c.

bool C_CollapseUnread

Config: Prevent the collapse of threads with unread emails.

Definition at line 107 of file index.c.

char* C_MarkMacroPrefix

Config: Prefix for macros using '<mark-message>'.

Definition at line 108 of file index.c.

bool C_PgpAutoDecode

Config: Automatically decrypt PGP messages.

Definition at line 109 of file index.c.

bool C_UncollapseJump

Config: When opening a thread, jump to the next unread message.

Definition at line 110 of file index.c.

bool C_UncollapseNew

Config: Open collapsed threads when new mail arrives.

Definition at line 111 of file index.c.

const struct Mapping IndexHelp[]
static
Initial value:
= {
{ N_("Quit"), OP_QUIT },
{ N_("Del"), OP_DELETE },
{ N_("Undel"), OP_UNDELETE },
{ N_("Save"), OP_SAVE },
{ N_("Mail"), OP_MAIL },
{ N_("Reply"), OP_REPLY },
{ N_("Group"), OP_GROUP_REPLY },
{ N_("Help"), OP_HELP },
{ NULL, 0 },
}
#define N_(a)
Definition: message.h:32

Definition at line 113 of file index.c.

struct Mapping IndexNewsHelp[]
Initial value:
= {
{ N_("Quit"), OP_QUIT },
{ N_("Del"), OP_DELETE },
{ N_("Undel"), OP_UNDELETE },
{ N_("Save"), OP_SAVE },
{ N_("Post"), OP_POST },
{ N_("Followup"), OP_FOLLOWUP },
{ N_("Catchup"), OP_CATCHUP },
{ N_("Help"), OP_HELP },
{ NULL, 0 },
}
#define N_(a)
Definition: message.h:32

Definition at line 126 of file index.c.