NeoMutt  2018-07-16 +1360-3df4a2
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 <stdio.h>
#include <string.h>
#include "mutt/mutt.h"
#include "config/lib.h"
#include "email/lib.h"
#include "conn/conn.h"
#include "mutt.h"
#include "index.h"
#include "account.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 "mailbox.h"
#include "mutt_account.h"
#include "mutt_curses.h"
#include "mutt_header.h"
#include "mutt_logging.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>

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...
 
bool mutt_reply_listener (const struct ConfigSet *cs, struct HashElem *he, const char *name, enum ConfigEvent ev)
 Listen for config changes to "reply_regex" - Implements cs_listener() 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 136 of file index.c.

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

Definition at line 137 of file index.c.

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

Definition at line 138 of file index.c.

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

Definition at line 140 of file index.c.

#define CHECK_NO_FLAGS   0

No flags are set.

Definition at line 148 of file index.c.

#define CHECK_IN_MAILBOX   (1 << 0)

Is there a mailbox open?

Definition at line 149 of file index.c.

#define CHECK_MSGCOUNT   (1 << 1)

Are there any messages?

Definition at line 150 of file index.c.

#define CHECK_VISIBLE   (1 << 2)

Is the selected message visible in the index?

Definition at line 151 of file index.c.

#define CHECK_READONLY   (1 << 3)

Is the mailbox readonly?

Definition at line 152 of file index.c.

#define CHECK_ATTACH   (1 << 4)

Is the user in message-attach mode?

Definition at line 153 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 147 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 163 of file index.c.

164 {
165  bool result = true;
166 
167  if (checks & (CHECK_MSGCOUNT | CHECK_VISIBLE | CHECK_READONLY))
168  checks |= CHECK_IN_MAILBOX;
169 
170  if ((checks & CHECK_IN_MAILBOX) && !Context)
171  {
172  mutt_error(_("No mailbox is open"));
173  result = false;
174  }
175 
176  if (result && (checks & CHECK_MSGCOUNT) && (Context->mailbox->msg_count == 0))
177  {
178  mutt_error(_("There are no messages"));
179  result = false;
180  }
181 
182  if (result && (checks & CHECK_VISIBLE) && (menu->current >= Context->mailbox->vcount))
183  {
184  mutt_error(_("No visible messages"));
185  result = false;
186  }
187 
188  if (result && (checks & CHECK_READONLY) && Context->mailbox->readonly)
189  {
190  mutt_error(_("Mailbox is read-only"));
191  result = false;
192  }
193 
194  if (result && (checks & CHECK_ATTACH) && OptAttachMsg)
195  {
196  mutt_error(_("Function not permitted in attach-message mode"));
197  result = false;
198  }
199 
200  if (!result)
201  mutt_flushinp();
202 
203  return result;
204 }
The "current" mailbox.
Definition: context.h:37
int msg_count
total number of messages
Definition: mailbox.h:93
void mutt_flushinp(void)
Empty all the keyboard buffers.
Definition: curs_lib.c:753
#define CHECK_ATTACH
Is the user in message-attach mode?
Definition: index.c:153
#define _(a)
Definition: message.h:28
int vcount
the number of virtual messages
Definition: mailbox.h:103
#define CHECK_VISIBLE
Is the selected message visible in the index?
Definition: index.c:151
struct Mailbox * mailbox
Definition: context.h:51
#define CHECK_IN_MAILBOX
Is there a mailbox open?
Definition: index.c:149
bool readonly
don&#39;t allow changes to the mailbox
Definition: mailbox.h:120
WHERE bool OptAttachMsg
(pseudo) used by attach-message
Definition: options.h:31
#define CHECK_READONLY
Is the mailbox readonly?
Definition: index.c:152
#define mutt_error(...)
Definition: logging.h:88
#define CHECK_MSGCOUNT
Are there any messages?
Definition: index.c:150
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 213 of file index.c.

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

+ 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 239 of file index.c.

240 {
241  struct Email *e = NULL, *base = NULL;
242  struct MuttThread *thread = NULL, *top = NULL;
243  int final;
244 
245  if (!Context || (Context->mailbox->msg_count == 0))
246  return;
247 
248  /* Figure out what the current message would be after folding / unfolding,
249  * so that we can restore the cursor in a sane way afterwards. */
250  if (CUR_EMAIL->collapsed && toggle)
252  else if (CAN_COLLAPSE(CUR_EMAIL))
254  else
255  final = CUR_EMAIL->virtual;
256 
257  base = Context->mailbox->emails[Context->mailbox->v2r[final]];
258 
259  /* Iterate all threads, perform collapse/uncollapse as needed */
260  top = Context->tree;
261  Context->collapsed = toggle ? !Context->collapsed : true;
262  while ((thread = top))
263  {
264  while (!thread->message)
265  thread = thread->child;
266  e = thread->message;
267 
268  if (e->collapsed != Context->collapsed)
269  {
270  if (e->collapsed)
272  else if (CAN_COLLAPSE(e))
274  }
275  top = top->next;
276  }
277 
278  /* Restore the cursor */
280  for (int j = 0; j < Context->mailbox->vcount; j++)
281  {
282  if (Context->mailbox->emails[Context->mailbox->v2r[j]]->index == base->index)
283  {
284  menu->current = j;
285  break;
286  }
287  }
288 
290 }
struct Email ** emails
Definition: mailbox.h:100
The "current" mailbox.
Definition: context.h:37
int msg_count
total number of messages
Definition: mailbox.h:93
The envelope/body of an email.
Definition: email.h:37
struct MuttThread * tree
top of thread tree
Definition: context.h:43
#define mutt_collapse_thread(ctx, cur)
Definition: mutt_thread.h:56
int vcount
the number of virtual messages
Definition: mailbox.h:103
struct Mailbox * mailbox
Definition: context.h:51
#define CUR_EMAIL
Definition: index.c:136
#define mutt_uncollapse_thread(ctx, cur)
Definition: mutt_thread.h:57
struct MuttThread * child
Definition: thread.h:45
#define CAN_COLLAPSE(email)
Definition: index.c:140
#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:76
struct Email * message
Definition: thread.h:48
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:102
#define REDRAW_INDEX
Redraw the index.
Definition: mutt_menu.h:42
bool collapsed
are all threads collapsed?
Definition: context.h:49
int index
the absolute (unsorted) message number
Definition: email.h:88
int current
current entry
Definition: mutt_menu.h:87
void mutt_set_virtual(struct Context *ctx)
Set the virtual index number of all the messages in a mailbox.
Definition: mutt_thread.c:1182

