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

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

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

Go to the source code of this file.

Macros

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

Typedefs

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

Functions

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

Variables

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

Detailed Description

GUI manage the main index (list of emails)

Authors
  • Michael R. Elkins

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

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

Definition in file index.c.

Macro Definition Documentation

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

Definition at line 136 of file index.c.

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

Definition at line 137 of file index.c.

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

Definition at line 138 of file index.c.

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

Definition at line 140 of file index.c.

#define CHECK_NO_FLAGS   0

No flags are set.

Definition at line 148 of file index.c.

#define CHECK_IN_MAILBOX   (1 << 0)

Is there a mailbox open?

Definition at line 149 of file index.c.

#define CHECK_MSGCOUNT   (1 << 1)

Are there any messages?

Definition at line 150 of file index.c.

#define CHECK_VISIBLE   (1 << 2)

Is the selected message visible in the index?

Definition at line 151 of file index.c.

#define CHECK_READONLY   (1 << 3)

Is the mailbox readonly?

Definition at line 152 of file index.c.

#define CHECK_ATTACH   (1 << 4)

Is the user in message-attach mode?

Definition at line 153 of file index.c.

Typedef Documentation

typedef uint8_t CheckFlags

typedef CheckFlags - Checks to perform before running a function

Flags, e.g. CHECK_IN_MAILBOX

Definition at line 147 of file index.c.

Function Documentation

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

Check the pre-requisites for a function.

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

Definition at line 163 of file index.c.

164 {
165  bool result = true;
166 
167  if (checks & (CHECK_MSGCOUNT | CHECK_VISIBLE | CHECK_READONLY))
168  checks |= CHECK_IN_MAILBOX;
169 
170  if ((checks & CHECK_IN_MAILBOX) && !Context)
171  {
172  mutt_error(_("No mailbox is open"));
173  result = false;
174  }
175 
176  if (result && (checks & CHECK_MSGCOUNT) && (Context->mailbox->msg_count == 0))
177  {
178  mutt_error(_("There are no messages"));
179  result = false;
180  }
181 
182  if (result && (checks & CHECK_VISIBLE) && (menu->current >= Context->mailbox->vcount))
183  {
184  mutt_error(_("No visible messages"));
185  result = false;
186  }
187 
188  if (result && (checks & CHECK_READONLY) && Context->mailbox->readonly)
189  {
190  mutt_error(_("Mailbox is read-only"));
191  result = false;
192  }
193 
194  if (result && (checks & CHECK_ATTACH) && OptAttachMsg)
195  {
196  mutt_error(_("Function not permitted in attach-message mode"));
197  result = false;
198  }
199 
200  if (!result)
201  mutt_flushinp();
202 
203  return result;
204 }
The "current" mailbox.
Definition: context.h:38
int msg_count
total number of messages
Definition: mailbox.h:92
void mutt_flushinp(void)
Empty all the keyboard buffers.
Definition: curs_lib.c:785
#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:102
#define CHECK_VISIBLE
Is the selected message visible in the index?
Definition: index.c:151
struct Mailbox * mailbox
Definition: context.h:52
#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:119
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:83
#define CHECK_MSGCOUNT
Are there any messages?
Definition: index.c:150
int current
current entry
Definition: mutt_menu.h:87

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Check the ACLs for a function.

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

Definition at line 213 of file index.c.

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

+ Here is the caller graph for this function:

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

Collapse/uncollapse all threads.

Parameters
menucurrent menu
toggletoggle collapsed state

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

Definition at line 239 of file index.c.

240 {
241  struct Email *e = NULL, *base = NULL;
242  struct MuttThread *thread = NULL, *top = NULL;
243  int final;
244 
245  if (!Context || (Context->mailbox->msg_count == 0))
246  return;
247 
248  /* Figure out what the current message would be after folding / unfolding,
249  * so that we can restore the cursor in a sane way afterwards. */
250  if (CUR_EMAIL->collapsed && toggle)
252  else if (CAN_COLLAPSE(CUR_EMAIL))
254  else
255  final = CUR_EMAIL->virtual;
256 
257  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
Definition: mailbox.h:99
The "current" mailbox.
Definition: context.h:38
int msg_count
total number of messages
Definition: mailbox.h:92
The envelope/body of an email.
Definition: email.h:37
struct MuttThread * tree
top of thread tree
Definition: context.h:44
#define mutt_collapse_thread(ctx, cur)
Definition: mutt_thread.h:56
int vcount
the number of virtual messages
Definition: mailbox.h:102
struct Mailbox * mailbox
Definition: context.h:52
#define CUR_EMAIL
Definition: index.c:136
#define mutt_uncollapse_thread(ctx, cur)
Definition: mutt_thread.h:57
struct MuttThread * child
Definition: thread.h:45
#define CAN_COLLAPSE(email)
Definition: index.c:140
#define REDRAW_STATUS
Redraw the status bar.
Definition: mutt_menu.h:46
bool collapsed
is this message part of a collapsed thread?
Definition: email.h:76
struct Email * message
Definition: thread.h:48
MuttRedrawFlags redraw
when to redraw the screen
Definition: mutt_menu.h:89
An email conversation.
Definition: thread.h:34
int * v2r
mapping from virtual to real msgno
Definition: mailbox.h:101
#define REDRAW_INDEX
Redraw the index.
Definition: mutt_menu.h:42
bool collapsed
are all threads collapsed?
Definition: context.h:50
int index
the absolute (unsorted) message number
Definition: email.h:88
int current
current entry
Definition: mutt_menu.h:87
void mutt_set_virtual(struct Context *ctx)
Set the virtual index number of all the messages in a mailbox.
Definition: mutt_thread.c:1181

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int ci_next_undeleted ( int  msgno)
static

Find the next undeleted email.

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

Definition at line 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
Definition: mailbox.h:99
The "current" mailbox.
Definition: context.h:38
int vcount
the number of virtual messages
Definition: mailbox.h:102
struct Mailbox * mailbox
Definition: context.h:52
int * v2r
mapping from virtual to real msgno
Definition: mailbox.h:101
bool deleted
Definition: email.h:45

+ Here is the caller graph for this function:

static int ci_previous_undeleted ( int  msgno)
static

Find the previous undeleted email.

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

Definition at line 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
Definition: mailbox.h:99
The "current" mailbox.
Definition: context.h:38
struct Mailbox * mailbox
Definition: context.h:52
int * v2r
mapping from virtual to real msgno
Definition: mailbox.h:101
bool deleted
Definition: email.h:45

+ Here is the caller graph for this function:

static int ci_first_message ( void  )
static

Get index of first new message.

Return values
numIndex of first new message

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

Definition at line 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
Definition: mailbox.h:99
The "current" mailbox.
Definition: context.h:38
int msg_count
total number of messages
Definition: mailbox.h:92
int vcount
the number of virtual messages
Definition: mailbox.h:102
bool read
Definition: email.h:51
struct Mailbox * mailbox
Definition: context.h:52
bool old
Definition: email.h:50
WHERE short C_Sort
Config: Sort method for the index.
Definition: sort.h:58
WHERE short C_SortAux
Config: Secondary sort method for the index.
Definition: sort.h:59
int * v2r
mapping from virtual to real msgno
Definition: mailbox.h:101
bool deleted
Definition: email.h:45
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort.h:86
Sort by email threads.
Definition: sort.h:56
#define SORT_MASK
Mask for the sort id.
Definition: sort.h:85

+ Here is the caller graph for this function:

static int mx_toggle_write ( struct Mailbox m)
static

Toggle the mailbox's readonly flag.

Parameters
mMailbox
Return values
0Success
-1Error

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

Definition at line 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:82
#define _(a)
Definition: message.h:28
bool readonly
don&#39;t allow changes to the mailbox
Definition: mailbox.h:119
bool dontwrite
don&#39;t write the mailbox on close
Definition: mailbox.h:115
#define mutt_error(...)
Definition: logging.h:83

+ Here is the caller graph for this function:

static void resort_index ( struct Menu menu)
static

Resort the index.

Parameters
menuCurrent Menu

Definition at line 403 of file index.c.

404 {
405  struct Email *current = 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]] == current)
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, current, 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
Definition: mailbox.h:99
The "current" mailbox.
Definition: context.h:38
The envelope/body of an email.
Definition: email.h:37
int vcount
the number of virtual messages
Definition: mailbox.h:102
struct Mailbox * mailbox
Definition: context.h:52
int mutt_parent_message(struct Context *ctx, struct Email *e, bool find_root)
Find the parent of a message.
Definition: mutt_thread.c:1135
#define CUR_EMAIL
Definition: index.c:136
WHERE short C_Sort
Config: Sort method for the index.
Definition: sort.h:58
static int ci_first_message(void)
Get index of first new message.
Definition: index.c:330
void mutt_sort_headers(struct Context *ctx, bool init)
Sort emails by their headers.
Definition: sort.c:361
#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:101
#define REDRAW_INDEX
Redraw the index.
Definition: mutt_menu.h:42
int current
current entry
Definition: mutt_menu.h:87
Sort by email threads.
Definition: sort.h:56
#define SORT_MASK
Mask for the sort id.
Definition: sort.h:85

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Update the index (if threaded)

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

Definition at line 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  /* virtual will get properly set by mutt_set_virtual(), which
468  * is called by mutt_sort_headers() just below. */
469  e->virtual = 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_virtual(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_virtual(ctx);
503  }
504  }
505 
506  FREE(&save_new);
507 }
struct Email ** emails
Definition: mailbox.h:99
struct MuttThread * next
Definition: thread.h:46
int msg_count
total number of messages
Definition: mailbox.h:92
The envelope/body of an email.
Definition: email.h:37
struct MuttThread * tree
top of thread tree
Definition: context.h:44
int virtual
virtual message number
Definition: email.h:90
struct PatternHead * limit_pattern
compiled limit pattern
Definition: context.h:42
struct Mailbox * mailbox
Definition: context.h:52
bool limited
is this message in a limited view?
Definition: email.h:77
#define mutt_uncollapse_thread(ctx, cur)
Definition: mutt_thread.h:57
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:1970
struct MuttThread * child
Definition: thread.h:45
void mutt_sort_headers(struct Context *ctx, bool init)
Sort emails by their headers.
Definition: sort.c:361
#define SLIST_FIRST(head)
Definition: queue.h:229
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:97
struct Email * message
Definition: thread.h:48
#define MUTT_MATCH_FULL_ADDRESS
Match the full address.
Definition: pattern.h:72
An email conversation.
Definition: thread.h:34
bool collapsed
are all threads collapsed?
Definition: context.h:50
#define FREE(x)
Definition: memory.h:40
Mailbox was reopened.
Definition: mx.h:72
void mutt_set_virtual(struct Context *ctx)
Set the virtual index number of all the messages in a mailbox.
Definition: mutt_thread.c:1181
char * pattern
limit pattern string
Definition: context.h:41
bool C_UncollapseNew
Config: Open collapsed threads when new mail arrives.
Definition: index.c:108

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Update the index (if unthreaded)

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

Definition at line 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]->virtual = 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
Definition: mailbox.h:99
int msg_count
total number of messages
Definition: mailbox.h:92
int virtual
virtual message number
Definition: email.h:90
struct Body * content
list of MIME parts
Definition: email.h:93
LOFF_T offset
offset where the actual data begins
Definition: body.h:46
int vcount
the number of virtual messages
Definition: mailbox.h:102
The body of an email.
Definition: body.h:34
struct PatternHead * limit_pattern
compiled limit pattern
Definition: context.h:42
struct Mailbox * mailbox
Definition: context.h:52
bool limited
is this message in a limited view?
Definition: email.h:77
off_t vsize
Definition: context.h:40
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:1970
void mutt_sort_headers(struct Context *ctx, bool init)
Sort emails by their headers.
Definition: sort.c:361
#define SLIST_FIRST(head)
Definition: queue.h:229
LOFF_T length
length (in bytes) of attachment
Definition: body.h:47
#define MUTT_MATCH_FULL_ADDRESS
Match the full address.
Definition: pattern.h:72
int * v2r
mapping from virtual to real msgno
Definition: mailbox.h:101
int mx_msg_padding_size(struct Mailbox *m)
Bytes of padding between messages - Wrapper for MxOps::msg_padding_size.
Definition: mx.c:1454
long hdr_offset
offset in stream where the headers begin.
Definition: body.h:42
Mailbox was reopened.
Definition: mx.h:72
char * pattern
limit pattern string
Definition: context.h:41

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Update the index.

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

Definition at line 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
Definition: mailbox.h:99
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:102
struct Mailbox * mailbox
Definition: context.h:52
WHERE short C_Sort
Config: Sort method for the index.
Definition: sort.h:58
static int ci_first_message(void)
Get index of first new message.
Definition: index.c:330
int * v2r
mapping from virtual to real msgno
Definition: mailbox.h:101
int index
the absolute (unsorted) message number
Definition: email.h:88
static void update_index_threaded(struct Context *ctx, int check, int oldcount)
Update the index (if threaded)
Definition: index.c: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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Change to a different mailbox.

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

