NeoMutt  2025-12-11-980-ge38c27
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
functions.c
Go to the documentation of this file.
1
22
28
29#include "config.h"
30#include <inttypes.h>
31#include <stdbool.h>
32#include <stdio.h>
33#include <sys/stat.h>
34#include "mutt/lib.h"
35#include "config/lib.h"
36#include "email/lib.h"
37#include "core/lib.h"
38#include "gui/lib.h"
39#include "mutt.h"
40#include "functions.h"
41#include "lib.h"
42#include "attach/lib.h"
43#include "browser/lib.h"
44#include "color/lib.h"
45#include "editor/lib.h"
46#include "history/lib.h"
47#include "index/lib.h"
48#include "key/lib.h"
49#include "menu/lib.h"
50#include "pattern/lib.h"
51#include "sidebar/lib.h"
52#include "display.h"
53#include "module_data.h"
54#include "muttlib.h"
55#include "private_data.h"
56
58static const char *Not_available_in_this_menu = N_("Not available in this menu");
59
60static int op_pager_search_next(struct PagerFunctionData *fdata, const struct KeyEvent *event);
61
62// clang-format off
66static const struct MenuFuncOp OpPager[] = { /* map: pager */
67 { "search-toggle", OP_SEARCH_TOGGLE },
68 { "skip-headers", OP_PAGER_SKIP_HEADERS },
69 { "skip-quoted", OP_PAGER_SKIP_QUOTED },
70 { "toggle-quoted", OP_PAGER_HIDE_QUOTED },
71
72 // Deprecated
73 { "bottom", OP_LAST_ENTRY, MFF_DEPRECATED },
74 { "buffy-list", OP_MAILBOX_LIST, MFF_DEPRECATED },
75 { "error-history", OP_SHOW_LOG_MESSAGES, MFF_DEPRECATED },
76 { "mark-as-new", OP_TOGGLE_NEW, MFF_DEPRECATED },
77 { "tag-message", OP_TAG, MFF_DEPRECATED },
78 { "top", OP_FIRST_ENTRY, MFF_DEPRECATED },
79 { NULL, 0 },
80};
81
85static const struct MenuOpSeq PagerDefaultBindings[] = { /* map: pager */
86 { OP_EXIT, "q" },
87 { OP_MAIN_NEXT_UNDELETED, "<right>" },
88 { OP_MAIN_PREV_UNDELETED, "<left>" },
89 { OP_NEXT_LINE, "<keypadenter>" },
90 { OP_NEXT_LINE, "\n" }, // <Enter>
91 { OP_NEXT_LINE, "\r" }, // <Return>
92 { OP_NEXT_PAGE, " " }, // <Space>
93 { OP_PAGER_HIDE_QUOTED, "T" },
94 { OP_PAGER_SKIP_HEADERS, "H" },
95 { OP_PAGER_SKIP_QUOTED, "S" },
96 { OP_FIRST_ENTRY, "^" },
97 { OP_PREV_LINE, "<backspace>" },
98 { OP_PREV_PAGE, "-" },
99 { OP_QUIT, "Q" },
100 { OP_SEARCH_TOGGLE, "\\" }, // <Backslash>
101 { 0, NULL },
102};
103// clang-format on
104
108void pager_init_keys(struct NeoMutt *n, struct SubMenu *sm_generic)
109{
110 struct MenuDefinition *md = NULL;
111 struct SubMenu *sm_pager = NULL;
112 struct SubMenu *sm_index = index_get_submenu();
113 struct SubMenu *sm_sidebar = sidebar_get_submenu();
114
115 sm_pager = km_register_submenu(OpPager);
116 md = km_register_menu(MENU_PAGER, "pager");
117 km_menu_add_submenu(md, sm_pager);
118 km_menu_add_submenu(md, sm_index);
119 km_menu_add_submenu(md, sm_sidebar);
120 km_menu_add_submenu(md, sm_generic);
122
124 ASSERT(mod_data);
125 mod_data->md_pager = md;
126}
127
136static inline bool assert_pager_mode(bool test)
137{
138 if (test)
139 return true;
140
143 return false;
144}
145
154static int up_n_lines(int nlines, struct Line *info, int cur, bool hiding)
155{
156 while ((cur > 0) && (nlines > 0))
157 {
158 cur--;
159 if (!hiding || !COLOR_QUOTED(info[cur].cid))
160 nlines--;
161 }
162
163 return cur;
164}
165
175static int down_n_lines(int nlines, struct Line *info, int cur, int max, bool hiding)
176{
177 while ((cur < max) && (nlines > 0))
178 {
179 cur++;
180 if ((cur < max) && (!hiding || !COLOR_QUOTED(info[cur].cid)))
181 nlines--;
182 }
183
184 if (cur > max)
185 cur = max;
186
187 return cur;
188}
189
197bool jump_to_bottom(struct PagerPrivateData *priv, struct PagerView *pview)
198{
199 if (!(priv->lines[priv->cur_line].offset < (priv->st.st_size - 1)))
200 {
201 return false;
202 }
203
204 int line_num = priv->cur_line;
205 /* make sure the types are defined to the end of file */
206 while (display_line(priv->fp, &priv->bytes_read, &priv->lines, line_num,
207 &priv->lines_used, &priv->lines_max,
208 priv->has_types | (pview->flags & MUTT_PAGER_NOWRAP),
209 &priv->quote_list, &priv->q_level, &priv->force_redraw,
210 &priv->search_re, priv->pview->win_pager, &priv->ansi_list) == 0)
211 {
212 line_num++;
213 }
214 priv->top_line = up_n_lines(priv->pview->win_pager->state.rows, priv->lines,
215 priv->lines_used, priv->hide_quoted);
217 return true;
218}
219
220// -----------------------------------------------------------------------------
221
225static int op_first_entry(struct PagerFunctionData *fdata, const struct KeyEvent *event)
226{
227 struct PagerPrivateData *priv = fdata->priv;
228 if (priv->top_line == 0)
229 {
230 mutt_message(_("Top of message is shown"));
231 return FR_ERROR;
232 }
233 else
234 {
235 priv->top_line = 0;
237 }
238
239 return FR_SUCCESS;
240}
241
245static int op_last_entry(struct PagerFunctionData *fdata, const struct KeyEvent *event)
246{
247 struct PagerPrivateData *priv = fdata->priv;
248 if (!jump_to_bottom(priv, priv->pview))
249 {
250 mutt_message(_("Bottom of message is shown"));
251 return FR_ERROR;
252 }
253
254 return FR_SUCCESS;
255}
256
260static int op_pager_half_down(struct PagerFunctionData *fdata, const struct KeyEvent *event)
261{
262 struct PagerPrivateData *priv = fdata->priv;
263 const bool c_pager_stop = cs_subset_bool(fdata->n->sub, "pager_stop");
264 if (priv->lines[priv->cur_line].offset < (priv->st.st_size - 1))
265 {
266 int rows = priv->pview->win_pager->state.rows;
267 if (event->count > 0)
268 {
269 int advance = event->count * (rows / 2);
270 priv->top_line = down_n_lines(advance, priv->lines, priv->top_line,
271 priv->lines_used, priv->hide_quoted);
272 }
273 else
274 {
275 priv->top_line = up_n_lines(rows / 2, priv->lines, priv->cur_line, priv->hide_quoted);
276 }
278 }
279 else if (c_pager_stop)
280 {
281 /* emulate "less -q" and don't go on to the next message. */
282 if (event->count == 0)
283 {
284 mutt_message(_("Bottom of message is shown"));
285 return FR_ERROR;
286 }
287 }
288 else
289 {
290 /* end of the current message, so display the next message. */
292 }
293 return FR_SUCCESS;
294}
295
299static int op_pager_half_up(struct PagerFunctionData *fdata, const struct KeyEvent *event)
300{
301 struct PagerPrivateData *priv = fdata->priv;
302 const int old_top_line = priv->top_line;
303 if (priv->top_line)
304 {
305 int rows = priv->pview->win_pager->state.rows;
306 int n = MAX(event->count, 1) * (rows / 2 + rows % 2);
307 priv->top_line = up_n_lines(n, priv->lines, priv->top_line, priv->hide_quoted);
309 }
310 else if (event->count == 0)
311 {
312 mutt_message(_("Top of message is shown"));
313 }
314 return (old_top_line == 0) ? FR_ERROR : FR_SUCCESS;
315}
316
320static int op_pager_hide_quoted(struct PagerFunctionData *fdata, const struct KeyEvent *event)
321{
322 struct PagerPrivateData *priv = fdata->priv;
323 if (!priv->has_types)
324 return FR_NO_ACTION;
325
326 priv->hide_quoted ^= MUTT_HIDE;
327 if (priv->hide_quoted && COLOR_QUOTED(priv->lines[priv->top_line].cid))
328 {
329 priv->top_line = up_n_lines(1, priv->lines, priv->top_line, priv->hide_quoted);
330 }
331 else
332 {
334 }
336 return FR_SUCCESS;
337}
338
342static int op_pager_next_line(struct PagerFunctionData *fdata, const struct KeyEvent *event)
343{
344 struct PagerPrivateData *priv = fdata->priv;
345 if (priv->lines[priv->cur_line].offset < (priv->st.st_size - 1))
346 {
347 int n = MAX(event->count, 1);
348 priv->top_line = down_n_lines(n, priv->lines, priv->top_line,
349 priv->lines_used, priv->hide_quoted);
351 }
352 else if (event->count == 0)
353 {
354 mutt_message(_("Bottom of message is shown"));
355 return FR_ERROR;
356 }
357 return FR_SUCCESS;
358}
359
363static int op_pager_next_page(struct PagerFunctionData *fdata, const struct KeyEvent *event)
364{
365 struct PagerPrivateData *priv = fdata->priv;
366 const bool c_pager_stop = cs_subset_bool(fdata->n->sub, "pager_stop");
367 if (priv->lines[priv->cur_line].offset < (priv->st.st_size - 1))
368 {
369 const short c_pager_context = cs_subset_number(fdata->n->sub, "pager_context");
370 if (event->count > 0)
371 {
372 int advance = event->count * (priv->pview->win_pager->state.rows - c_pager_context);
373 priv->top_line = down_n_lines(advance, priv->lines, priv->top_line,
374 priv->lines_used, priv->hide_quoted);
375 }
376 else
377 {
378 priv->top_line = up_n_lines(c_pager_context, priv->lines, priv->cur_line,
379 priv->hide_quoted);
380 }
382 }
383 else if (c_pager_stop)
384 {
385 /* emulate "less -q" and don't go on to the next message. */
386 if (event->count == 0)
387 {
388 mutt_message(_("Bottom of message is shown"));
389 return FR_ERROR;
390 }
391 }
392 else
393 {
394 /* end of the current message, so display the next message. */
396 }
397 return FR_SUCCESS;
398}
399
403static int op_pager_prev_line(struct PagerFunctionData *fdata, const struct KeyEvent *event)
404{
405 struct PagerPrivateData *priv = fdata->priv;
406 if (priv->top_line)
407 {
408 int n = MAX(event->count, 1);
409 priv->top_line = up_n_lines(n, priv->lines, priv->top_line, priv->hide_quoted);
411 }
412 else if (event->count == 0)
413 {
414 mutt_message(_("Top of message is shown"));
415 return FR_ERROR;
416 }
417 return FR_SUCCESS;
418}
419
423static int op_pager_prev_page(struct PagerFunctionData *fdata, const struct KeyEvent *event)
424{
425 struct PagerPrivateData *priv = fdata->priv;
426 if (priv->top_line == 0)
427 {
428 if (event->count == 0)
429 {
430 mutt_message(_("Top of message is shown"));
431 return FR_ERROR;
432 }
433 }
434 else
435 {
436 const short c_pager_context = cs_subset_number(fdata->n->sub, "pager_context");
437 int n = MAX(event->count, 1) * (priv->pview->win_pager->state.rows - c_pager_context);
438 priv->top_line = up_n_lines(n, priv->lines, priv->top_line, priv->hide_quoted);
440 }
441 return FR_SUCCESS;
442}
443
451static int op_pager_search(struct PagerFunctionData *fdata, const struct KeyEvent *event)
452{
453 struct PagerPrivateData *priv = fdata->priv;
454 struct PagerView *pview = priv->pview;
455
456 int rc = FR_NO_ACTION;
457 struct Buffer *buf = buf_pool_get();
458
459 buf_strcpy(buf, priv->search_str);
460 const int op = event->op;
461 if (mw_get_field(((op == OP_SEARCH) || (op == OP_SEARCH_NEXT)) ? _("Search for: ") : _("Reverse search for: "),
463 {
464 goto done;
465 }
466
467 if (mutt_str_equal(buf_string(buf), priv->search_str))
468 {
469 if (priv->search_compiled)
470 {
471 struct KeyEvent event_s = { 0, OP_NULL };
472
473 /* do an implicit search-next */
474 if (op == OP_SEARCH)
475 event_s.op = OP_SEARCH_NEXT;
476 else
477 event_s.op = OP_SEARCH_OPPOSITE;
478
479 priv->wrapped = false;
480 op_pager_search_next(fdata, &event_s);
481 }
482 }
483
484 if (buf_is_empty(buf))
485 goto done;
486
487 mutt_str_copy(priv->search_str, buf_string(buf), sizeof(priv->search_str));
488
489 /* leave search_back alone if op == OP_SEARCH_NEXT */
490 if (op == OP_SEARCH)
491 priv->search_back = false;
492 else if (op == OP_SEARCH_REVERSE)
493 priv->search_back = true;
494
495 if (priv->search_compiled)
496 {
497 regfree(&priv->search_re);
498 for (size_t i = 0; i < priv->lines_used; i++)
499 {
500 FREE(&(priv->lines[i].search));
501 priv->lines[i].search_arr_size = -1;
502 }
503 }
504
505 uint16_t rflags = mutt_mb_is_lower(priv->search_str) ? REG_ICASE : 0;
506 int err = REG_COMP(&priv->search_re, priv->search_str, REG_NEWLINE | rflags);
507 if (err != 0)
508 {
509 regerror(err, &priv->search_re, buf->data, buf->dsize);
510 mutt_error("%s", buf_string(buf));
511 for (size_t i = 0; i < priv->lines_max; i++)
512 {
513 /* cleanup */
514 FREE(&(priv->lines[i].search));
515 priv->lines[i].search_arr_size = -1;
516 }
517 priv->search_flag = 0;
518 priv->search_compiled = false;
519 rc = FR_ERROR;
520 }
521 else
522 {
523 priv->search_compiled = true;
524 /* update the search pointers */
525 int line_num = 0;
526 while (display_line(priv->fp, &priv->bytes_read, &priv->lines, line_num,
527 &priv->lines_used, &priv->lines_max,
528 MUTT_SEARCH | (pview->flags & MUTT_PAGER_NOWRAP) | priv->has_types,
529 &priv->quote_list, &priv->q_level, &priv->force_redraw,
530 &priv->search_re, priv->pview->win_pager, &priv->ansi_list) == 0)
531 {
532 line_num++;
533 }
534
535 if (priv->search_back)
536 {
537 /* searching backward */
538 int i;
539 for (i = priv->top_line; i >= 0; i--)
540 {
541 if ((!priv->hide_quoted || !COLOR_QUOTED(priv->lines[i].cid)) &&
542 !priv->lines[i].cont_line && (priv->lines[i].search_arr_size > 0))
543 {
544 break;
545 }
546 }
547
548 if (i >= 0)
549 priv->top_line = i;
550 }
551 else
552 {
553 /* searching forward */
554 int i;
555 for (i = priv->top_line; i < priv->lines_used; i++)
556 {
557 if ((!priv->hide_quoted || !COLOR_QUOTED(priv->lines[i].cid)) &&
558 !priv->lines[i].cont_line && (priv->lines[i].search_arr_size > 0))
559 {
560 break;
561 }
562 }
563
564 if (i < priv->lines_used)
565 priv->top_line = i;
566 }
567
568 if (priv->lines[priv->top_line].search_arr_size == 0)
569 {
570 priv->search_flag = 0;
571 mutt_error(_("Not found"));
572 rc = FR_ERROR;
573 }
574 else
575 {
576 const short c_search_context = cs_subset_number(fdata->n->sub, "search_context");
577 priv->search_flag = MUTT_SEARCH;
578 /* give some context for search results */
579 if (c_search_context < priv->pview->win_pager->state.rows)
580 priv->searchctx = c_search_context;
581 else
582 priv->searchctx = 0;
583 if (priv->top_line - priv->searchctx > 0)
584 priv->top_line -= priv->searchctx;
585 rc = FR_SUCCESS;
586 }
587 }
590
591done:
592 buf_pool_release(&buf);
593 return rc;
594}
595
603static int op_pager_search_next(struct PagerFunctionData *fdata, const struct KeyEvent *event)
604{
605 struct PagerPrivateData *priv = fdata->priv;
606 if (priv->search_compiled)
607 {
608 const short c_search_context = cs_subset_number(fdata->n->sub, "search_context");
609 bool found = false;
610 priv->wrapped = false;
611
612 if (c_search_context < priv->pview->win_pager->state.rows)
613 priv->searchctx = c_search_context;
614 else
615 priv->searchctx = 0;
616
617 const int op = event->op;
618
619 search_next:
620 if ((!priv->search_back && (op == OP_SEARCH_NEXT)) ||
621 (priv->search_back && (op == OP_SEARCH_OPPOSITE)))
622 {
623 /* searching forward */
624 int i;
625 for (i = priv->wrapped ? 0 : priv->top_line + priv->searchctx + 1;
626 i < priv->lines_used; i++)
627 {
628 if ((!priv->hide_quoted || !COLOR_QUOTED(priv->lines[i].cid)) &&
629 !priv->lines[i].cont_line && (priv->lines[i].search_arr_size > 0))
630 {
631 break;
632 }
633 }
634
635 const bool c_wrap_search = cs_subset_bool(fdata->n->sub, "wrap_search");
636 if (i < priv->lines_used)
637 {
638 priv->top_line = i;
639 found = true;
640 }
641 else if (priv->wrapped || !c_wrap_search)
642 {
643 mutt_error(_("Not found"));
644 }
645 else
646 {
647 mutt_message(_("Search wrapped to top"));
648 priv->wrapped = true;
649 goto search_next;
650 }
651 }
652 else
653 {
654 /* searching backward */
655 int i;
656 for (i = priv->wrapped ? priv->lines_used : priv->top_line + priv->searchctx - 1;
657 i >= 0; i--)
658 {
659 if ((!priv->hide_quoted ||
660 (priv->has_types && !COLOR_QUOTED(priv->lines[i].cid))) &&
661 !priv->lines[i].cont_line && (priv->lines[i].search_arr_size > 0))
662 {
663 break;
664 }
665 }
666
667 const bool c_wrap_search = cs_subset_bool(fdata->n->sub, "wrap_search");
668 if (i >= 0)
669 {
670 priv->top_line = i;
671 found = true;
672 }
673 else if (priv->wrapped || !c_wrap_search)
674 {
675 mutt_error(_("Not found"));
676 }
677 else
678 {
679 mutt_message(_("Search wrapped to bottom"));
680 priv->wrapped = true;
681 goto search_next;
682 }
683 }
684
685 if (!found)
686 return FR_ERROR;
687
688 if (priv->lines[priv->top_line].search_arr_size > 0)
689 {
690 priv->search_flag = MUTT_SEARCH;
691 /* give some context for search results */
692 if (priv->top_line - priv->searchctx > 0)
693 priv->top_line -= priv->searchctx;
694 }
695
697 return FR_SUCCESS;
698 }
699
700 /* no previous search pattern */
701 return op_pager_search(fdata, event);
702}
703
707static int op_pager_skip_headers(struct PagerFunctionData *fdata, const struct KeyEvent *event)
708{
709 struct PagerPrivateData *priv = fdata->priv;
710 struct PagerView *pview = priv->pview;
711
712 if (!priv->has_types)
713 return FR_NO_ACTION;
714
715 int rc = 0;
716 int new_topline = 0;
717
718 while (((new_topline < priv->lines_used) ||
719 (0 == (rc = display_line(priv->fp, &priv->bytes_read, &priv->lines,
720 new_topline, &priv->lines_used, &priv->lines_max,
721 MUTT_TYPES | (pview->flags & MUTT_PAGER_NOWRAP), &priv->quote_list,
722 &priv->q_level, &priv->force_redraw, &priv->search_re,
723 priv->pview->win_pager, &priv->ansi_list)))) &&
724 color_is_header(priv->lines[new_topline].cid))
725 {
726 new_topline++;
727 }
728
729 if (rc < 0)
730 {
731 /* L10N: Displayed if <skip-headers> is invoked in the pager, but
732 there is no text past the headers.
733 (I don't think this is actually possible in Mutt's code, but
734 display some kind of message in case it somehow occurs.) */
735 mutt_warning(_("No text past headers"));
736 return FR_ERROR;
737 }
738 priv->top_line = new_topline;
740 return FR_SUCCESS;
741}
742
750static int pager_skip_quoted_once(struct PagerPrivateData *priv, struct PagerFunctionData *fdata)
751{
752 struct PagerView *pview = priv->pview;
753 const short c_pager_skip_quoted_context = cs_subset_number(fdata->n->sub, "pager_skip_quoted_context");
754 int rc = 0;
755 int new_topline = priv->top_line;
756 int num_quoted = 0;
757
758 /* In a header? Skip all the email headers, and done */
759 if (color_is_header(priv->lines[new_topline].cid))
760 {
761 while (((new_topline < priv->lines_used) ||
762 (0 == (rc = display_line(priv->fp, &priv->bytes_read, &priv->lines,
763 new_topline, &priv->lines_used, &priv->lines_max,
764 MUTT_TYPES | (pview->flags & MUTT_PAGER_NOWRAP), &priv->quote_list,
765 &priv->q_level, &priv->force_redraw, &priv->search_re,
766 priv->pview->win_pager, &priv->ansi_list)))) &&
767 color_is_header(priv->lines[new_topline].cid))
768 {
769 new_topline++;
770 }
771 priv->top_line = new_topline;
773 return 0;
774 }
775
776 /* Already in the body? Skip past previous "context" quoted lines */
777 if (c_pager_skip_quoted_context > 0)
778 {
779 while (((new_topline < priv->lines_used) ||
780 (0 == (rc = display_line(priv->fp, &priv->bytes_read, &priv->lines,
781 new_topline, &priv->lines_used, &priv->lines_max,
782 MUTT_TYPES | (pview->flags & MUTT_PAGER_NOWRAP), &priv->quote_list,
783 &priv->q_level, &priv->force_redraw, &priv->search_re,
784 priv->pview->win_pager, &priv->ansi_list)))) &&
785 COLOR_QUOTED(priv->lines[new_topline].cid))
786 {
787 new_topline++;
788 num_quoted++;
789 }
790
791 if (rc < 0)
792 return -1;
793 }
794
795 if (num_quoted <= c_pager_skip_quoted_context)
796 {
797 num_quoted = 0;
798
799 while (((new_topline < priv->lines_used) ||
800 (0 == (rc = display_line(priv->fp, &priv->bytes_read, &priv->lines,
801 new_topline, &priv->lines_used, &priv->lines_max,
802 MUTT_TYPES | (pview->flags & MUTT_PAGER_NOWRAP), &priv->quote_list,
803 &priv->q_level, &priv->force_redraw, &priv->search_re,
804 priv->pview->win_pager, &priv->ansi_list)))) &&
805 !COLOR_QUOTED(priv->lines[new_topline].cid))
806 {
807 new_topline++;
808 }
809
810 if (rc < 0)
811 return -1;
812
813 while (((new_topline < priv->lines_used) ||
814 (0 == (rc = display_line(priv->fp, &priv->bytes_read, &priv->lines,
815 new_topline, &priv->lines_used, &priv->lines_max,
816 MUTT_TYPES | (pview->flags & MUTT_PAGER_NOWRAP), &priv->quote_list,
817 &priv->q_level, &priv->force_redraw, &priv->search_re,
818 priv->pview->win_pager, &priv->ansi_list)))) &&
819 COLOR_QUOTED(priv->lines[new_topline].cid))
820 {
821 new_topline++;
822 num_quoted++;
823 }
824
825 if (rc < 0)
826 return -1;
827 }
828 priv->top_line = new_topline - MIN(c_pager_skip_quoted_context, num_quoted);
830 return 0;
831}
832
838static int op_pager_skip_quoted(struct PagerFunctionData *fdata, const struct KeyEvent *event)
839{
840 struct PagerPrivateData *priv = fdata->priv;
841
842 if (!priv->has_types)
843 return FR_NO_ACTION;
844
845 const int count = MAX(event->count, 1);
846
847 for (int i = 0; i < count; i++)
848 {
849 if (pager_skip_quoted_once(priv, fdata) < 0)
850 return FR_NO_ACTION;
851 }
852
853 return FR_SUCCESS;
854}
855
856// -----------------------------------------------------------------------------
857
861static int op_exit(struct PagerFunctionData *fdata, const struct KeyEvent *event)
862{
863 struct PagerPrivateData *priv = fdata->priv;
864 priv->rc = -1;
865 priv->loop = PAGER_LOOP_QUIT;
866 return FR_DONE;
867}
868
875static int op_quit(struct PagerFunctionData *fdata, const struct KeyEvent *event)
876{
877 struct PagerPrivateData *priv = fdata->priv;
878 if (priv->pview->mode != PAGER_MODE_EMAIL)
879 return FR_UNKNOWN;
880
881 priv->rc = -1;
882 priv->loop = PAGER_LOOP_QUIT;
883
884 // Close the Pager, then let the Index handle the quit
885 mutt_push_macro_event(0, OP_QUIT);
886
887 return FR_DONE;
888}
889
893static int op_help(struct PagerFunctionData *fdata, const struct KeyEvent *event)
894{
895 struct PagerPrivateData *priv = fdata->priv;
896 if (priv->pview->mode == PAGER_MODE_HELP)
897 {
898 /* don't let the user enter the help-menu from the help screen! */
899 mutt_error(_("Help is currently being shown"));
900 return FR_ERROR;
901 }
902 mutt_help(fdata->mod_data->md_pager);
904 return FR_SUCCESS;
905}
906
910static int op_save(struct PagerFunctionData *fdata, const struct KeyEvent *event)
911{
912 struct PagerPrivateData *priv = fdata->priv;
913 struct PagerView *pview = priv->pview;
914 if (pview->mode != PAGER_MODE_OTHER)
915 return FR_UNKNOWN;
916
917 if (!priv->fp)
918 return FR_UNKNOWN;
919
920 int rc = FR_ERROR;
921 FILE *fp_save = NULL;
922 struct Buffer *buf = buf_pool_get();
923
924 // Save the current read position
925 long pos = ftell(priv->fp);
926 rewind(priv->fp);
927
928 struct FileCompletionData cdata = { false, NULL, NULL, NULL, NULL };
929 if ((mw_get_field(_("Save to file: "), buf, MUTT_COMP_CLEAR, HC_FILE,
930 &CompleteFileOps, &cdata) != 0) ||
931 buf_is_empty(buf))
932 {
933 rc = FR_SUCCESS;
934 goto done;
935 }
936
937 expand_path(buf, false);
938 fp_save = mutt_file_fopen(buf_string(buf), "a+");
939 if (!fp_save)
940 {
941 mutt_perror("%s", buf_string(buf));
942 goto done;
943 }
944
945 int bytes = mutt_file_copy_stream(priv->fp, fp_save);
946 if (bytes == -1)
947 {
948 mutt_perror("%s", buf_string(buf));
949 goto done;
950 }
951
952 mutt_message(_("Saved to: %s"), buf_string(buf));
953 rc = FR_SUCCESS;
954
955done:
956 // Restore the read position (rewound at start of function)
957 if (pos >= 0)
958 (void) mutt_file_seek(priv->fp, pos, SEEK_SET);
959
960 mutt_file_fclose(&fp_save);
961 buf_pool_release(&buf);
962
963 return rc;
964}
965
969static int op_search_toggle(struct PagerFunctionData *fdata, const struct KeyEvent *event)
970{
971 struct PagerPrivateData *priv = fdata->priv;
972 if (priv->search_compiled)
973 {
974 priv->search_flag ^= MUTT_SEARCH;
976 }
977 return FR_SUCCESS;
978}
979
983static int op_view_attachments(struct PagerFunctionData *fdata, const struct KeyEvent *event)
984{
985 struct IndexSharedData *shared = fdata->shared;
986 struct PagerPrivateData *priv = fdata->priv;
987 struct PagerView *pview = priv->pview;
988
989 // This needs to be delegated
990 if (pview->flags & MUTT_PAGER_ATTACHMENT)
991 return FR_UNKNOWN;
992
994 return FR_NOT_IMPL;
995 dlg_attach(fdata->n->sub, shared->mailbox_view, shared->email,
996 pview->pdata->fp, shared->attach_msg);
997 if (shared->email->attach_del)
998 shared->mailbox->changed = true;
1000 return FR_SUCCESS;
1001}
1002
1006static int op_ignore(struct PagerFunctionData *fdata, const struct KeyEvent *event)
1007{
1008 return FR_NO_ACTION;
1009}
1010
1011// -----------------------------------------------------------------------------
1012
1016static const struct PagerFunction PagerFunctions[] = {
1017 // clang-format off
1018 { OP_EXIT, op_exit },
1019 { OP_FIRST_ENTRY, op_first_entry },
1020 { OP_HALF_DOWN, op_pager_half_down },
1021 { OP_HALF_UP, op_pager_half_up },
1022 { OP_HELP, op_help },
1023 { OP_LAST_ENTRY, op_last_entry },
1024 { OP_NEXT_LINE, op_pager_next_line },
1025 { OP_NEXT_PAGE, op_pager_next_page },
1026 { OP_PAGER_HIDE_QUOTED, op_pager_hide_quoted },
1027 { OP_PAGER_SKIP_HEADERS, op_pager_skip_headers },
1028 { OP_PAGER_SKIP_QUOTED, op_pager_skip_quoted },
1029 { OP_PREV_LINE, op_pager_prev_line },
1030 { OP_PREV_PAGE, op_pager_prev_page },
1031 { OP_QUIT, op_quit },
1032 { OP_SAVE, op_save },
1033 { OP_SEARCH, op_pager_search },
1034 { OP_SEARCH_NEXT, op_pager_search_next },
1035 { OP_SEARCH_OPPOSITE, op_pager_search_next },
1036 { OP_SEARCH_REVERSE, op_pager_search },
1037 { OP_SEARCH_TOGGLE, op_search_toggle },
1038 { OP_VIEW_ATTACHMENTS, op_view_attachments },
1039
1040 // OpGeneric - Ignore
1041 { OP_CURRENT_MIDDLE, op_ignore },
1042 { OP_CURRENT_TOP, op_ignore },
1043 { OP_CURRENT_BOTTOM, op_ignore },
1044 { OP_BOTTOM_PAGE, op_ignore },
1045 { OP_MIDDLE_PAGE, op_ignore },
1046 { OP_GENERIC_SELECT_ENTRY, op_ignore },
1047 { OP_TOP_PAGE, op_ignore },
1048 { 0, NULL },
1049 // clang-format on
1050};
1051
1055int pager_function_dispatcher(struct MuttWindow *win, const struct KeyEvent *event)
1056{
1057 if (!win || !event)
1058 {
1061 return FR_ERROR;
1062 }
1063
1064 if (!win->parent || !win->parent->wdata)
1065 {
1067 return FR_ERROR;
1068 }
1069
1070 struct PagerPrivateData *priv = win->parent->wdata;
1071
1072 struct MuttWindow *dlg = dialog_find(win);
1073 if (!dlg || !dlg->wdata)
1074 {
1076 return FR_ERROR;
1077 }
1078
1079 const int op = event->op;
1080
1082
1083 struct PagerFunctionData fdata = {
1084 .n = NeoMutt,
1085 .mod_data = mod_data,
1086 .shared = dlg->wdata,
1087 .priv = priv,
1088 };
1089
1090 int rc = FR_UNKNOWN;
1091 for (size_t i = 0; PagerFunctions[i].op != OP_NULL; i++)
1092 {
1093 const struct PagerFunction *fn = &PagerFunctions[i];
1094 if (fn->op == op)
1095 {
1096 rc = fn->function(&fdata, event);
1097 break;
1098 }
1099 }
1100
1101 if (rc == FR_UNKNOWN) // Not our function
1102 return rc;
1103
1104 const char *result = dispatcher_get_retval_name(rc);
1105 mutt_debug(LL_DEBUG1, "Handled %s (%d) -> %s\n", opcodes_get_name(op), op, NONULL(result));
1106
1108 return rc;
1109}
1110
1116{
1118 ASSERT(mod_data);
1119
1120 return mod_data->md_pager;
1121}
GUI display the mailboxes in a side panel.
const struct CompleteOps CompleteFileOps
Auto-Completion of Files.
Definition complete.c:152
Select a Mailbox from a list.
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition buffer.c:298
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition buffer.c:401
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
Color and attribute parsing.
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition helpers.c:143
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition helpers.c:47
Convenience wrapper for the config headers.
Convenience wrapper for the core headers.
struct MuttWindow * dialog_find(struct MuttWindow *win)
Find the parent Dialog of a Window.
Definition dialog.c:89
const char * dispatcher_get_retval_name(int rv)
Get the name of a return value.
Definition dispatcher.c:55
void dispatcher_flush_on_error(int rv)
Flush pending keys after a dispatch error.
Definition dispatcher.c:65
@ FR_SUCCESS
Valid function - successfully performed.
Definition dispatcher.h:40
@ FR_DONE
Exit the Dialog.
Definition dispatcher.h:36
@ FR_UNKNOWN
Unknown function.
Definition dispatcher.h:34
@ FR_ERROR
Valid function - error occurred.
Definition dispatcher.h:39
@ FR_NOT_IMPL
Invalid function - feature not enabled.
Definition dispatcher.h:37
@ FR_NO_ACTION
Valid function - no action performed.
Definition dispatcher.h:38
bool color_is_header(enum ColorId cid)
Colour is for an Email header.
Definition display.c:488
int display_line(FILE *fp, LOFF_T *bytes_read, struct Line **lines, int line_num, int *lines_used, int *lines_max, PagerFlags flags, struct QuoteStyle **quote_list, int *q_level, bool *force_redraw, regex_t *search_re, struct MuttWindow *win_pager, struct AttrColorList *ansi_list)
Print a line on screen.
Definition display.c:1063
Pager Display.
void pager_queue_redraw(struct PagerPrivateData *priv, PagerRedrawFlags redraw)
Queue a request for a redraw.
Definition dlg_pager.c:121
Edit a string.
@ MUTT_COMP_CLEAR
Clear input if printable character is pressed.
Definition wdata.h:47
Structs that make up an email.
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition file.c:224
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition file.c:648
#define mutt_file_fclose(FP)
Definition file.h:144
#define mutt_file_fopen(PATH, MODE)
Definition file.h:143
struct SubMenu * sidebar_get_submenu(void)
Get the Sidebar SubMenu.
void mutt_flushinp(void)
MacroEvents moved to KeyModuleData UngetKeyEvents moved to KeyModuleData.
Definition get.c:81
void mutt_push_macro_event(int ch, int op)
Add the character/operation to the macro buffer.
Definition get.c:173
@ MFF_DEPRECATED
Function is deprecated.
Definition get.h:67
static int op_quit(struct AliasFunctionData *fdata, const struct KeyEvent *event)
Save changes and exit this dialog - Implements alias_function_t -.
Definition functions.c:308
int pager_function_dispatcher(struct MuttWindow *win, const struct KeyEvent *event)
Perform a Pager function - Implements function_dispatcher_t -.
Definition functions.c:1055
static int op_help(struct EnterFunctionData *fdata, const struct KeyEvent *event)
Display Help - Implements enter_function_t -.
Definition functions.c:476
void dlg_attach(struct ConfigSubset *sub, struct MailboxView *mv, struct Email *e, FILE *fp, bool attach_msg)
Show the attachments in a Menu -.
Definition dlg_attach.c:208
int mw_get_field(const char *prompt, struct Buffer *buf, CompletionFlags complete, enum HistoryClass hclass, const struct CompleteOps *comp_api, void *cdata)
Ask the user for a string -.
Definition window.c:502
static int op_save(struct IndexFunctionData *fdata, const struct KeyEvent *event)
Make decrypted copy - Implements index_function_t -.
Definition functions.c:2907
static int op_exit(struct IndexFunctionData *fdata, const struct KeyEvent *event)
Exit this menu - Implements index_function_t -.
Definition functions.c:1125
static int op_view_attachments(struct IndexFunctionData *fdata, const struct KeyEvent *event)
Show MIME attachments - Implements index_function_t -.
Definition functions.c:3236
#define mutt_warning(...)
Definition logging2.h:92
#define mutt_error(...)
Definition logging2.h:94
#define mutt_message(...)
Definition logging2.h:93
#define mutt_debug(LEVEL,...)
Definition logging2.h:91
#define mutt_perror(...)
Definition logging2.h:95
static int op_pager_skip_quoted(struct PagerFunctionData *fdata, const struct KeyEvent *event)
Skip beyond quoted text - Implements pager_function_t -.
Definition functions.c:838
static int op_pager_search_next(struct PagerFunctionData *fdata, const struct KeyEvent *event)
Search for next match - Implements pager_function_t -.
Definition functions.c:603
static int op_first_entry(struct PagerFunctionData *fdata, const struct KeyEvent *event)
Move to the first entry - Implements pager_function_t -.
Definition functions.c:225
static int op_pager_half_up(struct PagerFunctionData *fdata, const struct KeyEvent *event)
Scroll up 1/2 page - Implements pager_function_t -.
Definition functions.c:299
static int op_pager_next_page(struct PagerFunctionData *fdata, const struct KeyEvent *event)
Move to the next page - Implements pager_function_t -.
Definition functions.c:363
static int op_pager_prev_page(struct PagerFunctionData *fdata, const struct KeyEvent *event)
Move to the previous page - Implements pager_function_t -.
Definition functions.c:423
static int op_search_toggle(struct PagerFunctionData *fdata, const struct KeyEvent *event)
Toggle search pattern coloring - Implements pager_function_t -.
Definition functions.c:969
static int op_pager_hide_quoted(struct PagerFunctionData *fdata, const struct KeyEvent *event)
Toggle display of quoted text - Implements pager_function_t -.
Definition functions.c:320
static int op_pager_next_line(struct PagerFunctionData *fdata, const struct KeyEvent *event)
Scroll down one line - Implements pager_function_t -.
Definition functions.c:342
static int op_pager_prev_line(struct PagerFunctionData *fdata, const struct KeyEvent *event)
Scroll up one line - Implements pager_function_t -.
Definition functions.c:403
static int op_pager_skip_headers(struct PagerFunctionData *fdata, const struct KeyEvent *event)
Jump to first line after headers - Implements pager_function_t -.
Definition functions.c:707
static int op_pager_half_down(struct PagerFunctionData *fdata, const struct KeyEvent *event)
Scroll down 1/2 page - Implements pager_function_t -.
Definition functions.c:260
static int op_pager_search(struct PagerFunctionData *fdata, const struct KeyEvent *event)
Search for a regular expression - Implements pager_function_t -.
Definition functions.c:451
static int op_last_entry(struct PagerFunctionData *fdata, const struct KeyEvent *event)
Move to the last entry - Implements pager_function_t -.
Definition functions.c:245
static int op_ignore(struct PagerFunctionData *fdata, const struct KeyEvent *event)
Ignore this function - Implements pager_function_t -.
Definition functions.c:1006
Convenience wrapper for the gui headers.
void mutt_help(const struct MenuDefinition *md)
Display the Help Page.
Definition help.c:147
Read/write command history from/to a file.
@ HC_FILE
Files.
Definition lib.h:59
@ HC_PATTERN
Patterns.
Definition lib.h:60
bool index_next_undeleted(struct MuttWindow *win_index)
Select the next undeleted Email (if possible)
Definition functions.c:439
struct SubMenu * index_get_submenu(void)
Get the Index SubMenu.
Definition functions.c:350
GUI manage the main index (list of emails)
void km_menu_add_submenu(struct MenuDefinition *md, struct SubMenu *sm)
Add a SubMenu to a Menu Definition.
Definition init.c:123
struct SubMenu * km_register_submenu(const struct MenuFuncOp functions[])
Register a submenu.
Definition init.c:88
struct MenuDefinition * km_register_menu(int menu, const char *name)
Register a menu.
Definition init.c:105
void km_menu_add_bindings(struct MenuDefinition *md, const struct MenuOpSeq bindings[])
Add Keybindings to a Menu.
Definition init.c:136
Manage keymappings.
@ LL_DEBUG1
Log at debug level 1.
Definition logging2.h:45
bool mutt_mb_is_lower(const char *s)
Does a multi-byte string contain only lowercase characters?
Definition mbyte.c:355
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
#define MIN(a, b)
Return the minimum of two values.
Definition memory.h:40
#define MAX(a, b)
Return the maximum of two values.
Definition memory.h:38
GUI present the user with a selectable list.
@ MODULE_ID_PAGER
ModulePager, Pager
Definition module_api.h:85
Convenience wrapper for the library headers.
#define N_(a)
Definition message.h:32
#define _(a)
Definition message.h:28
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition notify.c:173
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:666
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:587
Many unsorted constants and some structs.
void expand_path(struct Buffer *buf, bool regex)
Create the canonical path.
Definition muttlib.c:122
Some miscellaneous functions.
void * neomutt_get_module_data(struct NeoMutt *n, enum ModuleId id)
Get the private data for a Module.
Definition neomutt.c:666
@ NT_PAGER
Pager data has changed, NotifyPager, PagerPrivateData.
Definition notify_type.h:54
const char * opcodes_get_name(int op)
Get the name of an opcode.
Definition opcodes.c:48
void pager_init_keys(struct NeoMutt *n, struct SubMenu *sm_generic)
Initialise the Pager Keybindings - Implements ::init_keys_api.
Definition functions.c:108
static int up_n_lines(int nlines, struct Line *info, int cur, bool hiding)
Reposition the pager's view up by n lines.
Definition functions.c:154
static const char * Not_available_in_this_menu
Error message for unavailable functions.
Definition functions.c:58
static int pager_skip_quoted_once(struct PagerPrivateData *priv, struct PagerFunctionData *fdata)
Skip to next unquoted block.
Definition functions.c:750
static const struct MenuOpSeq PagerDefaultBindings[]
Key bindings for the Pager Menu.
Definition functions.c:85
static int down_n_lines(int nlines, struct Line *info, int cur, int max, bool hiding)
Reposition the pager's view down by n lines.
Definition functions.c:175
static const struct MenuFuncOp OpPager[]
Functions for the Pager Menu.
Definition functions.c:66
struct MenuDefinition * pager_get_menu_definition(void)
Get the Pager Menu Definition.
Definition functions.c:1115
bool jump_to_bottom(struct PagerPrivateData *priv, struct PagerView *pview)
Make sure the bottom line is displayed.
Definition functions.c:197
static bool assert_pager_mode(bool test)
Check that pager is in correct mode.
Definition functions.c:136
static const struct PagerFunction PagerFunctions[]
All the NeoMutt functions that the Pager supports.
Definition functions.c:1016
Pager functions.
GUI display a file/email/help in a viewport with paging.
@ NT_PAGER_VIEW
Pager View has changed.
Definition lib.h:192
@ PAGER_LOOP_QUIT
Quit the Pager.
Definition lib.h:154
@ PAGER_REDRAW_PAGER
Redraw the pager.
Definition lib.h:202
#define MUTT_PAGER_NOWRAP
Format for term width, ignore $wrap.
Definition lib.h:74
#define MUTT_HIDE
Don't show quoted text.
Definition lib.h:66
#define MUTT_TYPES
Compute line's type.
Definition lib.h:68
#define MUTT_SEARCH
Resolve search patterns.
Definition lib.h:67
@ PAGER_MODE_OTHER
Pager is invoked via 3rd path. Non-email content is likely to be shown.
Definition lib.h:143
@ PAGER_MODE_HELP
Pager is invoked via 3rd path to show help.
Definition lib.h:142
@ PAGER_MODE_EMAIL
Pager is invoked via 1st path. The mime part is selected automatically.
Definition lib.h:139
#define MUTT_PAGER_ATTACHMENT
Attachments may exist.
Definition lib.h:73
Pager private Module data.
Private state data for the Pager.
const struct CompleteOps CompletePatternOps
Auto-Completion of Patterns.
Definition complete.c:98
Match patterns to emails.
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
#define COLOR_QUOTED(cid)
Definition quoted.h:28
#define REG_COMP(preg, regex, cflags)
Compile a regular expression.
Definition regex3.h:49
GUI display the mailboxes in a side panel.
#define ASSERT(COND)
Definition signal2.h:59
#define NONULL(x)
Definition string2.h:44
String manipulation buffer.
Definition buffer.h:36
size_t dsize
Length of data.
Definition buffer.h:39
char * data
Pointer to data.
Definition buffer.h:37
bool attach_del
Has an attachment marked for deletion.
Definition email.h:99
Input for the file completion function.
Definition curs_lib.h:39
Data shared between Index, Pager and Sidebar.
Definition shared_data.h:37
struct Email * email
Currently selected Email.
Definition shared_data.h:42
struct Mailbox * mailbox
Current Mailbox.
Definition shared_data.h:41
bool attach_msg
Are we in "attach message" mode?
Definition shared_data.h:46
struct MailboxView * mailbox_view
Current Mailbox view.
Definition shared_data.h:40
An event such as a keypress.
Definition get.h:75
int count
Optional count prefix, e.g. 3 for 3j
Definition get.h:78
int op
Function opcode, e.g. OP_HELP.
Definition get.h:77
A line of text in the pager.
Definition display.h:50
short search_arr_size
Number of items in search array.
Definition display.h:59
struct TextSyntax * search
Array of search text in the line.
Definition display.h:60
bool cont_line
Continuation of a previous line (wrapped by NeoMutt)
Definition display.h:53
short cid
Default line colour, e.g. MT_COLOR_SIGNATURE.
Definition display.h:52
LOFF_T offset
Offset into Email file (PagerPrivateData->fp)
Definition display.h:51
bool changed
Mailbox has been modified.
Definition mailbox.h:112
Functions for a Dialog or Window.
Definition menudef.h:44
Mapping between a function and an operation.
Definition menu.h:37
Mapping between an operation and a key sequence.
Definition menu.h:47
struct WindowState state
Current state of the Window.
void * wdata
Private data.
struct MuttWindow * parent
Parent Window.
Container for Accounts, Notifications.
Definition neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
FILE * fp
Source stream.
Definition lib.h:164
Data passed to Pager worker functions.
Definition functions.h:37
struct IndexSharedData * shared
Shared Index data.
Definition functions.h:40
struct PagerModuleData * mod_data
Pager module data.
Definition functions.h:39
struct PagerPrivateData * priv
Private Pager data.
Definition functions.h:41
struct NeoMutt * n
NeoMutt application data.
Definition functions.h:38
A NeoMutt function.
Definition functions.h:64
pager_function_t function
Function to call.
Definition functions.h:66
int op
Op code, e.g. OP_MAIN_LIMIT.
Definition functions.h:65
Pager private Module data.
Definition module_data.h:30
struct MenuDefinition * md_pager
Pager menu definition.
Definition module_data.h:32
Private state data for the Pager.
PagerFlags hide_quoted
Set to MUTT_HIDE when quoted email is hidden <toggle-quoted>
int rc
Return code from functions.
int q_level
Number of unique quoting levels.
int cur_line
Current line (last line visible on screen)
bool wrapped
Has the search/next wrapped around?
int lines_used
Size of lines array (used entries)
char search_str[256]
Current search string.
int lines_max
Capacity of lines array (total entries)
bool force_redraw
Repaint is needed.
enum PagerLoopMode loop
What the Event Loop should do next, e.g. PAGER_LOOP_CONTINUE.
struct Line * lines
Array of text lines in pager.
int has_types
Set to MUTT_TYPES for PAGER_MODE_EMAIL or MUTT_SHOWCOLOR.
struct Notify * notify
Notifications: NotifyPager, PagerPrivateData.
LOFF_T bytes_read
Number of bytes read from file.
int top_line
First visible line on screen.
struct stat st
Stats about Email file.
bool search_back
Search backwards.
struct QuoteStyle * quote_list
Tree of quoting levels.
struct PagerView * pview
Object to view in the pager.
struct AttrColorList ansi_list
List of ANSI colours used in the Pager.
int searchctx
Space to show around search matches.
regex_t search_re
Compiled search string.
int old_top_line
Old top line, used for repainting.
FILE * fp
File containing decrypted/decoded/weeded Email.
PagerFlags search_flag
Set to MUTT_SEARCH when search results are visible <search-toggle>
bool search_compiled
Search regex is in use.
Paged view into some data.
Definition lib.h:173
struct MuttWindow * win_index
Index Window.
Definition lib.h:179
struct PagerData * pdata
Data that pager displays. NOTNULL.
Definition lib.h:174
enum PagerMode mode
Pager mode.
Definition lib.h:175
PagerFlags flags
Additional settings to tweak pager's function.
Definition lib.h:176
struct MuttWindow * win_pager
Pager Window.
Definition lib.h:181
Collection of related functions.
Definition menudef.h:33
short rows
Number of rows, can be MUTT_WIN_SIZE_UNLIMITED.
Definition mutt_window.h:61
@ MENU_PAGER
Pager pager (email viewer)
Definition type.h:47