+ 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 298 of file index.c.

299 {
300  for (int i = msgno + 1; i < Context->mailbox->vcount; i++)
302  return i;
303  return -1;
304 }
struct Email ** emails
Definition: mailbox.h:100
The "current" mailbox.
Definition: context.h:37
int vcount
the number of virtual messages
Definition: mailbox.h:103
struct Mailbox * mailbox
Definition: context.h:51
int * v2r
mapping from virtual to real msgno
Definition: mailbox.h:102
bool deleted
Definition: email.h:45

+ 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 312 of file index.c.

313 {
314  for (int i = msgno - 1; i >= 0; i--)
316  return i;
317  return -1;
318 }
struct Email ** emails
Definition: mailbox.h:100
The "current" mailbox.
Definition: context.h:37
struct Mailbox * mailbox
Definition: context.h:51
int * v2r
mapping from virtual to real msgno
Definition: mailbox.h:102
bool deleted
Definition: email.h:45

+ 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 327 of file index.c.

328 {
329  if (!Context || (Context->mailbox->msg_count == 0))
330  return 0;
331 
332  int old = -1;
333  for (int i = 0; i < Context->mailbox->vcount; i++)
334  {
335  if (!Context->mailbox->emails[Context->mailbox->v2r[i]]->read &&
337  {
338  if (!Context->mailbox->emails[Context->mailbox->v2r[i]]->old)
339  return i;
340  else if (old == -1)
341  old = i;
342  }
343  }
344  if (old != -1)
345  return old;
346 
347  /* If C_Sort is reverse and not threaded, the latest message is first.
348  * If C_Sort is threaded, the latest message is first if exactly one
349  * of C_Sort and C_SortAux are reverse. */
350  if (((C_Sort & SORT_REVERSE) && ((C_Sort & SORT_MASK) != SORT_THREADS)) ||
351  (((C_Sort & SORT_MASK) == SORT_THREADS) && ((C_Sort ^ C_SortAux) & SORT_REVERSE)))
352  {
353  return 0;
354  }
355  else
356  {
357  return Context->mailbox->vcount ? Context->mailbox->vcount - 1 : 0;
358  }
359 
360  return 0;
361 }
struct Email ** emails
Definition: mailbox.h:100
The "current" mailbox.
Definition: context.h:37
int msg_count
total number of messages
Definition: mailbox.h:93
int vcount
the number of virtual messages
Definition: mailbox.h:103
bool read
Definition: email.h:51
struct Mailbox * mailbox
Definition: context.h:51
bool old
Definition: email.h:50
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:102
bool deleted
Definition: email.h:45
#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 371 of file index.c.

372 {
373  if (!m)
374  return -1;
375 
376  if (m->readonly)
377  {
378  mutt_error(_("Cannot toggle write on a readonly mailbox"));
379  return -1;
380  }
381 
382  if (m->dontwrite)
383  {
384  m->dontwrite = false;
385  mutt_message(_("Changes to folder will be written on folder exit"));
386  }
387  else
388  {
389  m->dontwrite = true;
390  mutt_message(_("Changes to folder will not be written"));
391  }
392 
393  return 0;
394 }
#define mutt_message(...)
Definition: logging.h:87
#define _(a)
Definition: message.h:28
bool readonly
don&#39;t allow changes to the mailbox
Definition: mailbox.h:120
bool dontwrite
don&#39;t write the mailbox on close
Definition: mailbox.h:116
#define mutt_error(...)
Definition: logging.h:88

+ 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 400 of file index.c.

401 {
402  struct Email *current = CUR_EMAIL;
403 
404  menu->current = -1;
405  mutt_sort_headers(Context, false);
406  /* Restore the current message */
407 
408  for (int i = 0; i < Context->mailbox->vcount; i++)
409  {
410  if (Context->mailbox->emails[Context->mailbox->v2r[i]] == current)
411  {
412  menu->current = i;
413  break;
414  }
415  }
416 
417  if (((C_Sort & SORT_MASK) == SORT_THREADS) && (menu->current < 0))
418  menu->current = mutt_parent_message(Context, current, false);
419 
420  if (menu->current < 0)
421  menu->current = ci_first_message();
422 
423  menu->redraw |= REDRAW_INDEX | REDRAW_STATUS;
424 }
struct Email ** emails
Definition: mailbox.h:100
The "current" mailbox.
Definition: context.h:37
The envelope/body of an email.
Definition: email.h:37
int vcount
the number of virtual messages
Definition: mailbox.h:103
struct Mailbox * mailbox
Definition: context.h:51
int mutt_parent_message(struct Context *ctx, struct Email *e, bool find_root)
Find the parent of a message.
Definition: mutt_thread.c:1136
#define CUR_EMAIL
Definition: index.c:136
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:327
void mutt_sort_headers(struct Context *ctx, bool init)
Sort emails by their headers.
Definition: sort.c:360
#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:102
#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 432 of file index.c.

433 {
434  struct Email **save_new = NULL;
435 
436  /* save the list of new messages */
437  if ((check != MUTT_REOPENED) && oldcount && (ctx->pattern || C_UncollapseNew))
438  {
439  save_new = mutt_mem_malloc(sizeof(struct Email *) * (ctx->mailbox->msg_count - oldcount));
440  for (int i = oldcount; i < ctx->mailbox->msg_count; i++)
441  save_new[i - oldcount] = ctx->mailbox->emails[i];
442  }
443 
444  /* Sort first to thread the new messages, because some patterns
445  * require the threading information.
446  *
447  * If the mailbox was reopened, need to rethread from scratch. */
448  mutt_sort_headers(ctx, (check == MUTT_REOPENED));
449 
450  if (ctx->pattern)
451  {
452  for (int i = (check == MUTT_REOPENED) ? 0 : oldcount; i < ctx->mailbox->msg_count; i++)
453  {
454  struct Email *e = NULL;
455 
456  if ((check != MUTT_REOPENED) && oldcount)
457  e = save_new[i - oldcount];
458  else
459  e = ctx->mailbox->emails[i];
460 
462  {
463  /* virtual will get properly set by mutt_set_virtual(), which
464  * is called by mutt_sort_headers() just below. */
465  e->virtual = 1;
466  e->limited = true;
467  }
468  }
469  /* Need a second sort to set virtual numbers and redraw the tree */
470  mutt_sort_headers(ctx, false);
471  }
472 
473  /* uncollapse threads with new mail */
474  if (C_UncollapseNew)
475  {
476  if (check == MUTT_REOPENED)
477  {
478  ctx->collapsed = false;
479 
480  for (struct MuttThread *h = ctx->tree; h; h = h->next)
481  {
482  struct MuttThread *j = h;
483  for (; !j->message; j = j->child)
484  ;
486  }
487  mutt_set_virtual(ctx);
488  }
489  else if (oldcount)
490  {
491  for (int j = 0; j < (ctx->mailbox->msg_count - oldcount); j++)
492  {
493  if (!ctx->pattern || save_new[j]->limited)
494  {
495  mutt_uncollapse_thread(ctx, save_new[j]);
496  }
497  }
498  mutt_set_virtual(ctx);
499  }
500  }
501 
502  FREE(&save_new);
503 }
struct Email ** emails
Definition: mailbox.h:100
struct MuttThread * next
Definition: thread.h:46
int msg_count
total number of messages
Definition: mailbox.h:93
The envelope/body of an email.
Definition: email.h:37
struct MuttThread * tree
top of thread tree
Definition: context.h:43
int virtual
virtual message number
Definition: email.h:90
Match the full address.
Definition: pattern.h:72
struct Mailbox * mailbox
Definition: context.h:51
bool limited
is this message in a limited view?
Definition: email.h:77
#define mutt_uncollapse_thread(ctx, cur)
Definition: mutt_thread.h:57
struct MuttThread * child
Definition: thread.h:45
void mutt_sort_headers(struct Context *ctx, bool init)
Sort emails by their headers.
Definition: sort.c:360
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:99
struct Email * message
Definition: thread.h:48
struct Pattern * limit_pattern
compiled limit pattern
Definition: context.h:41
An email conversation.
Definition: thread.h:34
bool collapsed
are all threads collapsed?
Definition: context.h:49
#define FREE(x)
Definition: memory.h:40
int mutt_pattern_exec(struct Pattern *pat, enum PatternExecFlag flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
Match a pattern against an email header.
Definition: pattern.c:1931
Mailbox was reopened.
Definition: mx.h:74
void mutt_set_virtual(struct Context *ctx)
Set the virtual index number of all the messages in a mailbox.
Definition: mutt_thread.c:1182
char * pattern
limit pattern string
Definition: context.h:40
bool C_UncollapseNew
Config: Open collapsed threads when new mail arrives.
Definition: index.c:108

+ 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 511 of file index.c.

512 {
513  /* We are in a limited view. Check if the new message(s) satisfy
514  * the limit criteria. If they do, set their virtual msgno so that
515  * they will be visible in the limited view */
516  if (ctx->pattern)
517  {
518  int padding = mx_msg_padding_size(ctx->mailbox);
519  for (int i = (check == MUTT_REOPENED) ? 0 : oldcount; i < ctx->mailbox->msg_count; i++)
520  {
521  if (!i)
522  {
523  ctx->mailbox->vcount = 0;
524  ctx->vsize = 0;
525  }
526 
528  ctx->mailbox, ctx->mailbox->emails[i], NULL))
529  {
530  assert(ctx->mailbox->vcount < ctx->mailbox->msg_count);
531  ctx->mailbox->emails[i]->virtual = ctx->mailbox->vcount;
532  ctx->mailbox->v2r[ctx->mailbox->vcount] = i;
533  ctx->mailbox->emails[i]->limited = true;
534  ctx->mailbox->vcount++;
535  struct Body *b = ctx->mailbox->emails[i]->content;
536  ctx->vsize += b->length + b->offset - b->hdr_offset + padding;
537  }
538  }
539  }
540 
541  /* if the mailbox was reopened, need to rethread from scratch */
542  mutt_sort_headers(ctx, (check == MUTT_REOPENED));
543 }
struct Email ** emails
Definition: mailbox.h:100
int msg_count
total number of messages
Definition: mailbox.h:93
int virtual
virtual message number
Definition: email.h:90
struct Body * content
list of MIME parts
Definition: email.h:93
LOFF_T offset
offset where the actual data begins
Definition: body.h:46
Match the full address.
Definition: pattern.h:72
int vcount
the number of virtual messages
Definition: mailbox.h:103
The body of an email.
Definition: body.h:34
struct Mailbox * mailbox
Definition: context.h:51
bool limited
is this message in a limited view?
Definition: email.h:77
off_t vsize
Definition: context.h:39
void mutt_sort_headers(struct Context *ctx, bool init)
Sort emails by their headers.
Definition: sort.c:360
LOFF_T length
length (in bytes) of attachment
Definition: body.h:47
struct Pattern * limit_pattern
compiled limit pattern
Definition: context.h:41
int * v2r
mapping from virtual to real msgno
Definition: mailbox.h:102
int mx_msg_padding_size(struct Mailbox *m)
Bytes of padding between messages - Wrapper for MxOps::msg_padding_size.
Definition: mx.c:1429
long hdr_offset
offset in stream where the headers begin.
Definition: body.h:42
int mutt_pattern_exec(struct Pattern *pat, enum PatternExecFlag flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
Match a pattern against an email header.
Definition: pattern.c:1931
Mailbox was reopened.
Definition: mx.h:74
char * pattern
limit pattern string
Definition: context.h:40

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

554 {
555  if (!menu || !ctx)
556  return;
557 
558  /* take note of the current message */
559  if (oldcount)
560  {
561  if (menu->current < ctx->mailbox->vcount)
562  menu->oldcurrent = index_hint;
563  else
564  oldcount = 0; /* invalid message number! */
565  }
566 
567  if ((C_Sort & SORT_MASK) == SORT_THREADS)
568  update_index_threaded(ctx, check, oldcount);
569  else
570  update_index_unthreaded(ctx, check, oldcount);
571 
572  menu->current = -1;
573  if (oldcount)
574  {
575  /* restore the current message to the message it was pointing to */
576  for (int i = 0; i < ctx->mailbox->vcount; i++)
577  {
578  if (ctx->mailbox->emails[ctx->mailbox->v2r[i]]->index == menu->oldcurrent)
579  {
580  menu->current = i;
581  break;
582  }
583  }
584  }
585 
586  if (menu->current < 0)
587  menu->current = ci_first_message();
588 }
struct Email ** emails
Definition: mailbox.h:100
int oldcurrent
for driver use only
Definition: mutt_menu.h:110
static void update_index_unthreaded(struct Context *ctx, int check, int oldcount)
Update the index (if unthreaded)
Definition: index.c:511
int vcount
the number of virtual messages
Definition: mailbox.h:103
struct Mailbox * mailbox
Definition: context.h:51
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:327
int * v2r
mapping from virtual to real msgno
Definition: mailbox.h:102
int index
the absolute (unsorted) message number
Definition: email.h:88
static void update_index_threaded(struct Context *ctx, int check, int oldcount)
Update the index (if threaded)
Definition: index.c:432
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 602 of file index.c.

604 {
605 #ifdef USE_NNTP
606  if (OptNews)
607  {
608  OptNews = false;
609  nntp_expand_path(buf, buflen, &CurrentNewsSrv->conn->account);
610  }
611  else
612 #endif
613  {
614  mx_path_canon(buf, buflen, C_Folder, NULL);
615  }
616 
617  enum MailboxType magic = mx_path_probe(buf, NULL);
618  if ((magic == MUTT_MAILBOX_ERROR) || (magic == MUTT_UNKNOWN))
619  {
620  // Try to see if the buffer matches a description before we bail.
621  // We'll receive a non-null pointer if there is a corresponding mailbox.
622  m = mutt_find_mailbox_desc(buf);
623  if (m)
624  {
625  magic = m->magic;
626  mutt_str_strfcpy(buf, m->path, buflen);
627  }
628  else
629  {
630  // Bail.
631  mutt_error(_("%s is not a mailbox"), buf);
632  return -1;
633  }
634  }
635 
636  /* keepalive failure in mutt_enter_fname may kill connection. #3028 */
637  if (Context && (Context->mailbox->path[0] == '\0'))
638  ctx_free(&Context);
639 
640  if (Context)
641  {
642  char *new_last_folder = NULL;
643 #ifdef USE_INOTIFY
644  int monitor_remove_rc = mutt_monitor_remove(NULL);
645 #endif
646 #ifdef USE_COMPRESSED
647  if (Context->mailbox->compress_info && (Context->mailbox->realpath[0] != '\0'))
648  new_last_folder = mutt_str_strdup(Context->mailbox->realpath);
649  else
650 #endif
651  new_last_folder = mutt_str_strdup(Context->mailbox->path);
652  *oldcount = Context ? Context->mailbox->msg_count : 0;
653 
654  int check = mx_mbox_close(&Context);
655  if (check != 0)
656  {
657 #ifdef USE_INOTIFY
658  if (monitor_remove_rc == 0)
659  mutt_monitor_add(NULL);
660 #endif
661  if ((check == MUTT_NEW_MAIL) || (check == MUTT_REOPENED))
662  update_index(menu, Context, check, *oldcount, *index_hint);
663 
664  FREE(&new_last_folder);
665  OptSearchInvalid = true;
666  menu->redraw |= REDRAW_INDEX | REDRAW_STATUS;
667  return 0;
668  }
669  FREE(&LastFolder);
670  LastFolder = new_last_folder;
671  }
673 
674  mutt_sleep(0);
675 
676  /* Note that menu->menu may be MENU_PAGER if the change folder
677  * operation originated from the pager.
678  *
679  * However, exec commands currently use CurrentMenu to determine what
680  * functions are available, which is automatically set by the
681  * mutt_push/pop_current_menu() functions. If that changes, the menu
682  * would need to be reset here, and the pager cleanup code after the
683  * switch statement would need to be run. */
684  mutt_folder_hook(buf, m ? m->desc : NULL);
685 
686  const int flags = (C_ReadOnly || (op == OP_MAIN_CHANGE_FOLDER_READONLY)
687 #ifdef USE_NOTMUCH
688  || (op == OP_MAIN_VFOLDER_FROM_QUERY_READONLY)
689 #endif
690  ) ?
691  MUTT_READONLY :
693 
694  bool free_m = false;
695  if (!m)
696  {
697  m = mx_path_resolve(buf);
698  free_m = true;
699  }
700  Context = mx_mbox_open(m, flags);
701  if (Context)
702  {
703  menu->current = ci_first_message();
704 #ifdef USE_INOTIFY
705  mutt_monitor_add(NULL);
706 #endif
707  }
708  else
709  {
710  menu->current = 0;
711  if (free_m)
712  mailbox_free(&m);
713  }
714 
715  if (((C_Sort & SORT_MASK) == SORT_THREADS) && C_CollapseAll)
716  collapse_all(menu, 0);
717 
718 #ifdef USE_SIDEBAR
720 #endif
721 
723  mutt_mailbox_check(Context ? Context->mailbox : NULL, MUTT_MAILBOX_CHECK_FORCE); /* force the mailbox check after we have changed the folder */
724  menu->redraw = REDRAW_FULL;
725  OptSearchInvalid = true;
726 
727  return 0;
728 }
#define MUTT_OPEN_NO_FLAGS
No flags are set.
Definition: mx.h:50
The "current" mailbox.
Definition: context.h:37
#define REDRAW_FULL
Redraw everything.
Definition: mutt_menu.h:47
int msg_count
total number of messages
Definition: mailbox.h:93
struct ConnAccount account
Definition: connection.h:36
int mx_mbox_close(struct Context **ptr)
Save changes and close mailbox.
Definition: mx.c:529
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:1267
char * desc
Definition: mailbox.h:88
int mutt_monitor_remove(struct Mailbox *m)
Remove a watch for a mailbox.
Definition: monitor.c:479
#define _(a)
Definition: message.h:28
struct Context * mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:246
WHERE char * LastFolder
Previously selected mailbox.
Definition: globals.h:54
bool C_CollapseAll
Config: Collapse all threads when entering a folder.
Definition: index.c:102
#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:441
static void collapse_all(struct Menu *menu, int toggle)
Collapse/uncollapse all threads.
Definition: index.c:239
void mutt_folder_hook(const char *path, const char *desc)
Perform a folder hook.
Definition: hook.c:374
void mutt_sleep(short s)
Sleep for a while.
Definition: muttlib.c:1471
struct Mailbox * mailbox
Definition: context.h:51
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:103
enum MailboxType magic
mailbox type
Definition: mailbox.h:106
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:141
WHERE bool C_ReadOnly
Config: Open folders in read-only mode.
Definition: globals.h:251
void ctx_free(struct Context **ctx)
Free a Context.
Definition: context.c:47
int mutt_mailbox_check(struct Mailbox *m_cur, int force)
Check all AllMailboxes for new mail.
Definition: mailbox.c:336
static int ci_first_message(void)
Get index of first new message.
Definition: index.c:327
#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:122
MailboxType
Supported mailbox formats.
Definition: magic.h:33
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:741
#define MUTT_MAILBOX_CHECK_FORCE
Definition: mailbox.h:170
Error occurred examining mailbox.
Definition: magic.h:35
WHERE bool OptSearchInvalid
(pseudo) used to invalidate the search pat
Definition: options.h:49
void update_index(struct Menu *menu, struct Context *ctx, int check, int oldcount, int index_hint)
Update the index.
Definition: index.c:553
void mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:459
void nntp_expand_path(char *buf, size_t buflen, struct ConnAccount *acct)
Make fully qualified url from newsgroup name.
Definition: newsrc.c:554
char path[PATH_MAX]
Definition: mailbox.h:85
MuttRedrawFlags redraw
when to redraw the screen
Definition: mutt_menu.h:89
struct Connection * conn
Definition: nntp.h:103
Mailbox wasn&#39;t recognised.
Definition: magic.h:36
#define REDRAW_INDEX
Redraw the index.
Definition: mutt_menu.h:42
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:383
#define mutt_error(...)
Definition: logging.h:88
void * compress_info
compressed mbox module private data
Definition: mailbox.h:125
#define FREE(x)
Definition: memory.h:40
struct Mailbox * mx_path_resolve(const char *path)
XXX.
Definition: mx.c:1506
char realpath[PATH_MAX]
used for duplicate detection, context comparison, and the sidebar
Definition: mailbox.h:86
New mail received in Mailbox.
Definition: mx.h:72
int current
current entry
Definition: mutt_menu.h:87
enum MailboxType mx_path_probe(const char *path, struct stat *st)
Find a mailbox that understands a path.
Definition: mx.c:1207
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:42
struct NntpAccountData * CurrentNewsSrv
Current NNTP news server.
Definition: nntp.c:79
struct Mailbox * mutt_find_mailbox_desc(const char *desc)
Find the mailbox with a given description.
Definition: mailbox.c:292

+ 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 733 of file index.c.

734 {
735  if (!Context || !menu || (line < 0) || (line >= Context->mailbox->email_max))
736  return;
737 
738  struct Email *e = Context->mailbox->emails[Context->mailbox->v2r[line]];
739  if (!e)
740  return;
741 
743  struct MuttThread *tmp = NULL;
744 
745  if (((C_Sort & SORT_MASK) == SORT_THREADS) && e->tree)
746  {
747  flags |= MUTT_FORMAT_TREE; /* display the thread tree */
748  if (e->display_subject)
749  flags |= MUTT_FORMAT_FORCESUBJ;
750  else
751  {
752  const int reverse = C_Sort & SORT_REVERSE;
753  int edgemsgno;
754  if (reverse)
755  {
756  if (menu->top + menu->pagelen > menu->max)
757  edgemsgno = Context->mailbox->v2r[menu->max - 1];
758  else
759  edgemsgno = Context->mailbox->v2r[menu->top + menu->pagelen - 1];
760  }
761  else
762  edgemsgno = Context->mailbox->v2r[menu->top];
763 
764  for (tmp = e->thread->parent; tmp; tmp = tmp->parent)
765  {
766  if (!tmp->message)
767  continue;
768 
769  /* if no ancestor is visible on current screen, provisionally force
770  * subject... */
771  if (reverse ? (tmp->message->msgno > edgemsgno) : (tmp->message->msgno < edgemsgno))
772  {
773  flags |= MUTT_FORMAT_FORCESUBJ;
774  break;
775  }
776  else if (tmp->message->virtual >= 0)
777  break;
778  }
779  if (flags & MUTT_FORMAT_FORCESUBJ)
780  {
781  for (tmp = e->thread->prev; tmp; tmp = tmp->prev)
782  {
783  if (!tmp->message)
784  continue;
785 
786  /* ...but if a previous sibling is available, don't force it */
787  if (reverse ? (tmp->message->msgno > edgemsgno) : (tmp->message->msgno < edgemsgno))
788  break;
789  else if (tmp->message->virtual >= 0)
790  {
791  flags &= ~MUTT_FORMAT_FORCESUBJ;
792  break;
793  }
794  }
795  }
796  }
797  }
798 
800  Context->mailbox, e, flags);
801 }
struct Email ** emails
Definition: mailbox.h:100
The "current" mailbox.
Definition: context.h:37
uint8_t MuttFormatFlags
Flags for mutt_expando_format(), e.g. MUTT_FORMAT_FORCESUBJ.
Definition: format_flags.h:29
#define NONULL(x)
Definition: string2.h:36
The envelope/body of an email.
Definition: email.h:37
#define MUTT_FORMAT_FORCESUBJ
Print the subject even if unchanged.
Definition: format_flags.h:31
struct MuttThread * thread
Definition: email.h:97
int virtual
virtual message number
Definition: email.h:90
#define MUTT_FORMAT_ARROWCURSOR
Reserve space for arrow_cursor.
Definition: format_flags.h:35
bool display_subject
used for threading
Definition: email.h:57
struct MuttThread * parent
Definition: thread.h:44
struct MuttThread * prev
Definition: thread.h:47
struct Mailbox * mailbox
Definition: context.h:51
#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:1466
WHERE short C_Sort
Config: Sort method for the index.
Definition: sort.h:58
const char * line
Definition: common.c:35
int email_max
number of pointers in emails
Definition: mailbox.h:101
WHERE char * C_IndexFormat
Config: printf-like format string for the index menu (emails)
Definition: globals.h:115
int top
entry that is the top of the current page
Definition: mutt_menu.h:109
int pagelen
number of entries per screen
Definition: mutt_menu.h:92
char * tree
character string to print thread tree
Definition: email.h:96
struct Email * message
Definition: thread.h:48
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:102
#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:89