Definition at line 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 = mutt_find_mailbox_desc(buf);
627  if (m)
628  {
629  magic = m->magic;
630  mutt_str_strfcpy(buf, mutt_b2s(m->pathbuf), buflen);
631  }
632  else
633  {
634  // Bail.
635  mutt_error(_("%s is not a mailbox"), buf);
636  return -1;
637  }
638  }
639 
640  /* keepalive failure in mutt_enter_fname may kill connection. #3028 */
642  ctx_free(&Context);
643 
644  if (Context)
645  {
646  char *new_last_folder = NULL;
647 #ifdef USE_INOTIFY
648  int monitor_remove_rc = mutt_monitor_remove(NULL);
649 #endif
650 #ifdef USE_COMPRESSED
651  if (Context->mailbox->compress_info && (Context->mailbox->realpath[0] != '\0'))
652  new_last_folder = mutt_str_strdup(Context->mailbox->realpath);
653  else
654 #endif
655  new_last_folder = mutt_str_strdup(mutt_b2s(Context->mailbox->pathbuf));
656  *oldcount = Context ? Context->mailbox->msg_count : 0;
657 
658  int check = mx_mbox_close(&Context);
659  if (check != 0)
660  {
661 #ifdef USE_INOTIFY
662  if (monitor_remove_rc == 0)
663  mutt_monitor_add(NULL);
664 #endif
665  if ((check == MUTT_NEW_MAIL) || (check == MUTT_REOPENED))
666  update_index(menu, Context, check, *oldcount, *index_hint);
667 
668  FREE(&new_last_folder);
669  OptSearchInvalid = true;
670  menu->redraw |= REDRAW_INDEX | REDRAW_STATUS;
671  return 0;
672  }
673  FREE(&LastFolder);
674  LastFolder = new_last_folder;
675  }
677 
678  mutt_sleep(0);
679 
680  /* Note that menu->menu may be MENU_PAGER if the change folder
681  * operation originated from the pager.
682  *
683  * However, exec commands currently use CurrentMenu to determine what
684  * functions are available, which is automatically set by the
685  * mutt_push/pop_current_menu() functions. If that changes, the menu
686  * would need to be reset here, and the pager cleanup code after the
687  * switch statement would need to be run. */
688  mutt_folder_hook(buf, m ? m->desc : NULL);
689 
690  const int flags = (C_ReadOnly || (op == OP_MAIN_CHANGE_FOLDER_READONLY)
691 #ifdef USE_NOTMUCH
692  || (op == OP_MAIN_VFOLDER_FROM_QUERY_READONLY)
693 #endif
694  ) ?
695  MUTT_READONLY :
697 
698  bool free_m = false;
699  if (!m)
700  {
701  m = mx_path_resolve(buf);
702  free_m = true;
703  }
704  Context = mx_mbox_open(m, flags);
705  if (Context)
706  {
707  menu->current = ci_first_message();
708 #ifdef USE_INOTIFY
709  mutt_monitor_add(NULL);
710 #endif
711  }
712  else
713  {
714  menu->current = 0;
715  if (free_m)
716  mailbox_free(&m);
717  }
718 
719  if (((C_Sort & SORT_MASK) == SORT_THREADS) && C_CollapseAll)
720  collapse_all(menu, 0);
721 
722 #ifdef USE_SIDEBAR
724 #endif
725 
727  mutt_mailbox_check(Context ? Context->mailbox : NULL, MUTT_MAILBOX_CHECK_FORCE); /* force the mailbox check after we have changed the folder */
728  menu->redraw = REDRAW_FULL;
729  OptSearchInvalid = true;
730 
731  return 0;
732 }
#define MUTT_OPEN_NO_FLAGS
No flags are set.
Definition: mx.h:48
The "current" mailbox.
Definition: context.h:38
#define REDRAW_FULL
Redraw everything.
Definition: mutt_menu.h:47
int msg_count
total number of messages
Definition: mailbox.h:92
struct ConnAccount account
Definition: connection.h:36
int mx_mbox_close(struct Context **ptr)
Save changes and close mailbox.
Definition: mx.c:546
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:1285
char * desc
Definition: mailbox.h:87
int mutt_monitor_remove(struct Mailbox *m)
Remove a watch for a mailbox.
Definition: monitor.c:506
char * realpath
used for duplicate detection, context comparison, and the sidebar
Definition: mailbox.h:86
#define _(a)
Definition: message.h:28
struct Context * mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:247
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:51
int mutt_monitor_add(struct Mailbox *m)
Add a watch for a mailbox.
Definition: monitor.c:461
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:514
void mutt_sleep(short s)
Sleep for a while.
Definition: muttlib.c:1498
struct Mailbox * mailbox
Definition: context.h:52
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:105
enum MailboxType magic
mailbox type
Definition: mailbox.h:105
WHERE char * CurrentFolder
Currently selected mailbox.
Definition: globals.h:53
WHERE short C_Sort
Config: Sort method for the index.
Definition: sort.h:58
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:141
WHERE bool C_ReadOnly
Config: Open folders in read-only mode.
Definition: globals.h:243
void ctx_free(struct Context **ctx)
Free a Context.
Definition: context.c:47
int mutt_mailbox_check(struct Mailbox *m_cur, int force)
Check all AllMailboxes for new mail.
Definition: mailbox.c:341
#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
MailboxType
Supported mailbox formats.
Definition: magic.h:33
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:753
#define MUTT_MAILBOX_CHECK_FORCE
Definition: mailbox.h:168
Error occurred examining mailbox.
Definition: magic.h:35
WHERE bool OptSearchInvalid
(pseudo) used to invalidate the search pat
Definition: options.h:49
void update_index(struct Menu *menu, struct Context *ctx, int check, int oldcount, int index_hint)
Update the index.
Definition: index.c:557
void mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:456
void nntp_expand_path(char *buf, size_t buflen, struct ConnAccount *acct)
Make fully qualified url from newsgroup name.
Definition: newsrc.c:549
struct Buffer * pathbuf
Definition: mailbox.h:85
MuttRedrawFlags redraw
when to redraw the screen
Definition: mutt_menu.h:89
struct Connection * conn
Definition: nntp.h:103
Mailbox wasn&#39;t recognised.
Definition: magic.h:36
#define REDRAW_INDEX
Redraw the index.
Definition: mutt_menu.h:42
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
#define mutt_error(...)
Definition: logging.h:83
void * compress_info
compressed mbox module private data
Definition: mailbox.h:124
#define FREE(x)
Definition: memory.h:40
struct Mailbox * mx_path_resolve(const char *path)
XXX.
Definition: mx.c:1531
New mail received in Mailbox.
Definition: mx.h:70
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:291
enum MailboxType mx_path_probe(const char *path, struct stat *st)
Find a mailbox that understands a path.
Definition: mx.c:1226
Mailbox was reopened.
Definition: mx.h:72
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:77
struct Mailbox * mutt_find_mailbox_desc(const char *desc)
Find the mailbox with a given description.
Definition: mailbox.c:297

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

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

Definition at line 737 of file index.c.

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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int index_color ( int  line)

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

Definition at line 810 of file index.c.

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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Draw a highlighted status bar.

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

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

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

Definition at line 839 of file index.c.

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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void index_custom_redraw ( struct Menu menu)
static

Redraw the index - Implements Menu::menu_custom_redraw()

Definition at line 965 of file index.c.

966 {
967  if (menu->redraw & REDRAW_FULL)
968  {
969  menu_redraw_full(menu);
970  mutt_show_error();
971  }
972 
973 #ifdef USE_SIDEBAR
974  if (menu->redraw & REDRAW_SIDEBAR)
975  menu_redraw_sidebar(menu);
976 #endif
977 
978  if (Context && Context->mailbox->emails && !(menu->current >= Context->mailbox->vcount))
979  {
980  menu_check_recenter(menu);
981 
982  if (menu->redraw & REDRAW_INDEX)
983  {
984  menu_redraw_index(menu);
985  menu->redraw |= REDRAW_STATUS;
986  }
987  else if (menu->redraw & (REDRAW_MOTION_RESYNC | REDRAW_MOTION))
988  menu_redraw_motion(menu);
989  else if (menu->redraw & REDRAW_CURRENT)
990  menu_redraw_current(menu);
991  }
992 
993  if (menu->redraw & REDRAW_STATUS)
994  {
995  char buf[1024];
996  menu_status_line(buf, sizeof(buf), menu, NONULL(C_StatusFormat));
999  mutt_draw_statusline(MuttStatusWindow->cols, buf, sizeof(buf));
1000  NORMAL_COLOR;
1001  menu->redraw &= ~REDRAW_STATUS;
1002  if (C_TsEnabled && TsSupported)
1003  {
1004  menu_status_line(buf, sizeof(buf), menu, NONULL(C_TsStatusFormat));
1005  mutt_ts_status(buf);
1006  menu_status_line(buf, sizeof(buf), menu, NONULL(C_TsIconFormat));
1007  mutt_ts_icon(buf);
1008  }
1009  }
1010 
1011  menu->redraw = 0;
1012 }
struct Email ** emails
Definition: mailbox.h:99
The "current" mailbox.
Definition: context.h:38
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:36
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:393
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:102
#define REDRAW_SIDEBAR
Redraw the sidebar.
Definition: mutt_menu.h:51
struct Mailbox * mailbox
Definition: context.h:52
#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:839
#define REDRAW_CURRENT
Redraw the current line of the menu.
Definition: mutt_menu.h:45

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int mutt_index_menu ( void  )

Display a list of emails.

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

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

Definition at line 1021 of file index.c.

