NeoMutt  2018-07-16 +2225-8687db
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 "alias.h"
#include "browser.h"
#include "commands.h"
#include "context.h"
#include "core/lib.h"
#include "curs_lib.h"
#include "format_flags.h"
#include "globals.h"
#include "hdrline.h"
#include "hook.h"
#include "keymap.h"
#include "mutt_account.h"
#include "mutt_curses.h"
#include "mutt_header.h"
#include "mutt_logging.h"
#include "mutt_mailbox.h"
#include "mutt_menu.h"
#include "mutt_thread.h"
#include "mutt_window.h"
#include "muttlib.h"
#include "mx.h"
#include "ncrypt/ncrypt.h"
#include "opcodes.h"
#include "options.h"
#include "pager.h"
#include "pattern.h"
#include "progress.h"
#include "protos.h"
#include "query.h"
#include "recvattach.h"
#include "score.h"
#include "send.h"
#include "sort.h"
#include "status.h"
#include "terminal.h"
#include "sidebar.h"
#include "pop/pop.h"
#include "imap/imap.h"
#include "notmuch/mutt_notmuch.h"
#include "nntp/nntp.h"
#include <libintl.h>

Go to the source code of this file.

Macros

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

Typedefs

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

Functions

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

Variables

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

Detailed Description

GUI manage the main index (list of emails)

Authors
  • Michael R. Elkins

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

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

Definition in file index.c.

Macro Definition Documentation

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

Definition at line 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) && (!ctx || !ctx->mailbox))
171  {
172  mutt_error(_("No mailbox is open"));
173  result = false;
174  }
175 
176  if (result && (checks & CHECK_MSGCOUNT) && (ctx->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 >= ctx->mailbox->vcount))
183  {
184  mutt_error(_("No visible messages"));
185  result = false;
186  }
187 
188  if (result && (checks & CHECK_READONLY) && ctx->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 }
int msg_count
Total number of messages.
Definition: mailbox.h:103
void mutt_flushinp(void)
Empty all the keyboard buffers.
Definition: curs_lib.c:800
#define CHECK_ATTACH
Is the user in message-attach mode?
Definition: index.c:153
#define _(a)
Definition: message.h:28
int vcount
The number of virtual messages.
Definition: mailbox.h:114
#define CHECK_VISIBLE
Is the selected message visible in the index?
Definition: index.c:151
struct Mailbox * mailbox
Definition: context.h:53
#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:131
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:84
#define CHECK_MSGCOUNT
Are there any messages?
Definition: index.c:150
int current
current entry
Definition: mutt_menu.h:87
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:53
AclFlags rights
ACL bits, see AclFlags.
Definition: mailbox.h:133
#define mutt_error(...)
Definition: logging.h:84
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->vnum;
256 
257  if (final == -1)
258  return;
259 
260  base = Context->mailbox->emails[Context->mailbox->v2r[final]];
261 
262  /* Iterate all threads, perform collapse/uncollapse as needed */
263  top = Context->tree;
264  Context->collapsed = toggle ? !Context->collapsed : true;
265  while ((thread = top))
266  {
267  while (!thread->message)
268  thread = thread->child;
269  e = thread->message;
270 
271  if (e->collapsed != Context->collapsed)
272  {
273  if (e->collapsed)
275  else if (CAN_COLLAPSE(e))
277  }
278  top = top->next;
279  }
280 
281  /* Restore the cursor */
283  for (int j = 0; j < Context->mailbox->vcount; j++)
284  {
285  if (Context->mailbox->emails[Context->mailbox->v2r[j]]->index == base->index)
286  {
287  menu->current = j;
288  break;
289  }
290  }
291 
293 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:111
The "current" mailbox.
Definition: context.h:39
int msg_count
Total number of messages.
Definition: mailbox.h:103
The envelope/body of an email.
Definition: email.h:37
void mutt_set_vnum(struct Context *ctx)
Set the virtual index number of all the messages in a mailbox.
Definition: mutt_thread.c:1187
struct MuttThread * tree
top of thread tree
Definition: context.h:45
#define mutt_collapse_thread(ctx, e)
Definition: mutt_thread.h:56
int vcount
The number of virtual messages.
Definition: mailbox.h:114
struct Mailbox * mailbox
Definition: context.h:53
#define CUR_EMAIL
Definition: index.c:136
struct MuttThread * child
Child of this Thread.
Definition: thread.h:46
#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:73
struct Email * message
Email this Thread refers to.
Definition: thread.h:49
MuttRedrawFlags redraw
when to redraw the screen
Definition: mutt_menu.h:89
An Email conversation.
Definition: thread.h:34
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:113
#define REDRAW_INDEX
Redraw the index.
Definition: mutt_menu.h:42
bool collapsed
are all threads collapsed?
Definition: context.h:51
int index
The absolute (unsorted) message number.
Definition: email.h:85
int current
current entry
Definition: mutt_menu.h:87
#define mutt_uncollapse_thread(ctx, e)
Definition: mutt_thread.h:57
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 301 of file index.c.