+ 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 806 of file index.c.

807 {
808  if (!Context || (line < 0))
809  return 0;
810 
811  struct Email *e = Context->mailbox->emails[Context->mailbox->v2r[line]];
812 
813  if (e && e->pair)
814  return e->pair;
815 
817  if (e)
818  return e->pair;
819 
820  return 0;
821 }
struct Email ** emails
Definition: mailbox.h:100
The "current" mailbox.
Definition: context.h:37
The envelope/body of an email.
Definition: email.h:37
struct Mailbox * mailbox
Definition: context.h:51
const char * line
Definition: common.c:35
void mutt_set_header_color(struct Mailbox *m, struct Email *e)
Select a colour for a message.
Definition: index.c:3612
int * v2r
mapping from virtual to real msgno
Definition: mailbox.h:102
int pair
color-pair to use when displaying in the index
Definition: email.h:82

+ 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 835 of file index.c.

836 {
837  size_t i = 0;
838  size_t offset = 0;
839  bool found = false;
840  size_t chunks = 0;
841  size_t len = 0;
842 
843  struct Syntax
844  {
845  int color;
846  int first;
847  int last;
848  } *syntax = NULL;
849 
850  if (!buf || !stdscr)
851  return;
852 
853  do
854  {
855  struct ColorLine *cl = NULL;
856  found = false;
857 
858  if (!buf[offset])
859  break;
860 
861  /* loop through each "color status regex" */
862  STAILQ_FOREACH(cl, &ColorStatusList, entries)
863  {
864  regmatch_t pmatch[cl->match + 1];
865 
866  if (regexec(&cl->regex, buf + offset, cl->match + 1, pmatch, 0) != 0)
867  continue; /* regex doesn't match the status bar */
868 
869  int first = pmatch[cl->match].rm_so + offset;
870  int last = pmatch[cl->match].rm_eo + offset;
871 
872  if (first == last)
873  continue; /* ignore an empty regex */
874 
875  if (!found)
876  {
877  chunks++;
878  mutt_mem_realloc(&syntax, chunks * sizeof(struct Syntax));
879  }
880 
881  i = chunks - 1;
882  if (!found || (first < syntax[i].first) ||
883  ((first == syntax[i].first) && (last > syntax[i].last)))
884  {
885  syntax[i].color = cl->pair;
886  syntax[i].first = first;
887  syntax[i].last = last;
888  }
889  found = true;
890  }
891 
892  if (syntax)
893  {
894  offset = syntax[i].last;
895  }
896  } while (found);
897 
898  /* Only 'len' bytes will fit into 'cols' screen columns */
899  len = mutt_wstr_trunc(buf, buflen, cols, NULL);
900 
901  offset = 0;
902 
903  if ((chunks > 0) && (syntax[0].first > 0))
904  {
905  /* Text before the first highlight */
906  addnstr(buf, MIN(len, syntax[0].first));
907  attrset(ColorDefs[MT_COLOR_STATUS]);
908  if (len <= syntax[0].first)
909  goto dsl_finish; /* no more room */
910 
911  offset = syntax[0].first;
912  }
913 
914  for (i = 0; i < chunks; i++)
915  {
916  /* Highlighted text */
917  attrset(syntax[i].color);
918  addnstr(buf + offset, MIN(len, syntax[i].last) - offset);
919  if (len <= syntax[i].last)
920  goto dsl_finish; /* no more room */
921 
922  size_t next;
923  if ((i + 1) == chunks)
924  {
925  next = len;
926  }
927  else
928  {
929  next = MIN(len, syntax[i + 1].first);
930  }
931 
932  attrset(ColorDefs[MT_COLOR_STATUS]);
933  offset = syntax[i].last;
934  addnstr(buf + offset, next - offset);
935 
936  offset = next;
937  if (offset >= len)
938  goto dsl_finish; /* no more room */
939  }
940 
941  attrset(ColorDefs[MT_COLOR_STATUS]);
942  if (offset < len)
943  {
944  /* Text after the last highlight */
945  addnstr(buf + offset, len - offset);
946  }
947 
948  int width = mutt_strwidth(buf);
949  if (width < cols)
950  {
951  /* Pad the rest of the line with whitespace */
952  mutt_paddstr(cols - width, "");
953  }
954 dsl_finish:
955  FREE(&syntax);
956 }
int first
Definition: pager.c:166
#define MIN(a, b)
Definition: memory.h:31
int last
Definition: pager.c:167
Highlighting for a line of text.
Definition: pager.c:163
int color
Definition: pager.c:165
void mutt_paddstr(int n, const char *s)
Display a string on screen, padded if necessary.
Definition: curs_lib.c:1083
int match
which substringmap 0 for old behaviour
Definition: mutt_curses.h:181
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:124
int mutt_strwidth(const char *s)
Measure a string&#39;s width in screen cells.
Definition: curs_lib.c:1176
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:1126
#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:52
LOFF_T offset
where in the stream does this message begin?
Definition: email.h:86
regex_t regex
Definition: mutt_curses.h:180
#define FREE(x)
Definition: memory.h:40
Status bar.
Definition: mutt_curses.h:128
struct ColorLineHead ColorStatusList
List of colours applied to the status bar.
Definition: color.c:61
A regular expression and a color to highlight a line.
Definition: mutt_curses.h:178