1022 {
1023  char buf[PATH_MAX], helpstr[1024];
1024  OpenMailboxFlags flags;
1025  int op = OP_NULL;
1026  bool done = false; /* controls when to exit the "event" loop */
1027  bool tag = false; /* has the tag-prefix command been pressed? */
1028  int newcount = -1;
1029  int oldcount = -1;
1030  int index_hint; /* used to restore cursor position */
1031  bool do_mailbox_notify = true;
1032  int close = 0; /* did we OP_QUIT or OP_EXIT out of this menu? */
1033  int attach_msg = OptAttachMsg;
1034 
1035  struct Menu *menu = mutt_menu_new(MENU_MAIN);
1037  menu->menu_color = index_color;
1038  menu->current = ci_first_message();
1039  menu->help = mutt_compile_help(helpstr, sizeof(helpstr), MENU_MAIN,
1040 #ifdef USE_NNTP
1041  (Context && (Context->mailbox->magic == MUTT_NNTP)) ?
1042  IndexNewsHelp :
1043 #endif
1044  IndexHelp);
1046  mutt_menu_push_current(menu);
1047 
1048  if (!attach_msg)
1049  {
1050  /* force the mailbox check after we enter the folder */
1052  }
1053 #ifdef USE_INOTIFY
1054  mutt_monitor_add(NULL);
1055 #endif
1056 
1057  if (((C_Sort & SORT_MASK) == SORT_THREADS) && C_CollapseAll)
1058  {
1059  collapse_all(menu, 0);
1060  menu->redraw = REDRAW_FULL;
1061  }
1062 
1063  while (true)
1064  {
1065  /* Clear the tag prefix unless we just started it. Don't clear
1066  * the prefix on a timeout (op==-2), but do clear on an abort (op==-1) */
1067  if (tag && (op != OP_TAG_PREFIX) && (op != OP_TAG_PREFIX_COND) && (op != -2))
1068  tag = false;
1069 
1070  /* check if we need to resort the index because just about
1071  * any 'op' below could do mutt_enter_command(), either here or
1072  * from any new menu launched, and change $sort/$sort_aux */
1073  if (OptNeedResort && Context && (Context->mailbox->msg_count != 0) &&
1074  (menu->current >= 0))
1075  resort_index(menu);
1076 
1077  menu->max = Context ? Context->mailbox->vcount : 0;
1078  oldcount = Context ? Context->mailbox->msg_count : 0;
1079 
1080  if (OptRedrawTree && Context && (Context->mailbox->msg_count != 0) &&
1081  ((C_Sort & SORT_MASK) == SORT_THREADS))
1082  {
1084  menu->redraw |= REDRAW_STATUS;
1085  OptRedrawTree = false;
1086  }
1087 
1088  if (Context)
1089  Context->menu = menu;
1090 
1091  if (Context && !attach_msg)
1092  {
1093  int check;
1094  /* check for new mail in the mailbox. If nonzero, then something has
1095  * changed about the file (either we got new mail or the file was
1096  * modified underneath us.) */
1097 
1098  index_hint = ((Context->mailbox->vcount != 0) && (menu->current >= 0) &&
1099  (menu->current < Context->mailbox->vcount)) ?
1100  CUR_EMAIL->index :
1101  0;
1102 
1103  check = mx_mbox_check(Context->mailbox, &index_hint);
1104  if (check < 0)
1105  {
1107  {
1108  /* fatal error occurred */
1109  ctx_free(&Context);
1110  menu->redraw = REDRAW_FULL;
1111  }
1112 
1113  OptSearchInvalid = true;
1114  }
1115  else if ((check == MUTT_NEW_MAIL) || (check == MUTT_REOPENED) || (check == MUTT_FLAGS))
1116  {
1117  /* notify the user of new mail */
1118  if (check == MUTT_REOPENED)
1119  {
1120  mutt_error(
1121  _("Mailbox was externally modified. Flags may be wrong."));
1122  }
1123  else if (check == MUTT_NEW_MAIL)
1124  {
1125  for (size_t i = oldcount; i < Context->mailbox->msg_count; i++)
1126  {
1127  if (!Context->mailbox->emails[i]->read)
1128  {
1129  mutt_message(_("New mail in this mailbox"));
1130  if (C_BeepNew)
1131  beep();
1132  if (C_NewMailCommand)
1133  {
1134  char cmd[1024];
1135  menu_status_line(cmd, sizeof(cmd), menu, NONULL(C_NewMailCommand));
1136  if (mutt_system(cmd) != 0)
1137  mutt_error(_("Error running \"%s\""), cmd);
1138  }
1139  break;
1140  }
1141  }
1142  }
1143  else if (check == MUTT_FLAGS)
1144  mutt_message(_("Mailbox was externally modified"));
1145 
1146  /* avoid the message being overwritten by mailbox */
1147  do_mailbox_notify = false;
1148 
1149  bool q = Context->mailbox->quiet;
1150  Context->mailbox->quiet = true;
1151  update_index(menu, Context, check, oldcount, index_hint);
1152  Context->mailbox->quiet = q;
1153 
1154  menu->redraw = REDRAW_FULL;
1155  menu->max = Context->mailbox->vcount;
1156 
1157  OptSearchInvalid = true;
1158  }
1159  }
1160 
1161  if (!attach_msg)
1162  {
1163  /* check for new mail in the incoming folders */
1164  oldcount = newcount;
1165  newcount = mutt_mailbox_check(Context ? Context->mailbox : NULL, 0);
1166  if (newcount != oldcount)
1167  menu->redraw |= REDRAW_STATUS;
1168  if (do_mailbox_notify)
1169  {
1170  if (mutt_mailbox_notify(Context ? Context->mailbox : NULL))
1171  {
1172  menu->redraw |= REDRAW_STATUS;
1173  if (C_BeepNew)
1174  beep();
1175  if (C_NewMailCommand)
1176  {
1177  char cmd[1024];
1178  menu_status_line(cmd, sizeof(cmd), menu, NONULL(C_NewMailCommand));
1179  if (mutt_system(cmd) != 0)
1180  mutt_error(_("Error running \"%s\""), cmd);
1181  }
1182  }
1183  }
1184  else
1185  do_mailbox_notify = true;
1186  }
1187 
1188  if (op >= 0)
1189  mutt_curs_set(0);
1190 
1191  if (menu->menu == MENU_MAIN)
1192  {
1193  index_custom_redraw(menu);
1194 
1195  /* give visual indication that the next command is a tag- command */
1196  if (tag)
1197  {
1198  mutt_window_mvaddstr(MuttMessageWindow, 0, 0, "tag-");
1200  }
1201 
1202  if (menu->current < menu->max)
1203  menu->oldcurrent = menu->current;
1204  else
1205  menu->oldcurrent = -1;
1206 
1207  if (C_ArrowCursor)
1208  mutt_window_move(MuttIndexWindow, menu->current - menu->top + menu->offset, 2);
1209  else if (C_BrailleFriendly)
1210  mutt_window_move(MuttIndexWindow, menu->current - menu->top + menu->offset, 0);
1211  else
1212  {
1213  mutt_window_move(MuttIndexWindow, menu->current - menu->top + menu->offset,
1214  MuttIndexWindow->cols - 1);
1215  }
1216  mutt_refresh();
1217 
1218  if (SigWinch)
1219  {
1220  mutt_flushinp();
1222  SigWinch = 0;
1223  menu->top = 0; /* so we scroll the right amount */
1224  /* force a real complete redraw. clrtobot() doesn't seem to be able
1225  * to handle every case without this. */
1226  clearok(stdscr, true);
1227  continue;
1228  }
1229 
1230  op = km_dokey(MENU_MAIN);
1231 
1232  mutt_debug(LL_DEBUG3, "[%d]: Got op %d\n", __LINE__, op);
1233 
1234  /* either user abort or timeout */
1235  if (op < 0)
1236  {
1238  if (tag)
1240  continue;
1241  }
1242 
1243  mutt_curs_set(1);
1244 
1245  /* special handling for the tag-prefix function */
1246  if ((op == OP_TAG_PREFIX) || (op == OP_TAG_PREFIX_COND))
1247  {
1248  /* A second tag-prefix command aborts */
1249  if (tag)
1250  {
1251  tag = false;
1253  continue;
1254  }
1255 
1256  if (!Context || !Context->mailbox)
1257  {
1258  mutt_error(_("No mailbox is open"));
1259  continue;
1260  }
1261 
1262  if (Context->mailbox->msg_tagged == 0)
1263  {
1264  if (op == OP_TAG_PREFIX)
1265  mutt_error(_("No tagged messages"));
1266  else if (op == OP_TAG_PREFIX_COND)
1267  {
1269  mutt_message(_("Nothing to do"));
1270  }
1271  continue;
1272  }
1273 
1274  /* get the real command */
1275  tag = true;
1276  continue;
1277  }
1278  else if (C_AutoTag && Context && Context->mailbox &&
1279  (Context->mailbox->msg_tagged != 0))
1280  tag = true;
1281 
1282  mutt_clear_error();
1283  }
1284  else
1285  {
1286  if (menu->current < menu->max)
1287  menu->oldcurrent = menu->current;
1288  else
1289  menu->oldcurrent = -1;
1290 
1291  mutt_curs_set(1); /* fallback from the pager */
1292  }
1293 
1294 #ifdef USE_NNTP
1295  OptNews = false; /* for any case */
1296 #endif
1297 
1298 #ifdef USE_NOTMUCH
1299  if (Context)
1301 #endif
1302 
1303  switch (op)
1304  {
1305  /* ----------------------------------------------------------------------
1306  * movement commands
1307  */
1308 
1309  case OP_BOTTOM_PAGE:
1310  menu_bottom_page(menu);
1311  break;
1312  case OP_CURRENT_BOTTOM:
1313  menu_current_bottom(menu);
1314  break;
1315  case OP_CURRENT_MIDDLE:
1316  menu_current_middle(menu);
1317  break;
1318  case OP_CURRENT_TOP:
1319  menu_current_top(menu);
1320  break;
1321  case OP_FIRST_ENTRY:
1322  menu_first_entry(menu);
1323  break;
1324  case OP_HALF_DOWN:
1325  menu_half_down(menu);
1326  break;
1327  case OP_HALF_UP:
1328  menu_half_up(menu);
1329  break;
1330  case OP_LAST_ENTRY:
1331  menu_last_entry(menu);
1332  break;
1333  case OP_MIDDLE_PAGE:
1334  menu_middle_page(menu);
1335  break;
1336  case OP_NEXT_LINE:
1337  menu_next_line(menu);
1338  break;
1339  case OP_NEXT_PAGE:
1340  menu_next_page(menu);
1341  break;
1342  case OP_PREV_LINE:
1343  menu_prev_line(menu);
1344  break;
1345  case OP_PREV_PAGE:
1346  menu_prev_page(menu);
1347  break;
1348  case OP_TOP_PAGE:
1349  menu_top_page(menu);
1350  break;
1351 
1352 #ifdef USE_NNTP
1353  case OP_GET_PARENT:
1355  break;
1356  /* fallthrough */
1357 
1358  case OP_GET_MESSAGE:
1360  break;
1361  if (Context->mailbox->magic == MUTT_NNTP)
1362  {
1363  struct Email *e = NULL;
1364 
1365  if (op == OP_GET_MESSAGE)
1366  {
1367  buf[0] = '\0';
1368  if ((mutt_get_field(_("Enter Message-Id: "), buf, sizeof(buf), 0) != 0) ||
1369  !buf[0])
1370  {
1371  break;
1372  }
1373  }
1374  else
1375  {
1376  if (STAILQ_EMPTY(&CUR_EMAIL->env->references))
1377  {
1378  mutt_error(_("Article has no parent reference"));
1379  break;
1380  }
1381  mutt_str_strfcpy(buf, STAILQ_FIRST(&CUR_EMAIL->env->references)->data,
1382  sizeof(buf));
1383  }
1384  if (!Context->mailbox->id_hash)
1386  e = mutt_hash_find(Context->mailbox->id_hash, buf);
1387  if (e)
1388  {
1389  if (e->virtual != -1)
1390  {
1391  menu->current = e->virtual;
1392  menu->redraw = REDRAW_MOTION_RESYNC;
1393  }
1394  else if (e->collapsed)
1395  {
1398  menu->current = e->virtual;
1399  menu->redraw = REDRAW_MOTION_RESYNC;
1400  }
1401  else
1402  mutt_error(_("Message is not visible in limited view"));
1403  }
1404  else
1405  {
1406  mutt_message(_("Fetching %s from server..."), buf);
1407  int rc = nntp_check_msgid(Context, buf);
1408  if (rc == 0)
1409  {
1411  mutt_sort_headers(Context, false);
1412  menu->current = e->virtual;
1413  menu->redraw = REDRAW_FULL;
1414  }
1415  else if (rc > 0)
1416  mutt_error(_("Article %s not found on the server"), buf);
1417  }
1418  }
1419  break;
1420 
1421  case OP_GET_CHILDREN:
1422  case OP_RECONSTRUCT_THREAD:
1423  if (!prereq(Context, menu,
1425  {
1426  break;
1427  }
1428  if (Context->mailbox->magic == MUTT_NNTP)
1429  {
1430  int oldmsgcount = Context->mailbox->msg_count;
1431  int oldindex = CUR_EMAIL->index;
1432  int rc = 0;
1433 
1434  if (!CUR_EMAIL->env->message_id)
1435  {
1436  mutt_error(_("No Message-Id. Unable to perform operation."));
1437  break;
1438  }
1439 
1440  mutt_message(_("Fetching message headers..."));
1441  if (!Context->mailbox->id_hash)
1443  mutt_str_strfcpy(buf, CUR_EMAIL->env->message_id, sizeof(buf));
1444 
1445  /* trying to find msgid of the root message */
1446  if (op == OP_RECONSTRUCT_THREAD)
1447  {
1448  struct ListNode *ref = NULL;
1449  STAILQ_FOREACH(ref, &CUR_EMAIL->env->references, entries)
1450  {
1451  if (!mutt_hash_find(Context->mailbox->id_hash, ref->data))
1452  {
1453  rc = nntp_check_msgid(Context, ref->data);
1454  if (rc < 0)
1455  break;
1456  }
1457 
1458  /* the last msgid in References is the root message */
1459  if (!STAILQ_NEXT(ref, entries))
1460  mutt_str_strfcpy(buf, ref->data, sizeof(buf));
1461  }
1462  }
1463 
1464  /* fetching all child messages */
1465  if (rc >= 0)
1466  rc = nntp_check_children(Context, buf);
1467 
1468  /* at least one message has been loaded */
1469  if (Context->mailbox->msg_count > oldmsgcount)
1470  {
1471  struct Email *oldcur = CUR_EMAIL;
1472  struct Email *e = NULL;
1473  bool quiet = Context->mailbox->quiet;
1474 
1475  if (rc < 0)
1476  Context->mailbox->quiet = true;
1477  mutt_sort_headers(Context, (op == OP_RECONSTRUCT_THREAD));
1478  Context->mailbox->quiet = quiet;
1479 
1480  /* Similar to OP_MAIN_ENTIRE_THREAD, keep displaying the old message, but
1481  * update the index */
1482  if (menu->menu == MENU_PAGER)
1483  {
1484  menu->current = oldcur->virtual;
1485  menu->redraw = REDRAW_STATUS | REDRAW_INDEX;
1486  op = OP_DISPLAY_MESSAGE;
1487  continue;
1488  }
1489 
1490  /* if the root message was retrieved, move to it */
1491  e = mutt_hash_find(Context->mailbox->id_hash, buf);
1492  if (e)
1493  menu->current = e->virtual;
1494 
1495  /* try to restore old position */
1496  else
1497  {
1498  for (int i = 0; i < Context->mailbox->msg_count; i++)
1499  {
1500  if (Context->mailbox->emails[i]->index == oldindex)
1501  {
1502  menu->current = Context->mailbox->emails[i]->virtual;
1503  /* as an added courtesy, recenter the menu
1504  * with the current entry at the middle of the screen */
1505  menu_check_recenter(menu);
1506  menu_current_middle(menu);
1507  }
1508  }
1509  }
1510  menu->redraw = REDRAW_FULL;
1511  }
1512  else if (rc >= 0)
1513  {
1514  mutt_error(_("No deleted messages found in the thread"));
1515  /* Similar to OP_MAIN_ENTIRE_THREAD, keep displaying the old message, but
1516  * update the index */
1517  if (menu->menu == MENU_PAGER)
1518  {
1519  op = OP_DISPLAY_MESSAGE;
1520  continue;
1521  }
1522  }
1523  }
1524  break;
1525 #endif
1526 
1527  case OP_JUMP:
1528  {
1529  int msg_num = 0;
1531  break;
1532  if (isdigit(LastKey))
1534  buf[0] = '\0';
1535  if ((mutt_get_field(_("Jump to message: "), buf, sizeof(buf), 0) != 0) ||
1536  (buf[0] == '\0'))
1537  {
1538  mutt_error(_("Nothing to do"));
1539  }
1540  else if (mutt_str_atoi(buf, &msg_num) < 0)
1541  mutt_error(_("Argument must be a message number"));
1542  else if ((msg_num < 1) || (msg_num > Context->mailbox->msg_count))
1543  mutt_error(_("Invalid message number"));
1544  else if (!message_is_visible(Context, msg_num - 1))
1545  mutt_error(_("That message is not visible"));
1546  else
1547  {
1548  struct Email *e = Context->mailbox->emails[msg_num - 1];
1549 
1550  if (mutt_messages_in_thread(Context->mailbox, e, 1) > 1)
1551  {
1554  }
1555  menu->current = e->virtual;
1556  }
1557 
1558  if (menu->menu == MENU_PAGER)
1559  {
1560  op = OP_DISPLAY_MESSAGE;
1561  continue;
1562  }
1563  else
1564  menu->redraw = REDRAW_FULL;
1565 
1566  break;
1567  }
1568 
1569  /* --------------------------------------------------------------------
1570  * 'index' specific commands
1571  */
1572 
1573  case OP_MAIN_DELETE_PATTERN:
1574  if (!prereq(Context, menu,
1576  {
1577  break;
1578  }
1579  /* L10N: CHECK_ACL */
1580  /* L10N: Due to the implementation details we do not know whether we
1581  delete zero, 1, 12, ... messages. So in English we use
1582  "messages". Your language might have other means to express this. */
1583  if (!check_acl(Context, MUTT_ACL_DELETE, _("Can't delete messages")))
1584  break;
1585 
1586  mutt_pattern_func(MUTT_DELETE, _("Delete messages matching: "));
1587  menu->redraw |= REDRAW_INDEX | REDRAW_STATUS;
1588  break;
1589 
1590 #ifdef USE_POP
1591  case OP_MAIN_FETCH_MAIL:
1592  if (!prereq(Context, menu, CHECK_ATTACH))
1593  break;
1594  pop_fetch_mail();
1595  menu->redraw = REDRAW_FULL;
1596  break;
1597 #endif /* USE_POP */
1598 
1599  case OP_SHOW_LOG_MESSAGES:
1600  {
1601  char tempfile[PATH_MAX];
1602  mutt_mktemp(tempfile, sizeof(tempfile));
1603 
1604  FILE *fp = mutt_file_fopen(tempfile, "a+");
1605  if (!fp)
1606  {
1607  mutt_perror("fopen");
1608  break;
1609  }
1610 
1611  log_queue_save(fp);
1612  mutt_file_fclose(&fp);
1613 
1614  mutt_do_pager("messages", tempfile, MUTT_PAGER_LOGS, NULL);
1615  break;
1616  }
1617 
1618  case OP_HELP:
1620  menu->redraw = REDRAW_FULL;
1621  break;
1622 
1623  case OP_MAIN_SHOW_LIMIT:
1624  if (!prereq(Context, menu, CHECK_IN_MAILBOX))
1625  break;
1626  if (!Context->pattern)
1627  mutt_message(_("No limit pattern is in effect"));
1628  else
1629  {
1630  char buf2[256];
1631  /* L10N: ask for a limit to apply */
1632  snprintf(buf2, sizeof(buf2), _("Limit: %s"), Context->pattern);
1633  mutt_message("%s", buf2);
1634  }
1635  break;
1636 
1637  case OP_LIMIT_CURRENT_THREAD:
1638  case OP_MAIN_LIMIT:
1639  case OP_TOGGLE_READ:
1640  if (!prereq(Context, menu, CHECK_IN_MAILBOX))
1641  break;
1642  menu->oldcurrent = ((Context->mailbox->vcount != 0) && (menu->current >= 0) &&
1643  (menu->current < Context->mailbox->vcount)) ?
1644  CUR_EMAIL->index :
1645  -1;
1646  if (op == OP_TOGGLE_READ)
1647  {
1648  char buf2[1024];
1649 
1650  if (!Context->pattern || (strncmp(Context->pattern, "!~R!~D~s", 8) != 0))
1651  {
1652  snprintf(buf2, sizeof(buf2), "!~R!~D~s%s",
1653  Context->pattern ? Context->pattern : ".*");
1654  }
1655  else
1656  {
1657  mutt_str_strfcpy(buf2, Context->pattern + 8, sizeof(buf2));
1658  if (!*buf2 || (strncmp(buf2, ".*", 2) == 0))
1659  snprintf(buf2, sizeof(buf2), "~A");
1660  }
1661  FREE(&Context->pattern);
1662  Context->pattern = mutt_str_strdup(buf2);
1664  }
1665 
1666  if (((op == OP_LIMIT_CURRENT_THREAD) && mutt_limit_current_thread(CUR_EMAIL)) ||
1667  (op == OP_TOGGLE_READ) ||
1668  ((op == OP_MAIN_LIMIT) &&
1670  _("Limit to messages matching: ")) == 0)))
1671  {
1672  if (menu->oldcurrent >= 0)
1673  {
1674  /* try to find what used to be the current message */
1675  menu->current = -1;
1676  for (size_t i = 0; i < Context->mailbox->vcount; i++)
1677  {
1678  if (Context->mailbox->emails[Context->mailbox->v2r[i]]->index == menu->oldcurrent)
1679  {
1680  menu->current = i;
1681  break;
1682  }
1683  }
1684  if (menu->current < 0)
1685  menu->current = 0;
1686  }
1687  else
1688  menu->current = 0;
1689  if ((Context->mailbox->msg_count != 0) && ((C_Sort & SORT_MASK) == SORT_THREADS))
1690  {
1691  if (C_CollapseAll)
1692  collapse_all(menu, 0);
1694  }
1695  menu->redraw = REDRAW_FULL;
1696  }
1697  if (Context->pattern)
1698  mutt_message(_("To view all messages, limit to \"all\""));
1699  break;
1700 
1701  case OP_QUIT:
1702  close = op;
1703  if (attach_msg)
1704  {
1705  done = true;
1706  break;
1707  }
1708 
1709  if (query_quadoption(C_Quit, _("Quit NeoMutt?")) == MUTT_YES)
1710  {
1711  int check;
1712 
1713  oldcount = Context ? Context->mailbox->msg_count : 0;
1714 
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  el_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  {
1962  if (!Context || (Context->mailbox->magic != MUTT_NOTMUCH))
1963  {
1964  if (!CUR_EMAIL || !CUR_EMAIL->env || !CUR_EMAIL->env->message_id)
1965  {
1966  mutt_message(_("No virtual folder and no Message-Id, aborting"));
1967  break;
1968  } // no virtual folder, but we have message-id, reconstruct thread on-the-fly
1969  strncpy(buf, "id:", sizeof(buf));
1970  int msg_id_offset = 0;
1971  if ((CUR_EMAIL->env->message_id)[0] == '<')
1972  msg_id_offset = 1;
1973  mutt_str_strcat(buf, sizeof(buf), (CUR_EMAIL->env->message_id) + msg_id_offset);
1974  if (buf[strlen(buf) - 1] == '>')
1975  buf[strlen(buf) - 1] = '\0';
1976  if (!nm_uri_from_query(Context->mailbox, buf, sizeof(buf)))
1977  {
1978  mutt_message(_("Failed to create query, aborting"));
1979  break;
1980  }
1981  else
1982  main_change_folder(menu, op, NULL, buf, sizeof(buf), &oldcount, &index_hint);
1983  }
1985  break;
1986  int oc = Context->mailbox->msg_count;
1988  {
1989  mutt_message(_("Failed to read thread, aborting"));
1990  break;
1991  }
1992  if (oc < Context->mailbox->msg_count)
1993  {
1994  struct Email *oldcur = CUR_EMAIL;
1995 
1996  if ((C_Sort & SORT_MASK) == SORT_THREADS)
1997  mutt_sort_headers(Context, false);
1998  menu->current = oldcur->virtual;
1999  menu->redraw = REDRAW_STATUS | REDRAW_INDEX;
2000 
2001  if (oldcur->collapsed || Context->collapsed)
2002  {
2005  }
2006  }
2007  if (menu->menu == MENU_PAGER)
2008  {
2009  op = OP_DISPLAY_MESSAGE;
2010  continue;
2011  }
2012  break;
2013  }
2014 
2015 #endif
2016  case OP_MAIN_MODIFY_TAGS:
2017  case OP_MAIN_MODIFY_TAGS_THEN_HIDE:
2018  {
2020  {
2021  mutt_message(_("Folder doesn't support tagging, aborting"));
2022  break;
2023  }
2025  break;
2026  char *tags = NULL;
2027  if (!tag)
2028  tags = driver_tags_get_with_hidden(&CUR_EMAIL->tags);
2029  int rc = mx_tags_edit(Context->mailbox, tags, buf, sizeof(buf));
2030  FREE(&tags);
2031  if (rc < 0)
2032  break;
2033  else if (rc == 0)
2034  {
2035  mutt_message(_("No tag specified, aborting"));
2036  break;
2037  }
2038 
2039  if (tag)
2040  {
2041  struct Progress progress;
2042 
2043  if (!Context->mailbox->quiet)
2044  {
2045  char msgbuf[256];
2046  snprintf(msgbuf, sizeof(msgbuf), _("Update tags..."));
2047  mutt_progress_init(&progress, msgbuf, MUTT_PROGRESS_MSG, 1,
2049  }
2050 
2051 #ifdef USE_NOTMUCH
2052  if (Context->mailbox->magic == MUTT_NOTMUCH)
2054 #endif
2055  for (int px = 0, i = 0; i < Context->mailbox->msg_count; i++)
2056  {
2057  if (!message_is_tagged(Context, i))
2058  continue;
2059 
2060  if (!Context->mailbox->quiet)
2061  mutt_progress_update(&progress, ++px, -1);
2063  if (op == OP_MAIN_MODIFY_TAGS_THEN_HIDE)
2064  {
2065  bool still_queried = false;
2066 #ifdef USE_NOTMUCH
2067  if (Context->mailbox->magic == MUTT_NOTMUCH)
2068  still_queried = nm_message_is_still_queried(
2070 #endif
2071  Context->mailbox->emails[i]->quasi_deleted = !still_queried;
2072  Context->mailbox->changed = true;
2073  }
2074  }
2075 #ifdef USE_NOTMUCH
2076  if (Context->mailbox->magic == MUTT_NOTMUCH)
2078 #endif
2079  menu->redraw = REDRAW_STATUS | REDRAW_INDEX;
2080  }
2081  else
2082  {
2084  {
2085  mutt_message(_("Failed to modify tags, aborting"));
2086  break;
2087  }
2088  if (op == OP_MAIN_MODIFY_TAGS_THEN_HIDE)
2089  {
2090  bool still_queried = false;
2091 #ifdef USE_NOTMUCH
2092  if (Context->mailbox->magic == MUTT_NOTMUCH)
2094 #endif
2095  CUR_EMAIL->quasi_deleted = !still_queried;
2096  Context->mailbox->changed = true;
2097  }
2098  if (menu->menu == MENU_PAGER)
2099  {
2100  op = OP_DISPLAY_MESSAGE;
2101  continue;
2102  }
2103  if (C_Resolve)
2104  {
2105  menu->current = ci_next_undeleted(menu->current);
2106  if (menu->current == -1)
2107  {
2108  menu->current = menu->oldcurrent;
2109  menu->redraw = REDRAW_CURRENT;
2110  }
2111  else
2112  menu->redraw = REDRAW_MOTION_RESYNC;
2113  }
2114  else
2115  menu->redraw = REDRAW_CURRENT;
2116  }
2117  menu->redraw |= REDRAW_STATUS;
2118  break;
2119  }
2120 
2121  case OP_CHECK_STATS:
2122  mutt_check_stats();
2123  break;
2124 
2125 #ifdef USE_NOTMUCH
2126  case OP_MAIN_VFOLDER_FROM_QUERY:
2127  case OP_MAIN_VFOLDER_FROM_QUERY_READONLY:
2128  buf[0] = '\0';
2129  if ((mutt_get_field("Query: ", buf, sizeof(buf), MUTT_NM_QUERY) != 0) || !buf[0])
2130  {
2131  mutt_message(_("No query, aborting"));
2132  break;
2133  }
2134  if (!nm_uri_from_query(NULL, buf, sizeof(buf)))
2135  mutt_message(_("Failed to create query, aborting"));
2136  else
2137  main_change_folder(menu, op, NULL, buf, sizeof(buf), &oldcount, &index_hint);
2138  break;
2139 
2140  case OP_MAIN_WINDOWED_VFOLDER_BACKWARD:
2141  if (!prereq(Context, menu, CHECK_IN_MAILBOX))
2142  break;
2143  mutt_debug(LL_DEBUG2, "OP_MAIN_WINDOWED_VFOLDER_BACKWARD\n");
2144  if (C_NmQueryWindowDuration <= 0)
2145  {
2146  mutt_message(_("Windowed queries disabled"));
2147  break;
2148  }
2150  {
2151  mutt_message(_("No notmuch vfolder currently loaded"));
2152  break;
2153  }
2156  if (!nm_uri_from_query(Context->mailbox, buf, sizeof(buf)))
2157  mutt_message(_("Failed to create query, aborting"));
2158  else
2159  main_change_folder(menu, op, NULL, buf, sizeof(buf), &oldcount, &index_hint);
2160  break;
2161 
2162  case OP_MAIN_WINDOWED_VFOLDER_FORWARD:
2163  if (!prereq(Context, menu, CHECK_IN_MAILBOX))
2164  break;
2165  if (C_NmQueryWindowDuration <= 0)
2166  {
2167  mutt_message(_("Windowed queries disabled"));
2168  break;
2169  }
2171  {
2172  mutt_message(_("No notmuch vfolder currently loaded"));
2173  break;
2174  }
2177  if (!nm_uri_from_query(Context->mailbox, buf, sizeof(buf)))
2178  mutt_message(_("Failed to create query, aborting"));
2179  else
2180  {
2181  mutt_debug(LL_DEBUG2, "nm: + windowed query (%s)\n", buf);
2182  main_change_folder(menu, op, NULL, buf, sizeof(buf), &oldcount, &index_hint);
2183  }
2184  break;
2185 
2186  case OP_MAIN_CHANGE_VFOLDER:
2187 #endif
2188 
2189 #ifdef USE_SIDEBAR
2190  case OP_SIDEBAR_OPEN:
2191 #endif
2192  case OP_MAIN_CHANGE_FOLDER:
2193  case OP_MAIN_NEXT_UNREAD_MAILBOX:
2194  case OP_MAIN_CHANGE_FOLDER_READONLY:
2195 #ifdef USE_NNTP
2196  case OP_MAIN_CHANGE_GROUP:
2197  case OP_MAIN_CHANGE_GROUP_READONLY:
2198 #endif
2199  {
2200  bool cont = false; /* Set if we want to continue instead of break */
2201 
2202  struct Buffer *folderbuf = mutt_buffer_pool_get();
2203  mutt_buffer_increase_size(folderbuf, PATH_MAX);
2204  struct Mailbox *m = NULL;
2205  char *cp = NULL;
2206 #ifdef USE_NNTP
2207  OptNews = false;
2208 #endif
2209  if (attach_msg || C_ReadOnly ||
2210 #ifdef USE_NNTP
2211  (op == OP_MAIN_CHANGE_GROUP_READONLY) ||
2212 #endif
2213  (op == OP_MAIN_CHANGE_FOLDER_READONLY))
2214  {
2215  flags = MUTT_READONLY;
2216  }
2217  else
2218  flags = MUTT_OPEN_NO_FLAGS;
2219 
2220  if (flags)
2221  cp = _("Open mailbox in read-only mode");
2222  else
2223  cp = _("Open mailbox");
2224 
2225  if ((op == OP_MAIN_NEXT_UNREAD_MAILBOX) && Context &&
2227  {
2229  mutt_buffer_pretty_mailbox(folderbuf);
2230  mutt_buffer_mailbox(Context ? Context->mailbox : NULL, folderbuf);
2231  if (mutt_buffer_is_empty(folderbuf))
2232  {
2233  mutt_error(_("No mailboxes have new mail"));
2234  goto changefoldercleanup;
2235  }
2236  }
2237 #ifdef USE_SIDEBAR
2238  else if (op == OP_SIDEBAR_OPEN)
2239  {
2240  m = mutt_sb_get_highlight();
2241  if (!m)
2242  goto changefoldercleanup;
2243  mutt_buffer_strcpy(folderbuf, mutt_b2s(m->pathbuf));
2244 
2245  /* Mark the selected dir for the neomutt browser */
2247  }
2248 #endif
2249  else
2250  {
2251  if (C_ChangeFolderNext && Context &&
2253  {
2255  mutt_buffer_pretty_mailbox(folderbuf);
2256  }
2257 #ifdef USE_NNTP
2258  if ((op == OP_MAIN_CHANGE_GROUP) || (op == OP_MAIN_CHANGE_GROUP_READONLY))
2259  {
2260  OptNews = true;
2261  m = Context ? Context->mailbox : NULL;
2263  if (!CurrentNewsSrv)
2264  break;
2265  if (flags)
2266  cp = _("Open newsgroup in read-only mode");
2267  else
2268  cp = _("Open newsgroup");
2269  nntp_mailbox(m, folderbuf->data, folderbuf->dsize);
2270  }
2271  else
2272 #endif
2273  {
2274  /* By default, fill buf with the next mailbox that contains unread
2275  * mail */
2276  mutt_buffer_mailbox(Context ? Context->mailbox : NULL, folderbuf);
2277  }
2278 
2279  if (mutt_buffer_enter_fname(cp, folderbuf, true) == -1)
2280  {
2281  if (menu->menu == MENU_PAGER)
2282  {
2283  op = OP_DISPLAY_MESSAGE;
2284  cont = true;
2285  }
2286  goto changefoldercleanup;
2287  }
2288 
2289  /* Selected directory is okay, let's save it. */
2290  mutt_browser_select_dir(mutt_b2s(folderbuf));
2291 
2292  if (mutt_buffer_is_empty(folderbuf))
2293  {
2295  goto changefoldercleanup;
2296  }
2297  }
2298 
2299  if (!m)
2300  m = mx_mbox_find2(mutt_b2s(folderbuf));
2301 
2302  main_change_folder(menu, op, m, folderbuf->data, folderbuf->dsize,
2303  &oldcount, &index_hint);
2304 #ifdef USE_NNTP
2305  /* mutt_mailbox_check() must be done with mail-reader mode! */
2306  menu->help = mutt_compile_help(
2307  helpstr, sizeof(helpstr), MENU_MAIN,
2309 #endif
2310  mutt_buffer_expand_path(folderbuf);
2311 #ifdef USE_SIDEBAR
2313 #endif
2314  goto changefoldercleanup;
2315 
2316  changefoldercleanup:
2317  mutt_buffer_pool_release(&folderbuf);
2318  if (cont)
2319  continue;
2320  else
2321  break;
2322  }
2323 
2324  case OP_DISPLAY_MESSAGE:
2325  case OP_DISPLAY_HEADERS: /* don't weed the headers */
2327  break;
2328  /* toggle the weeding of headers so that a user can press the key
2329  * again while reading the message. */
2330  if (op == OP_DISPLAY_HEADERS)
2331  bool_str_toggle(Config, "weed", NULL);
2332 
2333  OptNeedResort = false;
2334 
2335  if (((C_Sort & SORT_MASK) == SORT_THREADS) && CUR_EMAIL->collapsed)
2336  {
2339  if (C_UncollapseJump)
2341  }
2342 
2343  if (C_PgpAutoDecode && (tag || !(CUR_EMAIL->security & PGP_TRADITIONAL_CHECKED)))
2344  {
2345  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
2346  el_add_tagged(&el, Context, CUR_EMAIL, tag);
2347  mutt_check_traditional_pgp(&el, &menu->redraw);
2348  el_free(&el);
2349  }
2350  int hint =
2352 
2353  /* If we are returning to the pager via an index menu redirection, we
2354  * need to reset the menu->menu. Otherwise mutt_menu_pop_current() will
2355  * set CurrentMenu incorrectly when we return back to the index menu. */
2356  menu->menu = MENU_MAIN;
2357 
2359  if (op < 0)
2360  {
2361  OptNeedResort = false;
2362  break;
2363  }
2364 
2365  /* This is used to redirect a single operation back here afterwards. If
2366  * mutt_display_message() returns 0, then the menu and pager state will
2367  * be cleaned up after this switch statement. */
2368  menu->menu = MENU_PAGER;
2369  menu->oldcurrent = menu->current;
2370  if (Context)
2372 
2373  continue;
2374 
2375  case OP_EXIT:
2376  close = op;
2377  if ((menu->menu == MENU_MAIN) && attach_msg)
2378  {
2379  done = true;
2380  break;
2381  }
2382 
2383  if ((menu->menu == MENU_MAIN) &&
2384  (query_quadoption(C_Quit, _("Exit NeoMutt without saving?")) == MUTT_YES))
2385  {
2386  if (Context)
2387  {
2389  ctx_free(&Context);
2390  }
2391  done = true;
2392  }
2393  break;
2394 
2395  case OP_MAIN_BREAK_THREAD:
2397  break;
2398  /* L10N: CHECK_ACL */
2399  if (!check_acl(Context, MUTT_ACL_WRITE, _("Can't break thread")))
2400  break;
2401 
2402  if ((C_Sort & SORT_MASK) != SORT_THREADS)
2403  mutt_error(_("Threading is not enabled"));
2404  else if (!STAILQ_EMPTY(&CUR_EMAIL->env->in_reply_to) ||
2405  !STAILQ_EMPTY(&CUR_EMAIL->env->references))
2406  {
2407  {
2408  struct Email *oldcur = CUR_EMAIL;
2409 
2411  mutt_sort_headers(Context, true);
2412  menu->current = oldcur->virtual;
2413  }
2414 
2415  Context->mailbox->changed = true;
2416  mutt_message(_("Thread broken"));
2417 
2418  if (menu->menu == MENU_PAGER)
2419  {
2420  op = OP_DISPLAY_MESSAGE;
2421  continue;
2422  }
2423  else
2424  menu->redraw |= REDRAW_INDEX;
2425  }
2426  else
2427  {
2428  mutt_error(
2429  _("Thread can't be broken, message is not part of a thread"));
2430  }
2431 
2432  break;
2433 
2434  case OP_MAIN_LINK_THREADS:
2436  break;
2437  /* L10N: CHECK_ACL */
2438  if (!check_acl(Context, MUTT_ACL_WRITE, _("Can't link threads")))
2439  break;
2440 
2441  if ((C_Sort & SORT_MASK) != SORT_THREADS)
2442  mutt_error(_("Threading is not enabled"));
2443  else if (!CUR_EMAIL->env->message_id)
2444  mutt_error(_("No Message-ID: header available to link thread"));
2445  else if (!tag && (!Context->last_tag || !Context->last_tag->tagged))
2446  mutt_error(_("First, please tag a message to be linked here"));
2447  else
2448  {
2449  struct Email *oldcur = CUR_EMAIL;
2450  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
2451  el_add_tagged(&el, Context, Context->last_tag, tag);
2452 
2454  {
2455  mutt_sort_headers(Context, true);
2456  menu->current = oldcur->virtual;
2457 
2458  Context->mailbox->changed = true;
2459  mutt_message(_("Threads linked"));
2460  }
2461  else
2462  mutt_error(_("No thread linked"));
2463 
2464  el_free(&el);
2465  }
2466 
2467  if (menu->menu == MENU_PAGER)
2468  {
2469  op = OP_DISPLAY_MESSAGE;
2470  continue;
2471  }
2472  else
2473  menu->redraw |= REDRAW_STATUS | REDRAW_INDEX;
2474 
2475  break;
2476 
2477  case OP_EDIT_TYPE:
2479  break;
2480  mutt_edit_content_type(CUR_EMAIL, CUR_EMAIL->content, NULL);
2481  /* if we were in the pager, redisplay the message */
2482  if (menu->menu == MENU_PAGER)
2483  {
2484  op = OP_DISPLAY_MESSAGE;
2485  continue;
2486  }
2487  else
2488  menu->redraw = REDRAW_CURRENT;
2489  break;
2490 
2491  case OP_MAIN_NEXT_UNDELETED:
2493  break;
2494  if (menu->current >= (Context->mailbox->vcount - 1))
2495  {
2496  if (menu->menu == MENU_MAIN)
2497  mutt_message(_("You are on the last message"));
2498  break;
2499  }
2500  menu->current = ci_next_undeleted(menu->current);
2501  if (menu->current == -1)
2502  {
2503  menu->current = menu->oldcurrent;
2504  if (menu->menu == MENU_MAIN)
2505  mutt_error(_("No undeleted messages"));
2506  }
2507  else if (menu->menu == MENU_PAGER)
2508  {
2509  op = OP_DISPLAY_MESSAGE;
2510  continue;
2511  }
2512  else
2513  menu->redraw = REDRAW_MOTION;
2514  break;
2515 
2516  case OP_NEXT_ENTRY:
2518  break;
2519  if (menu->current >= (Context->mailbox->vcount - 1))
2520  {
2521  if (menu->menu == MENU_MAIN)
2522  mutt_message(_("You are on the last message"));
2523  break;
2524  }
2525  menu->current++;
2526  if (menu->menu == MENU_PAGER)
2527  {
2528  op = OP_DISPLAY_MESSAGE;
2529  continue;
2530  }
2531  else
2532  menu->redraw = REDRAW_MOTION;
2533  break;
2534 
2535  case OP_MAIN_PREV_UNDELETED:
2537  break;
2538  if (menu->current < 1)
2539  {
2540  mutt_message(_("You are on the first message"));
2541  break;
2542  }
2543  menu->current = ci_previous_undeleted(menu->current);
2544  if (menu->current == -1)
2545  {
2546  menu->current = menu->oldcurrent;
2547  if (menu->menu == MENU_MAIN)
2548  mutt_error(_("No undeleted messages"));
2549  }
2550  else if (menu->menu == MENU_PAGER)
2551  {
2552  op = OP_DISPLAY_MESSAGE;
2553  continue;
2554  }
2555  else
2556  menu->redraw = REDRAW_MOTION;
2557  break;
2558 
2559  case OP_PREV_ENTRY:
2561  break;
2562  if (menu->current < 1)
2563  {
2564  if (menu->menu == MENU_MAIN)
2565  mutt_message(_("You are on the first message"));
2566  break;
2567  }
2568  menu->current--;
2569  if (menu->menu == MENU_PAGER)
2570  {
2571  op = OP_DISPLAY_MESSAGE;
2572  continue;
2573  }
2574  else
2575  menu->redraw = REDRAW_MOTION;
2576  break;
2577 
2578  case OP_DECRYPT_COPY:
2579  case OP_DECRYPT_SAVE:
2580  if (!WithCrypto)
2581  break;
2582  /* fallthrough */
2583  case OP_COPY_MESSAGE:
2584  case OP_SAVE:
2585  case OP_DECODE_COPY:
2586  case OP_DECODE_SAVE:
2587  {
2589  break;
2590  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
2591  el_add_tagged(&el, Context, CUR_EMAIL, tag);
2592  if ((mutt_save_message(Context->mailbox, &el,
2593  (op == OP_DECRYPT_SAVE) || (op == OP_SAVE) || (op == OP_DECODE_SAVE),
2594  (op == OP_DECODE_SAVE) || (op == OP_DECODE_COPY),
2595  (op == OP_DECRYPT_SAVE) || (op == OP_DECRYPT_COPY)) == 0) &&
2596  ((op == OP_SAVE) || (op == OP_DECODE_SAVE) || (op == OP_DECRYPT_SAVE)))
2597  {
2598  menu->redraw |= REDRAW_STATUS;
2599  if (tag)
2600  menu->redraw |= REDRAW_INDEX;
2601  else if (C_Resolve)
2602  {
2603  menu->current = ci_next_undeleted(menu->current);
2604  if (menu->current == -1)
2605  {
2606  menu->current = menu->oldcurrent;
2607  menu->redraw |= REDRAW_CURRENT;
2608  }
2609  else
2610  menu->redraw |= REDRAW_MOTION_RESYNC;
2611  }
2612  else
2613  menu->redraw |= REDRAW_CURRENT;
2614  }
2615  el_free(&el);
2616  break;
2617  }
2618 
2619  case OP_MAIN_NEXT_NEW:
2620  case OP_MAIN_NEXT_UNREAD:
2621  case OP_MAIN_PREV_NEW:
2622  case OP_MAIN_PREV_UNREAD:
2623  case OP_MAIN_NEXT_NEW_THEN_UNREAD:
2624  case OP_MAIN_PREV_NEW_THEN_UNREAD:
2625  {
2627  break;
2628 
2629  int first_unread = -1;
2630  int first_new = -1;
2631 
2632  const int saved_current = menu->current;
2633  int cur = menu->current;
2634  menu->current = -1;
2635  for (size_t i = 0; i != Context->mailbox->vcount; i++)
2636  {
2637  if ((op == OP_MAIN_NEXT_NEW) || (op == OP_MAIN_NEXT_UNREAD) ||
2638  (op == OP_MAIN_NEXT_NEW_THEN_UNREAD))
2639  {
2640  cur++;
2641  if (cur > (Context->mailbox->vcount - 1))
2642  {
2643  cur = 0;
2644  }
2645  }
2646  else
2647  {
2648  cur--;
2649  if (cur < 0)
2650  {
2651  cur = Context->mailbox->vcount - 1;
2652  }
2653  }
2654 
2655  struct Email *e = Context->mailbox->emails[Context->mailbox->v2r[cur]];
2656  if (e->collapsed && ((C_Sort & SORT_MASK) == SORT_THREADS))
2657  {
2658  if ((UNREAD(e) != 0) && (first_unread == -1))
2659  first_unread = cur;
2660  if ((UNREAD(e) == 1) && (first_new == -1))
2661  first_new = cur;
2662  }
2663  else if (!e->deleted && !e->read)
2664  {
2665  if (first_unread == -1)
2666  first_unread = cur;
2667  if (!e->old && (first_new == -1))
2668  first_new = cur;
2669  }
2670 
2671  if (((op == OP_MAIN_NEXT_UNREAD) || (op == OP_MAIN_PREV_UNREAD)) &&
2672  (first_unread != -1))
2673  break;
2674  if (((op == OP_MAIN_NEXT_NEW) || (op == OP_MAIN_PREV_NEW) ||
2675  (op == OP_MAIN_NEXT_NEW_THEN_UNREAD) || (op == OP_MAIN_PREV_NEW_THEN_UNREAD)) &&
2676  (first_new != -1))
2677  {
2678  break;
2679  }
2680  }
2681  if (((op == OP_MAIN_NEXT_NEW) || (op == OP_MAIN_PREV_NEW) ||
2682  (op == OP_MAIN_NEXT_NEW_THEN_UNREAD) || (op == OP_MAIN_PREV_NEW_THEN_UNREAD)) &&
2683  (first_new != -1))
2684  {
2685  menu->current = first_new;
2686  }
2687  else if (((op == OP_MAIN_NEXT_UNREAD) || (op == OP_MAIN_PREV_UNREAD) ||
2688  (op == OP_MAIN_NEXT_NEW_THEN_UNREAD) || (op == OP_MAIN_PREV_NEW_THEN_UNREAD)) &&
2689  (first_unread != -1))
2690  {
2691  menu->current = first_unread;
2692  }
2693 
2694  if (menu->current == -1)
2695  {
2696  menu->current = menu->oldcurrent;
2697  if ((op == OP_MAIN_NEXT_NEW) || (op == OP_MAIN_PREV_NEW))
2698  {
2699  if (Context->pattern)
2700  mutt_error(_("No new messages in this limited view"));
2701  else
2702  mutt_error(_("No new messages"));
2703  }
2704  else
2705  {
2706  if (Context->pattern)
2707  mutt_error(_("No unread messages in this limited view"));
2708  else
2709  mutt_error(_("No unread messages"));
2710  }
2711  break;
2712  }
2713 
2714  if ((op == OP_MAIN_NEXT_NEW) || (op == OP_MAIN_NEXT_UNREAD) ||
2715  (op == OP_MAIN_NEXT_NEW_THEN_UNREAD))
2716  {
2717  if (saved_current > menu->current)
2718  {
2719  mutt_message(_("Search wrapped to top"));
2720  }
2721  }
2722  else if (saved_current < menu->current)
2723  {
2724  mutt_message(_("Search wrapped to bottom"));
2725  }
2726 
2727  if (menu->menu == MENU_PAGER)
2728  {
2729  op = OP_DISPLAY_MESSAGE;
2730  continue;
2731  }
2732  else
2733  menu->redraw = REDRAW_MOTION;
2734  break;
2735  }
2736  case OP_FLAG_MESSAGE:
2738  break;
2739  /* L10N: CHECK_ACL */
2740  if (!check_acl(Context, MUTT_ACL_WRITE, _("Can't flag message")))
2741  break;
2742 
2743  if (tag)
2744  {
2745  for (size_t i = 0; i < Context->mailbox->msg_count; i++)
2746  {
2747  if (message_is_tagged(Context, i))
2748  {
2751  }
2752  }
2753 
2754  menu->redraw |= REDRAW_INDEX;
2755  }
2756  else
2757  {
2759  if (C_Resolve)
2760  {
2761  menu->current = ci_next_undeleted(menu->current);
2762  if (menu->current == -1)
2763  {
2764  menu->current = menu->oldcurrent;
2765  menu->redraw |= REDRAW_CURRENT;
2766  }
2767  else
2768  menu->redraw |= REDRAW_MOTION_RESYNC;
2769  }
2770  else
2771  menu->redraw |= REDRAW_CURRENT;
2772  }
2773  menu->redraw |= REDRAW_STATUS;
2774  break;
2775 
2776  case OP_TOGGLE_NEW:
2778  break;
2779  /* L10N: CHECK_ACL */
2780  if (!check_acl(Context, MUTT_ACL_SEEN, _("Can't toggle new")))
2781  break;
2782 
2783  if (tag)
2784  {
2785  for (size_t i = 0; i < Context->mailbox->msg_count; i++)
2786  {
2787  if (!message_is_tagged(Context, i))
2788  continue;
2789 
2790  if (Context->mailbox->emails[i]->read || Context->mailbox->emails[i]->old)
2792  else
2794  }
2795  menu->redraw |= REDRAW_STATUS | REDRAW_INDEX;
2796  }
2797  else
2798  {
2799  if (CUR_EMAIL->read || CUR_EMAIL->old)
2801  else
2803 
2804  if (C_Resolve)
2805  {
2806  menu->current = ci_next_undeleted(menu->current);
2807  if (menu->current == -1)
2808  {
2809  menu->current = menu->oldcurrent;
2810  menu->redraw |= REDRAW_CURRENT;
2811  }
2812  else
2813  menu->redraw |= REDRAW_MOTION_RESYNC;
2814  }
2815  else
2816  menu->redraw |= REDRAW_CURRENT;
2817  menu->redraw |= REDRAW_STATUS;
2818  }
2819  break;
2820 
2821  case OP_TOGGLE_WRITE:
2822  if (!prereq(Context, menu, CHECK_IN_MAILBOX))
2823  break;
2824  if (mx_toggle_write(Context->mailbox) == 0)
2825  {
2826  if (menu->menu == MENU_PAGER)
2827  {
2828  op = OP_DISPLAY_MESSAGE;
2829  continue;
2830  }
2831  else
2832  menu->redraw |= REDRAW_STATUS;
2833  }
2834  break;
2835 
2836  case OP_MAIN_NEXT_THREAD:
2837  case OP_MAIN_NEXT_SUBTHREAD:
2838  case OP_MAIN_PREV_THREAD:
2839  case OP_MAIN_PREV_SUBTHREAD:
2841  break;
2842 
2843  switch (op)
2844  {
2845  case OP_MAIN_NEXT_THREAD:
2847  break;
2848 
2849  case OP_MAIN_NEXT_SUBTHREAD:
2851  break;
2852 
2853  case OP_MAIN_PREV_THREAD:
2855  break;
2856 
2857  case OP_MAIN_PREV_SUBTHREAD:
2859  break;
2860  }
2861 
2862  if (menu->current < 0)
2863  {
2864  menu->current = menu->oldcurrent;
2865  if ((op == OP_MAIN_NEXT_THREAD) || (op == OP_MAIN_NEXT_SUBTHREAD))
2866  mutt_error(_("No more threads"));
2867  else
2868  mutt_error(_("You are on the first thread"));
2869  }
2870  else if (menu->menu == MENU_PAGER)
2871  {
2872  op = OP_DISPLAY_MESSAGE;
2873  continue;
2874  }
2875  else
2876  menu->redraw = REDRAW_MOTION;
2877  break;
2878 
2879  case OP_MAIN_ROOT_MESSAGE:
2880  case OP_MAIN_PARENT_MESSAGE:
2882  break;
2883 
2884  menu->current = mutt_parent_message(Context, CUR_EMAIL, op == OP_MAIN_ROOT_MESSAGE);
2885  if (menu->current < 0)
2886  {
2887  menu->current = menu->oldcurrent;
2888  }
2889  else if (menu->menu == MENU_PAGER)
2890  {
2891  op = OP_DISPLAY_MESSAGE;
2892  continue;
2893  }
2894  else
2895  menu->redraw = REDRAW_MOTION;
2896  break;
2897 
2898  case OP_MAIN_SET_FLAG:
2899  case OP_MAIN_CLEAR_FLAG:
2900  {
2902  break;
2903  /* check_acl(MUTT_ACL_WRITE); */
2904 
2905  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
2906  el_add_tagged(&el, Context, CUR_EMAIL, tag);
2907 
2908  if (mutt_change_flag(Context->mailbox, &el, (op == OP_MAIN_SET_FLAG)) == 0)
2909  {
2910  menu->redraw |= REDRAW_STATUS;
2911  if (tag)
2912  menu->redraw |= REDRAW_INDEX;
2913  else if (C_Resolve)
2914  {
2915  menu->current = ci_next_undeleted(menu->current);
2916  if (menu->current == -1)
2917  {
2918  menu->current = menu->oldcurrent;
2919  menu->redraw |= REDRAW_CURRENT;
2920  }
2921  else
2922  menu->redraw |= REDRAW_MOTION_RESYNC;
2923  }
2924  else
2925  menu->redraw |= REDRAW_CURRENT;
2926  }
2927  el_free(&el);
2928  break;
2929  }
2930 
2931  case OP_MAIN_COLLAPSE_THREAD:
2933  break;
2934 
2935  if ((C_Sort & SORT_MASK) != SORT_THREADS)
2936  {
2937  mutt_error(_("Threading is not enabled"));
2938  break;
2939  }
2940 
2941  if (CUR_EMAIL->collapsed)
2942  {
2945  if (C_UncollapseJump)
2947  }
2948  else if (CAN_COLLAPSE(CUR_EMAIL))
2949  {
2952  }
2953  else
2954  {
2955  mutt_error(_("Thread contains unread or flagged messages"));
2956  break;
2957  }
2958 
2959  menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
2960 
2961  break;
2962 
2963  case OP_MAIN_COLLAPSE_ALL:
2965  break;
2966 
2967  if ((C_Sort & SORT_MASK) != SORT_THREADS)
2968  {
2969  mutt_error(_("Threading is not enabled"));
2970  break;
2971  }
2972  collapse_all(menu, 1);
2973  break;
2974 
2975  /* --------------------------------------------------------------------
2976  * These functions are invoked directly from the internal-pager
2977  */
2978 
2979  case OP_BOUNCE_MESSAGE:
2980  {
2982  break;
2983 
2984  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
2985  el_add_tagged(&el, Context, CUR_EMAIL, tag);
2987  el_free(&el);
2988  break;
2989  }
2990 
2991  case OP_CREATE_ALIAS:
2992  mutt_alias_create(Context && Context->mailbox->vcount ? CUR_EMAIL->env : NULL, NULL);
2993  menu->redraw |= REDRAW_CURRENT;
2994  break;
2995 
2996  case OP_QUERY:
2997  if (!prereq(Context, menu, CHECK_ATTACH))
2998  break;
2999  mutt_query_menu(NULL, 0);
3000  break;
3001 
3002  case OP_PURGE_MESSAGE:
3003  case OP_DELETE:
3004  {
3006  break;
3007  /* L10N: CHECK_ACL */
3008  if (!check_acl(Context, MUTT_ACL_DELETE, _("Can't delete message")))
3009  break;
3010 
3011  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3012  el_add_tagged(&el, Context, CUR_EMAIL, tag);
3013 
3015  mutt_emails_set_flag(Context->mailbox, &el, MUTT_PURGE, (op == OP_PURGE_MESSAGE));
3016  if (C_DeleteUntag)
3018  el_free(&el);
3019 
3020  if (tag)
3021  {
3022  menu->redraw |= REDRAW_INDEX;
3023  }
3024  else
3025  {
3026  if (C_Resolve)
3027  {
3028  menu->current = ci_next_undeleted(menu->current);
3029  if (menu->current == -1)
3030  {
3031  menu->current = menu->oldcurrent;
3032  menu->redraw |= REDRAW_CURRENT;
3033  }
3034  else if (menu->menu == MENU_PAGER)
3035  {
3036  op = OP_DISPLAY_MESSAGE;
3037  continue;
3038  }
3039  else
3040  menu->redraw |= REDRAW_MOTION_RESYNC;
3041  }
3042  else
3043  menu->redraw |= REDRAW_CURRENT;
3044  }
3045  menu->redraw |= REDRAW_STATUS;
3046  break;
3047  }
3048 
3049  case OP_DELETE_THREAD:
3050  case OP_DELETE_SUBTHREAD:
3051  case OP_PURGE_THREAD:
3052  {
3054  break;
3055  /* L10N: CHECK_ACL */
3056  /* L10N: Due to the implementation details we do not know whether we
3057  delete zero, 1, 12, ... messages. So in English we use
3058  "messages". Your language might have other means to express this. */
3059  if (!check_acl(Context, MUTT_ACL_DELETE, _("Can't delete messages")))
3060  break;
3061 
3062  int subthread = (op == OP_DELETE_SUBTHREAD);
3063  int rc = mutt_thread_set_flag(CUR_EMAIL, MUTT_DELETE, true, subthread);
3064  if (rc == -1)
3065  break;
3066  if (op == OP_PURGE_THREAD)
3067  {
3068  rc = mutt_thread_set_flag(CUR_EMAIL, MUTT_PURGE, true, subthread);
3069  if (rc == -1)
3070  break;
3071  }
3072 
3073  if (C_DeleteUntag)
3074  mutt_thread_set_flag(CUR_EMAIL, MUTT_TAG, false, subthread);
3075  if (C_Resolve)
3076  {
3077  menu->current = ci_next_undeleted(menu->current);
3078  if (menu->current == -1)
3079  menu->current = menu->oldcurrent;
3080  }
3081  menu->redraw |= REDRAW_INDEX | REDRAW_STATUS;
3082  break;
3083  }
3084 
3085 #ifdef USE_NNTP
3086  case OP_CATCHUP:
3088  break;
3089  if (Context && (Context->mailbox->magic == MUTT_NNTP))
3090  {
3091  struct NntpMboxData *mdata = Context->mailbox->mdata;
3092  if (mutt_newsgroup_catchup(Context->mailbox, mdata->adata, mdata->group))
3093  menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
3094  }
3095  break;
3096 #endif
3097 
3098  case OP_DISPLAY_ADDRESS:
3100  break;
3102  break;
3103 
3104  case OP_ENTER_COMMAND:
3106  if (Context)
3108  break;
3109 
3110  case OP_EDIT_OR_VIEW_RAW_MESSAGE:
3111  case OP_EDIT_RAW_MESSAGE:
3112  case OP_VIEW_RAW_MESSAGE:
3113  {
3114  /* TODO split this into 3 cases? */
3116  break;
3117  bool edit;
3118  if (op == OP_EDIT_RAW_MESSAGE)
3119  {
3120  if (!prereq(Context, menu, CHECK_READONLY))
3121  break;
3122  /* L10N: CHECK_ACL */
3123  if (!check_acl(Context, MUTT_ACL_INSERT, _("Can't edit message")))
3124  break;
3125  edit = true;
3126  }
3127  else if (op == OP_EDIT_OR_VIEW_RAW_MESSAGE)
3129  else
3130  edit = false;
3131 
3132  if (C_PgpAutoDecode && (tag || !(CUR_EMAIL->security & PGP_TRADITIONAL_CHECKED)))
3133  {
3134  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3135  el_add_tagged(&el, Context, CUR_EMAIL, tag);
3136  mutt_check_traditional_pgp(&el, &menu->redraw);
3137  el_free(&el);
3138  }
3139  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3140  el_add_tagged(&el, Context, CUR_EMAIL, tag);
3141  mutt_ev_message(Context->mailbox, &el, edit ? EVM_EDIT : EVM_VIEW);
3142  el_free(&el);
3143  menu->redraw = REDRAW_FULL;
3144 
3145  break;
3146  }
3147 
3148  case OP_FORWARD_MESSAGE:
3149  {
3151  break;
3152  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3153  el_add_tagged(&el, Context, CUR_EMAIL, tag);
3154  if (C_PgpAutoDecode && (tag || !(CUR_EMAIL->security & PGP_TRADITIONAL_CHECKED)))
3155  {
3156  mutt_check_traditional_pgp(&el, &menu->redraw);
3157  }
3158  ci_send_message(SEND_FORWARD, NULL, NULL, Context, &el);
3159  el_free(&el);
3160  menu->redraw = REDRAW_FULL;
3161  break;
3162  }
3163 
3164  case OP_FORGET_PASSPHRASE:
3166  break;
3167 
3168  case OP_GROUP_REPLY:
3169  case OP_GROUP_CHAT_REPLY:
3170  {
3171  SendFlags replyflags = SEND_REPLY;
3172  if (op == OP_GROUP_REPLY)
3173  replyflags |= SEND_GROUP_REPLY;
3174  else
3175  replyflags |= SEND_GROUP_CHAT_REPLY;
3177  break;
3178  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3179  el_add_tagged(&el, Context, CUR_EMAIL, tag);
3180  if (C_PgpAutoDecode && (tag || !(CUR_EMAIL->security & PGP_TRADITIONAL_CHECKED)))
3181  {
3182  mutt_check_traditional_pgp(&el, &menu->redraw);
3183  }
3184  ci_send_message(replyflags, NULL, NULL, Context, &el);
3185  el_free(&el);
3186  menu->redraw = REDRAW_FULL;
3187  break;
3188  }
3189 
3190  case OP_EDIT_LABEL:
3191  {
3193  break;
3194 
3195  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3196  el_add_tagged(&el, Context, CUR_EMAIL, tag);
3197  int num_changed = mutt_label_message(Context->mailbox, &el);
3198  el_free(&el);
3199 
3200  if (num_changed > 0)
3201  {
3202  Context->mailbox->changed = true;
3203  menu->redraw = REDRAW_FULL;
3204  /* L10N: This is displayed when the x-label on one or more
3205  messages is edited. */
3206  mutt_message(ngettext("%d label changed", "%d labels changed", num_changed),
3207  num_changed);
3208  }
3209  else
3210  {
3211  /* L10N: This is displayed when editing an x-label, but no messages
3212  were updated. Possibly due to canceling at the prompt or if the new
3213  label is the same as the old label. */
3214  mutt_message(_("No labels changed"));
3215  }
3216  break;
3217  }
3218 
3219  case OP_LIST_REPLY:
3220  {
3222  break;
3223  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3224  el_add_tagged(&el, Context, CUR_EMAIL, tag);
3225  if (C_PgpAutoDecode && (tag || !(CUR_EMAIL->security & PGP_TRADITIONAL_CHECKED)))
3226  {
3227  mutt_check_traditional_pgp(&el, &menu->redraw);
3228  }
3229  ci_send_message(SEND_REPLY | SEND_LIST_REPLY, NULL, NULL, Context, &el);
3230  el_free(&el);
3231  menu->redraw = REDRAW_FULL;
3232  break;
3233  }
3234 
3235  case OP_MAIL:
3236  if (!prereq(Context, menu, CHECK_ATTACH))
3237  break;
3238  ci_send_message(SEND_NO_FLAGS, NULL, NULL, Context, NULL);
3239  menu->redraw = REDRAW_FULL;
3240  break;
3241 
3242  case OP_MAIL_KEY:
3243  if (!(WithCrypto & APPLICATION_PGP))
3244  break;
3245  if (!prereq(Context, menu, CHECK_ATTACH))
3246  break;
3247  ci_send_message(SEND_KEY, NULL, NULL, NULL, NULL);
3248  menu->redraw = REDRAW_FULL;
3249  break;
3250 
3251  case OP_EXTRACT_KEYS:
3252  {
3253  if (!WithCrypto)
3254  break;
3256  break;
3257  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3258  el_add_tagged(&el, Context, CUR_EMAIL, tag);
3260  el_free(&el);
3261  menu->redraw = REDRAW_FULL;
3262  break;
3263  }
3264 
3265  case OP_CHECK_TRADITIONAL:
3266  {
3267  if (!(WithCrypto & APPLICATION_PGP))
3268  break;
3270  break;
3271  if (tag || !(CUR_EMAIL->security & PGP_TRADITIONAL_CHECKED))
3272  {
3273  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3274  el_add_tagged(&el, Context, CUR_EMAIL, tag);
3275  mutt_check_traditional_pgp(&el, &menu->redraw);
3276  el_free(&el);
3277  }
3278 
3279  if (menu->menu == MENU_PAGER)
3280  {
3281  op = OP_DISPLAY_MESSAGE;
3282  continue;
3283  }
3284  break;
3285  }
3286 
3287  case OP_PIPE:
3288  {
3290  break;
3291  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3292  el_add_tagged(&el, Context, CUR_EMAIL, tag);
3294  el_free(&el);
3295 
3296 #ifdef USE_IMAP
3297  /* in an IMAP folder index with imap_peek=no, piping could change
3298  * new or old messages status to read. Redraw what's needed. */
3299  if ((Context->mailbox->magic == MUTT_IMAP) && !C_ImapPeek)
3300  {
3301  menu->redraw |= (tag ? REDRAW_INDEX : REDRAW_CURRENT) | REDRAW_STATUS;
3302  }
3303 #endif
3304  break;
3305  }
3306 
3307  case OP_PRINT:
3308  {
3310  break;
3311  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3312  el_add_tagged(&el, Context, CUR_EMAIL, tag);
3314  el_free(&el);
3315 
3316 #ifdef USE_IMAP
3317  /* in an IMAP folder index with imap_peek=no, printing could change
3318  * new or old messages status to read. Redraw what's needed. */
3319  if ((Context->mailbox->magic == MUTT_IMAP) && !C_ImapPeek)
3320  {
3321  menu->redraw |= (tag ? REDRAW_INDEX : REDRAW_CURRENT) | REDRAW_STATUS;
3322  }
3323 #endif
3324  break;
3325  }
3326 
3327  case OP_MAIN_READ_THREAD:
3328  case OP_MAIN_READ_SUBTHREAD:
3329  {
3331  break;
3332  /* L10N: CHECK_ACL */
3333  /* L10N: Due to the implementation details we do not know whether we
3334  mark zero, 1, 12, ... messages as read. So in English we use
3335  "messages". Your language might have other means to express this. */
3336  if (!check_acl(Context, MUTT_ACL_SEEN, _("Can't mark messages as read")))
3337  break;
3338 
3339  int rc = mutt_thread_set_flag(CUR_EMAIL, MUTT_READ, true, (op != OP_MAIN_READ_THREAD));
3340  if (rc != -1)
3341  {
3342  if (C_Resolve)
3343  {
3344  menu->current =
3345  ((op == OP_MAIN_READ_THREAD) ? mutt_next_thread(CUR_EMAIL) :
3347  if (menu->current == -1)
3348  {
3349  menu->current = menu->oldcurrent;
3350  }
3351  else if (menu->menu == MENU_PAGER)
3352  {
3353  op = OP_DISPLAY_MESSAGE;
3354  continue;
3355  }
3356  }
3357  menu->redraw |= REDRAW_INDEX | REDRAW_STATUS;
3358  }
3359  break;
3360  }
3361 
3362  case OP_MARK_MSG:
3364  break;
3365  if (CUR_EMAIL->env->message_id)
3366  {
3367  char buf2[128];
3368 
3369  buf2[0] = '\0';
3370  /* L10N: This is the prompt for <mark-message>. Whatever they
3371  enter will be prefixed by $mark_macro_prefix and will become
3372  a macro hotkey to jump to the currently selected message. */
3373  if (!mutt_get_field(_("Enter macro stroke: "), buf2, sizeof(buf2), MUTT_CLEAR) &&
3374  buf2[0])
3375  {
3376  char str[256], macro[256];
3377  snprintf(str, sizeof(str), "%s%s", C_MarkMacroPrefix, buf2);
3378  snprintf(macro, sizeof(macro), "<search>~i \"%s\"\n", CUR_EMAIL->env->message_id);
3379  /* L10N: "message hotkey" is the key bindings menu description of a
3380  macro created by <mark-message>. */
3381  km_bind(str, MENU_MAIN, OP_MACRO, macro, _("message hotkey"));
3382 
3383  /* L10N: This is echoed after <mark-message> creates a new hotkey
3384  macro. %s is the hotkey string ($mark_macro_prefix followed
3385  by whatever they typed at the prompt.) */
3386  snprintf(buf2, sizeof(buf2), _("Message bound to %s"), str);
3387  mutt_message(buf2);
3388  mutt_debug(LL_DEBUG1, "Mark: %s => %s\n", str, macro);
3389  }
3390  }
3391  else
3392  {
3393  /* L10N: This error is printed if <mark-message> can't find a
3394  Message-ID for the currently selected message in the index. */
3395  mutt_error(_("No message ID to macro"));
3396  }
3397  break;
3398 
3399  case OP_RECALL_MESSAGE:
3400  if (!prereq(Context, menu, CHECK_ATTACH))
3401  break;
3402  ci_send_message(SEND_POSTPONED, NULL, NULL, Context, NULL);
3403  menu->redraw = REDRAW_FULL;
3404  break;
3405 
3406  case OP_RESEND:
3408  break;
3409 
3410  if (tag)
3411  {
3412  for (size_t i = 0; i < Context->mailbox->msg_count; i++)
3413  {
3414  if (message_is_tagged(Context, i))
3416  }
3417  }
3418  else
3420 
3421  menu->redraw = REDRAW_FULL;
3422  break;
3423 
3424 #ifdef USE_NNTP
3425  case OP_FOLLOWUP:
3426  case OP_FORWARD_TO_GROUP:
3428  break;
3429  /* fallthrough */
3430 
3431  case OP_POST:
3432  if (!prereq(Context, menu, CHECK_ATTACH))
3433  break;
3434  if ((op != OP_FOLLOWUP) || !CUR_EMAIL->env->followup_to ||
3435  (mutt_str_strcasecmp(CUR_EMAIL->env->followup_to, "poster") != 0) ||
3437  _("Reply by mail as poster prefers?")) != MUTT_YES))
3438  {
3439  if (Context && (Context->mailbox->magic == MUTT_NNTP) &&
3440  !((struct NntpMboxData *) Context->mailbox->mdata)->allowed && (query_quadoption(C_PostModerated, _("Posting to this group not allowed, may be moderated. Continue?")) != MUTT_YES))
3441  {
3442  break;
3443  }
3444  if (op == OP_POST)
3445  ci_send_message(SEND_NEWS, NULL, NULL, Context, NULL);
3446  else
3447  {
3449  break;
3450  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3451  el_add_tagged(&el, Context, CUR_EMAIL, tag);
3452  ci_send_message(((op == OP_FOLLOWUP) ? SEND_REPLY : SEND_FORWARD) | SEND_NEWS,
3453  NULL, NULL, Context, &el);
3454  el_free(&el);
3455  }
3456  menu->redraw = REDRAW_FULL;
3457  break;
3458  }
3459 #endif
3460  /* fallthrough */
3461  case OP_REPLY:
3462  {
3464  break;
3465  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3466  el_add_tagged(&el, Context, CUR_EMAIL, tag);
3467  if (C_PgpAutoDecode && (tag || !(CUR_EMAIL->security & PGP_TRADITIONAL_CHECKED)))
3468  {
3469  mutt_check_traditional_pgp(&el, &menu->redraw);
3470  }
3471  ci_send_message(SEND_REPLY, NULL, NULL, Context, &el);
3472  el_free(&el);
3473  menu->redraw = REDRAW_FULL;
3474  break;
3475  }
3476 
3477  case OP_SHELL_ESCAPE:
3479  break;
3480 
3481  case OP_TAG_THREAD:
3482  case OP_TAG_SUBTHREAD:
3483  {
3485  break;
3486 
3487  int rc = mutt_thread_set_flag(CUR_EMAIL, MUTT_TAG, !CUR_EMAIL->tagged,
3488  (op != OP_TAG_THREAD));
3489  if (rc != -1)
3490  {
3491  if (C_Resolve)
3492  {
3493  if (op == OP_TAG_THREAD)
3495  else
3497 
3498  if (menu->current == -1)
3499  menu->current = menu->oldcurrent;
3500  }
3501  menu->redraw |= REDRAW_INDEX | REDRAW_STATUS;
3502  }
3503  break;
3504  }
3505 
3506  case OP_UNDELETE:
3507  {
3509  break;
3510  /* L10N: CHECK_ACL */
3511  if (!check_acl(Context, MUTT_ACL_DELETE, _("Can't undelete message")))
3512  break;
3513 
3514  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3515  el_add_tagged(&el, Context, CUR_EMAIL, tag);
3516 
3519  el_free(&el);
3520 
3521  if (tag)
3522  {
3523  menu->redraw |= REDRAW_INDEX;
3524  }
3525  else
3526  {
3527  if (C_Resolve && (menu->current < (Context->mailbox->vcount - 1)))
3528  {
3529  menu->current++;
3530  menu->redraw |= REDRAW_MOTION_RESYNC;
3531  }
3532  else
3533  menu->redraw |= REDRAW_CURRENT;
3534  }
3535 
3536  menu->redraw |= REDRAW_STATUS;
3537  break;
3538  }
3539 
3540  case OP_UNDELETE_THREAD:
3541  case OP_UNDELETE_SUBTHREAD:
3542  {
3544  break;
3545  /* L10N: CHECK_ACL */
3546  /* L10N: Due to the implementation details we do not know whether we
3547  undelete zero, 1, 12, ... messages. So in English we use
3548  "messages". Your language might have other means to express this. */
3549  if (!check_acl(Context, MUTT_ACL_DELETE, _("Can't undelete messages")))
3550  break;
3551 
3552  int rc = mutt_thread_set_flag(CUR_EMAIL, MUTT_DELETE, false,
3553  (op != OP_UNDELETE_THREAD));
3554  if (rc != -1)
3555  {
3556  rc = mutt_thread_set_flag(CUR_EMAIL, MUTT_PURGE, false, (op != OP_UNDELETE_THREAD));
3557  }
3558  if (rc != -1)
3559  {
3560  if (C_Resolve)
3561  {
3562  if (op == OP_UNDELETE_THREAD)
3564  else
3566 
3567  if (menu->current == -1)
3568  menu->current = menu->oldcurrent;
3569  }
3570  menu->redraw |= REDRAW_INDEX | REDRAW_STATUS;
3571  }
3572  break;
3573  }
3574 
3575  case OP_VERSION:
3577  break;
3578 
3579  case OP_MAILBOX_LIST:
3581  break;
3582 
3583  case OP_VIEW_ATTACHMENTS:
3585  break;
3587  if (Context && CUR_EMAIL->attach_del)
3588  Context->mailbox->changed = true;
3589  menu->redraw = REDRAW_FULL;
3590  break;
3591 
3592  case OP_END_COND:
3593  break;
3594 
3595  case OP_WHAT_KEY:
3596  mutt_what_key();
3597  break;
3598 
3599 #ifdef USE_SIDEBAR
3600  case OP_SIDEBAR_NEXT:
3601  case OP_SIDEBAR_NEXT_NEW:
3602  case OP_SIDEBAR_PAGE_DOWN:
3603  case OP_SIDEBAR_PAGE_UP:
3604  case OP_SIDEBAR_PREV:
3605  case OP_SIDEBAR_PREV_NEW:
3607  break;
3608 
3609  case OP_SIDEBAR_TOGGLE_VISIBLE:
3610  bool_str_toggle(Config, "sidebar_visible", NULL);
3612  break;
3613 #endif
3614  default:
3615  if (menu->menu == MENU_MAIN)
3617  }
3618 
3619 #ifdef USE_NOTMUCH
3620  if (Context)
3622 #endif
3623 
3624  if (menu->menu == MENU_PAGER)
3625  {
3627  menu->menu = MENU_MAIN;
3628  menu->redraw = REDRAW_FULL;
3629  }
3630 
3631  if (done)
3632  break;
3633  }
3634 
3635  mutt_menu_pop_current(menu);
3636  mutt_menu_destroy(&menu);
3637  return close;
3638 }
struct Email ** emails
Definition: mailbox.h:99
#define MUTT_OPEN_NO_FLAGS
No flags are set.
Definition: mx.h:48
void mutt_buffer_pretty_mailbox(struct Buffer *s)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:688
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:38
struct NntpAccountData * nntp_select_server(struct Mailbox *m, char *server, bool leave_lock)
Open a connection to an NNTP server.
Definition: newsrc.c:982
&#39;Notmuch&#39; (virtual) Mailbox type
Definition: magic.h:43
int mutt_pattern_func(int op, char *prompt)
Perform some Pattern matching.
Definition: pattern.c:2382
#define MUTT_PROGRESS_MSG
message-based progress
Definition: progress.h:33
int mutt_thread_set_flag(struct Email *e, int flag, bool bf, bool subthread)
Set a flag on an entire thread.
Definition: flags.c:376
#define REDRAW_FULL
Redraw everything.
Definition: mutt_menu.h:47
#define NONULL(x)
Definition: string2.h:36
int msg_count
total number of messages
Definition: mailbox.h:92
#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:98
void mutt_pipe_message(struct Mailbox *m, struct EmailList *el)
Pipe a message.
Definition: commands.c:655
The envelope/body of an email.
Definition: email.h:37
#define MUTT_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:67
#define mutt_perror(...)
Definition: logging.h:84
#define MUTT_SHUTDOWN_HOOK
shutdown-hook: run when leaving NeoMutt
Definition: hook.h:64
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:569
int mx_mbox_check(struct Mailbox *m, int *index_hint)
Check for new mail - Wrapper for MxOps::mbox_check()
Definition: mx.c:1010
void mutt_buffer_increase_size(struct Buffer *buf, size_t new_size)
Increase the allocated size of a buffer.
Definition: buffer.c:347
int mx_mbox_close(struct Context **ptr)
Save changes and close mailbox.
Definition: mx.c:546
void nm_query_window_backward(void)
Function to move the current search window backward in time.
&#39;NNTP&#39; (Usenet) Mailbox type
Definition: magic.h:41
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:3367
#define mutt_message(...)
Definition: logging.h:82
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
int mutt_save_message(struct Mailbox *m, struct EmailList *el, bool delete, bool decode, bool decrypt)
Save an email.
Definition: commands.c:979
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:862
struct NntpAccountData * adata
Definition: nntp.h:154
int virtual
virtual message number
Definition: email.h:90
void mutt_emails_set_flag(struct Mailbox *m, struct EmailList *el, int flag, bool bf)
Set flag on messages.
Definition: flags.c:355
static void index_custom_redraw(struct Menu *menu)
Redraw the index - Implements Menu::menu_custom_redraw()
Definition: index.c:965
Messages in limited view.
Definition: mutt.h:108
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:1329
void mutt_flushinp(void)
Empty all the keyboard buffers.
Definition: curs_lib.c:785
bool mutt_limit_current_thread(struct Email *e)
Limit the email view to the current thread.
Definition: pattern.c:2341
#define SEND_FORWARD
Forward email.
Definition: send.h:89
void mutt_window_clrtoeol(struct MuttWindow *win)
Clear to the end of the line.
Definition: mutt_window.c:81
void mutt_resize_screen(void)
Update NeoMutt&#39;s opinion about the window size (CURSES)
Definition: resize.c:98
#define CHECK_ATTACH
Is the user in message-attach mode?
Definition: index.c:153
WHERE bool OptNeedResort
(pseudo) used to force a re-sort
Definition: options.h:40
void index_make_entry(char *buf, size_t buflen, struct Menu *menu, int line)
Format a menu item for the index list - Implements Menu::menu_make_entry()
Definition: index.c:737
void mutt_check_stats(void)
Forcibly update mailbox stats.
Definition: commands.c:1329
#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:1475
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_buffer_mailbox(struct Mailbox *m_cur, struct Buffer *s)
incoming folders completion routine
Definition: mailbox.c:502
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:71
void mutt_enter_command(void)
enter a neomutt command
Definition: commands.c:818
void el_free(struct EmailList *el)
Drop a private list of Emails.
Definition: context.c:321
String manipulation buffer.
Definition: buffer.h:33
#define MUTT_ACL_INSERT
Add/copy into the mailbox (used when editing a message)
Definition: mailbox.h:71
Messages to be un-deleted.
Definition: mutt.h:102
Flagged messages.
Definition: mutt.h:105
#define PGP_TRADITIONAL_CHECKED
Email has a traditional (inline) signature.
Definition: ncrypt.h:131
void mutt_unget_event(int ch, int op)
Return a keystroke to the input buffer.
Definition: curs_lib.c:700
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:810
void menu_status_line(char *buf, size_t buflen, struct Menu *menu, const char *p)
Create the status line.
Definition: status.c:393
bool mutt_check_traditional_pgp(struct EmailList *el, MuttRedrawFlags *redraw)
Check if a message has inline PGP content.
Definition: commands.c:1313
&#39;IMAP&#39; Mailbox type
Definition: magic.h:42
Messages to be purged (bypass trash)
Definition: mutt.h:103
struct TagHead tags
for drivers that support server tagging
Definition: email.h:110
void pop_fetch_mail(void)
Fetch messages and save them in $spoolfile.
Definition: pop.c:574
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:47
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:51
uint16_t SendFlags
Flags for ci_send_message(), e.g. SEND_REPLY.
Definition: send.h:84
#define mutt_collapse_thread(ctx, cur)
Definition: mutt_thread.h:56
int mutt_monitor_add(struct Mailbox *m)
Add a watch for a mailbox.
Definition: monitor.c:461
struct Mailbox * mx_mbox_find2(const char *path)
XXX.
Definition: mx.c:1508
int nntp_check_children(struct Context *ctx, const char *msgid)
Fetch children of article with the Message-ID.
Definition: nntp.c:2297
#define SEND_POSTPONED
Recall a postponed email.
Definition: send.h:90
A progress bar.
Definition: progress.h:38
void(* menu_make_entry)(char *buf, size_t buflen, struct Menu *menu, int line)
Format a item for a menu.
Definition: mutt_menu.h:122
void km_error_key(int menu)
Handle an unbound key sequence.
Definition: keymap.c:1036
#define MUTT_ACL_DELETE
Delete a message.
Definition: mailbox.h:68
struct Mapping IndexNewsHelp[]
Definition: index.c:123
#define mutt_get_field(field, buf, buflen, complete)
Definition: curs_lib.h:86
int vcount
the number of virtual messages
Definition: mailbox.h:102
char * mutt_compile_help(char *buf, size_t buflen, int menu, const struct Mapping *items)
Create the text for the help menu.
Definition: help.c:115
int ci_send_message(SendFlags flags, struct Email *msg, const char *tempfile, struct Context *ctx, struct EmailList *el)
Send an email.
Definition: send.c:1845
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:677
#define SEND_NO_FLAGS
No flags are set.
Definition: send.h:85
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
Definition: email.h:44
#define CHECK_VISIBLE
Is the selected message visible in the index?
Definition: index.c:151
bool read
Definition: email.h:51
void mutt_startup_shutdown_hook(HookFlags type)
Execute any startup/shutdown hooks.
Definition: hook.c:840
void crypt_extract_keys_from_messages(struct EmailList *el)
Extract keys from a message.
Definition: crypt.c:814
struct Mailbox * mailbox
Definition: context.h:52
Log at debug level 2.
Definition: logging.h:57
#define CHECK_IN_MAILBOX
Is there a mailbox open?
Definition: index.c:149
bool old
Definition: email.h:50
static bool prereq(struct Context *ctx, struct Menu *menu, CheckFlags checks)
Check the pre-requisites for a function.
Definition: index.c:163
void mutt_flush_macro_to_endcond(void)
Drop a macro from the input buffer.
Definition: curs_lib.c:756
enum MailboxType magic
mailbox type
Definition: mailbox.h:105
bool message_is_visible(struct Context *ctx, int index)
Is a message in the index within limit.
Definition: context.c:294
bool readonly
don&#39;t allow changes to the mailbox
Definition: mailbox.h:119
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_resend_message(FILE *fp, struct Context *ctx, struct Email *cur)
Resend an email.
Definition: send.c:1486
int mutt_parent_message(struct Context *ctx, struct Email *e, bool find_root)
Find the parent of a message.
Definition: mutt_thread.c:1135
void mutt_what_key(void)
Ask the user to press a key.
Definition: keymap.c:1555
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:1198
void mx_fastclose_mailbox(struct Mailbox *m)
free up memory associated with the Mailbox
Definition: mx.c:379
void mutt_shell_escape(void)
invoke a command in a subshell
Definition: commands.c:790
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:48
void mutt_break_thread(struct Email *e)
Break the email Thread.
Definition: thread.c:226
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:88
#define CUR_EMAIL
Definition: index.c:136
WHERE short C_Sort
Config: Sort method for the index.
Definition: sort.h:58
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:141
static int mx_toggle_write(struct Mailbox *m)
Toggle the mailbox&#39;s readonly flag.
Definition: index.c:374
#define mutt_uncollapse_thread(ctx, cur)
Definition: mutt_thread.h:57
WHERE bool C_ReadOnly
Config: Open folders in read-only mode.
Definition: globals.h:243
void * mdata
driver specific data
Definition: mailbox.h:136
void ctx_free(struct Context **ctx)
Free a Context.
Definition: context.c:47
int mutt_mailbox_check(struct Mailbox *m_cur, int force)
Check all AllMailboxes for new mail.
Definition: mailbox.c:341
#define MUTT_ACL_WRITE
Write to a message (for flagging or linking threads)
Definition: mailbox.h:76
#define REDRAW_MOTION
Redraw after moving the menu list.
Definition: mutt_menu.h:43
char * nm_uri_from_query(struct Mailbox *m, char *buf, size_t buflen)
Turn a query into a URI.
void mutt_window_reflow(void)
Resize the Windows to fit the screen.
Definition: mutt_window.c: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:93
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_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:322
#define mutt_mktemp(buf, buflen)
Definition: muttlib.h:74
void mutt_sort_headers(struct Context *ctx, bool init)
Sort emails by their headers.
Definition: sort.c:361
#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:101
A mailbox.
Definition: mailbox.h:83
#define PATH_MAX
Definition: mutt.h:49
struct MuttWindow * MuttIndexWindow
Index Window.
Definition: mutt_window.c:39
int mutt_change_flag(struct Mailbox *m, struct EmailList *el, int bf)
Change the flag on a Message.
Definition: flags.c:433
int top
entry that is the top of the current page
Definition: mutt_menu.h:110
Nondestructive flags change (IMAP)
Definition: mx.h:73
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:2225
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:106
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:753
#define mutt_next_thread(e)
Definition: mutt_thread.h:64
New messages.
Definition: mutt.h:96
Messages that have been read.
Definition: mutt.h:99
#define MUTT_MAILBOX_CHECK_FORCE
Definition: mailbox.h:168
bool collapsed
is this message part of a collapsed thread?
Definition: email.h:76
bool quiet
inhibit status messages?
Definition: mailbox.h:118
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:1178
int msg_tagged
how many messages are tagged?
Definition: mailbox.h:97
#define CHECK_READONLY
Is the mailbox readonly?
Definition: index.c:152
#define SEND_NEWS
Reply to a news article.
Definition: send.h:100
void nntp_mailbox(struct Mailbox *m, char *buf, size_t buflen)
Get first newsgroup with new messages.
Definition: newsrc.c:1335
#define mutt_thread_next_unread(ctx, cur)
Definition: mutt_thread.h:61
WHERE bool OptSearchInvalid
(pseudo) used to invalidate the search pat
Definition: options.h:49
AclFlags rights
ACL bits, see AclFlags.
Definition: mailbox.h:121
int mutt_messages_in_thread(struct Mailbox *m, struct Email *e, int flag)
Count the messages in a thread.
Definition: mutt_thread.c:1391
#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
WHERE bool OptRedrawTree
(pseudo) redraw the thread tree
Definition: options.h:47
#define STAILQ_NEXT(elm, field)
Definition: queue.h:398
#define SEND_REPLY
Reply to sender.
Definition: send.h:86
#define MUTT_PAGER_LOGS
Logview mode.
Definition: pager.h:57
struct Hash * mutt_make_id_hash(struct Mailbox *m)
Create a Hash Table for message-ids.
Definition: mutt_thread.c:1433
NNTP-specific Mailbox data -.
Definition: nntp.h:139
int mutt_window_mvaddstr(struct MuttWindow *win, int row, int col, const char *str)
Move the cursor and write a fixed string to a Window.
Definition: mutt_window.c:190
char * driver_tags_get_with_hidden(struct TagHead *head)
Get tags with hiddens.
Definition: tags.c:163
int mutt_window_move(struct MuttWindow *win, int row, int col)
Move the cursor in a Window.
Definition: mutt_window.c:162
void mutt_help(int menu)
Display the help menu.
Definition: help.c:438
void mutt_clear_pager_position(void)
Reset the pager&#39;s viewing position.
Definition: pager.c:1877
int(* menu_color)(int line)
Calculate the colour for a line of the menu.
Definition: mutt_menu.h:146
int max
the number of entries in the menu
Definition: mutt_menu.h:88
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: ncrypt.h:129
WHERE bool C_DeleteUntag
Config: Untag messages when they are marked for deletion.
Definition: globals.h:207
struct Buffer * pathbuf
Definition: mailbox.h:85
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:101
bool mutt_mailbox_list(void)
List the mailboxes with new mail.
Definition: mailbox.c:400
char * mutt_str_strcat(char *buf, size_t buflen, const char *s)
Concatenate two strings.
Definition: string.c:398
void ci_bounce_message(struct Mailbox *m, struct EmailList *el)
Bounce an email.
Definition: commands.c:370
int imap_check_mailbox(struct Mailbox *m, bool force)
use the NOOP or IDLE command to poll for new mail
Definition: imap.c:1192
int offset
row offset within the window to start the index
Definition: mutt_menu.h:91
#define SEND_GROUP_REPLY
Reply to all.
Definition: send.h:87
char * data
Definition: list.h:35
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:324
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:1105
#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:570
int mx_mbox_sync(struct Mailbox *m, int *index_hint)
Save changes to mailbox.
Definition: mx.c:814
#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:50
bool deleted
Definition: email.h:45
#define mutt_error(...)
Definition: logging.h:83
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:610
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:631
void mutt_timeout_hook(void)
Execute any timeout hooks.
Definition: hook.c:801
int mutt_select_sort(bool reverse)
Ask the user for a sort method.
Definition: commands.c:716
int index
the absolute (unsorted) message number
Definition: email.h:88
#define FREE(x)
Definition: memory.h:40
bool mutt_mailbox_notify(struct Mailbox *m_cur)
Notify the user if there&#39;s new mail.
Definition: mailbox.c:486
#define MUTT_ACL_SEEN
Change the &#39;seen&#39; status of a message.
Definition: mailbox.h:75
#define STAILQ_EMPTY(head)
Definition: queue.h:346
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:322
WHERE bool C_AutoTag
Config: Automatically apply actions to all tagged messages.
Definition: globals.h:200
bool C_PgpAutoDecode
Config: Automatically decrypt PGP messages.
Definition: index.c:106
struct MuttWindow * MuttMessageWindow
Message Window.
Definition: mutt_window.c:41
void mutt_alias_create(struct Envelope *cur, struct Address *iaddr)
Create a new Alias from an Envelope or an Address.
Definition: alias.c:369
int nm_read_entire_thread(struct Mailbox *m, struct Email *e)
Get the entire thread of an email.
int mutt_display_message(struct Email *cur)
Display a message in the pager.
Definition: commands.c:176
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:107
bool changed
mailbox has been modified
Definition: mailbox.h:114
void nm_db_longrun_init(struct Mailbox *m, bool writable)
Start a long transaction.
Definition: nm_db.c:292
#define mutt_debug(LEVEL,...)
Definition: logging.h:80
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:70
bool mx_tags_is_supported(struct Mailbox *m)
return true if mailbox support tagging
Definition: mx.c:1215
#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:99
bool mutt_edit_content_type(struct Email *e, struct Body *b, FILE *fp)
Edit the content type of an attachment.
Definition: commands.c:1182
int current
current entry
Definition: mutt_menu.h:87
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:344
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:578
A List node for strings.
Definition: list.h:33
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: buffer.c:409
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:291
Mailbox was reopened.
Definition: mx.h:72
void mutt_set_virtual(struct Context *ctx)
Set the virtual index number of all the messages in a mailbox.
Definition: mutt_thread.c:1181
char * pattern
limit pattern string
Definition: context.h:41
Sort by email threads.
Definition: sort.h:56
int mutt_search_command(int cur, int op)
Perform a search.
Definition: pattern.c:2525
#define STAILQ_FIRST(head)
Definition: queue.h:348
#define WithCrypto
Definition: ncrypt.h:155
#define SORT_MASK
Mask for the sort id.
Definition: sort.h:85
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:42
char * help
quickref for the current menu
Definition: mutt_menu.h:85
int mutt_ev_message(struct Mailbox *m, struct EmailList *el, enum EvMessage action)
Edit or view a message.
Definition: editmsg.c: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
Log at debug level 3.
Definition: logging.h:58
struct Hash * id_hash
hash table by msg id
Definition: mailbox.h:127
bool message_is_tagged(struct Context *ctx, int index)
Is a message in the index tagged (and within limit)
Definition: context.c:310
#define REDRAW_CURRENT
Redraw the current line of the menu.
Definition: mutt_menu.h:45
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: buffer.c:398
struct Email * last_tag
last tagged msg.
Definition: context.h:43
void mutt_draw_tree(struct Context *ctx)
Draw a tree of threaded emails.
Definition: mutt_thread.c:287
void nm_db_debug_check(struct Mailbox *m)
Check if the database is open.
Definition: nm_db.c:325
#define mutt_previous_subthread(e)
Definition: mutt_thread.h:67
struct NntpAccountData * CurrentNewsSrv
Current NNTP news server.
Definition: nntp.c:77
const char * mutt_make_version(void)
Generate the NeoMutt version string.
Definition: muttlib.c:1512
WHERE bool C_ArrowCursor
Config: Use an arrow &#39;->&#39; instead of highlighting in the index.
Definition: globals.h:195

+ Here is the caller graph for this function:

void mutt_set_header_color ( struct Mailbox m,
struct Email e 
)

Select a colour for a message.

Parameters
mMailbox
eCurrent Email

Definition at line 3645 of file index.c.

3646 {
3647  if (!e)
3648  return;
3649 
3650  struct ColorLine *color = NULL;
3651  struct PatternCache cache = { 0 };
3652 
3653  STAILQ_FOREACH(color, &ColorIndexList, entries)
3654  {
3656  MUTT_MATCH_FULL_ADDRESS, m, e, &cache))
3657  {
3658  e->pair = color->pair;
3659  return;
3660  }
3661  }
3663 }
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:1970
#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:72
Cache commonly-used patterns.
Definition: pattern.h:82
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:82
A regular expression and a color to highlight a line.
Definition: mutt_curses.h:180
struct PatternHead * color_pattern
compiled pattern to speed up index color calculation
Definition: mutt_curses.h:185

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

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

Definition at line 3668 of file index.c.

3670 {
3671  if (mutt_str_strcmp(name, "reply_regex") != 0)
3672  return true;
3673 
3674  if (!Context)
3675  return true;
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 true;
3697 }
struct Email ** emails
Definition: mailbox.h:99
The "current" mailbox.
Definition: context.h:38
int msg_count
total number of messages
Definition: mailbox.h:92
regex_t * regex
compiled expression
Definition: regex3.h:60
char * real_subj
offset of the real subject
Definition: envelope.h:51
struct Mailbox * mailbox
Definition: context.h:52
const char * name
Definition: pgpmicalg.c:45
struct Envelope * env
envelope information
Definition: email.h:92
struct Regex * C_ReplyRegex
Config: Regex to match message reply subjects like "re: ".
Definition: email_globals.c:37
WHERE bool OptResortInit
(pseudo) used to force the next resort to be from scratch
Definition: options.h:48
char * subject
Definition: envelope.h:50
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:618
The header of an email.
Definition: envelope.h:38

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

Variable Documentation

bool C_ChangeFolderNext

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

Definition at line 101 of file index.c.

bool C_CollapseAll

Config: Collapse all threads when entering a folder.

Definition at line 102 of file index.c.

bool C_CollapseFlagged

Config: Prevent the collapse of threads with flagged emails.

Definition at line 103 of file index.c.

bool C_CollapseUnread

Config: Prevent the collapse of threads with unread emails.

Definition at line 104 of file index.c.

char* C_MarkMacroPrefix

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

Definition at line 105 of file index.c.

bool C_PgpAutoDecode

Config: Automatically decrypt PGP messages.

Definition at line 106 of file index.c.

bool C_UncollapseJump

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

Definition at line 107 of file index.c.

bool C_UncollapseNew

Config: Open collapsed threads when new mail arrives.

Definition at line 108 of file index.c.

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

Definition at line 110 of file index.c.

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

Definition at line 123 of file index.c.