NeoMutt  2020-08-07-1-gab41a1
Teaching an old dog new tricks
DOXYGEN
pager.h File Reference

GUI display a file/email/help in a viewport with paging. More...

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
+ Include dependency graph for pager.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  Pager
 An email being displayed. More...
 

Macros

#define MUTT_PAGER_NO_FLAGS   0
 No flags are set. More...
 
#define MUTT_SHOWFLAT   (1 << 0)
 Show characters (used for displaying help) More...
 
#define MUTT_SHOWCOLOR   (1 << 1)
 Show characters in color otherwise don't show characters. More...
 
#define MUTT_HIDE   (1 << 2)
 Don't show quoted text. More...
 
#define MUTT_SEARCH   (1 << 3)
 Resolve search patterns. More...
 
#define MUTT_TYPES   (1 << 4)
 Compute line's type. More...
 
#define MUTT_SHOW   (MUTT_SHOWCOLOR | MUTT_SHOWFLAT)
 
#define MUTT_PAGER_NSKIP   (1 << 5)
 Preserve whitespace with smartwrap. More...
 
#define MUTT_PAGER_MARKER   (1 << 6)
 Use markers if option is set. More...
 
#define MUTT_PAGER_RETWINCH   (1 << 7)
 Need reformatting on SIGWINCH. More...
 
#define MUTT_PAGER_ATTACHMENT   (1 << 8)
 Attachments may exist. More...
 
#define MUTT_PAGER_NOWRAP   (1 << 9)
 Format for term width, ignore $wrap. More...
 
#define MUTT_PAGER_LOGS   (1 << 10)
 Logview mode. More...
 
#define MUTT_PAGER_MESSAGE   (MUTT_SHOWCOLOR | MUTT_PAGER_MARKER)
 
#define MUTT_DISPLAYFLAGS   (MUTT_SHOW | MUTT_PAGER_NSKIP | MUTT_PAGER_MARKER | MUTT_PAGER_LOGS)
 

Typedefs

typedef uint16_t PagerFlags
 Flags for mutt_pager(), e.g. MUTT_SHOWFLAT. More...
 

Functions

int mutt_pager (const char *banner, const char *fname, PagerFlags flags, struct Pager *extra)
 Display a file, or help, in a window. More...
 
void mutt_buffer_strip_formatting (struct Buffer *dest, const char *src, bool strip_markers)
 Removes ANSI and backspace formatting. More...
 
void mutt_clear_pager_position (void)
 Reset the pager's viewing position. More...
 

Variables

bool C_AllowAnsi
 Config: Allow ANSI colour codes in rich text messages. More...
 
bool C_HeaderColorPartial
 Config: Only colour the part of the header matching the regex. More...
 
short C_PagerContext
 Config: Number of lines of overlap when changing pages in the pager. More...
 
short C_PagerIndexLines
 Config: Number of index lines to display above the pager. More...
 
bool C_PagerStop
 Config: Don't automatically open the next message when at the end of a message. More...
 
short C_SearchContext
 Config: Context to display around search matches. More...
 
short C_SkipQuotedOffset
 Config: Lines of context to show when skipping quoted text. More...
 
bool C_SmartWrap
 Config: Wrap text at word boundaries. More...
 
struct RegexC_Smileys
 Config: Regex to match smileys to prevent mistakes when quoting text. More...
 
bool C_Tilde
 Config: Character to pad blank lines in the pager. More...
 

Detailed Description

GUI display a file/email/help in a viewport with paging.

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

Macro Definition Documentation

◆ MUTT_PAGER_NO_FLAGS

#define MUTT_PAGER_NO_FLAGS   0

No flags are set.

Definition at line 43 of file pager.h.

◆ MUTT_SHOWFLAT

#define MUTT_SHOWFLAT   (1 << 0)

Show characters (used for displaying help)

Definition at line 44 of file pager.h.

◆ MUTT_SHOWCOLOR

#define MUTT_SHOWCOLOR   (1 << 1)

Show characters in color otherwise don't show characters.

Definition at line 45 of file pager.h.

◆ MUTT_HIDE

#define MUTT_HIDE   (1 << 2)

Don't show quoted text.

Definition at line 46 of file pager.h.

◆ MUTT_SEARCH

#define MUTT_SEARCH   (1 << 3)

Resolve search patterns.

Definition at line 47 of file pager.h.

◆ MUTT_TYPES

#define MUTT_TYPES   (1 << 4)

Compute line's type.

Definition at line 48 of file pager.h.

◆ MUTT_SHOW

#define MUTT_SHOW   (MUTT_SHOWCOLOR | MUTT_SHOWFLAT)

Definition at line 49 of file pager.h.

◆ MUTT_PAGER_NSKIP

#define MUTT_PAGER_NSKIP   (1 << 5)

Preserve whitespace with smartwrap.

Definition at line 52 of file pager.h.

◆ MUTT_PAGER_MARKER

#define MUTT_PAGER_MARKER   (1 << 6)

Use markers if option is set.

Definition at line 53 of file pager.h.

◆ MUTT_PAGER_RETWINCH

#define MUTT_PAGER_RETWINCH   (1 << 7)

Need reformatting on SIGWINCH.

Definition at line 54 of file pager.h.

◆ MUTT_PAGER_ATTACHMENT

#define MUTT_PAGER_ATTACHMENT   (1 << 8)

Attachments may exist.

Definition at line 55 of file pager.h.

◆ MUTT_PAGER_NOWRAP

#define MUTT_PAGER_NOWRAP   (1 << 9)

Format for term width, ignore $wrap.

Definition at line 56 of file pager.h.

◆ MUTT_PAGER_LOGS

#define MUTT_PAGER_LOGS   (1 << 10)

Logview mode.

Definition at line 57 of file pager.h.

◆ MUTT_PAGER_MESSAGE

#define MUTT_PAGER_MESSAGE   (MUTT_SHOWCOLOR | MUTT_PAGER_MARKER)

Definition at line 58 of file pager.h.

◆ MUTT_DISPLAYFLAGS

#define MUTT_DISPLAYFLAGS   (MUTT_SHOW | MUTT_PAGER_NSKIP | MUTT_PAGER_MARKER | MUTT_PAGER_LOGS)

Definition at line 60 of file pager.h.

Typedef Documentation

◆ PagerFlags

typedef uint16_t PagerFlags

Flags for mutt_pager(), e.g. MUTT_SHOWFLAT.

Definition at line 42 of file pager.h.

Function Documentation

◆ mutt_pager()

int mutt_pager ( const char *  banner,
const char *  fname,
PagerFlags  flags,
struct Pager extra 
)

Display a file, or help, in a window.

Parameters
bannerTitle to display in status bar
fnameName of file to read
flagsFlags, e.g. MUTT_SHOWCOLOR
extraInfo about email to display
Return values
0Success
-1Error

This pager is actually not so simple as it once was. It now operates in two modes: one for viewing messages and the other for viewing help. These can be distinguished by whether or not "email" is NULL. The "email" arg is there so that we can do operations on the current message without the need to pop back out to the main-menu.

Definition at line 2251 of file pager.c.