+ 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 961 of file index.c.

962 {
963  if (menu->redraw & REDRAW_FULL)
964  {
965  menu_redraw_full(menu);
966  mutt_show_error();
967  }
968 
969 #ifdef USE_SIDEBAR
970  if (menu->redraw & REDRAW_SIDEBAR)
971  menu_redraw_sidebar(menu);
972 #endif
973 
974  if (Context && Context->mailbox->emails && !(menu->current >= Context->mailbox->vcount))
975  {
976  menu_check_recenter(menu);
977 
978  if (menu->redraw & REDRAW_INDEX)
979  {
980  menu_redraw_index(menu);
981  menu->redraw |= REDRAW_STATUS;
982  }
983  else if (menu->redraw & (REDRAW_MOTION_RESYNC | REDRAW_MOTION))
984  menu_redraw_motion(menu);
985  else if (menu->redraw & REDRAW_CURRENT)
986  menu_redraw_current(menu);
987  }
988 
989  if (menu->redraw & REDRAW_STATUS)
990  {
991  char buf[1024];
992  menu_status_line(buf, sizeof(buf), menu, NONULL(C_StatusFormat));
995  mutt_draw_statusline(MuttStatusWindow->cols, buf, sizeof(buf));
996  NORMAL_COLOR;
997  menu->redraw &= ~REDRAW_STATUS;
998  if (C_TsEnabled && TsSupported)
999  {
1000  menu_status_line(buf, sizeof(buf), menu, NONULL(C_TsStatusFormat));
1001  mutt_ts_status(buf);
1002  menu_status_line(buf, sizeof(buf), menu, NONULL(C_TsIconFormat));
1003  mutt_ts_icon(buf);
1004  }
1005  }
1006 
1007  menu->redraw = 0;
1008 }
struct Email ** emails
Definition: mailbox.h:100
The "current" mailbox.
Definition: context.h:37
WHERE char * C_TsIconFormat
Config: printf-like format string for the terminal&#39;s icon title.
Definition: globals.h:153
#define REDRAW_FULL
Redraw everything.
Definition: mutt_menu.h:47
#define NONULL(x)
Definition: string2.h:36
struct MuttWindow * MuttStatusWindow
Status Window.
Definition: mutt_window.c:40
#define NORMAL_COLOR
Definition: mutt_curses.h:237
void menu_status_line(char *buf, size_t buflen, struct Menu *menu, const char *p)
Create the status line.
Definition: status.c:393
WHERE char * C_StatusFormat
Config: printf-like format string for the index&#39;s status line.
Definition: globals.h:151
WHERE bool C_TsEnabled
Config: Allow NeoMutt to set the terminal status line and icon.
Definition: globals.h:264
int vcount
the number of virtual messages
Definition: mailbox.h:103
#define REDRAW_SIDEBAR
Redraw the sidebar.
Definition: mutt_menu.h:51
struct Mailbox * mailbox
Definition: context.h:51
#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:43
int mutt_window_move(struct MuttWindow *win, int row, int col)
Move the cursor in a Window.
Definition: mutt_window.c:162
WHERE char * C_TsStatusFormat
Config: printf-like format string for the terminal&#39;s status (window title)
Definition: globals.h:152
#define SETCOLOR(X)
Definition: mutt_curses.h:222
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:128
void mutt_ts_icon(char *str)
Set the icon in the terminal title bar.
Definition: terminal.c:118
void mutt_show_error(void)
Show the user an error message.
Definition: curs_lib.c:483
void mutt_ts_status(char *str)
Set the text of the terminal title bar.
Definition: terminal.c:104
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:835
#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 1017 of file index.c.

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

