NeoMutt  2020-11-20
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 2239 of file pager.c.

2240 {
2241  static char searchbuf[256] = { 0 };
2242  char buf[1024];
2243  int ch = 0, rc = -1;
2244  bool first = true;
2245  int searchctx = 0;
2246  bool wrapped = false;
2247 
2248  struct Menu *pager_menu = NULL;
2249  int old_PagerIndexLines; /* some people want to resize it while inside the pager */
2250 #ifdef USE_NNTP
2251  char *followup_to = NULL;
2252 #endif
2253 
2254  struct Mailbox *m = Context ? Context->mailbox : NULL;
2255 
2256  if (!(flags & MUTT_SHOWCOLOR))
2257  flags |= MUTT_SHOWFLAT;
2258 
2259  int index_space = C_PagerIndexLines;
2260  if (extra->ctx && extra->ctx->mailbox)
2261  index_space = MIN(index_space, extra->ctx->mailbox->vcount);
2262 
2263  struct PagerRedrawData rd = { 0 };
2264  rd.banner = banner;
2265  rd.flags = flags;
2266  rd.extra = extra;
2267  rd.indexlen = index_space;
2268  rd.indicator = rd.indexlen / 3;
2269  rd.searchbuf = searchbuf;
2270  rd.has_types = (IsEmail(extra) || (flags & MUTT_SHOWCOLOR)) ? MUTT_TYPES : 0; /* main message or rfc822 attachment */
2271 
2272  rd.fp = fopen(fname, "r");
2273  if (!rd.fp)
2274  {
2275  mutt_perror(fname);
2276  return -1;
2277  }
2278 
2279  if (stat(fname, &rd.sb) != 0)
2280  {
2281  mutt_perror(fname);
2282  mutt_file_fclose(&rd.fp);
2283  return -1;
2284  }
2285  unlink(fname);
2286 
2287  if (rd.extra->win_index)
2288  {
2290  rd.extra->win_index->req_rows = index_space;
2292  window_set_visible(rd.extra->win_index->parent, (index_space > 0));
2293  }
2297 
2298  /* Initialize variables */
2299 
2300  if (Context && IsEmail(extra) && !extra->email->read)
2301  {
2302  Context->msg_in_pager = extra->email->msgno;
2303  mutt_set_flag(m, extra->email, MUTT_READ, true);
2304  }
2305 
2306  rd.max_line = LINES; /* number of lines on screen, from curses */
2307  rd.line_info = mutt_mem_calloc(rd.max_line, sizeof(struct Line));
2308  for (size_t i = 0; i < rd.max_line; i++)
2309  {
2310  rd.line_info[i].type = -1;
2311  rd.line_info[i].search_cnt = -1;
2312  rd.line_info[i].syntax = mutt_mem_malloc(sizeof(struct TextSyntax));
2313  (rd.line_info[i].syntax)[0].first = -1;
2314  (rd.line_info[i].syntax)[0].last = -1;
2315  }
2316 
2317  pager_menu = mutt_menu_new(MENU_PAGER);
2318  pager_menu->pagelen = extra->win_pager->state.rows;
2319  pager_menu->win_index = extra->win_pager;
2320  pager_menu->win_ibar = extra->win_pbar;
2321 
2322  pager_menu->custom_redraw = pager_custom_redraw;
2323  pager_menu->redraw_data = &rd;
2324  mutt_menu_push_current(pager_menu);
2325 
2326  if (IsEmail(extra))
2327  {
2328  // Viewing a Mailbox
2329 #ifdef USE_NNTP
2330  if (m && (m->type == MUTT_NNTP))
2331  extra->win_pager->help_data = PagerNewsHelp;
2332  else
2333 #endif
2335  }
2336  else
2337  {
2338  // Viewing Help
2339  if (InHelp)
2340  extra->win_pager->help_data = PagerHelpHelp;
2341  else
2342  extra->win_pager->help_data = PagerHelp;
2343  }
2344  extra->win_pager->help_menu = MENU_PAGER;
2345  window_set_focus(extra->win_pager);
2346 
2347  while (ch != -1)
2348  {
2350 
2351  pager_custom_redraw(pager_menu);
2352  window_redraw(RootWindow, true);
2353 
2354  if (C_BrailleFriendly)
2355  {
2356  if (braille_line != -1)
2357  {
2359  braille_line = -1;
2360  }
2361  }
2362  else
2364 
2365  mutt_refresh();
2366 
2367  if (IsEmail(extra) && (OldEmail == extra->email) && (TopLine != rd.topline) &&
2368  (rd.line_info[rd.curline].offset < (rd.sb.st_size - 1)))
2369  {
2370  if ((TopLine - rd.topline) > rd.lines)
2371  rd.topline += rd.lines;
2372  else
2373  rd.topline = TopLine;
2374  continue;
2375  }
2376  else
2377  OldEmail = NULL;
2378 
2379  ch = km_dokey(MENU_PAGER);
2380  if (ch >= 0)
2381  {
2382  mutt_clear_error();
2383  mutt_debug(LL_DEBUG1, "Got op %s (%d)\n", OpStrings[ch][0], ch);
2384  }
2386 
2387  bool do_new_mail = false;
2388 
2389  if (m && !OptAttachMsg)
2390  {
2391  int oldcount = m->msg_count;
2392  /* check for new mail */
2393  int check = mx_mbox_check(m);
2394  if (check < 0)
2395  {
2396  if (!m || mutt_buffer_is_empty(&m->pathbuf))
2397  {
2398  /* fatal error occurred */
2399  ctx_free(&Context);
2400  pager_menu->redraw = REDRAW_FULL;
2401  break;
2402  }
2403  }
2404  else if ((check == MUTT_NEW_MAIL) || (check == MUTT_REOPENED) || (check == MUTT_FLAGS))
2405  {
2406  /* notify user of newly arrived mail */
2407  if (check == MUTT_NEW_MAIL)
2408  {
2409  for (size_t i = oldcount; i < m->msg_count; i++)
2410  {
2411  struct Email *e = m->emails[i];
2412 
2413  if (e && !e->read)
2414  {
2415  mutt_message(_("New mail in this mailbox"));
2416  do_new_mail = true;
2417  break;
2418  }
2419  }
2420  }
2421 
2422  if ((check == MUTT_NEW_MAIL) || (check == MUTT_REOPENED))
2423  {
2424  if (rd.menu && m)
2425  {
2426  /* After the mailbox has been updated,
2427  * rd.menu->current might be invalid */
2428  rd.menu->current = MIN(rd.menu->current, MAX(m->msg_count - 1, 0));
2429  struct Email *e = mutt_get_virt_email(m, rd.menu->current);
2430  if (!e)
2431  continue;
2432 
2433  bool verbose = m->verbose;
2434  m->verbose = false;
2435  mutt_update_index(rd.menu, Context, check, oldcount, e);
2436  m->verbose = verbose;
2437 
2438  rd.menu->max = m->vcount;
2439 
2440  /* If these header pointers don't match, then our email may have
2441  * been deleted. Make the pointer safe, then leave the pager.
2442  * This have a unpleasant behaviour to close the pager even the
2443  * deleted message is not the opened one, but at least it's safe. */
2444  e = mutt_get_virt_email(m, rd.menu->current);
2445  if (extra->email != e)
2446  {
2447  extra->email = e;
2448  break;
2449  }
2450  }
2451 
2452  pager_menu->redraw = REDRAW_FULL;
2453  OptSearchInvalid = true;
2454  }
2455  }
2456 
2457  if (mutt_mailbox_notify(m) || do_new_mail)
2458  {
2459  if (C_BeepNew)
2460  mutt_beep(true);
2461  if (C_NewMailCommand)
2462  {
2463  char cmd[1024];
2464  menu_status_line(cmd, sizeof(cmd), rd.menu, m, NONULL(C_NewMailCommand));
2465  if (mutt_system(cmd) != 0)
2466  mutt_error(_("Error running \"%s\""), cmd);
2467  }
2468  }
2469  }
2470 
2471  if (SigWinch)
2472  {
2473  SigWinch = 0;
2475  clearok(stdscr, true); /* force complete redraw */
2476 
2477  if (flags & MUTT_PAGER_RETWINCH)
2478  {
2479  /* Store current position. */
2480  rd.lines = -1;
2481  for (size_t i = 0; i <= rd.topline; i++)
2482  if (!rd.line_info[i].continuation)
2483  rd.lines++;
2484 
2485  Resize = mutt_mem_malloc(sizeof(struct Resize));
2486 
2487  Resize->line = rd.lines;
2490 
2491  ch = -1;
2492  rc = OP_REFORMAT_WINCH;
2493  }
2494  else
2495  {
2496  /* note: mutt_resize_screen() -> mutt_window_reflow() sets
2497  * REDRAW_FULL and REDRAW_FLOW */
2498  ch = 0;
2499  }
2500  continue;
2501  }
2502 
2503  if (ch < 0)
2504  {
2505  ch = 0;
2507  continue;
2508  }
2509 
2510  rc = ch;
2511 
2512  switch (ch)
2513  {
2514  case OP_EXIT:
2515  rc = -1;
2516  ch = -1;
2517  break;
2518 
2519  case OP_QUIT:
2520  if (query_quadoption(C_Quit, _("Quit NeoMutt?")) == MUTT_YES)
2521  {
2522  /* avoid prompting again in the index menu */
2523  cs_subset_str_native_set(NeoMutt->sub, "quit", MUTT_YES, NULL);
2524  ch = -1;
2525  }
2526  break;
2527 
2528  case OP_NEXT_PAGE:
2529  if (rd.line_info[rd.curline].offset < (rd.sb.st_size - 1))
2530  {
2532  }
2533  else if (C_PagerStop)
2534  {
2535  /* emulate "less -q" and don't go on to the next message. */
2536  mutt_error(_("Bottom of message is shown"));
2537  }
2538  else
2539  {
2540  /* end of the current message, so display the next message. */
2541  rc = OP_MAIN_NEXT_UNDELETED;
2542  ch = -1;
2543  }
2544  break;
2545 
2546  case OP_PREV_PAGE:
2547  if (rd.topline == 0)
2548  {
2549  mutt_message(_("Top of message is shown"));
2550  }
2551  else
2552  {
2554  rd.line_info, rd.topline, rd.hide_quoted);
2555  }
2556  break;
2557 
2558  case OP_NEXT_LINE:
2559  if (rd.line_info[rd.curline].offset < (rd.sb.st_size - 1))
2560  {
2561  rd.topline++;
2562  if (rd.hide_quoted)
2563  {
2564  while ((rd.line_info[rd.topline].type == MT_COLOR_QUOTED) &&
2565  (rd.topline < rd.last_line))
2566  {
2567  rd.topline++;
2568  }
2569  }
2570  }
2571  else
2572  mutt_message(_("Bottom of message is shown"));
2573  break;
2574 
2575  case OP_PREV_LINE:
2576  if (rd.topline)
2577  rd.topline = up_n_lines(1, rd.line_info, rd.topline, rd.hide_quoted);
2578  else
2579  mutt_error(_("Top of message is shown"));
2580  break;
2581 
2582  case OP_PAGER_TOP:
2583  if (rd.topline)
2584  rd.topline = 0;
2585  else
2586  mutt_error(_("Top of message is shown"));
2587  break;
2588 
2589  case OP_HALF_UP:
2590  if (rd.topline)
2591  {
2592  rd.topline = up_n_lines(rd.extra->win_pager->state.rows / 2 +
2593  (rd.extra->win_pager->state.rows % 2),
2594  rd.line_info, rd.topline, rd.hide_quoted);
2595  }
2596  else
2597  mutt_error(_("Top of message is shown"));
2598  break;
2599 
2600  case OP_HALF_DOWN:
2601  if (rd.line_info[rd.curline].offset < (rd.sb.st_size - 1))
2602  {
2603  rd.topline = up_n_lines(rd.extra->win_pager->state.rows / 2,
2604  rd.line_info, rd.curline, rd.hide_quoted);
2605  }
2606  else if (C_PagerStop)
2607  {
2608  /* emulate "less -q" and don't go on to the next message. */
2609  mutt_error(_("Bottom of message is shown"));
2610  }
2611  else
2612  {
2613  /* end of the current message, so display the next message. */
2614  rc = OP_MAIN_NEXT_UNDELETED;
2615  ch = -1;
2616  }
2617  break;
2618 
2619  case OP_SEARCH_NEXT:
2620  case OP_SEARCH_OPPOSITE:
2621  if (rd.search_compiled)
2622  {
2623  wrapped = false;
2624 
2625  if (C_SearchContext < rd.extra->win_pager->state.rows)
2626  searchctx = C_SearchContext;
2627  else
2628  searchctx = 0;
2629 
2630  search_next:
2631  if ((!rd.search_back && (ch == OP_SEARCH_NEXT)) ||
2632  (rd.search_back && (ch == OP_SEARCH_OPPOSITE)))
2633  {
2634  /* searching forward */
2635  int i;
2636  for (i = wrapped ? 0 : rd.topline + searchctx + 1; i < rd.last_line; i++)
2637  {
2638  if ((!rd.hide_quoted || (rd.line_info[i].type != MT_COLOR_QUOTED)) &&
2639  !rd.line_info[i].continuation && (rd.line_info[i].search_cnt > 0))
2640  {
2641  break;
2642  }
2643  }
2644 
2645  if (i < rd.last_line)
2646  rd.topline = i;
2647  else if (wrapped || !C_WrapSearch)
2648  mutt_error(_("Not found"));
2649  else
2650  {
2651  mutt_message(_("Search wrapped to top"));
2652  wrapped = true;
2653  goto search_next;
2654  }
2655  }
2656  else
2657  {
2658  /* searching backward */
2659  int i;
2660  for (i = wrapped ? rd.last_line : rd.topline + searchctx - 1; i >= 0; i--)
2661  {
2662  if ((!rd.hide_quoted ||
2663  (rd.has_types && (rd.line_info[i].type != MT_COLOR_QUOTED))) &&
2664  !rd.line_info[i].continuation && (rd.line_info[i].search_cnt > 0))
2665  {
2666  break;
2667  }
2668  }
2669 
2670  if (i >= 0)
2671  rd.topline = i;
2672  else if (wrapped || !C_WrapSearch)
2673  mutt_error(_("Not found"));
2674  else
2675  {
2676  mutt_message(_("Search wrapped to bottom"));
2677  wrapped = true;
2678  goto search_next;
2679  }
2680  }
2681 
2682  if (rd.line_info[rd.topline].search_cnt > 0)
2683  {
2684  rd.search_flag = MUTT_SEARCH;
2685  /* give some context for search results */
2686  if (rd.topline - searchctx > 0)
2687  rd.topline -= searchctx;
2688  }
2689 
2690  break;
2691  }
2692  /* no previous search pattern */
2693  /* fallthrough */
2694 
2695  case OP_SEARCH:
2696  case OP_SEARCH_REVERSE:
2697  mutt_str_copy(buf, searchbuf, sizeof(buf));
2698  if (mutt_get_field(((ch == OP_SEARCH) || (ch == OP_SEARCH_NEXT)) ?
2699  _("Search for: ") :
2700  _("Reverse search for: "),
2701  buf, sizeof(buf), MUTT_CLEAR | MUTT_PATTERN) != 0)
2702  {
2703  break;
2704  }
2705 
2706  if (strcmp(buf, searchbuf) == 0)
2707  {
2708  if (rd.search_compiled)
2709  {
2710  /* do an implicit search-next */
2711  if (ch == OP_SEARCH)
2712  ch = OP_SEARCH_NEXT;
2713  else
2714  ch = OP_SEARCH_OPPOSITE;
2715 
2716  wrapped = false;
2717  goto search_next;
2718  }
2719  }
2720 
2721  if (buf[0] == '\0')
2722  break;
2723 
2724  mutt_str_copy(searchbuf, buf, sizeof(searchbuf));
2725 
2726  /* leave search_back alone if ch == OP_SEARCH_NEXT */
2727  if (ch == OP_SEARCH)
2728  rd.search_back = false;
2729  else if (ch == OP_SEARCH_REVERSE)
2730  rd.search_back = true;
2731 
2732  if (rd.search_compiled)
2733  {
2734  regfree(&rd.search_re);
2735  for (size_t i = 0; i < rd.last_line; i++)
2736  {
2737  FREE(&(rd.line_info[i].search));
2738  rd.line_info[i].search_cnt = -1;
2739  }
2740  }
2741 
2742  int rflags = mutt_mb_is_lower(searchbuf) ? REG_ICASE : 0;
2743  int err = REG_COMP(&rd.search_re, searchbuf, REG_NEWLINE | rflags);
2744  if (err != 0)
2745  {
2746  regerror(err, &rd.search_re, buf, sizeof(buf));
2747  mutt_error("%s", buf);
2748  for (size_t i = 0; i < rd.max_line; i++)
2749  {
2750  /* cleanup */
2751  FREE(&(rd.line_info[i].search));
2752  rd.line_info[i].search_cnt = -1;
2753  }
2754  rd.search_flag = 0;
2755  rd.search_compiled = false;
2756  }
2757  else
2758  {
2759  rd.search_compiled = true;
2760  /* update the search pointers */
2761  int line_num = 0;
2762  while (display_line(rd.fp, &rd.last_pos, &rd.line_info, line_num,
2763  &rd.last_line, &rd.max_line,
2764  MUTT_SEARCH | (flags & MUTT_PAGER_NSKIP) | (flags & MUTT_PAGER_NOWRAP),
2765  &rd.quote_list, &rd.q_level, &rd.force_redraw,
2766  &rd.search_re, rd.extra->win_pager) == 0)
2767  {
2768  line_num++;
2769  }
2770 
2771  if (!rd.search_back)
2772  {
2773  /* searching forward */
2774  int i;
2775  for (i = rd.topline; i < rd.last_line; i++)
2776  {
2777  if ((!rd.hide_quoted || (rd.line_info[i].type != MT_COLOR_QUOTED)) &&
2778  !rd.line_info[i].continuation && (rd.line_info[i].search_cnt > 0))
2779  {
2780  break;
2781  }
2782  }
2783 
2784  if (i < rd.last_line)
2785  rd.topline = i;
2786  }
2787  else
2788  {
2789  /* searching backward */
2790  int i;
2791  for (i = rd.topline; i >= 0; i--)
2792  {
2793  if ((!rd.hide_quoted || (rd.line_info[i].type != MT_COLOR_QUOTED)) &&
2794  !rd.line_info[i].continuation && (rd.line_info[i].search_cnt > 0))
2795  {
2796  break;
2797  }
2798  }
2799 
2800  if (i >= 0)
2801  rd.topline = i;
2802  }
2803 
2804  if (rd.line_info[rd.topline].search_cnt == 0)
2805  {
2806  rd.search_flag = 0;
2807  mutt_error(_("Not found"));
2808  }
2809  else
2810  {
2811  rd.search_flag = MUTT_SEARCH;
2812  /* give some context for search results */
2813  if (C_SearchContext < rd.extra->win_pager->state.rows)
2814  searchctx = C_SearchContext;
2815  else
2816  searchctx = 0;
2817  if (rd.topline - searchctx > 0)
2818  rd.topline -= searchctx;
2819  }
2820  }
2821  pager_menu->redraw = REDRAW_BODY;
2822  break;
2823 
2824  case OP_SEARCH_TOGGLE:
2825  if (rd.search_compiled)
2826  {
2827  rd.search_flag ^= MUTT_SEARCH;
2828  pager_menu->redraw = REDRAW_BODY;
2829  }
2830  break;
2831 
2832  case OP_SORT:
2833  case OP_SORT_REVERSE:
2834  CHECK_MODE(IsEmail(extra))
2835  if (mutt_select_sort((ch == OP_SORT_REVERSE)) == 0)
2836  {
2837  OptNeedResort = true;
2838  ch = -1;
2839  rc = OP_DISPLAY_MESSAGE;
2840  }
2841  break;
2842 
2843  case OP_HELP:
2844  if (InHelp)
2845  {
2846  /* don't let the user enter the help-menu from the help screen! */
2847  mutt_error(_("Help is currently being shown"));
2848  break;
2849  }
2850 
2851  InHelp = true;
2852  mutt_help(MENU_PAGER, pager_menu->win_index->state.cols);
2853  pager_menu->redraw = REDRAW_FULL;
2854  InHelp = false;
2855  break;
2856 
2857  case OP_PAGER_HIDE_QUOTED:
2858  if (!rd.has_types)
2859  break;
2860 
2861  rd.hide_quoted ^= MUTT_HIDE;
2862  if (rd.hide_quoted && (rd.line_info[rd.topline].type == MT_COLOR_QUOTED))
2863  rd.topline = up_n_lines(1, rd.line_info, rd.topline, rd.hide_quoted);
2864  else
2865  pager_menu->redraw = REDRAW_BODY;
2866  break;
2867 
2868  case OP_PAGER_SKIP_QUOTED:
2869  if (!rd.has_types)
2870  break;
2871 
2872  int dretval = 0;
2873  int new_topline = rd.topline;
2874 
2875  /* Skip all the email headers */
2876  if (IS_HEADER(rd.line_info[new_topline].type))
2877  {
2878  while (((new_topline < rd.last_line) ||
2879  (0 == (dretval = display_line(
2880  rd.fp, &rd.last_pos, &rd.line_info, new_topline, &rd.last_line,
2881  &rd.max_line, MUTT_TYPES | (flags & MUTT_PAGER_NOWRAP),
2882  &rd.quote_list, &rd.q_level, &rd.force_redraw,
2883  &rd.search_re, rd.extra->win_pager)))) &&
2884  IS_HEADER(rd.line_info[new_topline].type))
2885  {
2886  new_topline++;
2887  }
2888  rd.topline = new_topline;
2889  break;
2890  }
2891 
2892  while ((((new_topline + C_SkipQuotedOffset) < rd.last_line) ||
2893  (0 == (dretval = display_line(
2894  rd.fp, &rd.last_pos, &rd.line_info, new_topline, &rd.last_line,
2895  &rd.max_line, MUTT_TYPES | (flags & MUTT_PAGER_NOWRAP),
2896  &rd.quote_list, &rd.q_level, &rd.force_redraw,
2897  &rd.search_re, rd.extra->win_pager)))) &&
2898  (rd.line_info[new_topline + C_SkipQuotedOffset].type != MT_COLOR_QUOTED))
2899  {
2900  new_topline++;
2901  }
2902 
2903  if (dretval < 0)
2904  {
2905  mutt_error(_("No more quoted text"));
2906  break;
2907  }
2908 
2909  while ((((new_topline + C_SkipQuotedOffset) < rd.last_line) ||
2910  (0 == (dretval = display_line(
2911  rd.fp, &rd.last_pos, &rd.line_info, new_topline, &rd.last_line,
2912  &rd.max_line, MUTT_TYPES | (flags & MUTT_PAGER_NOWRAP),
2913  &rd.quote_list, &rd.q_level, &rd.force_redraw,
2914  &rd.search_re, rd.extra->win_pager)))) &&
2915  (rd.line_info[new_topline + C_SkipQuotedOffset].type == MT_COLOR_QUOTED))
2916  {
2917  new_topline++;
2918  }
2919 
2920  if (dretval < 0)
2921  {
2922  mutt_error(_("No more unquoted text after quoted text"));
2923  break;
2924  }
2925  rd.topline = new_topline;
2926  break;
2927 
2928  case OP_PAGER_BOTTOM: /* move to the end of the file */
2929  if (rd.line_info[rd.curline].offset < (rd.sb.st_size - 1))
2930  {
2931  int line_num = rd.curline;
2932  /* make sure the types are defined to the end of file */
2933  while (display_line(rd.fp, &rd.last_pos, &rd.line_info, line_num, &rd.last_line,
2934  &rd.max_line, rd.has_types | (flags & MUTT_PAGER_NOWRAP),
2935  &rd.quote_list, &rd.q_level, &rd.force_redraw,
2936  &rd.search_re, rd.extra->win_pager) == 0)
2937  {
2938  line_num++;
2939  }
2941  rd.last_line, rd.hide_quoted);
2942  }
2943  else
2944  mutt_error(_("Bottom of message is shown"));
2945  break;
2946 
2947  case OP_REDRAW:
2948  mutt_window_reflow(NULL);
2949  clearok(stdscr, true);
2950  pager_menu->redraw = REDRAW_FULL;
2951  break;
2952 
2953  case OP_NULL:
2955  break;
2956 
2957  /* --------------------------------------------------------------------
2958  * The following are operations on the current message rather than
2959  * adjusting the view of the message. */
2960 
2961  case OP_BOUNCE_MESSAGE:
2962  {
2963  CHECK_MODE(IsEmail(extra) || IsMsgAttach(extra))
2964  CHECK_ATTACH;
2965  if (IsMsgAttach(extra))
2966  mutt_attach_bounce(m, extra->fp, extra->actx, extra->body);
2967  else
2968  {
2969  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
2970  emaillist_add_email(&el, extra->email);
2971  ci_bounce_message(m, &el);
2972  emaillist_clear(&el);
2973  }
2974  break;
2975  }
2976 
2977  case OP_RESEND:
2978  CHECK_MODE(IsEmail(extra) || IsMsgAttach(extra))
2979  CHECK_ATTACH;
2980  if (IsMsgAttach(extra))
2981  mutt_attach_resend(extra->fp, extra->actx, extra->body);
2982  else
2983  mutt_resend_message(NULL, extra->ctx, extra->email, NeoMutt->sub);
2984  pager_menu->redraw = REDRAW_FULL;
2985  break;
2986 
2987  case OP_COMPOSE_TO_SENDER:
2988  CHECK_MODE(IsEmail(extra) || IsMsgAttach(extra));
2989  CHECK_ATTACH;
2990  if (IsMsgAttach(extra))
2991  mutt_attach_mail_sender(extra->fp, extra->email, extra->actx, extra->body);
2992  else
2993  {
2994  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
2995  emaillist_add_email(&el, extra->email);
2996  mutt_send_message(SEND_TO_SENDER, NULL, NULL, extra->ctx, &el, NeoMutt->sub);
2997  emaillist_clear(&el);
2998  }
2999  pager_menu->redraw = REDRAW_FULL;
3000  break;
3001 
3002  case OP_CHECK_TRADITIONAL:
3003  CHECK_MODE(IsEmail(extra));
3004  if (!(WithCrypto & APPLICATION_PGP))
3005  break;
3006  if (!(extra->email->security & PGP_TRADITIONAL_CHECKED))
3007  {
3008  ch = -1;
3009  rc = OP_CHECK_TRADITIONAL;
3010  }
3011  break;
3012 
3013  case OP_CREATE_ALIAS:
3014  CHECK_MODE(IsEmail(extra) || IsMsgAttach(extra));
3015  struct AddressList *al = NULL;
3016  if (IsMsgAttach(extra))
3017  al = mutt_get_address(extra->body->email->env, NULL);
3018  else
3019  al = mutt_get_address(extra->email->env, NULL);
3020  alias_create(al, NeoMutt->sub);
3021  break;
3022 
3023  case OP_PURGE_MESSAGE:
3024  case OP_DELETE:
3025  CHECK_MODE(IsEmail(extra));
3027  /* L10N: CHECK_ACL */
3028  CHECK_ACL(MUTT_ACL_DELETE, _("Can't delete message"));
3029 
3030  mutt_set_flag(Context->mailbox, extra->email, MUTT_DELETE, true);
3031  mutt_set_flag(Context->mailbox, extra->email, MUTT_PURGE, (ch == OP_PURGE_MESSAGE));
3032  if (C_DeleteUntag)
3033  mutt_set_flag(Context->mailbox, extra->email, MUTT_TAG, false);
3034  pager_menu->redraw |= REDRAW_STATUS | REDRAW_INDEX;
3035  if (C_Resolve)
3036  {
3037  ch = -1;
3038  rc = OP_MAIN_NEXT_UNDELETED;
3039  }
3040  break;
3041 
3042  case OP_MAIN_SET_FLAG:
3043  case OP_MAIN_CLEAR_FLAG:
3044  {
3045  CHECK_MODE(IsEmail(extra));
3047 
3048  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3049  emaillist_add_email(&el, extra->email);
3050 
3051  if (mutt_change_flag(Context->mailbox, &el, (ch == OP_MAIN_SET_FLAG)) == 0)
3052  pager_menu->redraw |= REDRAW_STATUS | REDRAW_INDEX;
3053  if (extra->email->deleted && C_Resolve)
3054  {
3055  ch = -1;
3056  rc = OP_MAIN_NEXT_UNDELETED;
3057  }
3058  emaillist_clear(&el);
3059  break;
3060  }
3061 
3062  case OP_DELETE_THREAD:
3063  case OP_DELETE_SUBTHREAD:
3064  case OP_PURGE_THREAD:
3065  {
3066  CHECK_MODE(IsEmail(extra));
3068  /* L10N: CHECK_ACL */
3069  /* L10N: Due to the implementation details we do not know whether we
3070  delete zero, 1, 12, ... messages. So in English we use
3071  "messages". Your language might have other means to express this. */
3072  CHECK_ACL(MUTT_ACL_DELETE, _("Can't delete messages"));
3073 
3074  int subthread = (ch == OP_DELETE_SUBTHREAD);
3075  int r = mutt_thread_set_flag(extra->email, MUTT_DELETE, 1, subthread);
3076  if (r == -1)
3077  break;
3078  if (ch == OP_PURGE_THREAD)
3079  {
3080  r = mutt_thread_set_flag(extra->email, MUTT_PURGE, true, subthread);
3081  if (r == -1)
3082  break;
3083  }
3084 
3085  if (C_DeleteUntag)
3086  mutt_thread_set_flag(extra->email, MUTT_TAG, 0, subthread);
3087  if (C_Resolve)
3088  {
3089  rc = OP_MAIN_NEXT_UNDELETED;
3090  ch = -1;
3091  }
3092 
3093  if (!C_Resolve && (C_PagerIndexLines != 0))
3094  pager_menu->redraw = REDRAW_FULL;
3095  else
3096  pager_menu->redraw |= REDRAW_STATUS | REDRAW_INDEX;
3097 
3098  break;
3099  }
3100 
3101  case OP_DISPLAY_ADDRESS:
3102  CHECK_MODE(IsEmail(extra) || IsMsgAttach(extra));
3103  if (IsMsgAttach(extra))
3104  mutt_display_address(extra->body->email->env);
3105  else
3106  mutt_display_address(extra->email->env);
3107  break;
3108 
3109  case OP_ENTER_COMMAND:
3110  old_PagerIndexLines = C_PagerIndexLines;
3111 
3114  pager_menu->redraw = REDRAW_FULL;
3115 
3116  if (OptNeedResort)
3117  {
3118  OptNeedResort = false;
3119  CHECK_MODE(IsEmail(extra));
3120  OptNeedResort = true;
3121  }
3122 
3123  if (old_PagerIndexLines != C_PagerIndexLines)
3124  {
3125  mutt_menu_free(&rd.menu);
3126  }
3127 
3128  if ((pager_menu->redraw & REDRAW_FLOW) && (flags & MUTT_PAGER_RETWINCH))
3129  {
3130  ch = -1;
3131  rc = OP_REFORMAT_WINCH;
3132  continue;
3133  }
3134 
3135  ch = 0;
3136  break;
3137 
3138  case OP_FLAG_MESSAGE:
3139  CHECK_MODE(IsEmail(extra));
3141  /* L10N: CHECK_ACL */
3142  CHECK_ACL(MUTT_ACL_WRITE, "Can't flag message");
3143 
3144  mutt_set_flag(Context->mailbox, extra->email, MUTT_FLAG, !extra->email->flagged);
3145  pager_menu->redraw |= REDRAW_STATUS | REDRAW_INDEX;
3146  if (C_Resolve)
3147  {
3148  ch = -1;
3149  rc = OP_MAIN_NEXT_UNDELETED;
3150  }
3151  break;
3152 
3153  case OP_PIPE:
3154  CHECK_MODE(IsEmail(extra) || IsAttach(extra));
3155  if (IsAttach(extra))
3156  mutt_pipe_attachment_list(extra->actx, extra->fp, false, extra->body, false);
3157  else
3158  {
3159  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3160  el_add_tagged(&el, extra->ctx, extra->email, false);
3161  mutt_pipe_message(extra->ctx->mailbox, &el);
3162  emaillist_clear(&el);
3163  }
3164  break;
3165 
3166  case OP_PRINT:
3167  CHECK_MODE(IsEmail(extra) || IsAttach(extra));
3168  if (IsAttach(extra))
3169  mutt_print_attachment_list(extra->actx, extra->fp, false, extra->body);
3170  else
3171  {
3172  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3173  el_add_tagged(&el, extra->ctx, extra->email, false);
3174  mutt_print_message(extra->ctx->mailbox, &el);
3175  emaillist_clear(&el);
3176  }
3177  break;
3178 
3179  case OP_MAIL:
3180  CHECK_MODE(IsEmail(extra) && !IsAttach(extra));
3181  CHECK_ATTACH;
3182  mutt_send_message(SEND_NO_FLAGS, NULL, NULL, extra->ctx, NULL, NeoMutt->sub);
3183  pager_menu->redraw = REDRAW_FULL;
3184  break;
3185 
3186 #ifdef USE_NNTP
3187  case OP_POST:
3188  CHECK_MODE(IsEmail(extra) && !IsAttach(extra));
3189  CHECK_ATTACH;
3190  if (extra->ctx && (extra->ctx->mailbox->type == MUTT_NNTP) &&
3191  !((struct NntpMboxData *) extra->ctx->mailbox->mdata)->allowed && (query_quadoption(C_PostModerated, _("Posting to this group not allowed, may be moderated. Continue?")) != MUTT_YES))
3192  {
3193  break;
3194  }
3195  mutt_send_message(SEND_NEWS, NULL, NULL, extra->ctx, NULL, NeoMutt->sub);
3196  pager_menu->redraw = REDRAW_FULL;
3197  break;
3198 
3199  case OP_FORWARD_TO_GROUP:
3200  CHECK_MODE(IsEmail(extra) || IsMsgAttach(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  if (IsMsgAttach(extra))
3208  mutt_attach_forward(extra->fp, extra->email, extra->actx, extra->body, SEND_NEWS);
3209  else
3210  {
3211  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3212  emaillist_add_email(&el, extra->email);
3213  mutt_send_message(SEND_NEWS | SEND_FORWARD, NULL, NULL, extra->ctx,
3214  &el, NeoMutt->sub);
3215  emaillist_clear(&el);
3216  }
3217  pager_menu->redraw = REDRAW_FULL;
3218  break;
3219 
3220  case OP_FOLLOWUP:
3221  CHECK_MODE(IsEmail(extra) || IsMsgAttach(extra));
3222  CHECK_ATTACH;
3223 
3224  if (IsMsgAttach(extra))
3225  followup_to = extra->body->email->env->followup_to;
3226  else
3227  followup_to = extra->email->env->followup_to;
3228 
3229  if (!followup_to || !mutt_istr_equal(followup_to, "poster") ||
3231  _("Reply by mail as poster prefers?")) != MUTT_YES))
3232  {
3233  if (extra->ctx && (extra->ctx->mailbox->type == MUTT_NNTP) &&
3234  !((struct NntpMboxData *) extra->ctx->mailbox->mdata)->allowed && (query_quadoption(C_PostModerated, _("Posting to this group not allowed, may be moderated. Continue?")) != MUTT_YES))
3235  {
3236  break;
3237  }
3238  if (IsMsgAttach(extra))
3239  {
3240  mutt_attach_reply(extra->fp, extra->email, extra->actx, extra->body,
3241  SEND_NEWS | SEND_REPLY);
3242  }
3243  else
3244  {
3245  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3246  emaillist_add_email(&el, extra->email);
3247  mutt_send_message(SEND_NEWS | SEND_REPLY, NULL, NULL, extra->ctx,
3248  &el, NeoMutt->sub);
3249  emaillist_clear(&el);
3250  }
3251  pager_menu->redraw = REDRAW_FULL;
3252  break;
3253  }
3254 #endif
3255  /* fallthrough */
3256  case OP_REPLY:
3257  case OP_GROUP_REPLY:
3258  case OP_GROUP_CHAT_REPLY:
3259  case OP_LIST_REPLY:
3260  {
3261  CHECK_MODE(IsEmail(extra) || IsMsgAttach(extra));
3262  CHECK_ATTACH;
3263 
3264  SendFlags replyflags = SEND_REPLY;
3265  if (ch == OP_GROUP_REPLY)
3266  replyflags |= SEND_GROUP_REPLY;
3267  else if (ch == OP_GROUP_CHAT_REPLY)
3268  replyflags |= SEND_GROUP_CHAT_REPLY;
3269  else if (ch == OP_LIST_REPLY)
3270  replyflags |= SEND_LIST_REPLY;
3271 
3272  if (IsMsgAttach(extra))
3273  mutt_attach_reply(extra->fp, extra->email, extra->actx, extra->body, replyflags);
3274  else
3275  {
3276  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3277  emaillist_add_email(&el, extra->email);
3278  mutt_send_message(replyflags, NULL, NULL, extra->ctx, &el, NeoMutt->sub);
3279  emaillist_clear(&el);
3280  }
3281  pager_menu->redraw = REDRAW_FULL;
3282  break;
3283  }
3284 
3285  case OP_RECALL_MESSAGE:
3286  {
3287  CHECK_MODE(IsEmail(extra) && !IsAttach(extra));
3288  CHECK_ATTACH;
3289  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3290  emaillist_add_email(&el, extra->email);
3291  mutt_send_message(SEND_POSTPONED, NULL, NULL, extra->ctx, &el, NeoMutt->sub);
3292  emaillist_clear(&el);
3293  pager_menu->redraw = REDRAW_FULL;
3294  break;
3295  }
3296 
3297  case OP_FORWARD_MESSAGE:
3298  CHECK_MODE(IsEmail(extra) || IsMsgAttach(extra));
3299  CHECK_ATTACH;
3300  if (IsMsgAttach(extra))
3301  mutt_attach_forward(extra->fp, extra->email, extra->actx, extra->body, SEND_NO_FLAGS);
3302  else
3303  {
3304  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3305  emaillist_add_email(&el, extra->email);
3306  mutt_send_message(SEND_FORWARD, NULL, NULL, extra->ctx, &el, NeoMutt->sub);
3307  emaillist_clear(&el);
3308  }
3309  pager_menu->redraw = REDRAW_FULL;
3310  break;
3311 
3312  case OP_DECRYPT_SAVE:
3313  if (!WithCrypto)
3314  {
3315  ch = -1;
3316  break;
3317  }
3318  /* fallthrough */
3319  case OP_SAVE:
3320  if (IsAttach(extra))
3321  {
3322  mutt_save_attachment_list(extra->actx, extra->fp, false, extra->body,
3323  extra->email, NULL);
3324  break;
3325  }
3326  /* fallthrough */
3327  case OP_COPY_MESSAGE:
3328  case OP_DECODE_SAVE:
3329  case OP_DECODE_COPY:
3330  case OP_DECRYPT_COPY:
3331  {
3332  if (!(WithCrypto != 0) && (ch == OP_DECRYPT_COPY))
3333  {
3334  ch = -1;
3335  break;
3336  }
3337  CHECK_MODE(IsEmail(extra));
3338  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3339  emaillist_add_email(&el, extra->email);
3340 
3341  const bool delete_original =
3342  (ch == OP_SAVE) || (ch == OP_DECODE_SAVE) || (ch == OP_DECRYPT_SAVE);
3343  const bool decode = (ch == OP_DECODE_SAVE) || (ch == OP_DECODE_COPY);
3344  const bool decrypt = (ch == OP_DECRYPT_SAVE) || (ch == OP_DECRYPT_COPY);
3345 
3346  if ((mutt_save_message(Context->mailbox, &el, delete_original, decode, decrypt) == 0) &&
3347  delete_original)
3348  {
3349  if (C_Resolve)
3350  {
3351  ch = -1;
3352  rc = OP_MAIN_NEXT_UNDELETED;
3353  }
3354  else
3355  pager_menu->redraw |= REDRAW_STATUS | REDRAW_INDEX;
3356  }
3357  emaillist_clear(&el);
3358  break;
3359  }
3360 
3361  case OP_SHELL_ESCAPE:
3363  break;
3364 
3365  case OP_TAG:
3366  CHECK_MODE(IsEmail(extra));
3367  if (Context)
3368  {
3369  mutt_set_flag(Context->mailbox, extra->email, MUTT_TAG, !extra->email->tagged);
3370  }
3371 
3372  pager_menu->redraw |= REDRAW_STATUS | REDRAW_INDEX;
3373  if (C_Resolve)
3374  {
3375  ch = -1;
3376  rc = OP_NEXT_ENTRY;
3377  }
3378  break;
3379 
3380  case OP_TOGGLE_NEW:
3381  CHECK_MODE(IsEmail(extra));
3383  /* L10N: CHECK_ACL */
3384  CHECK_ACL(MUTT_ACL_SEEN, _("Can't toggle new"));
3385 
3386  if (extra->email->read || extra->email->old)
3387  mutt_set_flag(Context->mailbox, extra->email, MUTT_NEW, true);
3388  else if (!first)
3389  mutt_set_flag(Context->mailbox, extra->email, MUTT_READ, true);
3390  first = false;
3391  Context->msg_in_pager = -1;
3392  pager_menu->redraw |= REDRAW_STATUS | REDRAW_INDEX;
3393  if (C_Resolve)
3394  {
3395  ch = -1;
3396  rc = OP_MAIN_NEXT_UNDELETED;
3397  }
3398  break;
3399 
3400  case OP_UNDELETE:
3401  CHECK_MODE(IsEmail(extra));
3403  /* L10N: CHECK_ACL */
3404  CHECK_ACL(MUTT_ACL_DELETE, _("Can't undelete message"));
3405 
3406  mutt_set_flag(Context->mailbox, extra->email, MUTT_DELETE, false);
3407  mutt_set_flag(Context->mailbox, extra->email, MUTT_PURGE, false);
3408  pager_menu->redraw |= REDRAW_STATUS | REDRAW_INDEX;
3409  if (C_Resolve)
3410  {
3411  ch = -1;
3412  rc = OP_NEXT_ENTRY;
3413  }
3414  break;
3415 
3416  case OP_UNDELETE_THREAD:
3417  case OP_UNDELETE_SUBTHREAD:
3418  {
3419  CHECK_MODE(IsEmail(extra));
3421  /* L10N: CHECK_ACL */
3422  /* L10N: Due to the implementation details we do not know whether we
3423  undelete zero, 1, 12, ... messages. So in English we use
3424  "messages". Your language might have other means to express this. */
3425  CHECK_ACL(MUTT_ACL_DELETE, _("Can't undelete messages"));
3426 
3427  int r = mutt_thread_set_flag(extra->email, MUTT_DELETE, false,
3428  (ch != OP_UNDELETE_THREAD));
3429  if (r != -1)
3430  {
3431  r = mutt_thread_set_flag(extra->email, MUTT_PURGE, false,
3432  (ch != OP_UNDELETE_THREAD));
3433  }
3434  if (r != -1)
3435  {
3436  if (C_Resolve)
3437  {
3438  rc = (ch == OP_DELETE_THREAD) ? OP_MAIN_NEXT_THREAD : OP_MAIN_NEXT_SUBTHREAD;
3439  ch = -1;
3440  }
3441 
3442  if (!C_Resolve && (C_PagerIndexLines != 0))
3443  pager_menu->redraw = REDRAW_FULL;
3444  else
3445  pager_menu->redraw |= REDRAW_STATUS | REDRAW_INDEX;
3446  }
3447  break;
3448  }
3449 
3450  case OP_VERSION:
3452  break;
3453 
3454  case OP_MAILBOX_LIST:
3456  break;
3457 
3458  case OP_VIEW_ATTACHMENTS:
3459  if (flags & MUTT_PAGER_ATTACHMENT)
3460  {
3461  ch = -1;
3462  rc = OP_ATTACH_COLLAPSE;
3463  break;
3464  }
3465  CHECK_MODE(IsEmail(extra));
3466  dlg_select_attachment(extra->email);
3467  if (Context && extra->email->attach_del)
3468  Context->mailbox->changed = true;
3469  pager_menu->redraw = REDRAW_FULL;
3470  break;
3471 
3472  case OP_MAIL_KEY:
3473  {
3474  if (!(WithCrypto & APPLICATION_PGP))
3475  {
3476  ch = -1;
3477  break;
3478  }
3479  CHECK_MODE(IsEmail(extra));
3480  CHECK_ATTACH;
3481  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3482  emaillist_add_email(&el, extra->email);
3483  mutt_send_message(SEND_KEY, NULL, NULL, extra->ctx, &el, NeoMutt->sub);
3484  emaillist_clear(&el);
3485  pager_menu->redraw = REDRAW_FULL;
3486  break;
3487  }
3488 
3489  case OP_EDIT_LABEL:
3490  {
3491  CHECK_MODE(IsEmail(extra));
3492 
3493  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3494  emaillist_add_email(&el, extra->email);
3495  rc = mutt_label_message(Context->mailbox, &el);
3496  emaillist_clear(&el);
3497 
3498  if (rc > 0)
3499  {
3500  Context->mailbox->changed = true;
3501  pager_menu->redraw = REDRAW_FULL;
3502  mutt_message(ngettext("%d label changed", "%d labels changed", rc), rc);
3503  }
3504  else
3505  {
3506  mutt_message(_("No labels changed"));
3507  }
3508  break;
3509  }
3510 
3511  case OP_FORGET_PASSPHRASE:
3513  break;
3514 
3515  case OP_EXTRACT_KEYS:
3516  {
3517  if (!WithCrypto)
3518  {
3519  ch = -1;
3520  break;
3521  }
3522  CHECK_MODE(IsEmail(extra));
3523  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
3524  emaillist_add_email(&el, extra->email);
3526  emaillist_clear(&el);
3527  pager_menu->redraw = REDRAW_FULL;
3528  break;
3529  }
3530 
3531  case OP_WHAT_KEY:
3532  mutt_what_key();
3533  break;
3534 
3535  case OP_CHECK_STATS:
3536  mutt_check_stats();
3537  break;
3538 
3539 #ifdef USE_SIDEBAR
3540  case OP_SIDEBAR_FIRST:
3541  case OP_SIDEBAR_LAST:
3542  case OP_SIDEBAR_NEXT:
3543  case OP_SIDEBAR_NEXT_NEW:
3544  case OP_SIDEBAR_PAGE_DOWN:
3545  case OP_SIDEBAR_PAGE_UP:
3546  case OP_SIDEBAR_PREV:
3547  case OP_SIDEBAR_PREV_NEW:
3548  {
3549  struct MuttWindow *win_sidebar =
3551  if (!win_sidebar)
3552  break;
3553  sb_change_mailbox(win_sidebar, ch);
3554  break;
3555  }
3556 
3557  case OP_SIDEBAR_TOGGLE_VISIBLE:
3558  bool_str_toggle(NeoMutt->sub, "sidebar_visible", NULL);
3560  break;
3561 #endif
3562 
3563  default:
3564  ch = -1;
3565  break;
3566  }
3567  }
3568 
3569  mutt_file_fclose(&rd.fp);
3570  if (IsEmail(extra))
3571  {
3572  if (Context)
3573  Context->msg_in_pager = -1;
3574  switch (rc)
3575  {
3576  case -1:
3577  case OP_DISPLAY_HEADERS:
3579  break;
3580  default:
3581  TopLine = rd.topline;
3582  OldEmail = extra->email;
3583  break;
3584  }
3585  }
3586 
3588 
3589  for (size_t i = 0; i < rd.max_line; i++)
3590  {
3591  FREE(&(rd.line_info[i].syntax));
3592  if (rd.search_compiled && rd.line_info[i].search)
3593  FREE(&(rd.line_info[i].search));
3594  }
3595  if (rd.search_compiled)
3596  {
3597  regfree(&rd.search_re);
3598  rd.search_compiled = false;
3599  }
3600  FREE(&rd.line_info);
3601  mutt_menu_pop_current(pager_menu);
3602  mutt_menu_free(&pager_menu);
3603  mutt_menu_free(&rd.menu);
3604 
3605  if (rd.extra->win_index)
3606  {
3612  }
3615 
3616  return (rc != -1) ? rc : 0;
3617 }
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:651
#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:371
#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:217
#define NONULL(x)
Definition: string2.h:37
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:145
struct Email * mutt_get_virt_email(struct Mailbox *m, int vnum)
Get a virtual Email.
Definition: context.c:396
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:52
PagerFlags search_flag
Definition: pager.c:192
void window_set_focus(struct MuttWindow *win)
Set the Window focus.
Definition: mutt_window.c:763
&#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:151
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
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:678
#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
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:139
struct Line * line_info
Definition: pager.c:196
#define REG_COMP(preg, regex, cflags)
Compile a regular expression.
Definition: regex3.h:53
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:539
WHERE bool C_BrailleFriendly
Config: Move the cursor to the beginning of the line.
Definition: mutt_globals.h:140
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:382
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:123
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:64
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
void alias_create(struct AddressList *al, const struct ConfigSubset *sub)
Create a new Alias from an Address.
Definition: alias.c:366
FILE * fp
Definition: pager.c:197
bool mutt_mailbox_notify(struct Mailbox *m_cur)
Notify the user if there&#39;s new mail.
Definition: mutt_mailbox.c:204
short continuation
Definition: pager.c:137
void mutt_shell_escape(void)
invoke a command in a subshell
Definition: commands.c:844
int bool_str_toggle(struct ConfigSubset *sub, const char *name, struct Buffer *err)
Toggle the value of a bool.
Definition: bool.c:213
#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:883
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:421
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
struct MuttWindow * RootWindow
Parent of all Windows.
Definition: mutt_window.c:45
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:76
#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 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:104
void(* custom_redraw)(struct Menu *menu)
Redraw the menu.
Definition: mutt_menu.h:121
#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:60
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:170
int max
Number of entries in the menu.
Definition: mutt_menu.h:57
int mutt_resend_message(FILE *fp, struct Context *ctx, struct Email *e_cur, struct ConfigSubset *sub)
Resend an email.
Definition: send.c:1508
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:58
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:130
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:716
#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:433
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:129
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:1995
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:747
#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:429
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:73
#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:56
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:348
struct Buffer pathbuf
Definition: mailbox.h:83
struct MuttWindow * win_index
Definition: mutt_menu.h:63
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:75
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:155
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
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:40
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.