NeoMutt
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
functions.c
Go to the documentation of this file.
1
29#include "config.h"
30#ifdef _MAKEDOC
31#include "docs/makedoc_defs.h"
32#else
33#include <stddef.h>
34#include <inttypes.h>
35#include <stdbool.h>
36#include <sys/stat.h>
37#include "mutt/lib.h"
38#include "config/lib.h"
39#include "email/lib.h"
40#include "core/lib.h"
41#include "gui/lib.h"
42#include "mutt.h"
43#include "lib.h"
44#include "attach/lib.h"
45#include "color/lib.h"
46#include "editor/lib.h"
47#include "history/lib.h"
48#include "index/lib.h"
49#include "key/lib.h"
50#include "menu/lib.h"
51#include "pattern/lib.h"
52#include "display.h"
53#include "functions.h"
54#include "private_data.h"
55#include "protos.h"
56#endif
57
59static const char *Not_available_in_this_menu = N_("Not available in this menu");
60
61static int op_pager_search_next(struct IndexSharedData *shared,
62 struct PagerPrivateData *priv, int op);
63
64// clang-format off
68const struct MenuFuncOp OpPager[] = { /* map: pager */
69 { "bottom", OP_PAGER_BOTTOM },
70 { "bounce-message", OP_BOUNCE_MESSAGE },
71 { "break-thread", OP_MAIN_BREAK_THREAD },
72 { "change-folder", OP_MAIN_CHANGE_FOLDER },
73 { "change-folder-readonly", OP_MAIN_CHANGE_FOLDER_READONLY },
74#ifdef USE_NNTP
75 { "change-newsgroup", OP_MAIN_CHANGE_GROUP },
76 { "change-newsgroup-readonly", OP_MAIN_CHANGE_GROUP_READONLY },
77#endif
78#ifdef USE_NOTMUCH
79 { "change-vfolder", OP_MAIN_CHANGE_VFOLDER },
80#endif
81 { "check-stats", OP_CHECK_STATS },
82 { "check-traditional-pgp", OP_CHECK_TRADITIONAL },
83 { "clear-flag", OP_MAIN_CLEAR_FLAG },
84 { "compose-to-sender", OP_COMPOSE_TO_SENDER },
85 { "copy-message", OP_COPY_MESSAGE },
86 { "create-alias", OP_CREATE_ALIAS },
87 { "decode-copy", OP_DECODE_COPY },
88 { "decode-save", OP_DECODE_SAVE },
89 { "decrypt-copy", OP_DECRYPT_COPY },
90 { "decrypt-save", OP_DECRYPT_SAVE },
91 { "delete-message", OP_DELETE },
92 { "delete-subthread", OP_DELETE_SUBTHREAD },
93 { "delete-thread", OP_DELETE_THREAD },
94 { "display-address", OP_DISPLAY_ADDRESS },
95 { "display-toggle-weed", OP_DISPLAY_HEADERS },
96 { "edit", OP_EDIT_RAW_MESSAGE },
97 { "edit-label", OP_EDIT_LABEL },
98 { "edit-or-view-raw-message", OP_EDIT_OR_VIEW_RAW_MESSAGE },
99 { "edit-raw-message", OP_EDIT_RAW_MESSAGE },
100 { "edit-type", OP_ATTACHMENT_EDIT_TYPE },
101 { "enter-command", OP_ENTER_COMMAND },
102#ifdef USE_NOTMUCH
103 { "entire-thread", OP_MAIN_ENTIRE_THREAD },
104#endif
105 { "exit", OP_EXIT },
106 { "extract-keys", OP_EXTRACT_KEYS },
107 { "flag-message", OP_FLAG_MESSAGE },
108#ifdef USE_NNTP
109 { "followup-message", OP_FOLLOWUP },
110#endif
111 { "forget-passphrase", OP_FORGET_PASSPHRASE },
112 { "forward-message", OP_FORWARD_MESSAGE },
113#ifdef USE_NNTP
114 { "forward-to-group", OP_FORWARD_TO_GROUP },
115#endif
116 { "group-chat-reply", OP_GROUP_CHAT_REPLY },
117 { "group-reply", OP_GROUP_REPLY },
118 { "half-down", OP_HALF_DOWN },
119 { "half-up", OP_HALF_UP },
120 { "help", OP_HELP },
121#ifdef USE_IMAP
122 { "imap-fetch-mail", OP_MAIN_IMAP_FETCH },
123 { "imap-logout-all", OP_MAIN_IMAP_LOGOUT_ALL },
124#endif
125 { "jump", OP_JUMP },
126 { "jump", OP_JUMP_1 },
127 { "jump", OP_JUMP_2 },
128 { "jump", OP_JUMP_3 },
129 { "jump", OP_JUMP_4 },
130 { "jump", OP_JUMP_5 },
131 { "jump", OP_JUMP_6 },
132 { "jump", OP_JUMP_7 },
133 { "jump", OP_JUMP_8 },
134 { "jump", OP_JUMP_9 },
135 { "link-threads", OP_MAIN_LINK_THREADS },
136 { "list-reply", OP_LIST_REPLY },
137 { "list-subscribe", OP_LIST_SUBSCRIBE },
138 { "list-unsubscribe", OP_LIST_UNSUBSCRIBE },
139 { "mail", OP_MAIL },
140 { "mail-key", OP_MAIL_KEY },
141 { "mailbox-list", OP_MAILBOX_LIST },
142 { "mark-as-new", OP_TOGGLE_NEW },
143 { "modify-labels", OP_MAIN_MODIFY_TAGS },
144 { "modify-labels-then-hide", OP_MAIN_MODIFY_TAGS_THEN_HIDE },
145 { "modify-tags", OP_MAIN_MODIFY_TAGS },
146 { "modify-tags-then-hide", OP_MAIN_MODIFY_TAGS_THEN_HIDE },
147 { "next-entry", OP_NEXT_ENTRY },
148 { "next-line", OP_NEXT_LINE },
149 { "next-new", OP_MAIN_NEXT_NEW },
150 { "next-new-then-unread", OP_MAIN_NEXT_NEW_THEN_UNREAD },
151 { "next-page", OP_NEXT_PAGE },
152 { "next-subthread", OP_MAIN_NEXT_SUBTHREAD },
153 { "next-thread", OP_MAIN_NEXT_THREAD },
154 { "next-undeleted", OP_MAIN_NEXT_UNDELETED },
155 { "next-unread", OP_MAIN_NEXT_UNREAD },
156 { "next-unread-mailbox", OP_MAIN_NEXT_UNREAD_MAILBOX },
157 { "parent-message", OP_MAIN_PARENT_MESSAGE },
158 { "pipe-entry", OP_PIPE },
159 { "pipe-message", OP_PIPE },
160#ifdef USE_NNTP
161 { "post-message", OP_POST },
162#endif
163 { "previous-entry", OP_PREV_ENTRY },
164 { "previous-line", OP_PREV_LINE },
165 { "previous-new", OP_MAIN_PREV_NEW },
166 { "previous-new-then-unread", OP_MAIN_PREV_NEW_THEN_UNREAD },
167 { "previous-page", OP_PREV_PAGE },
168 { "previous-subthread", OP_MAIN_PREV_SUBTHREAD },
169 { "previous-thread", OP_MAIN_PREV_THREAD },
170 { "previous-undeleted", OP_MAIN_PREV_UNDELETED },
171 { "previous-unread", OP_MAIN_PREV_UNREAD },
172 { "print-entry", OP_ATTACHMENT_PRINT },
173 { "print-message", OP_PRINT },
174 { "purge-message", OP_PURGE_MESSAGE },
175 { "purge-thread", OP_PURGE_THREAD },
176 { "quasi-delete", OP_MAIN_QUASI_DELETE },
177 { "quit", OP_QUIT },
178 { "read-subthread", OP_MAIN_READ_SUBTHREAD },
179 { "read-thread", OP_MAIN_READ_THREAD },
180 { "recall-message", OP_RECALL_MESSAGE },
181#ifdef USE_NNTP
182 { "reconstruct-thread", OP_RECONSTRUCT_THREAD },
183#endif
184 { "redraw-screen", OP_REDRAW },
185 { "reply", OP_REPLY },
186 { "resend-message", OP_RESEND },
187 { "root-message", OP_MAIN_ROOT_MESSAGE },
188 { "save-entry", OP_ATTACHMENT_SAVE },
189 { "save-message", OP_SAVE },
190 { "search", OP_SEARCH },
191 { "search-next", OP_SEARCH_NEXT },
192 { "search-opposite", OP_SEARCH_OPPOSITE },
193 { "search-reverse", OP_SEARCH_REVERSE },
194 { "search-toggle", OP_SEARCH_TOGGLE },
195 { "set-flag", OP_MAIN_SET_FLAG },
196 { "shell-escape", OP_SHELL_ESCAPE },
197 { "show-log-messages", OP_SHOW_LOG_MESSAGES },
198 { "show-version", OP_VERSION },
199#ifdef USE_SIDEBAR
200 { "sidebar-first", OP_SIDEBAR_FIRST },
201 { "sidebar-last", OP_SIDEBAR_LAST },
202 { "sidebar-next", OP_SIDEBAR_NEXT },
203 { "sidebar-next-new", OP_SIDEBAR_NEXT_NEW },
204 { "sidebar-open", OP_SIDEBAR_OPEN },
205 { "sidebar-page-down", OP_SIDEBAR_PAGE_DOWN },
206 { "sidebar-page-up", OP_SIDEBAR_PAGE_UP },
207 { "sidebar-prev", OP_SIDEBAR_PREV },
208 { "sidebar-prev-new", OP_SIDEBAR_PREV_NEW },
209 { "sidebar-toggle-virtual", OP_SIDEBAR_TOGGLE_VIRTUAL },
210 { "sidebar-toggle-visible", OP_SIDEBAR_TOGGLE_VISIBLE },
211#endif
212 { "skip-headers", OP_PAGER_SKIP_HEADERS },
213 { "skip-quoted", OP_PAGER_SKIP_QUOTED },
214 { "sort-mailbox", OP_SORT },
215 { "sort-reverse", OP_SORT_REVERSE },
216 { "sync-mailbox", OP_MAIN_SYNC_FOLDER },
217 { "tag-message", OP_TAG },
218 { "toggle-quoted", OP_PAGER_HIDE_QUOTED },
219 { "toggle-write", OP_TOGGLE_WRITE },
220 { "top", OP_PAGER_TOP },
221 { "undelete-message", OP_UNDELETE },
222 { "undelete-subthread", OP_UNDELETE_SUBTHREAD },
223 { "undelete-thread", OP_UNDELETE_THREAD },
224#ifdef USE_NOTMUCH
225 { "vfolder-from-query", OP_MAIN_VFOLDER_FROM_QUERY },
226 { "vfolder-from-query-readonly", OP_MAIN_VFOLDER_FROM_QUERY_READONLY },
227#endif
228 { "view-attachments", OP_VIEW_ATTACHMENTS },
229 { "view-raw-message", OP_VIEW_RAW_MESSAGE },
230 { "what-key", OP_WHAT_KEY },
231 // Deprecated
232 { "buffy-list", OP_MAILBOX_LIST },
233 { "error-history", OP_SHOW_LOG_MESSAGES },
234 { NULL, 0 },
235};
236
240const struct MenuOpSeq PagerDefaultBindings[] = { /* map: pager */
241 { OP_ATTACHMENT_EDIT_TYPE, "\005" }, // <Ctrl-E>
242 { OP_BOUNCE_MESSAGE, "b" },
243 { OP_CHECK_TRADITIONAL, "\033P" }, // <Alt-P>
244 { OP_COPY_MESSAGE, "C" },
245 { OP_CREATE_ALIAS, "a" },
246 { OP_DECODE_COPY, "\033C" }, // <Alt-C>
247 { OP_DECODE_SAVE, "\033s" }, // <Alt-s>
248 { OP_DELETE, "d" },
249 { OP_DELETE_SUBTHREAD, "\033d" }, // <Alt-d>
250 { OP_DELETE_THREAD, "\004" }, // <Ctrl-D>
251 { OP_DISPLAY_ADDRESS, "@" },
252 { OP_DISPLAY_HEADERS, "h" },
253 { OP_EDIT_LABEL, "Y" },
254 { OP_EDIT_OR_VIEW_RAW_MESSAGE, "e" },
255 { OP_ENTER_COMMAND, ":" },
256 { OP_EXIT, "i" },
257 { OP_EXIT, "q" },
258 { OP_EXIT, "x" },
259 { OP_EXTRACT_KEYS, "\013" }, // <Ctrl-K>
260 { OP_FLAG_MESSAGE, "F" },
261 { OP_FORGET_PASSPHRASE, "\006" }, // <Ctrl-F>
262 { OP_FORWARD_MESSAGE, "f" },
263 { OP_GROUP_REPLY, "g" },
264 { OP_HELP, "?" },
265 { OP_JUMP_1, "1" },
266 { OP_JUMP_2, "2" },
267 { OP_JUMP_3, "3" },
268 { OP_JUMP_4, "4" },
269 { OP_JUMP_5, "5" },
270 { OP_JUMP_6, "6" },
271 { OP_JUMP_7, "7" },
272 { OP_JUMP_8, "8" },
273 { OP_JUMP_9, "9" },
274 { OP_LIST_REPLY, "L" },
275 { OP_MAIL, "m" },
276 { OP_MAILBOX_LIST, "." },
277 { OP_MAIL_KEY, "\033k" }, // <Alt-k>
278 { OP_MAIN_BREAK_THREAD, "#" },
279 { OP_MAIN_CHANGE_FOLDER, "c" },
280 { OP_MAIN_CHANGE_FOLDER_READONLY, "\033c" }, // <Alt-c>
281 { OP_MAIN_CLEAR_FLAG, "W" },
282 { OP_MAIN_LINK_THREADS, "&" },
283 { OP_MAIN_NEXT_NEW_THEN_UNREAD, "\t" }, // <Tab>
284 { OP_MAIN_NEXT_SUBTHREAD, "\033n" }, // <Alt-n>
285 { OP_MAIN_NEXT_THREAD, "\016" }, // <Ctrl-N>
286 { OP_MAIN_NEXT_UNDELETED, "<down>" },
287 { OP_MAIN_NEXT_UNDELETED, "<right>" },
288 { OP_MAIN_NEXT_UNDELETED, "j" },
289 { OP_MAIN_PARENT_MESSAGE, "P" },
290 { OP_MAIN_PREV_SUBTHREAD, "\033p" }, // <Alt-p>
291 { OP_MAIN_PREV_THREAD, "\020" }, // <Ctrl-P>
292 { OP_MAIN_PREV_UNDELETED, "<left>" },
293 { OP_MAIN_PREV_UNDELETED, "<up>" },
294 { OP_MAIN_PREV_UNDELETED, "k" },
295 { OP_MAIN_READ_SUBTHREAD, "\033r" }, // <Alt-r>
296 { OP_MAIN_READ_THREAD, "\022" }, // <Ctrl-R>
297 { OP_MAIN_SET_FLAG, "w" },
298 { OP_MAIN_SYNC_FOLDER, "$" },
299 { OP_NEXT_ENTRY, "J" },
300 { OP_NEXT_LINE, "<keypadenter>" },
301 { OP_NEXT_LINE, "\n" }, // <Enter>
302 { OP_NEXT_LINE, "\r" }, // <Return>
303 { OP_NEXT_PAGE, " " }, // <Space>
304 { OP_NEXT_PAGE, "<pagedown>" },
305 { OP_PAGER_BOTTOM, "<end>" },
306 { OP_PAGER_HIDE_QUOTED, "T" },
307 { OP_PAGER_SKIP_HEADERS, "H" },
308 { OP_PAGER_SKIP_QUOTED, "S" },
309 { OP_PAGER_TOP, "<home>" },
310 { OP_PAGER_TOP, "^" },
311 { OP_PIPE, "|" },
312 { OP_PREV_ENTRY, "K" },
313 { OP_PREV_LINE, "<backspace>" },
314 { OP_PREV_PAGE, "-" },
315 { OP_PREV_PAGE, "<pageup>" },
316 { OP_PRINT, "p" },
317 { OP_QUIT, "Q" },
318 { OP_RECALL_MESSAGE, "R" },
319 { OP_REDRAW, "\014" }, // <Ctrl-L>
320 { OP_REPLY, "r" },
321 { OP_RESEND, "\033e" }, // <Alt-e>
322 { OP_SAVE, "s" },
323 { OP_SEARCH, "/" },
324 { OP_SEARCH_NEXT, "n" },
325 { OP_SEARCH_REVERSE, "\033/" }, // <Alt-/>
326 { OP_SEARCH_TOGGLE, "\\" }, // <Backslash>
327 { OP_SHELL_ESCAPE, "!" },
328 { OP_SORT, "o" },
329 { OP_SORT_REVERSE, "O" },
330 { OP_TAG, "t" },
331 { OP_TOGGLE_NEW, "N" },
332 { OP_TOGGLE_WRITE, "%" },
333 { OP_UNDELETE, "u" },
334 { OP_UNDELETE_SUBTHREAD, "\033u" }, // <Alt-u>
335 { OP_UNDELETE_THREAD, "\025" }, // <Ctrl-U>
336 { OP_VERSION, "V" },
337 { OP_VIEW_ATTACHMENTS, "v" },
338 { 0, NULL },
339};
340// clang-format on
341
350static inline bool assert_pager_mode(bool test)
351{
352 if (test)
353 return true;
354
357 return false;
358}
359
368static int up_n_lines(int nlines, struct Line *info, int cur, bool hiding)
369{
370 while ((cur > 0) && (nlines > 0))
371 {
372 cur--;
373 if (!hiding || (info[cur].cid != MT_COLOR_QUOTED))
374 nlines--;
375 }
376
377 return cur;
378}
379
387bool jump_to_bottom(struct PagerPrivateData *priv, struct PagerView *pview)
388{
389 if (!(priv->lines[priv->cur_line].offset < (priv->st.st_size - 1)))
390 {
391 return false;
392 }
393
394 int line_num = priv->cur_line;
395 /* make sure the types are defined to the end of file */
396 while (display_line(priv->fp, &priv->bytes_read, &priv->lines, line_num,
397 &priv->lines_used, &priv->lines_max,
398 priv->has_types | (pview->flags & MUTT_PAGER_NOWRAP),
399 &priv->quote_list, &priv->q_level, &priv->force_redraw,
400 &priv->search_re, priv->pview->win_pager, &priv->ansi_list) == 0)
401 {
402 line_num++;
403 }
404 priv->top_line = up_n_lines(priv->pview->win_pager->state.rows, priv->lines,
405 priv->lines_used, priv->hide_quoted);
407 return true;
408}
409
410// -----------------------------------------------------------------------------
411
415static int op_pager_bottom(struct IndexSharedData *shared,
416 struct PagerPrivateData *priv, int op)
417{
418 if (!jump_to_bottom(priv, priv->pview))
419 mutt_message(_("Bottom of message is shown"));
420
421 return FR_SUCCESS;
422}
423
427static int op_pager_half_down(struct IndexSharedData *shared,
428 struct PagerPrivateData *priv, int op)
429{
430 const bool c_pager_stop = cs_subset_bool(NeoMutt->sub, "pager_stop");
431 if (priv->lines[priv->cur_line].offset < (priv->st.st_size - 1))
432 {
433 priv->top_line = up_n_lines(priv->pview->win_pager->state.rows / 2,
434 priv->lines, priv->cur_line, priv->hide_quoted);
436 }
437 else if (c_pager_stop)
438 {
439 /* emulate "less -q" and don't go on to the next message. */
440 mutt_message(_("Bottom of message is shown"));
441 }
442 else
443 {
444 /* end of the current message, so display the next message. */
446 }
447 return FR_SUCCESS;
448}
449
453static int op_pager_half_up(struct IndexSharedData *shared,
454 struct PagerPrivateData *priv, int op)
455{
456 if (priv->top_line)
457 {
458 priv->top_line = up_n_lines(priv->pview->win_pager->state.rows / 2 +
459 (priv->pview->win_pager->state.rows % 2),
460 priv->lines, priv->top_line, priv->hide_quoted);
462 }
463 else
464 {
465 mutt_message(_("Top of message is shown"));
466 }
467 return FR_SUCCESS;
468}
469
473static int op_pager_hide_quoted(struct IndexSharedData *shared,
474 struct PagerPrivateData *priv, int op)
475{
476 if (!priv->has_types)
477 return FR_NO_ACTION;
478
479 priv->hide_quoted ^= MUTT_HIDE;
480 if (priv->hide_quoted && (priv->lines[priv->top_line].cid == MT_COLOR_QUOTED))
481 {
482 priv->top_line = up_n_lines(1, priv->lines, priv->top_line, priv->hide_quoted);
483 }
484 else
485 {
487 }
489 return FR_SUCCESS;
490}
491
495static int op_pager_next_line(struct IndexSharedData *shared,
496 struct PagerPrivateData *priv, int op)
497{
498 if (priv->lines[priv->cur_line].offset < (priv->st.st_size - 1))
499 {
500 priv->top_line++;
501 if (priv->hide_quoted)
502 {
503 while ((priv->top_line < priv->lines_used) &&
504 (priv->lines[priv->top_line].cid == MT_COLOR_QUOTED))
505 {
506 priv->top_line++;
507 }
508 }
510 }
511 else
512 {
513 mutt_message(_("Bottom of message is shown"));
514 }
515 return FR_SUCCESS;
516}
517
521static int op_pager_next_page(struct IndexSharedData *shared,
522 struct PagerPrivateData *priv, int op)
523{
524 const bool c_pager_stop = cs_subset_bool(NeoMutt->sub, "pager_stop");
525 if (priv->lines[priv->cur_line].offset < (priv->st.st_size - 1))
526 {
527 const short c_pager_context = cs_subset_number(NeoMutt->sub, "pager_context");
528 priv->top_line = up_n_lines(c_pager_context, priv->lines, priv->cur_line, priv->hide_quoted);
530 }
531 else if (c_pager_stop)
532 {
533 /* emulate "less -q" and don't go on to the next message. */
534 mutt_message(_("Bottom of message is shown"));
535 }
536 else
537 {
538 /* end of the current message, so display the next message. */
540 }
541 return FR_SUCCESS;
542}
543
547static int op_pager_prev_line(struct IndexSharedData *shared,
548 struct PagerPrivateData *priv, int op)
549{
550 if (priv->top_line)
551 {
552 priv->top_line = up_n_lines(1, priv->lines, priv->top_line, priv->hide_quoted);
554 }
555 else
556 {
557 mutt_message(_("Top of message is shown"));
558 }
559 return FR_SUCCESS;
560}
561
565static int op_pager_prev_page(struct IndexSharedData *shared,
566 struct PagerPrivateData *priv, int op)
567{
568 if (priv->top_line == 0)
569 {
570 mutt_message(_("Top of message is shown"));
571 }
572 else
573 {
574 const short c_pager_context = cs_subset_number(NeoMutt->sub, "pager_context");
575 priv->top_line = up_n_lines(priv->pview->win_pager->state.rows - c_pager_context,
576 priv->lines, priv->top_line, priv->hide_quoted);
578 }
579 return FR_SUCCESS;
580}
581
589static int op_pager_search(struct IndexSharedData *shared,
590 struct PagerPrivateData *priv, int op)
591{
592 struct PagerView *pview = priv->pview;
593
594 int rc = FR_NO_ACTION;
595 struct Buffer *buf = buf_pool_get();
596
597 buf_strcpy(buf, priv->search_str);
598 if (mw_get_field(((op == OP_SEARCH) || (op == OP_SEARCH_NEXT)) ? _("Search for: ") : _("Reverse search for: "),
600 {
601 goto done;
602 }
603
604 if (mutt_str_equal(buf_string(buf), priv->search_str))
605 {
606 if (priv->search_compiled)
607 {
608 /* do an implicit search-next */
609 if (op == OP_SEARCH)
610 op = OP_SEARCH_NEXT;
611 else
612 op = OP_SEARCH_OPPOSITE;
613
614 priv->wrapped = false;
615 op_pager_search_next(shared, priv, op);
616 }
617 }
618
619 if (buf_is_empty(buf))
620 goto done;
621
622 mutt_str_copy(priv->search_str, buf_string(buf), sizeof(priv->search_str));
623
624 /* leave search_back alone if op == OP_SEARCH_NEXT */
625 if (op == OP_SEARCH)
626 priv->search_back = false;
627 else if (op == OP_SEARCH_REVERSE)
628 priv->search_back = true;
629
630 if (priv->search_compiled)
631 {
632 regfree(&priv->search_re);
633 for (size_t i = 0; i < priv->lines_used; i++)
634 {
635 FREE(&(priv->lines[i].search));
636 priv->lines[i].search_arr_size = -1;
637 }
638 }
639
640 uint16_t rflags = mutt_mb_is_lower(priv->search_str) ? REG_ICASE : 0;
641 int err = REG_COMP(&priv->search_re, priv->search_str, REG_NEWLINE | rflags);
642 if (err != 0)
643 {
644 regerror(err, &priv->search_re, buf->data, buf->dsize);
645 mutt_error("%s", buf_string(buf));
646 for (size_t i = 0; i < priv->lines_max; i++)
647 {
648 /* cleanup */
649 FREE(&(priv->lines[i].search));
650 priv->lines[i].search_arr_size = -1;
651 }
652 priv->search_flag = 0;
653 priv->search_compiled = false;
654 }
655 else
656 {
657 priv->search_compiled = true;
658 /* update the search pointers */
659 int line_num = 0;
660 while (display_line(priv->fp, &priv->bytes_read, &priv->lines, line_num,
661 &priv->lines_used, &priv->lines_max,
662 MUTT_SEARCH | (pview->flags & MUTT_PAGER_NSKIP) |
663 (pview->flags & MUTT_PAGER_NOWRAP) | priv->has_types,
664 &priv->quote_list, &priv->q_level, &priv->force_redraw,
665 &priv->search_re, priv->pview->win_pager, &priv->ansi_list) == 0)
666 {
667 line_num++;
668 }
669
670 if (priv->search_back)
671 {
672 /* searching backward */
673 int i;
674 for (i = priv->top_line; i >= 0; i--)
675 {
676 if ((!priv->hide_quoted || (priv->lines[i].cid != MT_COLOR_QUOTED)) &&
677 !priv->lines[i].cont_line && (priv->lines[i].search_arr_size > 0))
678 {
679 break;
680 }
681 }
682
683 if (i >= 0)
684 priv->top_line = i;
685 }
686 else
687 {
688 /* searching forward */
689 int i;
690 for (i = priv->top_line; i < priv->lines_used; i++)
691 {
692 if ((!priv->hide_quoted || (priv->lines[i].cid != MT_COLOR_QUOTED)) &&
693 !priv->lines[i].cont_line && (priv->lines[i].search_arr_size > 0))
694 {
695 break;
696 }
697 }
698
699 if (i < priv->lines_used)
700 priv->top_line = i;
701 }
702
703 if (priv->lines[priv->top_line].search_arr_size == 0)
704 {
705 priv->search_flag = 0;
706 mutt_error(_("Not found"));
707 }
708 else
709 {
710 const short c_search_context = cs_subset_number(NeoMutt->sub, "search_context");
711 priv->search_flag = MUTT_SEARCH;
712 /* give some context for search results */
713 if (c_search_context < priv->pview->win_pager->state.rows)
714 priv->searchctx = c_search_context;
715 else
716 priv->searchctx = 0;
717 if (priv->top_line - priv->searchctx > 0)
718 priv->top_line -= priv->searchctx;
719 }
720 }
723 rc = FR_SUCCESS;
724
725done:
726 buf_pool_release(&buf);
727 return rc;
728}
729
737static int op_pager_search_next(struct IndexSharedData *shared,
738 struct PagerPrivateData *priv, int op)
739{
740 if (priv->search_compiled)
741 {
742 const short c_search_context = cs_subset_number(NeoMutt->sub, "search_context");
743 priv->wrapped = false;
744
745 if (c_search_context < priv->pview->win_pager->state.rows)
746 priv->searchctx = c_search_context;
747 else
748 priv->searchctx = 0;
749
750 search_next:
751 if ((!priv->search_back && (op == OP_SEARCH_NEXT)) ||
752 (priv->search_back && (op == OP_SEARCH_OPPOSITE)))
753 {
754 /* searching forward */
755 int i;
756 for (i = priv->wrapped ? 0 : priv->top_line + priv->searchctx + 1;
757 i < priv->lines_used; i++)
758 {
759 if ((!priv->hide_quoted || (priv->lines[i].cid != MT_COLOR_QUOTED)) &&
760 !priv->lines[i].cont_line && (priv->lines[i].search_arr_size > 0))
761 {
762 break;
763 }
764 }
765
766 const bool c_wrap_search = cs_subset_bool(NeoMutt->sub, "wrap_search");
767 if (i < priv->lines_used)
768 {
769 priv->top_line = i;
770 }
771 else if (priv->wrapped || !c_wrap_search)
772 {
773 mutt_error(_("Not found"));
774 }
775 else
776 {
777 mutt_message(_("Search wrapped to top"));
778 priv->wrapped = true;
779 goto search_next;
780 }
781 }
782 else
783 {
784 /* searching backward */
785 int i;
786 for (i = priv->wrapped ? priv->lines_used : priv->top_line + priv->searchctx - 1;
787 i >= 0; i--)
788 {
789 if ((!priv->hide_quoted || (priv->has_types && (priv->lines[i].cid != MT_COLOR_QUOTED))) &&
790 !priv->lines[i].cont_line && (priv->lines[i].search_arr_size > 0))
791 {
792 break;
793 }
794 }
795
796 const bool c_wrap_search = cs_subset_bool(NeoMutt->sub, "wrap_search");
797 if (i >= 0)
798 {
799 priv->top_line = i;
800 }
801 else if (priv->wrapped || !c_wrap_search)
802 {
803 mutt_error(_("Not found"));
804 }
805 else
806 {
807 mutt_message(_("Search wrapped to bottom"));
808 priv->wrapped = true;
809 goto search_next;
810 }
811 }
812
813 if (priv->lines[priv->top_line].search_arr_size > 0)
814 {
815 priv->search_flag = MUTT_SEARCH;
816 /* give some context for search results */
817 if (priv->top_line - priv->searchctx > 0)
818 priv->top_line -= priv->searchctx;
819 }
820
822 return FR_SUCCESS;
823 }
824
825 /* no previous search pattern */
826 return op_pager_search(shared, priv, op);
827}
828
832static int op_pager_skip_headers(struct IndexSharedData *shared,
833 struct PagerPrivateData *priv, int op)
834{
835 struct PagerView *pview = priv->pview;
836
837 if (!priv->has_types)
838 return FR_NO_ACTION;
839
840 int rc = 0;
841 int new_topline = 0;
842
843 while (((new_topline < priv->lines_used) ||
844 (0 == (rc = display_line(priv->fp, &priv->bytes_read, &priv->lines,
845 new_topline, &priv->lines_used, &priv->lines_max,
846 MUTT_TYPES | (pview->flags & MUTT_PAGER_NOWRAP), &priv->quote_list,
847 &priv->q_level, &priv->force_redraw, &priv->search_re,
848 priv->pview->win_pager, &priv->ansi_list)))) &&
849 simple_color_is_header(priv->lines[new_topline].cid))
850 {
851 new_topline++;
852 }
853
854 if (rc < 0)
855 {
856 /* L10N: Displayed if <skip-headers> is invoked in the pager, but
857 there is no text past the headers.
858 (I don't think this is actually possible in Mutt's code, but
859 display some kind of message in case it somehow occurs.) */
860 mutt_warning(_("No text past headers"));
861 return FR_NO_ACTION;
862 }
863 priv->top_line = new_topline;
865 return FR_SUCCESS;
866}
867
871static int op_pager_skip_quoted(struct IndexSharedData *shared,
872 struct PagerPrivateData *priv, int op)
873{
874 struct PagerView *pview = priv->pview;
875
876 if (!priv->has_types)
877 return FR_NO_ACTION;
878
879 const short c_pager_skip_quoted_context = cs_subset_number(NeoMutt->sub, "pager_skip_quoted_context");
880 int rc = 0;
881 int new_topline = priv->top_line;
882 int num_quoted = 0;
883
884 /* In a header? Skip all the email headers, and done */
885 if (simple_color_is_header(priv->lines[new_topline].cid))
886 {
887 while (((new_topline < priv->lines_used) ||
888 (0 == (rc = display_line(priv->fp, &priv->bytes_read, &priv->lines,
889 new_topline, &priv->lines_used, &priv->lines_max,
890 MUTT_TYPES | (pview->flags & MUTT_PAGER_NOWRAP), &priv->quote_list,
891 &priv->q_level, &priv->force_redraw, &priv->search_re,
892 priv->pview->win_pager, &priv->ansi_list)))) &&
893 simple_color_is_header(priv->lines[new_topline].cid))
894 {
895 new_topline++;
896 }
897 priv->top_line = new_topline;
899 return FR_SUCCESS;
900 }
901
902 /* Already in the body? Skip past previous "context" quoted lines */
903 if (c_pager_skip_quoted_context > 0)
904 {
905 while (((new_topline < priv->lines_used) ||
906 (0 == (rc = display_line(priv->fp, &priv->bytes_read, &priv->lines,
907 new_topline, &priv->lines_used, &priv->lines_max,
908 MUTT_TYPES | (pview->flags & MUTT_PAGER_NOWRAP), &priv->quote_list,
909 &priv->q_level, &priv->force_redraw, &priv->search_re,
910 priv->pview->win_pager, &priv->ansi_list)))) &&
911 (priv->lines[new_topline].cid == MT_COLOR_QUOTED))
912 {
913 new_topline++;
914 num_quoted++;
915 }
916
917 if (rc < 0)
918 {
919 mutt_error(_("No more unquoted text after quoted text"));
920 return FR_NO_ACTION;
921 }
922 }
923
924 if (num_quoted <= c_pager_skip_quoted_context)
925 {
926 num_quoted = 0;
927
928 while (((new_topline < priv->lines_used) ||
929 (0 == (rc = display_line(priv->fp, &priv->bytes_read, &priv->lines,
930 new_topline, &priv->lines_used, &priv->lines_max,
931 MUTT_TYPES | (pview->flags & MUTT_PAGER_NOWRAP), &priv->quote_list,
932 &priv->q_level, &priv->force_redraw, &priv->search_re,
933 priv->pview->win_pager, &priv->ansi_list)))) &&
934 (priv->lines[new_topline].cid != MT_COLOR_QUOTED))
935 {
936 new_topline++;
937 }
938
939 if (rc < 0)
940 {
941 mutt_error(_("No more quoted text"));
942 return FR_NO_ACTION;
943 }
944
945 while (((new_topline < priv->lines_used) ||
946 (0 == (rc = display_line(priv->fp, &priv->bytes_read, &priv->lines,
947 new_topline, &priv->lines_used, &priv->lines_max,
948 MUTT_TYPES | (pview->flags & MUTT_PAGER_NOWRAP), &priv->quote_list,
949 &priv->q_level, &priv->force_redraw, &priv->search_re,
950 priv->pview->win_pager, &priv->ansi_list)))) &&
951 (priv->lines[new_topline].cid == MT_COLOR_QUOTED))
952 {
953 new_topline++;
954 num_quoted++;
955 }
956
957 if (rc < 0)
958 {
959 mutt_error(_("No more unquoted text after quoted text"));
960 return FR_NO_ACTION;
961 }
962 }
963 priv->top_line = new_topline - MIN(c_pager_skip_quoted_context, num_quoted);
965 return FR_SUCCESS;
966}
967
971static int op_pager_top(struct IndexSharedData *shared, struct PagerPrivateData *priv, int op)
972{
973 if (priv->top_line)
974 priv->top_line = 0;
975 else
976 mutt_message(_("Top of message is shown"));
977 return FR_SUCCESS;
978}
979
980// -----------------------------------------------------------------------------
981
985static int op_exit(struct IndexSharedData *shared, struct PagerPrivateData *priv, int op)
986{
987 priv->rc = -1;
988 priv->loop = PAGER_LOOP_QUIT;
989 return FR_DONE;
990}
991
995static int op_help(struct IndexSharedData *shared, struct PagerPrivateData *priv, int op)
996{
997 if (priv->pview->mode == PAGER_MODE_HELP)
998 {
999 /* don't let the user enter the help-menu from the help screen! */
1000 mutt_error(_("Help is currently being shown"));
1001 return FR_ERROR;
1002 }
1005 return FR_SUCCESS;
1006}
1007
1011static int op_search_toggle(struct IndexSharedData *shared,
1012 struct PagerPrivateData *priv, int op)
1013{
1014 if (priv->search_compiled)
1015 {
1016 priv->search_flag ^= MUTT_SEARCH;
1018 }
1019 return FR_SUCCESS;
1020}
1021
1025static int op_view_attachments(struct IndexSharedData *shared,
1026 struct PagerPrivateData *priv, int op)
1027{
1028 struct PagerView *pview = priv->pview;
1029
1030 // This needs to be delegated
1031 if (pview->flags & MUTT_PAGER_ATTACHMENT)
1032 return FR_UNKNOWN;
1033
1034 if (!assert_pager_mode(pview->mode == PAGER_MODE_EMAIL))
1035 return FR_NOT_IMPL;
1036 dlg_attachment(NeoMutt->sub, shared->mailbox_view, shared->email,
1037 pview->pdata->fp, shared->attach_msg);
1038 if (shared->email->attach_del)
1039 shared->mailbox->changed = true;
1041 return FR_SUCCESS;
1042}
1043
1044// -----------------------------------------------------------------------------
1045
1049static const struct PagerFunction PagerFunctions[] = {
1050 // clang-format off
1051 { OP_EXIT, op_exit },
1052 { OP_HALF_DOWN, op_pager_half_down },
1053 { OP_HALF_UP, op_pager_half_up },
1054 { OP_HELP, op_help },
1055 { OP_NEXT_LINE, op_pager_next_line },
1056 { OP_NEXT_PAGE, op_pager_next_page },
1057 { OP_PAGER_BOTTOM, op_pager_bottom },
1058 { OP_PAGER_HIDE_QUOTED, op_pager_hide_quoted },
1059 { OP_PAGER_SKIP_HEADERS, op_pager_skip_headers },
1060 { OP_PAGER_SKIP_QUOTED, op_pager_skip_quoted },
1061 { OP_PAGER_TOP, op_pager_top },
1062 { OP_PREV_LINE, op_pager_prev_line },
1063 { OP_PREV_PAGE, op_pager_prev_page },
1064 { OP_SEARCH, op_pager_search },
1065 { OP_SEARCH_REVERSE, op_pager_search },
1066 { OP_SEARCH_NEXT, op_pager_search_next },
1067 { OP_SEARCH_OPPOSITE, op_pager_search_next },
1068 { OP_SEARCH_TOGGLE, op_search_toggle },
1069 { OP_VIEW_ATTACHMENTS, op_view_attachments },
1070 { 0, NULL },
1071 // clang-format on
1072};
1073
1078{
1079 if (!win)
1080 {
1082 return FR_ERROR;
1083 }
1084
1085 struct PagerPrivateData *priv = win->parent->wdata;
1086 if (!priv)
1087 return FR_ERROR;
1088
1089 struct MuttWindow *dlg = dialog_find(win);
1090 if (!dlg || !dlg->wdata)
1091 return FR_ERROR;
1092
1093 int rc = FR_UNKNOWN;
1094 for (size_t i = 0; PagerFunctions[i].op != OP_NULL; i++)
1095 {
1096 const struct PagerFunction *fn = &PagerFunctions[i];
1097 if (fn->op == op)
1098 {
1099 struct IndexSharedData *shared = dlg->wdata;
1100 rc = fn->function(shared, priv, op);
1101 break;
1102 }
1103 }
1104
1105 if (rc == FR_UNKNOWN) // Not our function
1106 return rc;
1107
1108 const char *result = dispatcher_get_retval_name(rc);
1109 mutt_debug(LL_DEBUG1, "Handled %s (%d) -> %s\n", opcodes_get_name(op), op, NONULL(result));
1110
1111 return rc;
1112}
static const char * Not_available_in_this_menu
Error message for unavailable functions.
Definition: functions.c:55
GUI display the mailboxes in a side panel.
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:303
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:407
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:93
Color and attribute parsing.
bool simple_color_is_header(enum ColorId cid)
Colour is for an Email header.
Definition: simple.c:112
@ MT_COLOR_QUOTED
Pager: quoted text.
Definition: color.h:61
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:144
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:48
Convenience wrapper for the config headers.
Convenience wrapper for the core headers.
void mutt_flushinp(void)
Empty all the keyboard buffers.
Definition: get.c:57
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:54
@ FR_SUCCESS
Valid function - successfully performed.
Definition: dispatcher.h:39
@ FR_DONE
Exit the Dialog.
Definition: dispatcher.h:35
@ FR_UNKNOWN
Unknown function.
Definition: dispatcher.h:33
@ FR_ERROR
Valid function - error occurred.
Definition: dispatcher.h:38
@ FR_NOT_IMPL
Invalid function - feature not enabled.
Definition: dispatcher.h:36
@ FR_NO_ACTION
Valid function - no action performed.
Definition: dispatcher.h:37
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:1013
Pager Display.
void pager_queue_redraw(struct PagerPrivateData *priv, PagerRedrawFlags redraw)
Queue a request for a redraw.
Definition: dlg_pager.c:131
Enter a string.
Structs that make up an email.
static int op_exit(struct AliasMenuData *mdata, int op)
exit this menu - Implements alias_function_t -
Definition: functions.c:190
int pager_function_dispatcher(struct MuttWindow *win, int op)
Perform a Pager function - Implements function_dispatcher_t -.
Definition: functions.c:1077
static int op_help(struct EnterWindowData *wdata, int op)
Display Help - Implements enter_function_t -.
Definition: functions.c:424
void dlg_attachment(struct ConfigSubset *sub, struct MailboxView *mv, struct Email *e, FILE *fp, bool attach_msg)
Show the attachments in a Menu -.
Definition: dlg_attach.c:471
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:275
static int op_view_attachments(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Show MIME attachments - Implements index_function_t -.
Definition: functions.c:2512
#define mutt_warning(...)
Definition: logging2.h:90
#define mutt_error(...)
Definition: logging2.h:92
#define mutt_message(...)
Definition: logging2.h:91
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
static int op_pager_skip_quoted(struct IndexSharedData *shared, struct PagerPrivateData *priv, int op)
Skip beyond quoted text - Implements pager_function_t -.
Definition: functions.c:871
static int op_pager_skip_headers(struct IndexSharedData *shared, struct PagerPrivateData *priv, int op)
Jump to first line after headers - Implements pager_function_t -.
Definition: functions.c:832
static int op_pager_half_up(struct IndexSharedData *shared, struct PagerPrivateData *priv, int op)
Scroll up 1/2 page - Implements pager_function_t -.
Definition: functions.c:453
static int op_pager_next_line(struct IndexSharedData *shared, struct PagerPrivateData *priv, int op)
Scroll down one line - Implements pager_function_t -.
Definition: functions.c:495
static int op_search_toggle(struct IndexSharedData *shared, struct PagerPrivateData *priv, int op)
Toggle search pattern coloring - Implements pager_function_t -.
Definition: functions.c:1011
static int op_pager_top(struct IndexSharedData *shared, struct PagerPrivateData *priv, int op)
Jump to the top of the message - Implements pager_function_t -.
Definition: functions.c:971
static int op_pager_hide_quoted(struct IndexSharedData *shared, struct PagerPrivateData *priv, int op)
Toggle display of quoted text - Implements pager_function_t -.
Definition: functions.c:473
static int op_pager_next_page(struct IndexSharedData *shared, struct PagerPrivateData *priv, int op)
Move to the next page - Implements pager_function_t -.
Definition: functions.c:521
static int op_pager_prev_page(struct IndexSharedData *shared, struct PagerPrivateData *priv, int op)
Move to the previous page - Implements pager_function_t -.
Definition: functions.c:565
static int op_pager_bottom(struct IndexSharedData *shared, struct PagerPrivateData *priv, int op)
Jump to the bottom of the message - Implements pager_function_t -.
Definition: functions.c:415
static int op_pager_half_down(struct IndexSharedData *shared, struct PagerPrivateData *priv, int op)
Scroll down 1/2 page - Implements pager_function_t -.
Definition: functions.c:427
static int op_pager_search(struct IndexSharedData *shared, struct PagerPrivateData *priv, int op)
Search for a regular expression - Implements pager_function_t -.
Definition: functions.c:589
static int op_pager_search_next(struct IndexSharedData *shared, struct PagerPrivateData *priv, int op)
Search for next match - Implements pager_function_t -.
Definition: functions.c:737
static int op_pager_prev_line(struct IndexSharedData *shared, struct PagerPrivateData *priv, int op)
Scroll up one line - Implements pager_function_t -.
Definition: functions.c:547
Convenience wrapper for the gui headers.
void mutt_help(enum MenuType menu)
Display the help menu.
Definition: help.c:462
Read/write command history from/to a file.
@ HC_PATTERN
Patterns.
Definition: lib.h:53
bool index_next_undeleted(struct MuttWindow *win_index)
Select the next undeleted Email (if possible)
Definition: functions.c:421
GUI manage the main index (list of emails)
Manage keymappings.
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43
bool mutt_mb_is_lower(const char *s)
Does a multi-byte string contain only lowercase characters?
Definition: mbyte.c:353
#define FREE(x)
Definition: memory.h:45
#define MIN(a, b)
Definition: memory.h:32
GUI present the user with a selectable list.
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:798
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:653
Many unsorted constants and some structs.
#define MUTT_COMP_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:56
@ NT_PAGER
Pager data has changed, NotifyPager, PagerPrivateData.
Definition: notify_type.h:53
const char * opcodes_get_name(int op)
Get the name of an opcode.
Definition: opcodes.c:48
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:368
const struct MenuOpSeq PagerDefaultBindings[]
Key bindings for the Pager Menu.
Definition: functions.c:240
const struct MenuFuncOp OpPager[]
Functions for the Pager Menu.
Definition: functions.c:68
bool jump_to_bottom(struct PagerPrivateData *priv, struct PagerView *pview)
Make sure the bottom line is displayed.
Definition: functions.c:387
static bool assert_pager_mode(bool test)
Check that pager is in correct mode.
Definition: functions.c:350
static const struct PagerFunction PagerFunctions[]
All the NeoMutt functions that the Pager supports.
Definition: functions.c:1049
@ PAGER_LOOP_QUIT
Quit the Pager.
Definition: lib.h:152
#define NT_PAGER_VIEW
Pager View has changed.
Definition: lib.h:186
#define MUTT_PAGER_NSKIP
Preserve whitespace with smartwrap.
Definition: lib.h:68
#define MUTT_PAGER_NOWRAP
Format for term width, ignore $wrap.
Definition: lib.h:72
#define MUTT_HIDE
Don't show quoted text.
Definition: lib.h:62
#define MUTT_TYPES
Compute line's type.
Definition: lib.h:64
#define MUTT_SEARCH
Resolve search patterns.
Definition: lib.h:63
@ PAGER_MODE_HELP
Pager is invoked via 3rd path to show help.
Definition: lib.h:140
@ PAGER_MODE_EMAIL
Pager is invoked via 1st path. The mime part is selected automatically.
Definition: lib.h:137
#define PAGER_REDRAW_PAGER
Redraw the pager.
Definition: lib.h:190
#define MUTT_PAGER_ATTACHMENT
Attachments may exist.
Definition: lib.h:71
Private state data for the Pager.
const struct CompleteOps CompletePatternOps
Auto-Completion of Patterns.
Definition: complete.c:82
Match patterns to emails.
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
Prototypes for many functions.
#define REG_COMP(preg, regex, cflags)
Compile a regular expression.
Definition: regex3.h:53
Sidebar functions.
Key value store.
#define NONULL(x)
Definition: string2.h:37
String manipulation buffer.
Definition: buffer.h:34
size_t dsize
Length of data.
Definition: buffer.h:37
char * data
Pointer to data.
Definition: buffer.h:35
bool attach_del
Has an attachment marked for deletion.
Definition: email.h:98
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
A line of text in the pager.
Definition: display.h:51
short search_arr_size
Number of items in search array.
Definition: display.h:60
struct TextSyntax * search
Array of search text in the line.
Definition: display.h:61
bool cont_line
Continuation of a previous line (wrapped by NeoMutt)
Definition: display.h:54
short cid
Default line colour, e.g. MT_COLOR_QUOTED.
Definition: display.h:53
LOFF_T offset
Offset into Email file (PagerPrivateData->fp)
Definition: display.h:52
bool changed
Mailbox has been modified.
Definition: mailbox.h:109
Mapping between a function and an operation.
Definition: lib.h:102
Mapping between an operation and a key sequence.
Definition: lib.h:111
int op
Operation, e.g. OP_DELETE.
Definition: lib.h:112
struct WindowState state
Current state of the Window.
Definition: mutt_window.h:127
void * wdata
Private data.
Definition: mutt_window.h:145
struct MuttWindow * parent
Parent Window.
Definition: mutt_window.h:135
Container for Accounts, Notifications.
Definition: neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:45
FILE * fp
Source stream.
Definition: lib.h:162
A NeoMutt function.
Definition: functions.h:50
pager_function_t function
Function to call.
Definition: functions.h:52
int op
Op code, e.g. OP_MAIN_LIMIT.
Definition: functions.h:51
Private state data for the Pager.
Definition: private_data.h:41
PagerFlags hide_quoted
Set to MUTT_HIDE when quoted email is hidden <toggle-quoted>
Definition: private_data.h:60
int rc
Return code from functions.
Definition: private_data.h:73
int q_level
Number of unique quoting levels.
Definition: private_data.h:59
int cur_line
Current line (last line visible on screen)
Definition: private_data.h:51
bool wrapped
Has the search/next wrapped around?
Definition: private_data.h:76
int lines_used
Size of lines array (used entries)
Definition: private_data.h:49
char search_str[256]
Current search string.
Definition: private_data.h:63
int lines_max
Capacity of lines array (total entries)
Definition: private_data.h:50
bool force_redraw
Repaint is needed.
Definition: private_data.h:68
enum PagerLoopMode loop
What the Event Loop should do next, e.g. PAGER_LOOP_CONTINUE.
Definition: private_data.h:79
struct Line * lines
Array of text lines in pager.
Definition: private_data.h:48
int has_types
Set to MUTT_TYPES for PAGER_MODE_EMAIL or MUTT_SHOWCOLOR.
Definition: private_data.h:56
struct Notify * notify
Notifications: NotifyPager, PagerPrivateData.
Definition: private_data.h:71
LOFF_T bytes_read
Number of bytes read from file.
Definition: private_data.h:46
int top_line
First visible line on screen.
Definition: private_data.h:55
struct stat st
Stats about Email file.
Definition: private_data.h:45
bool search_back
Search backwards.
Definition: private_data.h:66
struct QuoteStyle * quote_list
Tree of quoting levels.
Definition: private_data.h:58
struct PagerView * pview
Object to view in the pager.
Definition: private_data.h:42
struct AttrColorList ansi_list
List of ANSI colours used in the Pager.
Definition: private_data.h:70
int searchctx
Space to show around search matches.
Definition: private_data.h:74
regex_t search_re
Compiled search string.
Definition: private_data.h:65
FILE * fp
File containing decrypted/decoded/weeded Email.
Definition: private_data.h:44
PagerFlags search_flag
Set to MUTT_SEARCH when search results are visible <search-toggle>
Definition: private_data.h:62
bool search_compiled
Search regex is in use.
Definition: private_data.h:64
Paged view into some data.
Definition: lib.h:171
struct MuttWindow * win_index
Index Window.
Definition: lib.h:177
struct PagerData * pdata
Data that pager displays. NOTNULL.
Definition: lib.h:172
enum PagerMode mode
Pager mode.
Definition: lib.h:173
PagerFlags flags
Additional settings to tweak pager's function.
Definition: lib.h:174
struct MuttWindow * win_pager
Pager Window.
Definition: lib.h:179
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:55