+ 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 3612 of file index.c.

3613 {
3614  struct ColorLine *color = NULL;
3615  struct PatternCache cache = { 0 };
3616 
3617  if (!e)
3618  return;
3619 
3620  STAILQ_FOREACH(color, &ColorIndexList, entries)
3621  {
3622  if (mutt_pattern_exec(color->color_pattern, MUTT_MATCH_FULL_ADDRESS, m, e, &cache))
3623  {
3624  e->pair = color->pair;
3625  return;
3626  }
3627  }
3629 }
Match the full address.
Definition: pattern.h:72
Plain text.
Definition: mutt_curses.h:130
struct Pattern * color_pattern
compiled pattern to speed up index color calculation
Definition: mutt_curses.h:183
#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:52
Cache commonly-used patterns.
Definition: pattern.h:83
int mutt_pattern_exec(struct Pattern *pat, enum PatternExecFlag flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
Match a pattern against an email header.
Definition: pattern.c:1931
struct ColorLineHead ColorIndexList
List of default colours applied to the index.
Definition: color.c:58
int pair
color-pair to use when displaying in the index
Definition: email.h:82
A regular expression and a color to highlight a line.
Definition: mutt_curses.h:178

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

bool mutt_reply_listener ( const struct ConfigSet cs,
struct HashElem he,
const char *  name,
enum ConfigEvent  ev 
)

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

Definition at line 3634 of file index.c.

3636 {
3637  if (mutt_str_strcmp(name, "reply_regex") != 0)
3638  return true;
3639 
3640  if (!Context)
3641  return true;
3642 
3643  regmatch_t pmatch[1];
3644 
3645  for (int i = 0; i < Context->mailbox->msg_count; i++)
3646  {
3647  struct Envelope *e = Context->mailbox->emails[i]->env;
3648  if (!e || !e->subject)
3649  continue;
3650 
3651  if (C_ReplyRegex && C_ReplyRegex->regex &&
3652  (regexec(C_ReplyRegex->regex, e->subject, 1, pmatch, 0) == 0))
3653  {
3654  e->real_subj = e->subject + pmatch[0].rm_eo;
3655  continue;
3656  }
3657 
3658  e->real_subj = e->subject;
3659  }
3660 
3661  OptResortInit = true; /* trigger a redraw of the index */
3662  return true;
3663 }
struct Email ** emails
Definition: mailbox.h:100
The "current" mailbox.
Definition: context.h:37
int msg_count
total number of messages
Definition: mailbox.h:93
regex_t * regex
compiled expression
Definition: regex3.h:60
char * real_subj
offset of the real subject
Definition: envelope.h:51
struct Mailbox * mailbox
Definition: context.h:51
const char * name
Definition: pgpmicalg.c:45
struct Envelope * env
envelope information
Definition: email.h:92
struct Regex * C_ReplyRegex
Config: Regex to match message reply subjects like "re: ".
Definition: email_globals.c:36
WHERE bool OptResortInit
(pseudo) used to force the next resort to be from scratch
Definition: options.h:48
char * subject
Definition: envelope.h:50
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:611
The header of an email.
Definition: envelope.h:38

+ 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 101 of file index.c.

bool C_CollapseAll

Config: Collapse all threads when entering a folder.

Definition at line 102 of file index.c.

bool C_CollapseFlagged

Config: Prevent the collapse of threads with flagged emails.

Definition at line 103 of file index.c.

bool C_CollapseUnread

Config: Prevent the collapse of threads with unread emails.

Definition at line 104 of file index.c.

char* C_MarkMacroPrefix

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

Definition at line 105 of file index.c.

bool C_PgpAutoDecode

Config: Automatically decrypt PGP messages.

Definition at line 106 of file index.c.

bool C_UncollapseJump

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

Definition at line 107 of file index.c.

bool C_UncollapseNew

Config: Open collapsed threads when new mail arrives.

Definition at line 108 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 110 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 123 of file index.c.