302 {
303  for (int i = msgno + 1; i < Context->mailbox->vcount; i++)
305  return i;
306  return -1;
307 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:111
The "current" mailbox.
Definition: context.h:39
int vcount
The number of virtual messages.
Definition: mailbox.h:114
struct Mailbox * mailbox
Definition: context.h:53
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:113
bool deleted
Email is deleted.
Definition: email.h:45
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 315 of file index.c.

316 {
317  for (int i = msgno - 1; i >= 0; i--)
319  return i;
320  return -1;
321 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:111
The "current" mailbox.
Definition: context.h:39
struct Mailbox * mailbox
Definition: context.h:53
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:113
bool deleted
Email is deleted.
Definition: email.h:45
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 330 of file index.c.

331 {
332  if (!Context || (Context->mailbox->msg_count == 0))
333  return 0;
334 
335  int old = -1;
336  for (int i = 0; i < Context->mailbox->vcount; i++)
337  {
338  if (!Context->mailbox->emails[Context->mailbox->v2r[i]]->read &&
340  {
341  if (!Context->mailbox->emails[Context->mailbox->v2r[i]]->old)
342  return i;
343  else if (old == -1)
344  old = i;
345  }
346  }
347  if (old != -1)
348  return old;
349 
350  /* If C_Sort is reverse and not threaded, the latest message is first.
351  * If C_Sort is threaded, the latest message is first if exactly one
352  * of C_Sort and C_SortAux are reverse. */
353  if (((C_Sort & SORT_REVERSE) && ((C_Sort & SORT_MASK) != SORT_THREADS)) ||
354  (((C_Sort & SORT_MASK) == SORT_THREADS) && ((C_Sort ^ C_SortAux) & SORT_REVERSE)))
355  {
356  return 0;
357  }
358  else
359  {
360  return Context->mailbox->vcount ? Context->mailbox->vcount - 1 : 0;
361  }
362 
363  return 0;
364 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:111
The "current" mailbox.
Definition: context.h:39
int msg_count
Total number of messages.
Definition: mailbox.h:103
int vcount
The number of virtual messages.
Definition: mailbox.h:114
bool read
Email is read.
Definition: email.h:51
struct Mailbox * mailbox
Definition: context.h:53
bool old
Email is seen, but unread.
Definition: email.h:50
WHERE short C_Sort
Config: Sort method for the index.
Definition: sort.h:59
WHERE short C_SortAux
Config: Secondary sort method for the index.
Definition: sort.h:60
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:113
bool deleted
Email is 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
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 374 of file index.c.

375 {
376  if (!m)
377  return -1;
378 
379  if (m->readonly)
380  {
381  mutt_error(_("Can't toggle write on a readonly mailbox"));
382  return -1;
383  }
384 
385  if (m->dontwrite)
386  {
387  m->dontwrite = false;
388  mutt_message(_("Changes to folder will be written on folder exit"));
389  }
390  else
391  {
392  m->dontwrite = true;
393  mutt_message(_("Changes to folder will not be written"));
394  }
395 
396  return 0;
397 }
#define mutt_message(...)
Definition: logging.h:83
#define _(a)
Definition: message.h:28
bool readonly
Don&#39;t allow changes to the mailbox.
Definition: mailbox.h:131
bool dontwrite
Don&#39;t write the mailbox on close.
Definition: mailbox.h:127
#define mutt_error(...)
Definition: logging.h:84
static void resort_index ( struct Menu menu)
static

Resort the index.

Parameters
menuCurrent Menu

Definition at line 403 of file index.c.

404 {
405  struct Email *e = CUR_EMAIL;
406 
407  menu->current = -1;
408  mutt_sort_headers(Context, false);
409  /* Restore the current message */
410 
411  for (int i = 0; i < Context->mailbox->vcount; i++)
412  {
413  if (Context->mailbox->emails[Context->mailbox->v2r[i]] == e)
414  {
415  menu->current = i;
416  break;
417  }
418  }
419 
420  if (((C_Sort & SORT_MASK) == SORT_THREADS) && (menu->current < 0))
421  menu->current = mutt_parent_message(Context, e, false);
422 
423  if (menu->current < 0)
424  menu->current = ci_first_message();
425 
426  menu->redraw |= REDRAW_INDEX | REDRAW_STATUS;
427 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:111
The "current" mailbox.
Definition: context.h:39
The envelope/body of an email.
Definition: email.h:37
int vcount
The number of virtual messages.
Definition: mailbox.h:114
struct Mailbox * mailbox
Definition: context.h:53
int mutt_parent_message(struct Context *ctx, struct Email *e, bool find_root)
Find the parent of a message.
Definition: mutt_thread.c:1141
#define CUR_EMAIL
Definition: index.c:136
WHERE short C_Sort
Config: Sort method for the index.
Definition: sort.h:59
static int ci_first_message(void)
Get index of first new message.
Definition: index.c:330
void mutt_sort_headers(struct Context *ctx, bool init)
Sort emails by their headers.
Definition: sort.c:363
#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:113
#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
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 435 of file index.c.

436 {
437  struct Email **save_new = NULL;
438 
439  /* save the list of new messages */
440  if ((check != MUTT_REOPENED) && oldcount && (ctx->pattern || C_UncollapseNew))
441  {
442  save_new = mutt_mem_malloc(sizeof(struct Email *) * (ctx->mailbox->msg_count - oldcount));
443  for (int i = oldcount; i < ctx->mailbox->msg_count; i++)
444  save_new[i - oldcount] = ctx->mailbox->emails[i];
445  }
446 
447  /* Sort first to thread the new messages, because some patterns
448  * require the threading information.
449  *
450  * If the mailbox was reopened, need to rethread from scratch. */
451  mutt_sort_headers(ctx, (check == MUTT_REOPENED));
452 
453  if (ctx->pattern)
454  {
455  for (int i = (check == MUTT_REOPENED) ? 0 : oldcount; i < ctx->mailbox->msg_count; i++)
456  {
457  struct Email *e = NULL;
458 
459  if ((check != MUTT_REOPENED) && oldcount)
460  e = save_new[i - oldcount];
461  else
462  e = ctx->mailbox->emails[i];
463 
465  MUTT_MATCH_FULL_ADDRESS, ctx->mailbox, e, NULL))
466  {
467  /* vnum will get properly set by mutt_set_vnum(), which
468  * is called by mutt_sort_headers() just below. */
469  e->vnum = 1;
470  e->limited = true;
471  }
472  }
473  /* Need a second sort to set virtual numbers and redraw the tree */
474  mutt_sort_headers(ctx, false);
475  }
476 
477  /* uncollapse threads with new mail */
478  if (C_UncollapseNew)
479  {
480  if (check == MUTT_REOPENED)
481  {
482  ctx->collapsed = false;
483 
484  for (struct MuttThread *h = ctx->tree; h; h = h->next)
485  {
486  struct MuttThread *j = h;
487  for (; !j->message; j = j->child)
488  ;
490  }
491  mutt_set_vnum(ctx);
492  }
493  else if (oldcount)
494  {
495  for (int j = 0; j < (ctx->mailbox->msg_count - oldcount); j++)
496  {
497  if (!ctx->pattern || save_new[j]->limited)
498  {
499  mutt_uncollapse_thread(ctx, save_new[j]);
500  }
501  }
502  mutt_set_vnum(ctx);
503  }
504  }
505 
506  FREE(&save_new);
507 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:111
struct MuttThread * next
Next sibling Thread.
Definition: thread.h:47
int msg_count
Total number of messages.
Definition: mailbox.h:103
The envelope/body of an email.
Definition: email.h:37
void mutt_set_vnum(struct Context *ctx)
Set the virtual index number of all the messages in a mailbox.
Definition: mutt_thread.c:1187
struct MuttThread * tree
top of thread tree
Definition: context.h:45
struct PatternHead * limit_pattern
compiled limit pattern
Definition: context.h:43
struct Mailbox * mailbox
Definition: context.h:53
bool limited
Is this message in a limited view?
Definition: email.h:74
int mutt_pattern_exec(struct Pattern *pat, PatternExecFlags flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
Match a pattern against an email header.
Definition: pattern.c:2005
struct MuttThread * child
Child of this Thread.
Definition: thread.h:46
void mutt_sort_headers(struct Context *ctx, bool init)
Sort emails by their headers.
Definition: sort.c:363
#define SLIST_FIRST(head)
Definition: queue.h:229
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
int vnum
Virtual message number.
Definition: email.h:87
struct Email * message
Email this Thread refers to.
Definition: thread.h:49
#define MUTT_MATCH_FULL_ADDRESS
Match the full address.
Definition: pattern.h:73
An Email conversation.
Definition: thread.h:34
bool collapsed
are all threads collapsed?
Definition: context.h:51
#define FREE(x)
Definition: memory.h:40
Mailbox was reopened.
Definition: mx.h:75
char * pattern
limit pattern string
Definition: context.h:42
bool C_UncollapseNew
Config: Open collapsed threads when new mail arrives.
Definition: index.c:108
#define mutt_uncollapse_thread(ctx, e)
Definition: mutt_thread.h:57
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 515 of file index.c.

516 {
517  /* We are in a limited view. Check if the new message(s) satisfy
518  * the limit criteria. If they do, set their virtual msgno so that
519  * they will be visible in the limited view */
520  if (ctx->pattern)
521  {
522  int padding = mx_msg_padding_size(ctx->mailbox);
523  for (int i = (check == MUTT_REOPENED) ? 0 : oldcount; i < ctx->mailbox->msg_count; i++)
524  {
525  if (i == 0)
526  {
527  ctx->mailbox->vcount = 0;
528  ctx->vsize = 0;
529  }
530 
532  ctx->mailbox, ctx->mailbox->emails[i], NULL))
533  {
534  assert(ctx->mailbox->vcount < ctx->mailbox->msg_count);
535  ctx->mailbox->emails[i]->vnum = ctx->mailbox->vcount;
536  ctx->mailbox->v2r[ctx->mailbox->vcount] = i;
537  ctx->mailbox->emails[i]->limited = true;
538  ctx->mailbox->vcount++;
539  struct Body *b = ctx->mailbox->emails[i]->content;
540  ctx->vsize += b->length + b->offset - b->hdr_offset + padding;
541  }
542  }
543  }
544 
545  /* if the mailbox was reopened, need to rethread from scratch */
546  mutt_sort_headers(ctx, (check == MUTT_REOPENED));
547 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:111
int msg_count
Total number of messages.
Definition: mailbox.h:103
struct Body * content
List of MIME parts.
Definition: email.h:90
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
int vcount
The number of virtual messages.
Definition: mailbox.h:114
The body of an email.
Definition: body.h:34
struct PatternHead * limit_pattern
compiled limit pattern
Definition: context.h:43
struct Mailbox * mailbox
Definition: context.h:53
bool limited
Is this message in a limited view?
Definition: email.h:74
off_t vsize
Definition: context.h:41
int mutt_pattern_exec(struct Pattern *pat, PatternExecFlags flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
Match a pattern against an email header.
Definition: pattern.c:2005
void mutt_sort_headers(struct Context *ctx, bool init)
Sort emails by their headers.
Definition: sort.c:363
#define SLIST_FIRST(head)
Definition: queue.h:229
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
int vnum
Virtual message number.
Definition: email.h:87
#define MUTT_MATCH_FULL_ADDRESS
Match the full address.
Definition: pattern.h:73
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:113
int mx_msg_padding_size(struct Mailbox *m)
Bytes of padding between messages - Wrapper for MxOps::msg_padding_size.
Definition: mx.c:1467
long hdr_offset
Offset in stream where the headers begin.
Definition: body.h:42
Mailbox was reopened.
Definition: mx.h:75
char * pattern
limit pattern string
Definition: context.h:42
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 557 of file index.c.

558 {
559  if (!menu || !ctx)
560  return;
561 
562  /* take note of the current message */
563  if (oldcount)
564  {
565  if (menu->current < ctx->mailbox->vcount)
566  menu->oldcurrent = index_hint;
567  else
568  oldcount = 0; /* invalid message number! */
569  }
570 
571  if ((C_Sort & SORT_MASK) == SORT_THREADS)
572  update_index_threaded(ctx, check, oldcount);
573  else
574  update_index_unthreaded(ctx, check, oldcount);
575 
576  menu->current = -1;
577  if (oldcount)
578  {
579  /* restore the current message to the message it was pointing to */
580  for (int i = 0; i < ctx->mailbox->vcount; i++)
581  {
582  if (ctx->mailbox->emails[ctx->mailbox->v2r[i]]->index == menu->oldcurrent)
583  {
584  menu->current = i;
585  break;
586  }
587  }
588  }
589 
590  if (menu->current < 0)
591  menu->current = ci_first_message();
592 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:111
int oldcurrent
for driver use only
Definition: mutt_menu.h:111
static void update_index_unthreaded(struct Context *ctx, int check, int oldcount)
Update the index (if unthreaded)
Definition: index.c:515
int vcount
The number of virtual messages.
Definition: mailbox.h:114
struct Mailbox * mailbox
Definition: context.h:53
WHERE short C_Sort
Config: Sort method for the index.
Definition: sort.h:59
static int ci_first_message(void)
Get index of first new message.
Definition: index.c:330
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:113
int index
The absolute (unsorted) message number.
Definition: email.h:85
static void update_index_threaded(struct Context *ctx, int check, int oldcount)
Update the index (if threaded)
Definition: index.c:435
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
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 606 of file index.c.

608 {
609 #ifdef USE_NNTP
610  if (OptNews)
611  {
612  OptNews = false;
613  nntp_expand_path(buf, buflen, &CurrentNewsSrv->conn->account);
614  }
615  else
616 #endif
617  {
618  mx_path_canon(buf, buflen, C_Folder, NULL);
619  }
620 
621  enum MailboxType magic = mx_path_probe(buf, NULL);
622  if ((magic == MUTT_MAILBOX_ERROR) || (magic == MUTT_UNKNOWN))
623  {
624  // Try to see if the buffer matches a description before we bail.
625  // We'll receive a non-null pointer if there is a corresponding mailbox.
626  m = mailbox_find_name(buf);
627  if (m)
628  {
629  mutt_str_strfcpy(buf, mutt_b2s(m->pathbuf), buflen);
630  }
631  else
632  {
633  // Bail.
634  mutt_error(_("%s is not a mailbox"), buf);
635  return -1;
636  }
637  }
638 
639  /* keepalive failure in mutt_enter_fname may kill connection. #3028 */
641  ctx_free(&Context);
642 
643  if (Context)
644  {
645  char *new_last_folder = NULL;
646 #ifdef USE_INOTIFY
647  int monitor_remove_rc = mutt_monitor_remove(NULL);
648 #endif
649 #ifdef USE_COMPRESSED
650  if (Context->mailbox->compress_info && (Context->mailbox->realpath[0] != '\0'))
651  new_last_folder = mutt_str_strdup(Context->mailbox->realpath);
652  else
653 #endif
654  new_last_folder = mutt_str_strdup(mutt_b2s(Context->mailbox->pathbuf));
655  *oldcount = Context->mailbox->msg_count;
656 
657  int check = mx_mbox_close(&Context);
658  if (check != 0)
659  {
660 #ifdef USE_INOTIFY
661  if (monitor_remove_rc == 0)
662  mutt_monitor_add(NULL);
663 #endif
664  if ((check == MUTT_NEW_MAIL) || (check == MUTT_REOPENED))
665  update_index(menu, Context, check, *oldcount, *index_hint);
666 
667  FREE(&new_last_folder);
668  OptSearchInvalid = true;
669  menu->redraw |= REDRAW_INDEX | REDRAW_STATUS;
670  return 0;
671  }
672  FREE(&LastFolder);
673  LastFolder = new_last_folder;
674  }
676 
677  mutt_sleep(0);
678 
679  /* Note that menu->menu may be MENU_PAGER if the change folder
680  * operation originated from the pager.
681  *
682  * However, exec commands currently use CurrentMenu to determine what
683  * functions are available, which is automatically set by the
684  * mutt_push/pop_current_menu() functions. If that changes, the menu
685  * would need to be reset here, and the pager cleanup code after the
686  * switch statement would need to be run. */
687  mutt_folder_hook(buf, m ? m->name : NULL);
688 
689  const int flags = (C_ReadOnly || (op == OP_MAIN_CHANGE_FOLDER_READONLY)
690 #ifdef USE_NOTMUCH
691  || (op == OP_MAIN_VFOLDER_FROM_QUERY_READONLY)
692 #endif
693  ) ?
694  MUTT_READONLY :
696 
697  bool free_m = false;
698  if (!m)
699  {
700  m = mx_path_resolve(buf);
701  free_m = true;
702  }
703  Context = mx_mbox_open(m, flags);
704  if (Context)
705  {
706  menu->current = ci_first_message();
707 #ifdef USE_INOTIFY
708  mutt_monitor_add(NULL);
709 #endif
710  }
711  else
712  {
713  menu->current = 0;
714  if (free_m)
715  mailbox_free(&m);
716  }
717 
718  if (((C_Sort & SORT_MASK) == SORT_THREADS) && C_CollapseAll)
719  collapse_all(menu, 0);
720 
721 #ifdef USE_SIDEBAR
723 #endif
724 
726  mutt_mailbox_check(Context ? Context->mailbox : NULL, MUTT_MAILBOX_CHECK_FORCE); /* force the mailbox check after we have changed the folder */
727  menu->redraw = REDRAW_FULL;
728  OptSearchInvalid = true;
729 
730  return 0;
731 }
#define MUTT_OPEN_NO_FLAGS
No flags are set.
Definition: mx.h:51
The "current" mailbox.
Definition: context.h:39
#define REDRAW_FULL
Redraw everything.
Definition: mutt_menu.h:47
int msg_count
Total number of messages.
Definition: mailbox.h:103
struct ConnAccount account
Definition: connection.h:36
int mx_mbox_close(struct Context **ptr)
Save changes and close mailbox.
Definition: mx.c:561
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:1300
int mutt_monitor_remove(struct Mailbox *m)
Remove a watch for a mailbox.
Definition: monitor.c:511
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:96
#define _(a)
Definition: message.h:28
Mailbox wasn&#39;t recognised.
Definition: mailbox.h:47
Error occurred examining Mailbox.
Definition: mailbox.h:46
struct Context * mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:264
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:54
int mutt_monitor_add(struct Mailbox *m)
Add a watch for a mailbox.
Definition: monitor.c:466
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:515
char * name
A short name for the Mailbox.
Definition: mailbox.h:97
void mutt_sleep(short s)
Sleep for a while.
Definition: muttlib.c:1505
struct Mailbox * mailbox
Definition: context.h:53
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:56
WHERE char * CurrentFolder
Currently selected mailbox.
Definition: globals.h:53
WHERE short C_Sort
Config: Sort method for the index.
Definition: sort.h:59
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:243
#define mutt_b2s(buf)
Definition: buffer.h:42
static int ci_first_message(void)
Get index of first new message.
Definition: index.c:330
#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:114
struct Mailbox * mailbox_find_name(const char *name)
Find the mailbox with a given name.
Definition: mailbox.c:114
int mutt_mailbox_check(struct Mailbox *m_cur, int force)
Check all all Mailboxes for new mail.
Definition: mutt_mailbox.c:126
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:750
WHERE bool OptSearchInvalid
(pseudo) used to invalidate the search pat
Definition: options.h:49
void update_index(struct Menu *menu, struct Context *ctx, int check, int oldcount, int index_hint)
Update the index.
Definition: index.c:557
void mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:453
void nntp_expand_path(char *buf, size_t buflen, struct ConnAccount *acct)
Make fully qualified url from newsgroup name.
Definition: newsrc.c:549
#define MUTT_MAILBOX_CHECK_FORCE
Definition: mutt_mailbox.h:17
struct Buffer * pathbuf
Definition: mailbox.h:95
MuttRedrawFlags redraw
when to redraw the screen
Definition: mutt_menu.h:89
struct Connection * conn
Definition: nntp.h:103
MailboxType
Supported mailbox formats.
Definition: mailbox.h:43
#define REDRAW_INDEX
Redraw the index.
Definition: mutt_menu.h:42
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
#define mutt_error(...)
Definition: logging.h:84
void * compress_info
Compressed mbox module private data.
Definition: mailbox.h:136
#define FREE(x)
Definition: memory.h:40
struct Mailbox * mx_path_resolve(const char *path)
XXX.
Definition: mx.c:1544
void ctx_free(struct Context **ptr)
Free a Context.
Definition: context.c:47
New mail received in Mailbox.
Definition: mx.h:73
int current
current entry
Definition: mutt_menu.h:87
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:283
enum MailboxType mx_path_probe(const char *path, struct stat *st)
Find a mailbox that understands a path.
Definition: mx.c:1241
Mailbox was reopened.
Definition: mx.h:75
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:76
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 736 of file index.c.

737 {
738  if (!Context || !menu || (line < 0) || (line >= Context->mailbox->email_max))
739  return;
740 
741  struct Email *e = Context->mailbox->emails[Context->mailbox->v2r[line]];
742  if (!e)
743  return;
744 
746  struct MuttThread *tmp = NULL;
747 
748  if (((C_Sort & SORT_MASK) == SORT_THREADS) && e->tree)
749  {
750  flags |= MUTT_FORMAT_TREE; /* display the thread tree */
751  if (e->display_subject)
752  flags |= MUTT_FORMAT_FORCESUBJ;
753  else
754  {
755  const int reverse = C_Sort & SORT_REVERSE;
756  int edgemsgno;
757  if (reverse)
758  {
759  if (menu->top + menu->pagelen > menu->max)
760  edgemsgno = Context->mailbox->v2r[menu->max - 1];
761  else
762  edgemsgno = Context->mailbox->v2r[menu->top + menu->pagelen - 1];
763  }
764  else
765  edgemsgno = Context->mailbox->v2r[menu->top];
766 
767  for (tmp = e->thread->parent; tmp; tmp = tmp->parent)
768  {
769  if (!tmp->message)
770  continue;
771 
772  /* if no ancestor is visible on current screen, provisionally force
773  * subject... */
774  if (reverse ? (tmp->message->msgno > edgemsgno) : (tmp->message->msgno < edgemsgno))
775  {
776  flags |= MUTT_FORMAT_FORCESUBJ;
777  break;
778  }
779  else if (tmp->message->vnum >= 0)
780  break;
781  }
782  if (flags & MUTT_FORMAT_FORCESUBJ)
783  {
784  for (tmp = e->thread->prev; tmp; tmp = tmp->prev)
785  {
786  if (!tmp->message)
787  continue;
788 
789  /* ...but if a previous sibling is available, don't force it */
790  if (reverse ? (tmp->message->msgno > edgemsgno) : (tmp->message->msgno < edgemsgno))
791  break;
792  else if (tmp->message->vnum >= 0)
793  {
794  flags &= ~MUTT_FORMAT_FORCESUBJ;
795  break;
796  }
797  }
798  }
799  }
800  }
801 
803  Context->mailbox, e, flags);
804 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:111
The "current" mailbox.
Definition: context.h:39
uint8_t MuttFormatFlags
Flags for mutt_expando_format(), e.g. MUTT_FORMAT_FORCESUBJ.
Definition: format_flags.h:29
#define NONULL(x)
Definition: string2.h:37
The envelope/body of an email.
Definition: email.h:37
#define MUTT_FORMAT_FORCESUBJ
Print the subject even if unchanged.
Definition: format_flags.h:31
struct MuttThread * thread
Thread of Emails.
Definition: email.h:94
#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
Parent of this Thread.
Definition: thread.h:45
struct MuttThread * prev
Previous sibling Thread.
Definition: thread.h:48
struct Mailbox * mailbox
Definition: context.h:53
#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:1501
WHERE short C_Sort
Config: Sort method for the index.
Definition: sort.h:59
const char * line
Definition: common.c:36
int email_max
Number of pointers in emails.
Definition: mailbox.h:112
WHERE char * C_IndexFormat
Config: printf-like format string for the index menu (emails)
Definition: globals.h:107
int top
entry that is the top of the current page
Definition: mutt_menu.h:110
int vnum
Virtual message number.
Definition: email.h:87
int pagelen
number of entries per screen
Definition: mutt_menu.h:92
char * tree
Character string to print thread tree.
Definition: email.h:93
struct Email * message
Email this Thread refers to.
Definition: thread.h:49
int max
the number of entries in the menu
Definition: mutt_menu.h:88
An Email conversation.
Definition: thread.h:34
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:113
#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:86
int index_color ( int  line)

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

Definition at line 809 of file index.c.

810 {
811  if (!Context || (line < 0))
812  return 0;
813 
814  struct Email *e = Context->mailbox->emails[Context->mailbox->v2r[line]];
815 
816  if (e && e->pair)
817  return e->pair;
818 
820  if (e)
821  return e->pair;
822 
823  return 0;
824 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:111
The "current" mailbox.
Definition: context.h:39
The envelope/body of an email.
Definition: email.h:37
struct Mailbox * mailbox
Definition: context.h:53
const char * line
Definition: common.c:36
void mutt_set_header_color(struct Mailbox *m, struct Email *e)
Select a colour for a message.
Definition: index.c:3641
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:113
int pair
Color-pair to use when displaying in the index.
Definition: email.h:79
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 838 of file index.c.

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

Redraw the index - Implements Menu::menu_custom_redraw()

Definition at line 964 of file index.c.

965 {
966  if (menu->redraw & REDRAW_FULL)
967  {
968  menu_redraw_full(menu);
969  mutt_show_error();
970  }
971 
972 #ifdef USE_SIDEBAR
973  if (menu->redraw & REDRAW_SIDEBAR)
974  menu_redraw_sidebar(menu);
975 #endif
976 
977  if (Context && Context->mailbox->emails && !(menu->current >= Context->mailbox->vcount))
978  {
979  menu_check_recenter(menu);
980 
981  if (menu->redraw & REDRAW_INDEX)
982  {
983  menu_redraw_index(menu);
984  menu->redraw |= REDRAW_STATUS;
985  }
986  else if (menu->redraw & (REDRAW_MOTION_RESYNC | REDRAW_MOTION))
987  menu_redraw_motion(menu);
988  else if (menu->redraw & REDRAW_CURRENT)
989  menu_redraw_current(menu);
990  }
991 
992  if (menu->redraw & REDRAW_STATUS)
993  {
994  char buf[1024];
995  menu_status_line(buf, sizeof(buf), menu, NONULL(C_StatusFormat));
998  mutt_draw_statusline(MuttStatusWindow->cols, buf, sizeof(buf));
999  NORMAL_COLOR;
1000  menu->redraw &= ~REDRAW_STATUS;
1001  if (C_TsEnabled && TsSupported)
1002  {
1003  menu_status_line(buf, sizeof(buf), menu, NONULL(C_TsStatusFormat));
1004  mutt_ts_status(buf);
1005  menu_status_line(buf, sizeof(buf), menu, NONULL(C_TsIconFormat));
1006  mutt_ts_icon(buf);
1007  }
1008  }
1009 
1010  menu->redraw = 0;
1011 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:111
The "current" mailbox.
Definition: context.h:39
WHERE char * C_TsIconFormat
Config: printf-like format string for the terminal&#39;s icon title.
Definition: globals.h:145
#define REDRAW_FULL
Redraw everything.
Definition: mutt_menu.h:47
#define NONULL(x)
Definition: string2.h:37
struct MuttWindow * MuttStatusWindow
Status Window.
Definition: mutt_window.c:40
#define NORMAL_COLOR
Definition: mutt_curses.h:239
void menu_status_line(char *buf, size_t buflen, struct Menu *menu, const char *p)
Create the status line.
Definition: status.c:394
WHERE char * C_StatusFormat
Config: printf-like format string for the index&#39;s status line.
Definition: globals.h:143
WHERE bool C_TsEnabled
Config: Allow NeoMutt to set the terminal status line and icon.
Definition: globals.h:256
int vcount
The number of virtual messages.
Definition: mailbox.h:114
#define REDRAW_SIDEBAR
Redraw the sidebar.
Definition: mutt_menu.h:51
struct Mailbox * mailbox
Definition: context.h:53
#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
#define SET_COLOR(X)
Definition: mutt_curses.h:224
int mutt_window_move(struct MuttWindow *win, int row, int col)
Move the cursor in a Window.
Definition: mutt_window.c:162
WHERE char * C_TsStatusFormat
Config: printf-like format string for the terminal&#39;s status (window title)
Definition: globals.h:144
MuttRedrawFlags redraw
when to redraw the screen
Definition: mutt_menu.h:89
#define REDRAW_INDEX
Redraw the index.
Definition: mutt_menu.h:42
Status bar.
Definition: mutt_curses.h:129
void mutt_ts_icon(char *str)
Set the icon in the terminal title bar.
Definition: terminal.c:118
void mutt_show_error(void)
Show the user an error message.
Definition: curs_lib.c:485
void mutt_ts_status(char *str)
Set the text of the terminal title bar.
Definition: terminal.c: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:838
#define REDRAW_CURRENT
Redraw the current line of the menu.
Definition: mutt_menu.h:45
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 1020 of file index.c.

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

Select a colour for a message.

Parameters
mMailbox
eCurrent Email

Definition at line 3641 of file index.c.

3642 {
3643  if (!e)
3644  return;
3645 
3646  struct ColorLine *color = NULL;
3647  struct PatternCache cache = { 0 };
3648 
3649  STAILQ_FOREACH(color, &ColorIndexList, entries)
3650  {
3652  MUTT_MATCH_FULL_ADDRESS, m, e, &cache))
3653  {
3654  e->pair = color->pair;
3655  return;
3656  }
3657  }
3659 }
Plain text.
Definition: mutt_curses.h:131
int mutt_pattern_exec(struct Pattern *pat, PatternExecFlags flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
Match a pattern against an email header.
Definition: pattern.c:2005
#define SLIST_FIRST(head)
Definition: queue.h:229
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
int ColorDefs[MT_COLOR_MAX]
Array of all fixed colours, see enum ColorId.
Definition: color.c:53
#define MUTT_MATCH_FULL_ADDRESS
Match the full address.
Definition: pattern.h:73
Cache commonly-used patterns.
Definition: pattern.h:83
struct ColorLineHead ColorIndexList
List of default colours applied to the index.
Definition: color.c:59
int pair
Color-pair to use when displaying in the index.
Definition: email.h:79
A regular expression and a color to highlight a line.
Definition: mutt_curses.h:180
struct PatternHead * color_pattern
compiled pattern to speed up index color calculation
Definition: mutt_curses.h:185
int mutt_reply_observer ( struct NotifyCallback nc)

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

Definition at line 3664 of file index.c.

3665 {
3666  if (!nc)
3667  return -1;
3668 
3669  struct EventConfig *ec = (struct EventConfig *) nc->event;
3670 
3671  if (mutt_str_strcmp(ec->name, "reply_regex") != 0)
3672  return 0;
3673 
3674  if (!Context)
3675  return 0;
3676 
3677  regmatch_t pmatch[1];
3678 
3679  for (int i = 0; i < Context->mailbox->msg_count; i++)
3680  {
3681  struct Envelope *e = Context->mailbox->emails[i]->env;
3682  if (!e || !e->subject)
3683  continue;
3684 
3685  if (C_ReplyRegex && C_ReplyRegex->regex &&
3686  (regexec(C_ReplyRegex->regex, e->subject, 1, pmatch, 0) == 0))
3687  {
3688  e->real_subj = e->subject + pmatch[0].rm_eo;
3689  continue;
3690  }
3691 
3692  e->real_subj = e->subject;
3693  }
3694 
3695  OptResortInit = true; /* trigger a redraw of the index */
3696  return 0;
3697 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:111
The "current" mailbox.
Definition: context.h:39
int msg_count
Total number of messages.
Definition: mailbox.h:103
regex_t * regex
compiled expression
Definition: regex3.h:60
A config-change event.
Definition: set.h:199
char * real_subj
Offset of the real subject.
Definition: envelope.h:53
intptr_t event
Send: event data.
Definition: observer.h:46
struct Mailbox * mailbox
Definition: context.h:53
struct Envelope * env
Envelope information.
Definition: email.h:89
struct Regex * C_ReplyRegex
Config: Regex to match message reply subjects like "re: ".
Definition: email_globals.c:37
WHERE bool OptResortInit
(pseudo) used to force the next resort to be from scratch
Definition: options.h:48
char * subject
Email&#39;s subject.
Definition: envelope.h:52
const char * name
Name of config item that changed.
Definition: set.h:203
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:615
The header of an Email.
Definition: envelope.h:40

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.