2252 {
2253  static char searchbuf[256] = { 0 };
2254  char buf[1024];
2255  int ch = 0, rc = -1;
2256  bool first = true;
2257  int searchctx = 0;
2258  bool wrapped = false;
2259 
2260  struct Menu *pager_menu = NULL;
2261  int old_PagerIndexLines; /* some people want to resize it while inside the pager */
2262 #ifdef USE_NNTP
2263  char *followup_to = NULL;
2264 #endif
2265 
2266  struct Mailbox *m = Context ? Context->mailbox : NULL;
2267 
2268  if (!(flags & MUTT_SHOWCOLOR))
2269  flags |= MUTT_SHOWFLAT;
2270 
2271  int index_space = C_PagerIndexLines;
2272  if (extra->ctx && extra->ctx->mailbox)
2273  index_space = MIN(index_space, extra->ctx->mailbox->vcount);
2274 
2275  struct PagerRedrawData rd = { 0 };
2276  rd.banner = banner;
2277  rd.flags = flags;
2278  rd.extra = extra;
2279  rd.indexlen = index_space;
2280  rd.indicator = rd.indexlen / 3;
2281  rd.searchbuf = searchbuf;
2282  rd.has_types = (IsEmail(extra) || (flags & MUTT_SHOWCOLOR)) ? MUTT_TYPES : 0; /* main message or rfc822 attachment */
2283 
2284  rd.fp = fopen(fname, "r");
2285  if (!rd.fp)
2286  {
2287  mutt_perror(fname);
2288  return -1;
2289  }
2290 
2291  if (stat(fname, &rd.sb) != 0)
2292  {
2293  mutt_perror(fname);
2294  mutt_file_fclose(&rd.fp);
2295  return -1;
2296  }
2297  unlink(fname);
2298 
2299  if (rd.extra->win_index)
2300  {
2302  rd.extra->win_index->req_rows = index_space;
2304  window_set_visible(rd.extra->win_index->parent, (index_space > 0));
2305  }
2309 
2310  /* Initialize variables */
2311 
2312  if (Context && IsEmail(extra) && !extra->email->read)
2313  {
2314  Context->msg_in_pager = extra->email->msgno;
2315  mutt_set_flag(m, extra->email, MUTT_READ, true);
2316  }
2317 
2318  rd.max_line = LINES; /* number of lines on screen, from curses */
2319  rd.line_info = mutt_mem_calloc(rd.max_line, sizeof(struct Line));
2320  for (size_t i = 0; i < rd.max_line; i++)
2321  {
2322  rd.line_info[i].type = -1;
2323  rd.line_info[i].search_cnt = -1;
2324  rd.line_info[i].syntax = mutt_mem_malloc(sizeof(struct TextSyntax));
2325  (rd.line_info[i].syntax)[0].first = -1;
2326  (rd.line_info[i].syntax)[0].last = -1;
2327  }
2328 
2329  pager_menu = mutt_menu_new(MENU_PAGER);
2330  pager_menu->pagelen = extra->win_pager->state.rows;
2331  pager_menu->win_index = extra->win_pager;
2332  pager_menu->win_ibar = extra->win_pbar;
2333 
2334  pager_menu->custom_redraw = pager_custom_redraw;
2335  pager_menu->redraw_data = &rd;
2336  mutt_menu_push_current(pager_menu);
2337 
2338  if (IsEmail(extra))
2339  {
2340  // Viewing a Mailbox
2341 #ifdef USE_NNTP
2342  if (m && (m->type == MUTT_NNTP))
2343  extra->win_pager->help_data = PagerNewsHelp;
2344  else
2345 #endif
2347  }
2348  else
2349  {
2350  // Viewing Help
2351  if (InHelp)
2352  extra->win_pager->help_data = PagerHelpHelp;
2353  else
2354  extra->win_pager->help_data = PagerHelp;
2355  }
2356  extra->win_pager->help_menu = MENU_PAGER;
2357  window_set_focus(extra->win_pager);
2358 
2359  while (ch != -1)
2360  {
2362 
2363  pager_custom_redraw(pager_menu);
2364  window_redraw(RootWindow, true);
2365 
2366  if (C_BrailleFriendly)
2367  {
2368  if (braille_line != -1)
2369  {
2371  braille_line = -1;
2372  }
2373  }
2374  else
2376 
2377  mutt_refresh();
2378 
2379  if (IsEmail(extra) && (OldEmail == extra->email) && (TopLine != rd.topline) &&
2380  (rd.line_info[rd.curline].offset < (rd.sb.st_size - 1)))
2381  {
2382  if ((TopLine - rd.topline) > rd.lines)
2383  rd.topline += rd.lines;
2384  else
2385  rd.topline = TopLine;
2386  continue;
2387  }
2388  else
2389  OldEmail = NULL;
2390 
2391  ch = km_dokey(MENU_PAGER);
2392  if (ch >= 0)
2393  {
2394  mutt_clear_error();
2395  mutt_debug(LL_DEBUG1, "Got op %s (%d)\n", OpStrings[ch][0], ch);
2396  }
2398 
2399  bool do_new_mail = false;
2400 
2401  if (m && !OptAttachMsg)
2402  {
2403  int oldcount = m->msg_count;
2404  /* check for new mail */
2405  int check = mx_mbox_check(m);
2406  if (check < 0)
2407  {
2408  if (!m || mutt_buffer_is_empty(&m->pathbuf))
2409  {
2410  /* fatal error occurred */
2411  ctx_free(&Context);
2412  pager_menu->redraw = REDRAW_FULL;
2413  break;
2414  }
2415  }
2416  else if ((check == MUTT_NEW_MAIL) || (check == MUTT_REOPENED) || (check == MUTT_FLAGS))
2417  {
2418  /* notify user of newly arrived mail */
2419  if (check == MUTT_NEW_MAIL)
2420  {
2421  for (size_t i = oldcount; i < m->msg_count; i++)
2422  {
2423  struct Email *e = m->emails[i];
2424 
2425  if (e && !e->read)
2426  {
2427  mutt_message(_("New mail in this mailbox"));
2428  do_new_mail = true;
2429  break;
2430  }
2431  }
2432  }
2433 
2434  if ((check == MUTT_NEW_MAIL) || (check == MUTT_REOPENED))
2435  {
2436  if (rd.menu && m)
2437  {
2438  /* After the mailbox has been updated,
2439  * rd.menu->current might be invalid */
2440  rd.menu->current = MIN(rd.menu->current, MAX(m->msg_count - 1, 0));
2441  struct Email *e = mutt_get_virt_email(m, rd.menu->current);
2442  if (!e)
2443  continue;
2444 
2445  bool verbose = m->verbose;
2446  m->verbose = false;
2447  mutt_update_index(rd.menu, Context, check, oldcount, e);
2448  m->verbose = verbose;
2449 
2450  rd.menu->max = m->vcount;
2451 
2452  /* If these header pointers don't match, then our email may have
2453  * been deleted. Make the pointer safe, then leave the pager.
2454  * This have a unpleasant behaviour to close the pager even the
2455  * deleted message is not the opened one, but at least it's safe. */
2456  e = mutt_get_virt_email(m, rd.menu->current);
2457  if (extra->email != e)
2458  {
2459  extra->email = e;
2460  break;
2461  }
2462  }
2463 
2464  pager_menu->redraw = REDRAW_FULL;
2465  OptSearchInvalid = true;
2466  }
2467  }
2468 
2469  if (mutt_mailbox_notify(m) || do_new_mail)
2470  {
2471  if (C_BeepNew)
2472  mutt_beep(true);
2473  if (C_NewMailCommand)
2474  {
2475  char cmd[1024];
2476  menu_status_line(cmd, sizeof(cmd), rd.menu, m, NONULL(C_NewMailCommand));
2477  if (mutt_system(cmd) != 0)
2478  mutt_error(_("Error running \"%s\""), cmd);
2479  }
2480  }
2481  }
2482 
2483  if (SigWinch)
2484  {
2485  SigWinch = 0;
2487  clearok(stdscr, true); /* force complete redraw */
2488 
2489  if (flags & MUTT_PAGER_RETWINCH)
2490  {
2491  /* Store current position. */
2492  rd.lines = -1;
2493  for (size_t i = 0; i <= rd.topline; i++)
2494  if (!rd.line_info[i].continuation)
2495  rd.lines++;
2496 
2497  Resize = mutt_mem_malloc(sizeof(struct Resize));
2498 
2499  Resize->line = rd.lines;
2502 
2503  ch = -1;
2504  rc = OP_REFORMAT_WINCH;
2505  }
2506  else
2507  {
2508  /* note: mutt_resize_screen() -> mutt_window_reflow() sets
2509  * REDRAW_FULL and REDRAW_FLOW */
2510  ch = 0;
2511  }
2512  continue;
2513  }
2514 
2515  if (ch < 0)
2516  {
2517  ch = 0;
2519  continue;
2520  }
2521 
2522  rc = ch;
2523 
2524  switch (ch)
2525  {
2526  case OP_EXIT:
2527  rc = -1;
2528  ch = -1;
2529  break;
2530 
2531  case OP_QUIT:
2532  if (query_quadoption(C_Quit, _("Quit NeoMutt?")) == MUTT_YES)
2533  {
2534  /* avoid prompting again in the index menu */
2535  cs_subset_str_native_set(NeoMutt->sub, "quit", MUTT_YES, NULL);
2536  ch = -1;
2537  }
2538  break;
2539 
2540  case OP_NEXT_PAGE:
2541  if (rd.line_info[rd.curline].offset < (rd.sb.st_size - 1))
2542  {
2544  }
2545  else if (C_PagerStop)
2546  {
2547  /* emulate "less -q" and don't go on to the next message. */
2548  mutt_error(_("Bottom of message is shown"));
2549  }
2550  else
2551  {
2552  /* end of the current message, so display the next message. */
2553  rc = OP_MAIN_NEXT_UNDELETED;
2554  ch = -1;
2555  }
2556  break;
2557 
2558  case OP_PREV_PAGE:
2559  if (rd.topline == 0)
2560  {
2561  mutt_message(_("Top of message is shown"));
2562  }
2563  else
2564  {
2566  rd.line_info, rd.topline, rd.hide_quoted);
2567  }
2568  break;
2569 
2570  case OP_NEXT_LINE:
2571  if (rd.line_info[rd.curline].offset < (rd.sb.st_size - 1))
2572  {
2573  rd.topline++;
2574  if (rd.hide_quoted)
2575  {
2576  while ((rd.line_info[rd.topline].type == MT_COLOR_QUOTED) &&
2577  (rd.topline < rd.last_line))
2578  {
2579  rd.topline++;
2580  }
2581  }
2582  }
2583  else
2584  mutt_message(_("Bottom of message is shown"));
2585  break;
2586 
2587  case OP_PREV_LINE:
2588  if (rd.topline)
2589  rd.topline = up_n_lines(1, rd.line_info, rd.topline, rd.hide_quoted);
2590  else
2591  mutt_error(_("Top of message is shown"));
2592  break;
2593 
2594  case OP_PAGER_TOP:
2595  if (rd.topline)
2596  rd.topline = 0;
2597  else
2598  mutt_error(_("Top of message is shown"));
2599  break;
2600 
2601  case OP_HALF_UP:
2602  if (rd.topline)
2603  {
2604  rd.topline = up_n_lines(rd.extra->win_pager->state.rows / 2 +
2605  (rd.extra->win_pager->state.rows % 2),
2606  rd.line_info, rd.topline, rd.hide_quoted);
2607  }
2608  else
2609  mutt_error(_("Top of message is shown"));
2610  break;
2611 
2612  case OP_HALF_DOWN:
2613  if (rd.line_info[rd.curline].offset < (rd.sb.st_size - 1))
2614  {
2615  rd.topline = up_n_lines(rd.extra->win_pager->state.rows / 2,
2616  rd.line_info, rd.curline, rd.hide_quoted);
2617  }
2618  else if (C_PagerStop)
2619  {
2620  /* emulate "less -q" and don't go on to the next message. */
2621  mutt_error(_("Bottom of message is shown"));
2622  }
2623  else
2624  {
2625  /* end of the current message, so display the next message. */
2626  rc = OP_MAIN_NEXT_UNDELETED;
2627  ch = -1;
2628  }
2629  break;
2630 
2631  case OP_SEARCH_NEXT:
2632  case OP_SEARCH_OPPOSITE:
2633  if (rd.search_compiled)
2634  {
2635  wrapped = false;
2636 
2637  if (C_SearchContext < rd.extra->win_pager->state.rows)
2638  searchctx = C_SearchContext;
2639  else
2640  searchctx = 0;
2641 
2642  search_next:
2643  if ((!rd.search_back && (ch == OP_SEARCH_NEXT)) ||
2644  (rd.search_back && (ch == OP_SEARCH_OPPOSITE)))
2645  {
2646  /* searching forward */
2647  int i;
2648  for (i = wrapped ? 0 : rd.topline + searchctx + 1; i < rd.last_line; i++)
2649  {
2650  if ((!rd.hide_quoted || (rd.line_info[i].type != MT_COLOR_QUOTED)) &&
2651  !rd.line_info[i].continuation && (rd.line_info[i].search_cnt > 0))
2652  {
2653  break;
2654  }
2655  }
2656 
2657  if (i < rd.last_line)
2658  rd.topline = i;
2659  else if (wrapped || !C_WrapSearch)
2660  mutt_error(_("Not found"));
2661  else
2662  {
2663  mutt_message(_("Search wrapped to top"));
2664  wrapped = true;
2665  goto search_next;
2666  }
2667  }
2668  else
2669  {
2670  /* searching backward */
2671  int i;
2672  for (i = wrapped ? rd.last_line : rd.topline + searchctx - 1; i >= 0; i--)
2673  {
2674  if ((!rd.hide_quoted ||
2675  (rd.has_types && (rd.line_info[i].type != MT_COLOR_QUOTED))) &&
2676  !rd.line_info[i].continuation && (rd.line_info[i].search_cnt > 0))
2677  {
2678  break;
2679  }
2680  }
2681 
2682  if (i >= 0)
2683  rd.topline = i;
2684  else if (wrapped || !C_WrapSearch)
2685  mutt_error(_("Not found"));
2686  else
2687  {
2688  mutt_message(_("Search wrapped to bottom"));
2689  wrapped = true;
2690  goto search_next;
2691  }
2692  }
2693 
2694  if (rd.line_info[rd.topline].search_cnt > 0)
2695  {
2696  rd.search_flag = MUTT_SEARCH;
2697  /* give some context for search results */
2698  if (rd.topline - searchctx > 0)
2699  rd.topline -= searchctx;
2700  }
2701 
2702  break;
2703  }
2704  /* no previous search pattern */
2705  /* fallthrough */
2706 
2707  case OP_SEARCH:
2708  case OP_SEARCH_REVERSE:
2709  mutt_str_copy(buf, searchbuf, sizeof(buf));
2710  if (mutt_get_field(((ch == OP_SEARCH) || (ch == OP_SEARCH_NEXT)) ?
2711  _("Search for: ") :
2712  _("Reverse search for: "),
2713  buf, sizeof(buf), MUTT_CLEAR | MUTT_PATTERN) != 0)
2714  {
2715  break;
2716  }
2717 
2718  if (strcmp(buf, searchbuf) == 0)
2719  {
2720  if (rd.search_compiled)
2721  {
2722  /* do an implicit search-next */
2723  if (ch == OP_SEARCH)
2724  ch = OP_SEARCH_NEXT;
2725  else
2726  ch = OP_SEARCH_OPPOSITE;
2727 
2728  wrapped = false;
2729  goto search_next;
2730  }
2731  }
2732 
2733  if (buf[0] == '\0')
2734  break;
2735 
2736  mutt_str_copy(searchbuf, buf, sizeof(searchbuf));
2737 
2738  /* leave search_back alone if ch == OP_SEARCH_NEXT */
2739  if (ch == OP_SEARCH)
2740  rd.search_back = false;
2741  else if (ch == OP_SEARCH_REVERSE)
2742  rd.search_back = true;
2743 
2744  if (rd.search_compiled)
2745  {
2746  regfree(&rd.search_re);
2747  for (size_t i = 0; i < rd.last_line; i++)
2748  {
2749  FREE(&(rd.line_info[i].search));
2750  rd.line_info[i].search_cnt = -1;
2751  }
2752  }
2753 
2754  int rflags = mutt_mb_is_lower(searchbuf) ? REG_ICASE : 0;
2755  int err = REG_COMP(&rd.search_re, searchbuf, REG_NEWLINE | rflags);
2756  if (err != 0)
2757  {
2758  regerror(err, &rd.search_re, buf, sizeof(buf));
2759  mutt_error("%s", buf);
2760  for (size_t i = 0; i < rd.max_line; i++)
2761  {
2762  /* cleanup */
2763  FREE(&(rd.line_info[i].search));
2764  rd.line_info[i].search_cnt = -1;
2765  }
2766  rd.search_flag = 0;
2767  rd.search_compiled = false;
2768  }
2769  else
2770  {
2771  rd.search_compiled = true;
2772  /* update the search pointers */
2773  int line_num = 0;
2774  while (display_line(rd.fp, &rd.last_pos, &rd.line_info, line_num,
2775  &rd.last_line, &rd.max_line,
2776  MUTT_SEARCH | (flags & MUTT_PAGER_NSKIP) | (flags & MUTT_PAGER_NOWRAP),
2777  &rd.quote_list, &rd.q_level, &rd.force_redraw,
2778  &rd.search_re, rd.extra->win_pager) == 0)
2779  {
2780  line_num++;
2781  }
2782 
2783  if (!rd.search_back)
2784  {
2785  /* searching forward */
2786  int i;
2787  for (i = rd.topline; i < rd.last_line; i++)
2788  {
2789  if ((!rd.hide_quoted || (rd.line_info[i].type != MT_COLOR_QUOTED)) &&
2790  !rd.line_info[i].continuation && (rd.line_info[i].search_cnt > 0))
2791  {
2792  break;
2793  }
2794  }
2795 
2796  if (i < rd.last_line)
2797  rd.topline = i;
2798  }
2799  else
2800  {
2801  /* searching backward */
2802  int i;
2803  for (i = rd.topline; i >= 0; i--)
2804  {
2805  if ((!rd.hide_quoted || (rd.line_info[i].type != MT_COLOR_QUOTED)) &&
2806  !rd.line_info[i].continuation && (rd.line_info[i].search_cnt > 0))
2807  {
2808  break;
2809  }
2810  }
2811 
2812  if (i >= 0)
2813  rd.topline = i;
2814  }
2815 
2816  if (rd.line_info[rd.topline].search_cnt == 0)
2817  {
2818  rd.search_flag = 0;
2819  mutt_error(_("Not found"));
2820  }
2821  else
2822  {
2823  rd.search_flag = MUTT_SEARCH;
2824  /* give some context for search results */
2825  if (C_SearchContext < rd.extra->win_pager->state.rows)
2826  searchctx = C_SearchContext;
2827  else
2828  searchctx = 0;
2829  if (rd.topline - searchctx > 0)
2830  rd.topline -= searchctx;
2831  }
2832  }
2833  pager_menu->redraw = REDRAW_BODY;
2834  break;
2835 
2836  case OP_SEARCH_TOGGLE:
2837  if (rd.search_compiled)
2838  {
2839  rd.search_flag ^= MUTT_SEARCH;
2840  pager_menu->redraw = REDRAW_BODY;
2841  }
2842  break;
2843 
2844  case OP_SORT:
2845  case OP_SORT_REVERSE:
2846  CHECK_MODE(IsEmail(extra))
2847  if (mutt_select_sort((ch == OP_SORT_REVERSE)) == 0)
2848  {
2849  OptNeedResort = true;
2850  ch = -1;
2851  rc = OP_DISPLAY_MESSAGE;
2852  }
2853  break;
2854 
2855  case OP_HELP:
2856  if (InHelp)
2857  {
2858  /* don't let the user enter the help-menu from the help screen! */
2859  mutt_error(_("Help is currently being shown"));
2860  break;
2861  }
2862 
2863  InHelp = true;
2864  mutt_help(MENU_PAGER, pager_menu->win_index->state.cols);
2865  pager_menu->redraw = REDRAW_FULL;
2866  InHelp = false;
2867  break;
2868 
2869  case OP_PAGER_HIDE_QUOTED:
2870  if (!rd.has_types)
2871  break;
2872 
2873  rd.hide_quoted ^= MUTT_HIDE;
2874  if (rd.hide_quoted && (rd.line_info[rd.topline].type == MT_COLOR_QUOTED))
2875  rd.topline = up_n_lines(1, rd.line_info, rd.topline, rd.hide_quoted);
2876  else
2877  pager_menu->redraw = REDRAW_BODY;
2878  break;
2879 
2880  case OP_PAGER_SKIP_QUOTED:
2881  if (!rd.has_types)
2882  break;
2883 
2884  int dretval = 0;
2885  int new_topline = rd.topline;
2886 
2887  /* Skip all the email headers */
2888  if (IS_HEADER(rd.line_info[new_topline].type))
2889  {
2890  while (((new_topline < rd.last_line) ||
2891  (0 == (dretval = display_line(
2892  rd.fp, &rd.last_pos, &rd.line_info, new_topline, &rd.last_line,
2893  &rd.max_line, MUTT_TYPES | (flags & MUTT_PAGER_NOWRAP),
2894  &rd.quote_list, &rd.q_level, &rd.force_redraw,
2895  &rd.search_re, rd.extra->win_pager)))) &&
2896  IS_HEADER(rd.line_info[new_topline].type))
2897  {
2898  new_topline++;
2899  }
2900  rd.topline = new_topline;
2901  break;
2902  }
2903 
2904  while ((((new_topline + C_SkipQuotedOffset) < rd.last_line) ||
2905  (0 == (dretval = display_line(
2906  rd.fp, &rd.last_pos, &rd.line_info, new_topline, &rd.last_line,
2907  &rd.max_line, MUTT_TYPES | (flags & MUTT_PAGER_NOWRAP),
2908  &rd.quote_list, &rd.q_level, &rd.force_redraw,
2909  &rd.search_re, rd.extra->win_pager)))) &&
2910  (rd.line_info[new_topline + C_SkipQuotedOffset].type != MT_COLOR_QUOTED))
2911  {
2912  new_topline++;
2913  }
2914 
2915  if (dretval < 0)
2916  {
2917  mutt_error(_("No more quoted text"));
2918  break;
2919  }
2920 
2921  while ((((new_topline + C_SkipQuotedOffset) < rd.last_line) ||
2922  (0 == (dretval = display_line(
2923  rd.fp, &rd.last_pos, &rd.line_info, new_topline, &rd.last_line,
2924  &rd.max_line, MUTT_TYPES | (flags & MUTT_PAGER_NOWRAP),
2925  &rd.quote_list, &rd.q_level, &rd.force_redraw,
2926  &rd.search_re, rd.extra->win_pager)))) &&
2927  (rd.line_info[new_topline + C_SkipQuotedOffset].type == MT_COLOR_QUOTED))
2928  {
2929  new_topline++;
2930  }
2931 
2932  if (dretval < 0)
2933  {
2934  mutt_error(_("No more unquoted text after quoted text"));
2935  break;
2936  }
2937  rd.topline = new_topline;
2938  break;
2939 
2940  case OP_PAGER_BOTTOM: /* move to the end of the file */
2941  if (rd.line_info[rd.curline].offset < (rd.sb.st_size - 1))
2942  {
2943  int line_num = rd.curline;
2944  /* make sure the types are defined to the end of file */
2945  while (display_line(rd.fp, &rd.last_pos, &rd.line_info, line_num, &rd.last_line,
2946  &rd.max_line, rd.has_types | (flags & MUTT_PAGER_NOWRAP),
2947  &rd.quote_list, &rd.q_level, &rd.force_redraw,
2948  &rd.search_re, rd.extra->win_pager) == 0)
2949  {
2950  line_num++;
2951  }
2953  rd.last_line, rd.hide_quoted);
2954  }
2955  else
2956  mutt_error(_("Bottom of message is shown"));
2957  break;
2958 
2959  case OP_REDRAW:
2960  mutt_window_reflow(NULL);
2961  clearok(stdscr, true);
2962  pager_menu->redraw = REDRAW_FULL;
2963  break;
2964 
2965  case OP_NULL:
2967  break;
2968 
2969  /* --------------------------------------------------------------------
2970  * The following are operations on the current message rather than
2971  * adjusting the view of the message. */
2972 
2973  case OP_BOUNCE_MESSAGE:
2974  {
2975  CHECK_MODE(IsEmail(extra) || IsMsgAttach(extra))
2976  CHECK_ATTACH;
2977  if (IsMsgAttach(extra))
2978  mutt_attach_bounce(m, extra->fp, extra->actx, extra->body);
2979  else
2980  {
2981  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
2982  emaillist_add_email(&el, extra->email);
2983  ci_bounce_message(m, &el);
2984  emaillist_clear(&el);
2985  }
2986  break;
2987  }
2988 
2989  case OP_RESEND:
2990  CHECK_MODE(IsEmail(extra) || IsMsgAttach(extra))
2991  CHECK_ATTACH;
2992  if (IsMsgAttach(extra))
2993  mutt_attach_resend(extra->fp, extra->actx, extra->body);
2994  else
2995  mutt_resend_message(NULL, extra->ctx, extra->email, NeoMutt->sub);
2996  pager_menu->redraw = REDRAW_FULL;
2997  break;
2998 
2999  case OP_COMPOSE_TO_SENDER:
3000  CHECK_MODE(IsEmail(extra) || IsMsgAttach(extra));
3001  CHECK_ATTACH;
3002  if (IsMsgAttach(extra))
3003  mutt_attach_mail_sender(extra->fp, extra->email, extra->actx, extra->body);
3004  else
3005  {
3006  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3007  emaillist_add_email(&el, extra->email);
3008  mutt_send_message(SEND_TO_SENDER, NULL, NULL, extra->ctx, &el, NeoMutt->sub);
3009  emaillist_clear(&el);
3010  }
3011  pager_menu->redraw = REDRAW_FULL;
3012  break;
3013 
3014  case OP_CHECK_TRADITIONAL:
3015  CHECK_MODE(IsEmail(extra));
3016  if (!(WithCrypto & APPLICATION_PGP))
3017  break;
3018  if (!(extra->email->security & PGP_TRADITIONAL_CHECKED))
3019  {
3020  ch = -1;
3021  rc = OP_CHECK_TRADITIONAL;
3022  }
3023  break;
3024 
3025  case OP_CREATE_ALIAS:
3026  CHECK_MODE(IsEmail(extra) || IsMsgAttach(extra));
3027  struct AddressList *al = NULL;
3028  if (IsMsgAttach(extra))
3029  al = mutt_get_address(extra->body->email->env, NULL);
3030  else
3031  al = mutt_get_address(extra->email->env, NULL);
3032  alias_create(al);
3033  break;
3034 
3035  case OP_PURGE_MESSAGE:
3036  case OP_DELETE:
3037  CHECK_MODE(IsEmail(extra));
3039  /* L10N: CHECK_ACL */
3040  CHECK_ACL(MUTT_ACL_DELETE, _("Can't delete message"));
3041 
3042  mutt_set_flag(Context->mailbox, extra->email, MUTT_DELETE, true);
3043  mutt_set_flag(Context->mailbox, extra->email, MUTT_PURGE, (ch == OP_PURGE_MESSAGE));
3044  if (C_DeleteUntag)
3045  mutt_set_flag(Context->mailbox, extra->email, MUTT_TAG, false);
3046  pager_menu->redraw |= REDRAW_STATUS | REDRAW_INDEX;
3047  if (C_Resolve)
3048  {
3049  ch = -1;
3050  rc = OP_MAIN_NEXT_UNDELETED;
3051  }
3052  break;
3053 
3054  case OP_MAIN_SET_FLAG:
3055  case OP_MAIN_CLEAR_FLAG:
3056  {
3057  CHECK_MODE(IsEmail(extra));
3059 
3060  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3061  emaillist_add_email(&el, extra->email);
3062 
3063  if (mutt_change_flag(Context->mailbox, &el, (ch == OP_MAIN_SET_FLAG)) == 0)
3064  pager_menu->redraw |= REDRAW_STATUS | REDRAW_INDEX;
3065  if (extra->email->deleted && C_Resolve)
3066  {
3067  ch = -1;
3068  rc = OP_MAIN_NEXT_UNDELETED;
3069  }
3070  emaillist_clear(&el);
3071  break;
3072  }
3073 
3074  case OP_DELETE_THREAD:
3075  case OP_DELETE_SUBTHREAD:
3076  case OP_PURGE_THREAD:
3077  {
3078  CHECK_MODE(IsEmail(extra));
3080  /* L10N: CHECK_ACL */
3081  /* L10N: Due to the implementation details we do not know whether we
3082  delete zero, 1, 12, ... messages. So in English we use
3083  "messages". Your language might have other means to express this. */
3084  CHECK_ACL(MUTT_ACL_DELETE, _("Can't delete messages"));
3085 
3086  int subthread = (ch == OP_DELETE_SUBTHREAD);
3087  int r = mutt_thread_set_flag(extra->email, MUTT_DELETE, 1, subthread);
3088  if (r == -1)
3089  break;
3090  if (ch == OP_PURGE_THREAD)
3091  {
3092  r = mutt_thread_set_flag(extra->email, MUTT_PURGE, true, subthread);
3093  if (r == -1)
3094  break;
3095  }
3096 
3097  if (C_DeleteUntag)
3098  mutt_thread_set_flag(extra->email, MUTT_TAG, 0, subthread);
3099  if (C_Resolve)
3100  {
3101  rc = OP_MAIN_NEXT_UNDELETED;
3102  ch = -1;
3103  }
3104 
3105  if (!C_Resolve && (C_PagerIndexLines != 0))
3106  pager_menu->redraw = REDRAW_FULL;
3107  else
3108  pager_menu->redraw |= REDRAW_STATUS | REDRAW_INDEX;
3109 
3110  break;
3111  }
3112 
3113  case OP_DISPLAY_ADDRESS:
3114  CHECK_MODE(IsEmail(extra) || IsMsgAttach(extra));
3115  if (IsMsgAttach(extra))
3116  mutt_display_address(extra->body->email->env);
3117  else
3118  mutt_display_address(extra->email->env);
3119  break;
3120 
3121  case OP_ENTER_COMMAND:
3122  old_PagerIndexLines = C_PagerIndexLines;
3123 
3126  pager_menu->redraw = REDRAW_FULL;
3127 
3128  if (OptNeedResort)
3129  {
3130  OptNeedResort = false;
3131  CHECK_MODE(IsEmail(extra));
3132  OptNeedResort = true;
3133  }
3134 
3135  if (old_PagerIndexLines != C_PagerIndexLines)
3136  {
3137  mutt_menu_free(&rd.menu);
3138  }
3139 
3140  if ((pager_menu->redraw & REDRAW_FLOW) && (flags & MUTT_PAGER_RETWINCH))
3141  {
3142  ch = -1;
3143  rc = OP_REFORMAT_WINCH;
3144  continue;
3145  }
3146 
3147  ch = 0;
3148  break;
3149 
3150  case OP_FLAG_MESSAGE:
3151  CHECK_MODE(IsEmail(extra));
3153  /* L10N: CHECK_ACL */
3154  CHECK_ACL(MUTT_ACL_WRITE, "Can't flag message");
3155 
3156  mutt_set_flag(Context->mailbox, extra->email, MUTT_FLAG, !extra->email->flagged);
3157  pager_menu->redraw |= REDRAW_STATUS | REDRAW_INDEX;
3158  if (C_Resolve)
3159  {
3160  ch = -1;
3161  rc = OP_MAIN_NEXT_UNDELETED;
3162  }
3163  break;
3164 
3165  case OP_PIPE:
3166  CHECK_MODE(IsEmail(extra) || IsAttach(extra));
3167  if (IsAttach(extra))
3168  mutt_pipe_attachment_list(extra->actx, extra->fp, false, extra->body, false);
3169  else
3170  {
3171  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3172  el_add_tagged(&el, extra->ctx, extra->email, false);
3173  mutt_pipe_message(extra->ctx->mailbox, &el);
3174  emaillist_clear(&el);
3175  }
3176  break;
3177 
3178  case OP_PRINT:
3179  CHECK_MODE(IsEmail(extra) || IsAttach(extra));
3180  if (IsAttach(extra))
3181  mutt_print_attachment_list(extra->actx, extra->fp, false, extra->body);
3182  else
3183  {
3184  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3185  el_add_tagged(&el, extra->ctx, extra->email, false);
3186  mutt_print_message(extra->ctx->mailbox, &el);
3187  emaillist_clear(&el);
3188  }
3189  break;
3190 
3191  case OP_MAIL:
3192  CHECK_MODE(IsEmail(extra) && !IsAttach(extra));
3193  CHECK_ATTACH;
3194  mutt_send_message(SEND_NO_FLAGS, NULL, NULL, extra->ctx, NULL, NeoMutt->sub);
3195  pager_menu->redraw = REDRAW_FULL;
3196  break;
3197 
3198 #ifdef USE_NNTP
3199  case OP_POST:
3200  CHECK_MODE(IsEmail(extra) && !IsAttach(extra));
3201  CHECK_ATTACH;
3202  if (extra->ctx && (extra->ctx->mailbox->type == MUTT_NNTP) &&
3203  !((struct NntpMboxData *) extra->ctx->mailbox->mdata)->allowed && (query_quadoption(C_PostModerated, _("Posting to this group not allowed, may be moderated. Continue?")) != MUTT_YES))
3204  {
3205  break;
3206  }
3207  mutt_send_message(SEND_NEWS, NULL, NULL, extra->ctx, NULL, NeoMutt->sub);
3208  pager_menu->redraw = REDRAW_FULL;
3209  break;
3210 
3211  case OP_FORWARD_TO_GROUP:
3212  CHECK_MODE(IsEmail(extra) || IsMsgAttach(extra));
3213  CHECK_ATTACH;
3214  if (extra->ctx && (extra->ctx->mailbox->type == MUTT_NNTP) &&
3215  !((struct NntpMboxData *) extra->ctx->mailbox->mdata)->allowed && (query_quadoption(C_PostModerated, _("Posting to this group not allowed, may be moderated. Continue?")) != MUTT_YES))
3216  {
3217  break;
3218  }
3219  if (IsMsgAttach(extra))
3220  mutt_attach_forward(extra->fp, extra->email, extra->actx, extra->body, SEND_NEWS);
3221  else
3222  {
3223  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3224  emaillist_add_email(&el, extra->email);
3225  mutt_send_message(SEND_NEWS | SEND_FORWARD, NULL, NULL, extra->ctx,
3226  &el, NeoMutt->sub);
3227  emaillist_clear(&el);
3228  }
3229  pager_menu->redraw = REDRAW_FULL;
3230  break;
3231 
3232  case OP_FOLLOWUP:
3233  CHECK_MODE(IsEmail(extra) || IsMsgAttach(extra));
3234  CHECK_ATTACH;
3235 
3236  if (IsMsgAttach(extra))
3237  followup_to = extra->body->email->env->followup_to;
3238  else
3239  followup_to = extra->email->env->followup_to;
3240 
3241  if (!followup_to || !mutt_istr_equal(followup_to, "poster") ||
3243  _("Reply by mail as poster prefers?")) != MUTT_YES))
3244  {
3245  if (extra->ctx && (extra->ctx->mailbox->type == MUTT_NNTP) &&
3246  !((struct NntpMboxData *) extra->ctx->mailbox->mdata)->allowed && (query_quadoption(C_PostModerated, _("Posting to this group not allowed, may be moderated. Continue?")) != MUTT_YES))
3247  {
3248  break;
3249  }
3250  if (IsMsgAttach(extra))
3251  {
3252  mutt_attach_reply(extra->fp, extra->email, extra->actx, extra->body,
3253  SEND_NEWS | SEND_REPLY);
3254  }
3255  else
3256  {
3257  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3258  emaillist_add_email(&el, extra->email);
3259  mutt_send_message(SEND_NEWS | SEND_REPLY, NULL, NULL, extra->ctx,
3260  &el, NeoMutt->sub);
3261  emaillist_clear(&el);
3262  }
3263  pager_menu->redraw = REDRAW_FULL;
3264  break;
3265  }
3266 #endif
3267  /* fallthrough */
3268  case OP_REPLY:
3269  case OP_GROUP_REPLY:
3270  case OP_GROUP_CHAT_REPLY:
3271  case OP_LIST_REPLY:
3272  {
3273  CHECK_MODE(IsEmail(extra) || IsMsgAttach(extra));
3274  CHECK_ATTACH;
3275 
3276  SendFlags replyflags = SEND_REPLY;
3277  if (ch == OP_GROUP_REPLY)
3278  replyflags |= SEND_GROUP_REPLY;
3279  else if (ch == OP_GROUP_CHAT_REPLY)
3280  replyflags |= SEND_GROUP_CHAT_REPLY;
3281  else if (ch == OP_LIST_REPLY)
3282  replyflags |= SEND_LIST_REPLY;
3283 
3284  if (IsMsgAttach(extra))
3285  mutt_attach_reply(extra->fp, extra->email, extra->actx, extra->body, replyflags);
3286  else
3287  {
3288  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3289  emaillist_add_email(&el, extra->email);
3290  mutt_send_message(replyflags, NULL, NULL, extra->ctx, &el, NeoMutt->sub);
3291  emaillist_clear(&el);
3292  }
3293  pager_menu->redraw = REDRAW_FULL;
3294  break;
3295  }
3296 
3297  case OP_RECALL_MESSAGE:
3298  {
3299  CHECK_MODE(IsEmail(extra) && !IsAttach(extra));
3300  CHECK_ATTACH;
3301  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3302  emaillist_add_email(&el, extra->email);
3303  mutt_send_message(SEND_POSTPONED, NULL, NULL, extra->ctx, &el, NeoMutt->sub);
3304  emaillist_clear(&el);
3305  pager_menu->redraw = REDRAW_FULL;
3306  break;
3307  }
3308 
3309  case OP_FORWARD_MESSAGE:
3310  CHECK_MODE(IsEmail(extra) || IsMsgAttach(extra));
3311  CHECK_ATTACH;
3312  if (IsMsgAttach(extra))
3313  mutt_attach_forward(extra->fp, extra->email, extra->actx, extra->body, SEND_NO_FLAGS);
3314  else
3315  {
3316  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3317  emaillist_add_email(&el, extra->email);
3318  mutt_send_message(SEND_FORWARD, NULL, NULL, extra->ctx, &el, NeoMutt->sub);
3319  emaillist_clear(&el);
3320  }
3321  pager_menu->redraw = REDRAW_FULL;
3322  break;
3323 
3324  case OP_DECRYPT_SAVE:
3325  if (!WithCrypto)
3326  {
3327  ch = -1;
3328  break;
3329  }
3330  /* fallthrough */
3331  case OP_SAVE:
3332  if (IsAttach(extra))
3333  {
3334  mutt_save_attachment_list(extra->actx, extra->fp, false, extra->body,
3335  extra->email, NULL);
3336  break;
3337  }
3338  /* fallthrough */
3339  case OP_COPY_MESSAGE:
3340  case OP_DECODE_SAVE:
3341  case OP_DECODE_COPY:
3342  case OP_DECRYPT_COPY:
3343  {
3344  if (!(WithCrypto != 0) && (ch == OP_DECRYPT_COPY))
3345  {
3346  ch = -1;
3347  break;
3348  }
3349  CHECK_MODE(IsEmail(extra));
3350  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3351  emaillist_add_email(&el, extra->email);
3352 
3353  const bool delete_original =
3354  (ch == OP_SAVE) || (ch == OP_DECODE_SAVE) || (ch == OP_DECRYPT_SAVE);
3355  const bool decode = (ch == OP_DECODE_SAVE) || (ch == OP_DECODE_COPY);
3356  const bool decrypt = (ch == OP_DECRYPT_SAVE) || (ch == OP_DECRYPT_COPY);
3357 
3358  if ((mutt_save_message(Context->mailbox, &el, delete_original, decode, decrypt) == 0) &&
3359  delete_original)
3360  {
3361  if (C_Resolve)
3362  {
3363  ch = -1;
3364  rc = OP_MAIN_NEXT_UNDELETED;
3365  }
3366  else
3367  pager_menu->redraw |= REDRAW_STATUS | REDRAW_INDEX;
3368  }
3369  emaillist_clear(&el);
3370  break;
3371  }
3372 
3373  case OP_SHELL_ESCAPE:
3375  break;
3376 
3377  case OP_TAG:
3378  CHECK_MODE(IsEmail(extra));
3379  if (Context)
3380  {
3381  mutt_set_flag(Context->mailbox, extra->email, MUTT_TAG, !extra->email->tagged);
3382  }
3383 
3384  pager_menu->redraw |= REDRAW_STATUS | REDRAW_INDEX;
3385  if (C_Resolve)
3386  {
3387  ch = -1;
3388  rc = OP_NEXT_ENTRY;
3389  }
3390  break;
3391 
3392  case OP_TOGGLE_NEW:
3393  CHECK_MODE(IsEmail(extra));
3395  /* L10N: CHECK_ACL */
3396  CHECK_ACL(MUTT_ACL_SEEN, _("Can't toggle new"));
3397 
3398  if (extra->email->read || extra->email->old)
3399  mutt_set_flag(Context->mailbox, extra->email, MUTT_NEW, true);
3400  else if (!first)
3401  mutt_set_flag(Context->mailbox, extra->email, MUTT_READ, true);
3402  first = false;
3403  Context->msg_in_pager = -1;
3404  pager_menu->redraw |= REDRAW_STATUS | REDRAW_INDEX;
3405  if (C_Resolve)
3406  {
3407  ch = -1;
3408  rc = OP_MAIN_NEXT_UNDELETED;
3409  }
3410  break;
3411 
3412  case OP_UNDELETE:
3413  CHECK_MODE(IsEmail(extra));
3415  /* L10N: CHECK_ACL */
3416  CHECK_ACL(MUTT_ACL_DELETE, _("Can't undelete message"));
3417 
3418  mutt_set_flag(Context->mailbox, extra->email, MUTT_DELETE, false);
3419  mutt_set_flag(Context->mailbox, extra->email, MUTT_PURGE, false);
3420  pager_menu->redraw |= REDRAW_STATUS | REDRAW_INDEX;
3421  if (C_Resolve)
3422  {
3423  ch = -1;
3424  rc = OP_NEXT_ENTRY;
3425  }
3426  break;
3427 
3428  case OP_UNDELETE_THREAD:
3429  case OP_UNDELETE_SUBTHREAD:
3430  {
3431  CHECK_MODE(IsEmail(extra));
3433  /* L10N: CHECK_ACL */
3434  /* L10N: Due to the implementation details we do not know whether we
3435  undelete zero, 1, 12, ... messages. So in English we use
3436  "messages". Your language might have other means to express this. */
3437  CHECK_ACL(MUTT_ACL_DELETE, _("Can't undelete messages"));
3438 
3439  int r = mutt_thread_set_flag(extra->email, MUTT_DELETE, false,
3440  (ch != OP_UNDELETE_THREAD));
3441  if (r != -1)
3442  {
3443  r = mutt_thread_set_flag(extra->email, MUTT_PURGE, false,
3444  (ch != OP_UNDELETE_THREAD));
3445  }
3446  if (r != -1)
3447  {
3448  if (C_Resolve)
3449  {
3450  rc = (ch == OP_DELETE_THREAD) ? OP_MAIN_NEXT_THREAD : OP_MAIN_NEXT_SUBTHREAD;
3451  ch = -1;
3452  }
3453 
3454  if (!C_Resolve && (C_PagerIndexLines != 0))
3455  pager_menu->redraw = REDRAW_FULL;
3456  else
3457  pager_menu->redraw |= REDRAW_STATUS | REDRAW_INDEX;
3458  }
3459  break;
3460  }
3461 
3462  case OP_VERSION:
3464  break;
3465 
3466  case OP_MAILBOX_LIST:
3468  break;
3469 
3470  case OP_VIEW_ATTACHMENTS:
3471  if (flags & MUTT_PAGER_ATTACHMENT)
3472  {
3473  ch = -1;
3474  rc = OP_ATTACH_COLLAPSE;
3475  break;
3476  }
3477  CHECK_MODE(IsEmail(extra));
3478  dlg_select_attachment(extra->email);
3479  if (Context && extra->email->attach_del)
3480  Context->mailbox->changed = true;
3481  pager_menu->redraw = REDRAW_FULL;
3482  break;
3483 
3484  case OP_MAIL_KEY:
3485  {
3486  if (!(WithCrypto & APPLICATION_PGP))
3487  {
3488  ch = -1;
3489  break;
3490  }
3491  CHECK_MODE(IsEmail(extra));
3492  CHECK_ATTACH;
3493  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3494  emaillist_add_email(&el, extra->email);
3495  mutt_send_message(SEND_KEY, NULL, NULL, extra->ctx, &el, NeoMutt->sub);
3496  emaillist_clear(&el);
3497  pager_menu->redraw = REDRAW_FULL;
3498  break;
3499  }
3500 
3501  case OP_EDIT_LABEL:
3502  {
3503  CHECK_MODE(IsEmail(extra));
3504 
3505  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3506  emaillist_add_email(&el, extra->email);
3507  rc = mutt_label_message(Context->mailbox, &el);
3508  emaillist_clear(&el);
3509 
3510  if (rc > 0)
3511  {
3512  Context->mailbox->changed = true;
3513  pager_menu->redraw = REDRAW_FULL;
3514  mutt_message(ngettext("%d label changed", "%d labels changed", rc), rc);
3515  }
3516  else
3517  {
3518  mutt_message(_("No labels changed"));
3519  }
3520  break;
3521  }
3522 
3523  case OP_FORGET_PASSPHRASE:
3525  break;
3526 
3527  case OP_EXTRACT_KEYS:
3528  {
3529  if (!WithCrypto)
3530  {
3531  ch = -1;
3532  break;
3533  }
3534  CHECK_MODE(IsEmail(extra));
3535  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3536  emaillist_add_email(&el, extra->email);
3538  emaillist_clear(&el);
3539  pager_menu->redraw = REDRAW_FULL;
3540  break;
3541  }
3542 
3543  case OP_WHAT_KEY:
3544  mutt_what_key();
3545  break;
3546 
3547  case OP_CHECK_STATS:
3548  mutt_check_stats();
3549  break;
3550 
3551 #ifdef USE_SIDEBAR
3552  case OP_SIDEBAR_FIRST:
3553  case OP_SIDEBAR_LAST:
3554  case OP_SIDEBAR_NEXT:
3555  case OP_SIDEBAR_NEXT_NEW:
3556  case OP_SIDEBAR_PAGE_DOWN:
3557  case OP_SIDEBAR_PAGE_UP:
3558  case OP_SIDEBAR_PREV:
3559  case OP_SIDEBAR_PREV_NEW:
3560  {
3561  struct MuttWindow *win_sidebar =
3563  if (!win_sidebar)
3564  break;
3565  sb_change_mailbox(win_sidebar, ch);
3566  break;
3567  }
3568 
3569  case OP_SIDEBAR_TOGGLE_VISIBLE:
3570  bool_str_toggle(NeoMutt->sub, "sidebar_visible", NULL);
3572  break;
3573 #endif
3574 
3575  default:
3576  ch = -1;
3577  break;
3578  }
3579  }
3580 
3581  mutt_file_fclose(&rd.fp);
3582  if (IsEmail(extra))
3583  {
3584  if (Context)
3585  Context->msg_in_pager = -1;
3586  switch (rc)
3587  {
3588  case -1:
3589  case OP_DISPLAY_HEADERS:
3591  break;
3592  default:
3593  TopLine = rd.topline;
3594  OldEmail = extra->email;
3595  break;
3596  }
3597  }
3598 
3600 
3601  for (size_t i = 0; i < rd.max_line; i++)
3602  {
3603  FREE(&(rd.line_info[i].syntax));
3604  if (rd.search_compiled && rd.line_info[i].search)
3605  FREE(&(rd.line_info[i].search));
3606  }
3607  if (rd.search_compiled)
3608  {
3609  regfree(&rd.search_re);
3610  rd.search_compiled = false;
3611  }
3612  FREE(&rd.line_info);
3613  mutt_menu_pop_current(pager_menu);
3614  mutt_menu_free(&pager_menu);
3615  mutt_menu_free(&rd.menu);
3616 
3617  if (rd.extra->win_index)
3618  {
3624  }
3627 
3628  return (rc != -1) ? rc : 0;
3629 }
int km_dokey(enum MenuType menu)
Determine what a keypress should do.
Definition: keymap.c:658
struct Menu * menu
the Pager Index (PI)
Definition: pager.c:189
struct Email ** emails
Array of Emails.
Definition: mailbox.h:99
int mutt_save_message(struct Mailbox *m, struct EmailList *el, bool delete_original, bool decode, bool decrypt)
Save an email.
Definition: commands.c:1035
The "current" mailbox.
Definition: context.h:38
FILE * fp
Source stream.
Definition: pager.h:70
void mutt_update_index(struct Menu *menu, struct Context *ctx, int check, int oldcount, const struct Email *cur_email)
Update the index.
Definition: index.c:660
#define MUTT_TYPES
Compute line&#39;s type.
Definition: pager.h:48
struct MuttWindow * win_index
Definition: pager.h:74
int mutt_thread_set_flag(struct Email *e, int flag, bool bf, bool subthread)
Set a flag on an entire thread.
Definition: flags.c:374
#define REDRAW_FULL
Redraw everything.
Definition: mutt_menu.h:45
enum MailboxType type
Mailbox type.
Definition: mailbox.h:105
bool mutt_mailbox_list(void)
List the mailboxes with new mail.
Definition: mutt_mailbox.c:232
#define NONULL(x)
Definition: string2.h:37
void alias_create(struct AddressList *al)
Create a new Alias from an Address.
Definition: alias.c:365
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
int msg_count
Total number of messages.
Definition: mailbox.h:91
#define mutt_set_flag(m, e, flag, bf)
Definition: protos.h:67
#define WithCrypto
Definition: lib.h:123
short C_PagerContext
Config: Number of lines of overlap when changing pages in the pager.
Definition: pager.c:86
#define SEND_TO_SENDER
Compose new email to sender.
Definition: send.h:52
int msg_in_pager
Message currently shown in the pager.
Definition: context.h:44
const char * banner
Definition: pager.c:194
void mutt_pipe_message(struct Mailbox *m, struct EmailList *el)
Pipe a message.
Definition: commands.c:706
The envelope/body of an email.
Definition: email.h:37
#define MUTT_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:62
WHERE bool C_DeleteUntag
Config: Untag messages when they are marked for deletion.
Definition: mutt_globals.h:146
struct Email * mutt_get_virt_email(struct Mailbox *m, int vnum)
Get a virtual Email.
Definition: context.c:401
PagerFlags hide_quoted
Definition: pager.c:184
#define MIN(a, b)
Definition: memory.h:31
#define mutt_perror(...)
Definition: logging.h:85
GUI selectable list of items.
Definition: mutt_menu.h:55
PagerFlags search_flag
Definition: pager.c:192
void window_set_focus(struct MuttWindow *win)
Set the Window focus.
Definition: mutt_window.c:773
&#39;NNTP&#39; (Usenet) Mailbox type
Definition: mailbox.h:52
#define mutt_message(...)
Definition: logging.h:83
int emaillist_add_email(struct EmailList *el, struct Email *e)
Add an Email to a list.
Definition: email.c:148
int help_menu
Menu for key bindings, e.g. MENU_PAGER.
Definition: mutt_window.h:134
Keep track when the pager needs redrawing.
Definition: pager.c:170
static int up_n_lines(int nlines, struct Line *info, int cur, bool hiding)
Reposition the pager&#39;s view up by n lines.
Definition: pager.c:1960
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:40
void mutt_display_address(struct Envelope *env)
Display the address of a message.
Definition: commands.c:918
#define MUTT_SHOWCOLOR
Show characters in color otherwise don&#39;t show characters.
Definition: pager.h:45
#define REDRAW_FLOW
Used by pager to reflow text.
Definition: mutt_menu.h:47
static int TopLine
Definition: pager.c:202
static void cleanup_quote(struct QClass **quote_list)
Free a quote list.
Definition: pager.c:588
void mutt_save_attachment_list(struct AttachCtx *actx, FILE *fp, bool tag, struct Body *top, struct Email *e, struct Menu *menu)
Save a list of attachments.
Definition: recvattach.c:722
bool attach_del
Has an attachment marked for deletion.
Definition: email.h:49
#define CHECK_ACL(aclbit, action)
Definition: pager.c:304
struct MuttWindow * mutt_window_find(struct MuttWindow *root, enum WindowType type)
Find a Window of a given type.
Definition: mutt_window.c:688
#define SEND_FORWARD
Forward email.
Definition: send.h:44
void mutt_resize_screen(void)
Update NeoMutt&#39;s opinion about the window size (CURSES)
Definition: resize.c:101
WHERE bool OptNeedResort
(pseudo) used to force a re-sort
Definition: options.h:43
void mutt_check_stats(void)
Forcibly update mailbox stats.
Definition: commands.c:1428
struct MuttWindow * RootWindow
Parent of all Windows.
Definition: mutt_window.c:45
void crypt_forget_passphrase(void)
Forget a passphrase and display a message.
Definition: crypt.c:92
#define IsMsgAttach(pager)
Definition: pager.c:274
void mutt_enter_command(void)
enter a neomutt command
Definition: commands.c:872
static void pager_custom_redraw(struct Menu *pager_menu)
Redraw the pager window - Implements Menu::custom_redraw()
Definition: pager.c:1984
Flagged messages.
Definition: mutt.h:102
#define _(a)
Definition: message.h:28
WHERE bool C_BeepNew
Config: Make a noise when new mail arrives.
Definition: mutt_globals.h:141
struct Line * line_info
Definition: pager.c:196
struct Body * body
Current attachment.
Definition: pager.h:69
Messages to be purged (bypass trash)
Definition: mutt.h:100
A division of the screen.
Definition: mutt_window.h:115
void mutt_window_move_abs(int col, int row)
Move the cursor to an absolute screen position.
Definition: mutt_window.c:549
WHERE bool C_BrailleFriendly
Config: Move the cursor to the beginning of the line.
Definition: mutt_globals.h:142
PagerFlags flags
Definition: pager.c:172
static bool InHelp
Definition: pager.c:205
bool search_back
Definition: pager.c:164
bool search_compiled
Definition: pager.c:163
short type
Definition: pager.c:136
#define MUTT_PAGER_NOWRAP
Format for term width, ignore $wrap.
Definition: pager.h:56
uint16_t SendFlags
Flags for mutt_send_message(), e.g. SEND_REPLY.
Definition: send.h:37
Pager: quoted text.
Definition: color.h:81
#define SEND_POSTPONED
Recall a postponed email.
Definition: send.h:45
Container for Accounts, Notifications.
Definition: neomutt.h:36
#define MUTT_PATTERN
Pattern mode - only used for history classes.
Definition: mutt.h:64
#define MUTT_ACL_DELETE
Delete a message.
Definition: mailbox.h:66
static int display_line(FILE *fp, LOFF_T *last_pos, struct Line **line_info, int n, int *last, int *max, PagerFlags flags, struct QClass **quote_list, int *q_level, bool *force_redraw, regex_t *search_re, struct MuttWindow *win_pager)
Print a line on screen.
Definition: pager.c:1678
#define mutt_get_field(field, buf, buflen, complete)
Definition: curs_lib.h:91
int vcount
The number of virtual messages.
Definition: mailbox.h:102
#define MUTT_PAGER_ATTACHMENT
Attachments may exist.
Definition: pager.h:55
LOFF_T last_pos
Definition: pager.c:187
int mutt_window_move(struct MuttWindow *win, int col, int row)
Move the cursor in a Window.
Definition: mutt_window.c:392
void mutt_print_message(struct Mailbox *m, struct EmailList *el)
Print a message.
Definition: commands.c:731
#define SEND_NO_FLAGS
No flags are set.
Definition: send.h:40
void mutt_beep(bool force)
Irritate the user.
Definition: curs_lib.c:99
#define MAX(a, b)
Definition: memory.h:30
int cs_subset_str_native_set(const struct ConfigSubset *sub, const char *name, intptr_t value, struct Buffer *err)
Natively set the value of a string config item.
Definition: subset.c:292
int line
Definition: pager.c:162
void mutt_attach_reply(FILE *fp, struct Email *e, struct AttachCtx *actx, struct Body *e_cur, SendFlags flags)
Attach a reply.
Definition: recvcmd.c:917
Pager pager (email viewer)
Definition: keymap.h:81
bool tagged
Email is tagged.
Definition: email.h:44
void * redraw_data
Definition: mutt_menu.h:127
bool read
Email is read.
Definition: email.h:51
void mutt_print_attachment_list(struct AttachCtx *actx, FILE *fp, bool tag, struct Body *top)
Print a list of Attachments.
Definition: recvattach.c:1162
void mutt_curses_set_cursor(enum MuttCursorState state)
Set the cursor state.
Definition: mutt_curses.c:78
struct Mailbox * mailbox
Definition: context.h:50
static int braille_line
Definition: pager.c:207
bool old
Email is seen, but unread.
Definition: email.h:50
static const struct Mapping PagerHelpHelp[]
Help Bar for the Help Page itself.
Definition: pager.c:230
int indexlen
Definition: pager.c:174
struct MuttWindow * win_ibar
Definition: mutt_menu.h:67
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
void mutt_what_key(void)
Ask the user to press a key.
Definition: keymap.c:1676
struct Envelope * env
Envelope information.
Definition: email.h:90
int has_types
Definition: pager.c:183
Display a normal cursor.
Definition: mutt_curses.h:81
FILE * fp
Definition: pager.c:197
#define REG_COMP(preg, regex, cflags)
Compile a regular expression.
Definition: regex3.h:53
bool mutt_mailbox_notify(struct Mailbox *m_cur)
Notify the user if there&#39;s new mail.
Definition: mutt_mailbox.c:219
short continuation
Definition: pager.c:137
void mutt_shell_escape(void)
invoke a command in a subshell
Definition: commands.c:844
#define MUTT_PAGER_NSKIP
Preserve whitespace with smartwrap.
Definition: pager.h:52
#define SEND_LIST_REPLY
Reply to mailing list.
Definition: send.h:43
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:113
bool force_redraw
Definition: pager.c:182
const char * OpStrings[][2]
Definition: opcodes.c:28
void * mdata
Driver specific data.
Definition: mailbox.h:136
#define MUTT_ACL_WRITE
Write to a message (for flagging or linking threads)
Definition: mailbox.h:74
int flags
e.g. MB_NORMAL
Definition: mailbox.h:134
#define SEND_KEY
Mail a PGP public key.
Definition: send.h:47
Window has a fixed size.
Definition: mutt_window.h:44
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:888
struct MuttWindow * win_pager
Definition: pager.h:76
void menu_status_line(char *buf, size_t buflen, struct Menu *menu, struct Mailbox *m, const char *p)
Create the status line.
Definition: status.c:418
short cols
Number of columns, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:57
struct Pager * extra
Definition: pager.c:173
struct Context * ctx
Current mailbox.
Definition: pager.h:67
void mutt_refresh(void)
Force a refresh of the screen.
Definition: curs_lib.c:108
Side panel containing Accounts or groups of data.
Definition: mutt_window.h:99
Window size depends on its children.
Definition: mutt_window.h:46
void mutt_attach_bounce(struct Mailbox *m, FILE *fp, struct AttachCtx *actx, struct Body *cur)
Bounce function, from the attachment menu.
Definition: recvcmd.c:168
short search_cnt
Definition: pager.c:139
struct TextSyntax * search
Definition: pager.c:141
struct WindowState state
Current state of the Window.
Definition: mutt_window.h:120
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:97
WHERE bool OptAttachMsg
(pseudo) used by attach-message
Definition: options.h:31
#define REDRAW_STATUS
Redraw the status bar.
Definition: mutt_menu.h:44
struct AddressList * mutt_get_address(struct Envelope *env, const char **prefix)
Get an Address from an Envelope.
Definition: alias.c:326
bool search_compiled
Definition: pager.c:191
void km_error_key(enum MenuType menu)
Handle an unbound key sequence.
Definition: keymap.c:1137
#define CHECK_ATTACH
Definition: pager.c:296
Messages to be deleted.
Definition: mutt.h:98
A mailbox.
Definition: mailbox.h:81
#define MUTT_WIN_SIZE_UNLIMITED
Use as much space as possible.
Definition: mutt_window.h:49
short rows
Number of rows, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:58
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
Nondestructive flags change (IMAP)
Definition: mx.h:77
#define IS_HEADER(x)
Definition: pager.c:271
struct AttachCtx * actx
Attachment information.
Definition: pager.h:71
const struct Mapping * help_data
Data for the Help Bar.
Definition: mutt_window.h:135
Tagged messages.
Definition: mutt.h:103
int bool_str_toggle(struct ConfigSubset *sub, const char *name, struct Buffer *err)
Toggle the value of a bool.
Definition: bool.c:233
int max_line
Definition: pager.c:178
#define CHECK_READONLY
Definition: pager.c:288
A line of text in the pager.
Definition: pager.c:133
New messages.
Definition: mutt.h:93
Messages that have been read.
Definition: mutt.h:96
static const struct Mapping PagerHelp[]
Help Bar for the Pager&#39;s Help Page.
Definition: pager.c:219
int last_line
Definition: pager.c:179
bool verbose
Display status messages?
Definition: mailbox.h:118
WHERE char * C_NewMailCommand
Config: External command to run when new mail arrives.
Definition: mutt_globals.h:105
void(* custom_redraw)(struct Menu *menu)
Redraw the menu.
Definition: mutt_menu.h:125
#define SEND_NEWS
Reply to a news article.
Definition: send.h:54
void dlg_select_attachment(struct Email *e)
Show the attachments in a Menu.
Definition: recvattach.c:1545
WHERE bool OptSearchInvalid
(pseudo) used to invalidate the search pattern
Definition: options.h:52
enum MuttWindowSize size
Type of Window, e.g. MUTT_WIN_SIZE_FIXED.
Definition: mutt_window.h:124
#define MUTT_HIDE
Don&#39;t show quoted text.
Definition: pager.h:46
int pagelen
Number of entries per screen.
Definition: mutt_menu.h:63
int mx_mbox_check(struct Mailbox *m)
Check for new mail - Wrapper for MxOps::mbox_check()
Definition: mx.c:1139
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib...
Definition: email.h:39
#define SEND_REPLY
Reply to sender.
Definition: send.h:41
NNTP-specific Mailbox data -.
Definition: lib.h:138
void mutt_clear_pager_position(void)
Reset the pager&#39;s viewing position.
Definition: pager.c:1975
WHERE bool C_WrapSearch
Config: Wrap around when the search hits the end.
Definition: mutt_globals.h:172
int max
Number of entries in the menu.
Definition: mutt_menu.h:60
int mutt_resend_message(FILE *fp, struct Context *ctx, struct Email *e_cur, struct ConfigSubset *sub)
Resend an email.
Definition: send.c:1503
bool C_PagerStop
Config: Don&#39;t automatically open the next message when at the end of a message.
Definition: pager.c:88
MuttRedrawFlags redraw
When to redraw the screen.
Definition: mutt_menu.h:61
void mutt_attach_forward(FILE *fp, struct Email *e, struct AttachCtx *actx, struct Body *cur, SendFlags flags)
Forward an Attachment.
Definition: recvcmd.c:766
struct QClass * quote_list
Definition: pager.c:186
#define IsEmail(pager)
Definition: pager.c:276
int indicator
the indicator line of the PI
Definition: pager.c:175
void mutt_pipe_attachment_list(struct AttachCtx *actx, FILE *fp, bool tag, struct Body *top, bool filter)
Pipe a list of attachments to a command.
Definition: recvattach.c:1007
enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
Ask the user a quad-question.
Definition: curs_lib.c:517
struct Email * email
Current message.
Definition: pager.h:68
Highlighting for a line of text.
Definition: pager.c:123
void ci_bounce_message(struct Mailbox *m, struct EmailList *el)
Bounce an email.
Definition: commands.c:415
#define MUTT_PAGER_RETWINCH
Need reformatting on SIGWINCH.
Definition: pager.h:54
#define SEND_GROUP_REPLY
Reply to all.
Definition: send.h:42
#define MUTT_SEARCH
Resolve search patterns.
Definition: pager.h:47
#define REDRAW_BODY
Redraw the pager.
Definition: mutt_menu.h:46
int mutt_label_message(struct Mailbox *m, struct EmailList *el)
Let the user label a message.
Definition: mutt_header.c:124
char * searchbuf
Definition: pager.c:195
Log at debug level 1.
Definition: logging.h:40
static const struct Mapping PagerNormalHelp[]
Help Bar for the Pager of a normal Mailbox.
Definition: pager.c:240
bool flagged
Marked important?
Definition: email.h:43
void emaillist_clear(struct EmailList *el)
Drop a private list of Emails.
Definition: email.c:127
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:721
#define REDRAW_INDEX
Redraw the index.
Definition: mutt_menu.h:40
void mutt_help(enum MenuType menu, int wraplen)
Display the help menu.
Definition: help.c:386
void window_set_visible(struct MuttWindow *win, bool visible)
Set a Window visible or hidden.
Definition: mutt_window.c:149
bool deleted
Email is deleted.
Definition: email.h:45
void mutt_window_reflow(struct MuttWindow *win)
Resize a Window and its children.
Definition: mutt_window.c:443
struct MuttWindow * parent
Parent Window.
Definition: mutt_window.h:128
#define mutt_error(...)
Definition: logging.h:84
char * followup_to
List of &#39;followup-to&#39; fields.
Definition: envelope.h:77
WHERE unsigned char C_Quit
Config: Prompt before exiting NeoMutt.
Definition: mutt_globals.h:131
void mutt_timeout_hook(void)
Execute any timeout hooks.
Definition: hook.c:800
int mutt_select_sort(bool reverse)
Ask the user for a sort method.
Definition: commands.c:770
short C_SkipQuotedOffset
Config: Lines of context to show when skipping quoted text.
Definition: pager.c:90
static const struct Mapping PagerNewsHelp[]
Help Bar for the Pager of an NNTP Mailbox.
Definition: pager.c:256
#define FREE(x)
Definition: memory.h:40
int mutt_send_message(SendFlags flags, struct Email *e_templ, const char *tempfile, struct Context *ctx, struct EmailList *el, struct ConfigSubset *sub)
Send an email.
Definition: send.c:1990
void crypt_extract_keys_from_messages(struct Mailbox *m, struct EmailList *el)
Extract keys from a message.
Definition: crypt.c:844
#define MUTT_ACL_SEEN
Change the &#39;seen&#39; status of a message.
Definition: mailbox.h:73
Hide the cursor.
Definition: mutt_curses.h:80
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:321
void mutt_attach_mail_sender(FILE *fp, struct Email *e, struct AttachCtx *actx, struct Body *cur)
Compose an email to the sender in the email attachment.
Definition: recvcmd.c:1086
short req_rows
Number of rows required.
Definition: mutt_window.h:118
struct TextSyntax * syntax
Definition: pager.c:140
void window_redraw(struct MuttWindow *win, bool force)
Reflow, recalc and repaint a tree of Windows.
Definition: mutt_window.c:757
#define PGP_TRADITIONAL_CHECKED
Email has a traditional (inline) signature.
Definition: lib.h:99
bool changed
Mailbox has been modified.
Definition: mailbox.h:114
int mutt_change_flag(struct Mailbox *m, struct EmailList *el, bool bf)
Change the flag on a Message.
Definition: flags.c:432
Keep track of screen resizing.
Definition: pager.c:160
void ctx_free(struct Context **ptr)
Free a Context.
Definition: context.c:50
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
New mail received in Mailbox.
Definition: mx.h:74
#define SEND_GROUP_CHAT_REPLY
Reply to all recipients preserving To/Cc.
Definition: send.h:53
struct stat sb
Definition: pager.c:198
#define IsAttach(pager)
Definition: pager.c:273
int current
Current entry.
Definition: mutt_menu.h:59
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:353
struct Buffer pathbuf
Definition: mailbox.h:83
struct MuttWindow * win_index
Definition: mutt_menu.h:66
Window wants as much space as possible.
Definition: mutt_window.h:45
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
LOFF_T offset
Definition: pager.c:135
Mailbox was reopened.
Definition: mx.h:76
short C_SearchContext
Config: Context to display around search matches.
Definition: pager.c:89
#define CHECK_MODE(test)
Definition: pager.c:280
bool mutt_mb_is_lower(const char *s)
Does a multi-byte string contain only lowercase characters?
Definition: mbyte.c:358
WHERE SIG_ATOMIC_VOLATILE_T SigWinch
true after SIGWINCH is received
Definition: mutt_globals.h:75
struct Email * email
header information for message/rfc822
Definition: body.h:55
struct MuttWindow * dialog_find(struct MuttWindow *win)
Find the parent Dialog of a Window.
Definition: dialog.c:46
#define MUTT_SHOWFLAT
Show characters (used for displaying help)
Definition: pager.h:44
void mutt_attach_resend(FILE *fp, struct AttachCtx *actx, struct Body *cur)
resend-message, from the attachment menu
Definition: recvcmd.c:295
int mutt_system(const char *cmd)
Run an external command.
Definition: system.c:51
static struct Email * OldEmail
Definition: pager.c:203
short C_PagerIndexLines
Config: Number of index lines to display above the pager.
Definition: pager.c:87
unsigned char C_FollowupToPoster
Config: (nntp) Reply to the poster if &#39;poster&#39; is in the &#39;Followup-To&#39; header.
Definition: config.c:38
WHERE bool C_Resolve
Config: Move to the next email whenever a command modifies an email.
Definition: mutt_globals.h:157
regex_t search_re
Definition: pager.c:190
int msgno
Number displayed to the user.
Definition: email.h:87
const char * mutt_make_version(void)
Generate the NeoMutt version string.
Definition: muttlib.c:1460
unsigned char C_PostModerated
Config: (nntp) Allow posting to moderated newsgroups.
Definition: config.c:51
bool search_back
Definition: pager.c:193
struct MuttWindow * win_pbar
Definition: pager.h:75
+ Here is the caller graph for this function:

◆ mutt_buffer_strip_formatting()

void mutt_buffer_strip_formatting ( struct Buffer dest,
const char *  src,
bool  strip_markers 
)

Removes ANSI and backspace formatting.

Parameters
destBuffer for the result
srcString to strip
strip_markersRemove

Removes ANSI and backspace formatting, and optionally markers. This is separated out so that it can be used both by the pager and the autoview handler.

This logic is pulled from the pager fill_buffer() function, for use in stripping reply-quoted autoview output of ansi sequences.

Definition at line 1384 of file pager.c.

1385 {
1386  const char *s = src;
1387 
1388  mutt_buffer_reset(dest);
1389 
1390  if (!s)
1391  return;
1392 
1393  while (s[0] != '\0')
1394  {
1395  if ((s[0] == '\010') && (s > src))
1396  {
1397  if (s[1] == '_') /* underline */
1398  s += 2;
1399  else if (s[1] && mutt_buffer_len(dest)) /* bold or overstrike */
1400  {
1401  dest->dptr--;
1402  mutt_buffer_addch(dest, s[1]);
1403  s += 2;
1404  }
1405  else /* ^H */
1406  mutt_buffer_addch(dest, *s++);
1407  }
1408  else if ((s[0] == '\033') && (s[1] == '[') && is_ansi(s + 2))
1409  {
1410  while (*s++ != 'm')
1411  ; /* skip ANSI sequence */
1412  }
1413  else if (strip_markers && (s[0] == '\033') && (s[1] == ']') &&
1414  ((check_attachment_marker(s) == 0) || (check_protected_header_marker(s) == 0)))
1415  {
1416  mutt_debug(LL_DEBUG2, "Seen attachment marker\n");
1417  while (*s++ != '\a')
1418  ; /* skip pseudo-ANSI sequence */
1419  }
1420  else
1421  mutt_buffer_addch(dest, *s++);
1422  }
1423 }
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
static int check_protected_header_marker(const char *p)
Check that the unique marker is present.
Definition: pager.c:950
static bool is_ansi(const char *str)
Is this an ANSI escape sequence?
Definition: pager.c:1272
Log at debug level 2.
Definition: logging.h:41
size_t mutt_buffer_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:356
char * dptr
Current read/write position.
Definition: buffer.h:36
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
static int check_attachment_marker(const char *p)
Check that the unique marker is present.
Definition: pager.c:940
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_clear_pager_position()

void mutt_clear_pager_position ( void  )

Reset the pager's viewing position.

Definition at line 1975 of file pager.c.

1976 {
1977  TopLine = 0;
1978  OldEmail = NULL;
1979 }
static int TopLine
Definition: pager.c:202
static struct Email * OldEmail
Definition: pager.c:203
+ Here is the caller graph for this function:

Variable Documentation

◆ C_AllowAnsi

bool C_AllowAnsi

Config: Allow ANSI colour codes in rich text messages.

Definition at line 84 of file pager.c.

◆ C_HeaderColorPartial

bool C_HeaderColorPartial

Config: Only colour the part of the header matching the regex.

Definition at line 85 of file pager.c.

◆ C_PagerContext

short C_PagerContext

Config: Number of lines of overlap when changing pages in the pager.

Definition at line 86 of file pager.c.

◆ C_PagerIndexLines

short C_PagerIndexLines

Config: Number of index lines to display above the pager.

Definition at line 87 of file pager.c.

◆ C_PagerStop

bool C_PagerStop

Config: Don't automatically open the next message when at the end of a message.

Definition at line 88 of file pager.c.

◆ C_SearchContext

short C_SearchContext

Config: Context to display around search matches.

Definition at line 89 of file pager.c.

◆ C_SkipQuotedOffset

short C_SkipQuotedOffset

Config: Lines of context to show when skipping quoted text.

Definition at line 90 of file pager.c.

◆ C_SmartWrap

bool C_SmartWrap

Config: Wrap text at word boundaries.

Definition at line 91 of file pager.c.

◆ C_Smileys

struct Regex* C_Smileys

Config: Regex to match smileys to prevent mistakes when quoting text.

Definition at line 92 of file pager.c.

◆ C_Tilde

bool C_Tilde

Config: Character to pad blank lines in the pager.

Definition at line 93 of file pager.c.