NeoMutt  2024-11-14-34-g5aaf0d
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
functions.c
Go to the documentation of this file.
1
31#include "config.h"
32#ifdef _MAKEDOC
33#include "docs/makedoc_defs.h"
34#else
35#include <limits.h>
36#include <stdbool.h>
37#include <stdio.h>
38#include "mutt/lib.h"
39#include "config/lib.h"
40#include "email/lib.h"
41#include "core/lib.h"
42#include "alias/lib.h"
43#include "gui/lib.h"
44#include "mutt.h"
45#include "lib.h"
46#include "attach/lib.h"
47#include "browser/lib.h"
48#include "editor/lib.h"
49#include "history/lib.h"
50#include "imap/lib.h"
51#include "key/lib.h"
52#include "menu/lib.h"
53#include "ncrypt/lib.h"
54#include "nntp/lib.h"
55#include "pager/lib.h"
56#include "pattern/lib.h"
57#include "pop/lib.h"
58#include "progress/lib.h"
59#include "question/lib.h"
60#include "send/lib.h"
61#include "external.h"
62#include "functions.h"
63#include "globals.h"
64#include "hook.h"
65#include "mutt_header.h"
66#include "mutt_mailbox.h"
67#include "mutt_thread.h"
68#include "muttlib.h"
69#include "mview.h"
70#include "mx.h"
71#include "nntp/mdata.h"
72#include "private_data.h"
73#include "protos.h"
74#include "shared_data.h"
75#include "sort.h"
76#ifdef USE_AUTOCRYPT
77#include "autocrypt/lib.h"
78#endif
79#ifdef USE_NOTMUCH
80#include "notmuch/lib.h"
81#endif
82#ifdef ENABLE_NLS
83#include <libintl.h>
84#endif
85#endif
86
87// clang-format off
91const struct MenuFuncOp OpIndex[] = { /* map: index */
92 { "alias-dialog", OP_ALIAS_DIALOG },
93#ifdef USE_AUTOCRYPT
94 { "autocrypt-acct-menu", OP_AUTOCRYPT_ACCT_MENU },
95#endif
96 { "bounce-message", OP_BOUNCE_MESSAGE },
97 { "break-thread", OP_MAIN_BREAK_THREAD },
98 { "catchup", OP_CATCHUP },
99 { "change-folder", OP_MAIN_CHANGE_FOLDER },
100 { "change-folder-readonly", OP_MAIN_CHANGE_FOLDER_READONLY },
101 { "change-newsgroup", OP_MAIN_CHANGE_GROUP },
102 { "change-newsgroup-readonly", OP_MAIN_CHANGE_GROUP_READONLY },
103#ifdef USE_NOTMUCH
104 { "change-vfolder", OP_MAIN_CHANGE_VFOLDER },
105#endif
106 { "check-traditional-pgp", OP_CHECK_TRADITIONAL },
107 { "clear-flag", OP_MAIN_CLEAR_FLAG },
108 { "collapse-all", OP_MAIN_COLLAPSE_ALL },
109 { "collapse-thread", OP_MAIN_COLLAPSE_THREAD },
110 { "compose-to-sender", OP_COMPOSE_TO_SENDER },
111 { "copy-message", OP_COPY_MESSAGE },
112 { "create-alias", OP_CREATE_ALIAS },
113 { "decode-copy", OP_DECODE_COPY },
114 { "decode-save", OP_DECODE_SAVE },
115 { "decrypt-copy", OP_DECRYPT_COPY },
116 { "decrypt-save", OP_DECRYPT_SAVE },
117 { "delete-message", OP_DELETE },
118 { "delete-pattern", OP_MAIN_DELETE_PATTERN },
119 { "delete-subthread", OP_DELETE_SUBTHREAD },
120 { "delete-thread", OP_DELETE_THREAD },
121 { "display-address", OP_DISPLAY_ADDRESS },
122 { "display-message", OP_DISPLAY_MESSAGE },
123 { "display-toggle-weed", OP_DISPLAY_HEADERS },
124 { "edit", OP_EDIT_RAW_MESSAGE },
125 { "edit-label", OP_EDIT_LABEL },
126 { "edit-or-view-raw-message", OP_EDIT_OR_VIEW_RAW_MESSAGE },
127 { "edit-raw-message", OP_EDIT_RAW_MESSAGE },
128 { "edit-type", OP_ATTACHMENT_EDIT_TYPE },
129#ifdef USE_NOTMUCH
130 { "entire-thread", OP_MAIN_ENTIRE_THREAD },
131#endif
132 { "exit", OP_EXIT },
133 { "extract-keys", OP_EXTRACT_KEYS },
134 { "fetch-mail", OP_MAIN_FETCH_MAIL },
135 { "flag-message", OP_FLAG_MESSAGE },
136 { "followup-message", OP_FOLLOWUP },
137 { "forget-passphrase", OP_FORGET_PASSPHRASE },
138 { "forward-message", OP_FORWARD_MESSAGE },
139 { "forward-to-group", OP_FORWARD_TO_GROUP },
140 { "get-children", OP_GET_CHILDREN },
141 { "get-message", OP_GET_MESSAGE },
142 { "get-parent", OP_GET_PARENT },
143 { "group-chat-reply", OP_GROUP_CHAT_REPLY },
144 { "group-reply", OP_GROUP_REPLY },
145 { "imap-fetch-mail", OP_MAIN_IMAP_FETCH },
146 { "imap-logout-all", OP_MAIN_IMAP_LOGOUT_ALL },
147 { "limit", OP_MAIN_LIMIT },
148 { "limit-current-thread", OP_LIMIT_CURRENT_THREAD },
149 { "link-threads", OP_MAIN_LINK_THREADS },
150 { "list-reply", OP_LIST_REPLY },
151 { "list-subscribe", OP_LIST_SUBSCRIBE },
152 { "list-unsubscribe", OP_LIST_UNSUBSCRIBE },
153 { "mail", OP_MAIL },
154 { "mail-key", OP_MAIL_KEY },
155 { "mailbox-list", OP_MAILBOX_LIST },
156 { "mark-message", OP_MARK_MSG },
157 { "modify-labels", OP_MAIN_MODIFY_TAGS },
158 { "modify-labels-then-hide", OP_MAIN_MODIFY_TAGS_THEN_HIDE },
159 { "modify-tags", OP_MAIN_MODIFY_TAGS },
160 { "modify-tags-then-hide", OP_MAIN_MODIFY_TAGS_THEN_HIDE },
161 { "next-new", OP_MAIN_NEXT_NEW },
162 { "next-new-then-unread", OP_MAIN_NEXT_NEW_THEN_UNREAD },
163 { "next-subthread", OP_MAIN_NEXT_SUBTHREAD },
164 { "next-thread", OP_MAIN_NEXT_THREAD },
165 { "next-undeleted", OP_MAIN_NEXT_UNDELETED },
166 { "next-unread", OP_MAIN_NEXT_UNREAD },
167 { "next-unread-mailbox", OP_MAIN_NEXT_UNREAD_MAILBOX },
168 { "parent-message", OP_MAIN_PARENT_MESSAGE },
169 { "pipe-entry", OP_PIPE },
170 { "pipe-message", OP_PIPE },
171 { "post-message", OP_POST },
172 { "previous-new", OP_MAIN_PREV_NEW },
173 { "previous-new-then-unread", OP_MAIN_PREV_NEW_THEN_UNREAD },
174 { "previous-subthread", OP_MAIN_PREV_SUBTHREAD },
175 { "previous-thread", OP_MAIN_PREV_THREAD },
176 { "previous-undeleted", OP_MAIN_PREV_UNDELETED },
177 { "previous-unread", OP_MAIN_PREV_UNREAD },
178 { "print-message", OP_PRINT },
179 { "purge-message", OP_PURGE_MESSAGE },
180 { "purge-thread", OP_PURGE_THREAD },
181 { "quasi-delete", OP_MAIN_QUASI_DELETE },
182 { "query", OP_QUERY },
183 { "quit", OP_QUIT },
184 { "read-subthread", OP_MAIN_READ_SUBTHREAD },
185 { "read-thread", OP_MAIN_READ_THREAD },
186 { "recall-message", OP_RECALL_MESSAGE },
187 { "reconstruct-thread", OP_RECONSTRUCT_THREAD },
188 { "reply", OP_REPLY },
189 { "resend-message", OP_RESEND },
190 { "root-message", OP_MAIN_ROOT_MESSAGE },
191 { "save-message", OP_SAVE },
192 { "set-flag", OP_MAIN_SET_FLAG },
193 { "show-limit", OP_MAIN_SHOW_LIMIT },
194 { "sidebar-first", OP_SIDEBAR_FIRST },
195 { "sidebar-last", OP_SIDEBAR_LAST },
196 { "sidebar-next", OP_SIDEBAR_NEXT },
197 { "sidebar-next-new", OP_SIDEBAR_NEXT_NEW },
198 { "sidebar-open", OP_SIDEBAR_OPEN },
199 { "sidebar-page-down", OP_SIDEBAR_PAGE_DOWN },
200 { "sidebar-page-up", OP_SIDEBAR_PAGE_UP },
201 { "sidebar-prev", OP_SIDEBAR_PREV },
202 { "sidebar-prev-new", OP_SIDEBAR_PREV_NEW },
203 { "sidebar-toggle-virtual", OP_SIDEBAR_TOGGLE_VIRTUAL },
204 { "sidebar-toggle-visible", OP_SIDEBAR_TOGGLE_VISIBLE },
205 { "sort-mailbox", OP_SORT },
206 { "sort-reverse", OP_SORT_REVERSE },
207 { "sync-mailbox", OP_MAIN_SYNC_FOLDER },
208 { "tag-pattern", OP_MAIN_TAG_PATTERN },
209 { "tag-subthread", OP_TAG_SUBTHREAD },
210 { "tag-thread", OP_TAG_THREAD },
211 { "toggle-new", OP_TOGGLE_NEW },
212 { "toggle-read", OP_TOGGLE_READ },
213 { "toggle-write", OP_TOGGLE_WRITE },
214 { "undelete-message", OP_UNDELETE },
215 { "undelete-pattern", OP_MAIN_UNDELETE_PATTERN },
216 { "undelete-subthread", OP_UNDELETE_SUBTHREAD },
217 { "undelete-thread", OP_UNDELETE_THREAD },
218 { "untag-pattern", OP_MAIN_UNTAG_PATTERN },
219#ifdef USE_NOTMUCH
220 { "vfolder-from-query", OP_MAIN_VFOLDER_FROM_QUERY },
221 { "vfolder-from-query-readonly", OP_MAIN_VFOLDER_FROM_QUERY_READONLY },
222 { "vfolder-window-backward", OP_MAIN_WINDOWED_VFOLDER_BACKWARD },
223 { "vfolder-window-forward", OP_MAIN_WINDOWED_VFOLDER_FORWARD },
224 { "vfolder-window-reset", OP_MAIN_WINDOWED_VFOLDER_RESET },
225#endif
226 { "view-attachments", OP_VIEW_ATTACHMENTS },
227 { "view-raw-message", OP_VIEW_RAW_MESSAGE },
228 // Deprecated
229 { "buffy-list", OP_MAILBOX_LIST },
230 { NULL, 0 },
231};
232
236const struct MenuOpSeq IndexDefaultBindings[] = { /* map: index */
237 { OP_ATTACHMENT_EDIT_TYPE, "\005" }, // <Ctrl-E>
238#ifdef USE_AUTOCRYPT
239 { OP_AUTOCRYPT_ACCT_MENU, "A" },
240#endif
241 { OP_BOUNCE_MESSAGE, "b" },
242 { OP_CHECK_TRADITIONAL, "\033P" }, // <Alt-P>
243 { OP_COPY_MESSAGE, "C" },
244 { OP_CREATE_ALIAS, "a" },
245 { OP_DECODE_COPY, "\033C" }, // <Alt-C>
246 { OP_DECODE_SAVE, "\033s" }, // <Alt-s>
247 { OP_DELETE, "d" },
248 { OP_DELETE_SUBTHREAD, "\033d" }, // <Alt-d>
249 { OP_DELETE_THREAD, "\004" }, // <Ctrl-D>
250 { OP_DISPLAY_ADDRESS, "@" },
251 { OP_DISPLAY_HEADERS, "h" },
252 { OP_DISPLAY_MESSAGE, " " }, // <Space>
253 { OP_DISPLAY_MESSAGE, "<keypadenter>" },
254 { OP_DISPLAY_MESSAGE, "\n" }, // <Enter>
255 { OP_DISPLAY_MESSAGE, "\r" }, // <Return>
256 { OP_EDIT_LABEL, "Y" },
257 { OP_EDIT_OR_VIEW_RAW_MESSAGE, "e" },
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_LIST_REPLY, "L" },
265 { OP_MAIL, "m" },
266 { OP_MAILBOX_LIST, "." },
267 { OP_MAIL_KEY, "\033k" }, // <Alt-k>
268 { OP_MAIN_BREAK_THREAD, "#" },
269 { OP_MAIN_CHANGE_FOLDER, "c" },
270 { OP_MAIN_CHANGE_FOLDER_READONLY, "\033c" }, // <Alt-c>
271 { OP_MAIN_CHANGE_GROUP, "i" },
272 { OP_MAIN_CHANGE_GROUP_READONLY, "\033i" }, // <Alt-i>
273 { OP_MAIN_CLEAR_FLAG, "W" },
274 { OP_MAIN_COLLAPSE_ALL, "\033V" }, // <Alt-V>
275 { OP_MAIN_COLLAPSE_THREAD, "\033v" }, // <Alt-v>
276 { OP_MAIN_DELETE_PATTERN, "D" },
277 { OP_MAIN_FETCH_MAIL, "G" },
278 { OP_MAIN_LIMIT, "l" },
279 { OP_MAIN_LINK_THREADS, "&" },
280 { OP_MAIN_NEXT_NEW_THEN_UNREAD, "\t" }, // <Tab>
281 { OP_MAIN_NEXT_SUBTHREAD, "\033n" }, // <Alt-n>
282 { OP_MAIN_NEXT_THREAD, "\016" }, // <Ctrl-N>
283 { OP_MAIN_NEXT_UNDELETED, "<down>" },
284 { OP_MAIN_NEXT_UNDELETED, "j" },
285 { OP_MAIN_PARENT_MESSAGE, "P" },
286 { OP_MAIN_PREV_NEW_THEN_UNREAD, "\033\t" }, // <Alt->
287 { OP_MAIN_PREV_SUBTHREAD, "\033p" }, // <Alt-p>
288 { OP_MAIN_PREV_THREAD, "\020" }, // <Ctrl-P>
289 { OP_MAIN_PREV_UNDELETED, "<up>" },
290 { OP_MAIN_PREV_UNDELETED, "k" },
291 { OP_MAIN_READ_SUBTHREAD, "\033r" }, // <Alt-r>
292 { OP_MAIN_READ_THREAD, "\022" }, // <Ctrl-R>
293 { OP_MAIN_SET_FLAG, "w" },
294 { OP_MAIN_SHOW_LIMIT, "\033l" }, // <Alt-l>
295 { OP_MAIN_SYNC_FOLDER, "$" },
296 { OP_MAIN_TAG_PATTERN, "T" },
297 { OP_MAIN_UNDELETE_PATTERN, "U" },
298 { OP_MAIN_UNTAG_PATTERN, "\024" }, // <Ctrl-T>
299 { OP_MARK_MSG, "~" },
300 { OP_NEXT_ENTRY, "J" },
301 { OP_PIPE, "|" },
302 { OP_PREV_ENTRY, "K" },
303 { OP_PRINT, "p" },
304 { OP_QUERY, "Q" },
305 { OP_QUIT, "q" },
306 { OP_RECALL_MESSAGE, "R" },
307 { OP_REPLY, "r" },
308 { OP_RESEND, "\033e" }, // <Alt-e>
309 { OP_SAVE, "s" },
310 { OP_SHOW_LOG_MESSAGES, "M" },
311 { OP_SORT, "o" },
312 { OP_SORT_REVERSE, "O" },
313 { OP_TAG_THREAD, "\033t" }, // <Alt-t>
314 { OP_TOGGLE_NEW, "N" },
315 { OP_TOGGLE_WRITE, "%" },
316 { OP_UNDELETE, "u" },
317 { OP_UNDELETE_SUBTHREAD, "\033u" }, // <Alt-u>
318 { OP_UNDELETE_THREAD, "\025" }, // <Ctrl-U>
319 { OP_VIEW_ATTACHMENTS, "v" },
320 { 0, NULL },
321};
322// clang-format on
323
328{
333};
334
342static bool resolve_email(struct IndexPrivateData *priv,
343 struct IndexSharedData *shared, enum ResolveMethod rm)
344{
345 if (!priv || !priv->menu || !shared || !shared->mailbox || !shared->email)
346 return false;
347
348 const bool c_resolve = cs_subset_bool(shared->sub, "resolve");
349 if (!c_resolve)
350 return false;
351
352 int index = -1;
353 switch (rm)
354 {
356 index = menu_get_index(priv->menu) + 1;
357 break;
358
360 {
361 const bool uncollapse = mutt_using_threads() && !window_is_focused(priv->win_index);
362 index = find_next_undeleted(shared->mailbox_view, menu_get_index(priv->menu), uncollapse);
363 break;
364 }
365
367 index = mutt_next_thread(shared->email);
368 break;
369
371 index = mutt_next_subthread(shared->email);
372 break;
373 }
374
375 if ((index < 0) || (index >= shared->mailbox->vcount))
376 {
377 // Resolve failed
378 notify_send(shared->notify, NT_INDEX, NT_INDEX_EMAIL, NULL);
379 return false;
380 }
381
382 menu_set_index(priv->menu, index);
383 return true;
384}
385
391bool index_next_undeleted(struct MuttWindow *win_index)
392{
393 struct MuttWindow *dlg = dialog_find(win_index);
394 if (!dlg)
395 return false;
396
397 struct Menu *menu = win_index->wdata;
398 struct IndexSharedData *shared = dlg->wdata;
399 if (!shared)
400 return false;
401
402 struct IndexPrivateData *priv = win_index->parent->wdata;
403 const bool uncollapse = mutt_using_threads() && !window_is_focused(priv->win_index);
404
405 int index = find_next_undeleted(shared->mailbox_view, menu_get_index(menu), uncollapse);
406 if ((index < 0) || (index >= shared->mailbox->vcount))
407 {
408 // Selection failed
410 return false;
411 }
412
413 menu_set_index(menu, index);
414 return true;
415}
416
417// -----------------------------------------------------------------------------
418
423 struct IndexPrivateData *priv, int op)
424{
426 return FR_SUCCESS;
427}
428
433 struct IndexPrivateData *priv, int op)
434{
435 if (!shared->email)
436 return FR_NO_ACTION;
438
440 return FR_SUCCESS;
441}
442
447 struct IndexPrivateData *priv, int op)
448{
449 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
450 ea_add_tagged(&ea, shared->mailbox_view, shared->email, priv->tag_prefix);
451 index_bounce_message(shared->mailbox, &ea);
452 ARRAY_FREE(&ea);
453
454 return FR_SUCCESS;
455}
456
460static int op_check_traditional(struct IndexSharedData *shared,
461 struct IndexPrivateData *priv, int op)
462{
464 return FR_NOT_IMPL;
465 if (!shared->email)
466 return FR_NO_ACTION;
467
468 if (priv->tag_prefix || !(shared->email->security & PGP_TRADITIONAL_CHECKED))
469 {
470 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
471 ea_add_tagged(&ea, shared->mailbox_view, shared->email, priv->tag_prefix);
472 if (mutt_check_traditional_pgp(shared->mailbox, &ea))
474 ARRAY_FREE(&ea);
475 }
476
477 return FR_SUCCESS;
478}
479
483static int op_compose_to_sender(struct IndexSharedData *shared,
484 struct IndexPrivateData *priv, int op)
485{
486 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
487 ea_add_tagged(&ea, shared->mailbox_view, shared->email, priv->tag_prefix);
488 int rc = mutt_send_message(SEND_TO_SENDER, NULL, NULL, shared->mailbox, &ea,
489 shared->sub);
490 ARRAY_FREE(&ea);
492
493 return (rc == -1) ? FR_ERROR : FR_SUCCESS;
494}
495
499static int op_create_alias(struct IndexSharedData *shared,
500 struct IndexPrivateData *priv, int op)
501{
502 struct AddressList *al = NULL;
503 if (shared->email && shared->email->env)
504 al = mutt_get_address(shared->email->env, NULL);
505 alias_create(al, shared->sub);
507
508 return FR_SUCCESS;
509}
510
518static int op_delete(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
519{
520 /* L10N: CHECK_ACL */
521 if (!check_acl(shared->mailbox, MUTT_ACL_DELETE, _("Can't delete message")))
522 return FR_ERROR;
523
524 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
525 ea_add_tagged(&ea, shared->mailbox_view, shared->email, priv->tag_prefix);
526
527 mutt_emails_set_flag(shared->mailbox, &ea, MUTT_DELETE, true);
528 mutt_emails_set_flag(shared->mailbox, &ea, MUTT_PURGE, (op == OP_PURGE_MESSAGE));
529 const bool c_delete_untag = cs_subset_bool(shared->sub, "delete_untag");
530 if (c_delete_untag)
531 mutt_emails_set_flag(shared->mailbox, &ea, MUTT_TAG, false);
532 ARRAY_FREE(&ea);
533
534 if (priv->tag_prefix)
535 {
537 }
538 else
539 {
541 }
542
543 return FR_SUCCESS;
544}
545
554static int op_delete_thread(struct IndexSharedData *shared,
555 struct IndexPrivateData *priv, int op)
556{
557 /* L10N: CHECK_ACL */
558 /* L10N: Due to the implementation details we do not know whether we
559 delete zero, 1, 12, ... messages. So in English we use
560 "messages". Your language might have other means to express this. */
561 if (!check_acl(shared->mailbox, MUTT_ACL_DELETE, _("Can't delete messages")))
562 return FR_ERROR;
563 if (!shared->email)
564 return FR_NO_ACTION;
565
566 int subthread = (op == OP_DELETE_SUBTHREAD);
567 int rc = mutt_thread_set_flag(shared->mailbox, shared->email, MUTT_DELETE, true, subthread);
568 if (rc == -1)
569 return FR_ERROR;
570 if (op == OP_PURGE_THREAD)
571 {
572 rc = mutt_thread_set_flag(shared->mailbox, shared->email, MUTT_PURGE, true, subthread);
573 if (rc == -1)
574 return FR_ERROR;
575 }
576
577 const bool c_delete_untag = cs_subset_bool(shared->sub, "delete_untag");
578 if (c_delete_untag)
579 mutt_thread_set_flag(shared->mailbox, shared->email, MUTT_TAG, false, subthread);
580
583 return FR_SUCCESS;
584}
585
589static int op_display_address(struct IndexSharedData *shared,
590 struct IndexPrivateData *priv, int op)
591{
592 if (!shared->email)
593 return FR_NO_ACTION;
595
596 return FR_SUCCESS;
597}
598
606static int op_display_message(struct IndexSharedData *shared,
607 struct IndexPrivateData *priv, int op)
608{
609 if (!shared->email)
610 return FR_NO_ACTION;
611 /* toggle the weeding of headers so that a user can press the key
612 * again while reading the message. */
613 if (op == OP_DISPLAY_HEADERS)
614 {
615 bool_str_toggle(shared->sub, "weed", NULL);
616 notify_send(shared->notify, NT_INDEX, NT_INDEX_EMAIL, shared);
617 if (!window_is_focused(priv->win_index))
618 return FR_SUCCESS;
619 }
620
621 OptNeedResort = false;
622
623 if (mutt_using_threads() && shared->email->collapsed)
624 {
626 mutt_set_vnum(shared->mailbox);
627 const bool c_uncollapse_jump = cs_subset_bool(shared->sub, "uncollapse_jump");
628 if (c_uncollapse_jump)
630 }
631
632 const bool c_pgp_auto_decode = cs_subset_bool(shared->sub, "pgp_auto_decode");
633 if (c_pgp_auto_decode &&
634 (priv->tag_prefix || !(shared->email->security & PGP_TRADITIONAL_CHECKED)))
635 {
636 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
637 ea_add_tagged(&ea, shared->mailbox_view, shared->email, priv->tag_prefix);
638 if (mutt_check_traditional_pgp(shared->mailbox, &ea))
640 ARRAY_FREE(&ea);
641 }
642 const int index = menu_get_index(priv->menu);
644
645 const char *const c_pager = pager_get_pager(NeoMutt->sub);
646 if (c_pager)
647 {
648 op = external_pager(shared->mailbox_view, shared->email, c_pager);
649 }
650 else
651 {
652 op = mutt_display_message(priv->win_index, shared);
653 }
654
656 if (op < OP_NULL)
657 {
658 OptNeedResort = false;
659 return FR_ERROR;
660 }
661
662 if (shared->mailbox)
663 {
665 shared->mailbox->msg_count, shared);
666 }
667
668 return op;
669}
670
674static int op_edit_label(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
675{
676 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
677 ea_add_tagged(&ea, shared->mailbox_view, shared->email, priv->tag_prefix);
678 int num_changed = mutt_label_message(shared->mailbox_view, &ea);
679 ARRAY_FREE(&ea);
680
681 if (num_changed > 0)
682 {
683 shared->mailbox->changed = true;
685 /* L10N: This is displayed when the x-label on one or more
686 messages is edited. */
687 mutt_message(ngettext("%d label changed", "%d labels changed", num_changed), num_changed);
688
689 if (!priv->tag_prefix)
691 return FR_SUCCESS;
692 }
693
694 /* L10N: This is displayed when editing an x-label, but no messages
695 were updated. Possibly due to canceling at the prompt or if the new
696 label is the same as the old label. */
697 mutt_message(_("No labels changed"));
698 return FR_NO_ACTION;
699}
700
709static int op_edit_raw_message(struct IndexSharedData *shared,
710 struct IndexPrivateData *priv, int op)
711{
712 /* TODO split this into 3 cases? */
713 bool edit;
714 if (op == OP_EDIT_RAW_MESSAGE)
715 {
716 /* L10N: CHECK_ACL */
717 if (!check_acl(shared->mailbox, MUTT_ACL_INSERT, _("Can't edit message")))
718 return FR_ERROR;
719 edit = true;
720 }
721 else if (op == OP_EDIT_OR_VIEW_RAW_MESSAGE)
722 {
723 edit = !shared->mailbox->readonly && (shared->mailbox->rights & MUTT_ACL_INSERT);
724 }
725 else
726 {
727 edit = false;
728 }
729
730 if (!shared->email)
731 return FR_NO_ACTION;
732 const bool c_pgp_auto_decode = cs_subset_bool(shared->sub, "pgp_auto_decode");
733 if (c_pgp_auto_decode &&
734 (priv->tag_prefix || !(shared->email->security & PGP_TRADITIONAL_CHECKED)))
735 {
736 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
737 ea_add_tagged(&ea, shared->mailbox_view, shared->email, priv->tag_prefix);
738 if (mutt_check_traditional_pgp(shared->mailbox, &ea))
740 ARRAY_FREE(&ea);
741 }
742 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
743 ea_add_tagged(&ea, shared->mailbox_view, shared->email, priv->tag_prefix);
744 mutt_ev_message(shared->mailbox, &ea, edit ? EVM_EDIT : EVM_VIEW);
745 ARRAY_FREE(&ea);
747
748 return FR_SUCCESS;
749}
750
754static int op_end_cond(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
755{
756 return FR_SUCCESS;
757}
758
762static int op_exit(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
763{
764 if (shared->attach_msg)
765 return FR_DONE;
766
767 if (query_quadoption(_("Exit NeoMutt without saving?"), shared->sub, "quit") == MUTT_YES)
768 {
769 if (shared->mailbox_view)
770 {
771 mx_fastclose_mailbox(shared->mailbox, false);
772 mview_free(&shared->mailbox_view);
773 }
774 return FR_DONE;
775 }
776
777 return FR_NO_ACTION;
778}
779
783static int op_extract_keys(struct IndexSharedData *shared,
784 struct IndexPrivateData *priv, int op)
785{
786 if (!WithCrypto)
787 return FR_NOT_IMPL;
788 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
789 ea_add_tagged(&ea, shared->mailbox_view, shared->email, priv->tag_prefix);
791 ARRAY_FREE(&ea);
793
794 return FR_SUCCESS;
795}
796
800static int op_flag_message(struct IndexSharedData *shared,
801 struct IndexPrivateData *priv, int op)
802{
803 /* L10N: CHECK_ACL */
804 if (!check_acl(shared->mailbox, MUTT_ACL_WRITE, _("Can't flag message")))
805 return FR_ERROR;
806
807 struct Mailbox *m = shared->mailbox;
808 if (priv->tag_prefix)
809 {
810 for (size_t i = 0; i < m->msg_count; i++)
811 {
812 struct Email *e = m->emails[i];
813 if (!e)
814 break;
815 if (message_is_tagged(e))
816 mutt_set_flag(m, e, MUTT_FLAG, !e->flagged, true);
817 }
818
820 }
821 else
822 {
823 if (!shared->email)
824 return FR_NO_ACTION;
825 mutt_set_flag(m, shared->email, MUTT_FLAG, !shared->email->flagged, true);
826
828 }
829
830 return FR_SUCCESS;
831}
832
836static int op_forget_passphrase(struct IndexSharedData *shared,
837 struct IndexPrivateData *priv, int op)
838{
840 return FR_SUCCESS;
841}
842
846static int op_forward_message(struct IndexSharedData *shared,
847 struct IndexPrivateData *priv, int op)
848{
849 if (!shared->email)
850 return FR_NO_ACTION;
851 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
852 ea_add_tagged(&ea, shared->mailbox_view, shared->email, priv->tag_prefix);
853 const bool c_pgp_auto_decode = cs_subset_bool(shared->sub, "pgp_auto_decode");
854 if (c_pgp_auto_decode &&
855 (priv->tag_prefix || !(shared->email->security & PGP_TRADITIONAL_CHECKED)))
856 {
857 if (mutt_check_traditional_pgp(shared->mailbox, &ea))
859 }
860 int rc = mutt_send_message(SEND_FORWARD, NULL, NULL, shared->mailbox, &ea,
861 shared->sub);
862 ARRAY_FREE(&ea);
864
865 return (rc == -1) ? FR_ERROR : FR_SUCCESS;
866}
867
875static int op_group_reply(struct IndexSharedData *shared,
876 struct IndexPrivateData *priv, int op)
877{
878 SendFlags replyflags = SEND_REPLY;
879 if (op == OP_GROUP_REPLY)
880 replyflags |= SEND_GROUP_REPLY;
881 else
882 replyflags |= SEND_GROUP_CHAT_REPLY;
883 if (!shared->email)
884 return FR_NO_ACTION;
885 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
886 ea_add_tagged(&ea, shared->mailbox_view, shared->email, priv->tag_prefix);
887 const bool c_pgp_auto_decode = cs_subset_bool(shared->sub, "pgp_auto_decode");
888 if (c_pgp_auto_decode &&
889 (priv->tag_prefix || !(shared->email->security & PGP_TRADITIONAL_CHECKED)))
890 {
891 if (mutt_check_traditional_pgp(shared->mailbox, &ea))
893 }
894 int rc = mutt_send_message(replyflags, NULL, NULL, shared->mailbox, &ea,
895 shared->sub);
896 ARRAY_FREE(&ea);
898
899 return (rc == -1) ? FR_ERROR : FR_SUCCESS;
900}
901
905static int op_jump(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
906{
907 int rc = FR_ERROR;
908 struct Buffer *buf = buf_pool_get();
909
910 const int digit = op - OP_JUMP;
911 if ((digit > 0) && (digit < 10))
912 {
913 mutt_unget_ch('0' + digit);
914 }
915
916 int msg_num = 0;
917 if ((mw_get_field(_("Jump to message: "), buf, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0) ||
918 buf_is_empty(buf))
919 {
920 mutt_message(_("Nothing to do"));
921 rc = FR_NO_ACTION;
922 }
923 else if (!mutt_str_atoi_full(buf_string(buf), &msg_num))
924 {
925 mutt_warning(_("Argument must be a message number"));
926 }
927 else if ((msg_num < 1) || (msg_num > shared->mailbox->msg_count))
928 {
929 mutt_warning(_("Invalid message number"));
930 }
931 else if (!shared->mailbox->emails[msg_num - 1]->visible)
932 {
933 mutt_warning(_("That message is not visible"));
934 }
935 else
936 {
937 struct Email *e = shared->mailbox->emails[msg_num - 1];
938
939 if (mutt_messages_in_thread(shared->mailbox, e, MIT_POSITION) > 1)
940 {
942 mutt_set_vnum(shared->mailbox);
943 }
944 menu_set_index(priv->menu, e->vnum);
945 rc = FR_SUCCESS;
946 }
947
948 buf_pool_release(&buf);
949 return rc;
950}
951
955static int op_list_reply(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
956{
957 if (!shared->email)
958 return FR_NO_ACTION;
959 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
960 ea_add_tagged(&ea, shared->mailbox_view, shared->email, priv->tag_prefix);
961 const bool c_pgp_auto_decode = cs_subset_bool(shared->sub, "pgp_auto_decode");
962 if (c_pgp_auto_decode &&
963 (priv->tag_prefix || !(shared->email->security & PGP_TRADITIONAL_CHECKED)))
964 {
965 if (mutt_check_traditional_pgp(shared->mailbox, &ea))
967 }
968 int rc = mutt_send_message(SEND_REPLY | SEND_LIST_REPLY, NULL, NULL,
969 shared->mailbox, &ea, shared->sub);
970 ARRAY_FREE(&ea);
972
973 return (rc == -1) ? FR_ERROR : FR_SUCCESS;
974}
975
979static int op_list_subscribe(struct IndexSharedData *shared,
980 struct IndexPrivateData *priv, int op)
981{
982 return mutt_send_list_subscribe(shared->mailbox, shared->email) ? FR_SUCCESS : FR_NO_ACTION;
983}
984
988static int op_list_unsubscribe(struct IndexSharedData *shared,
989 struct IndexPrivateData *priv, int op)
990{
992}
993
997static int op_mail(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
998{
999 int rc = mutt_send_message(SEND_NO_FLAGS, NULL, NULL, shared->mailbox, NULL,
1000 shared->sub);
1002 return (rc == -1) ? FR_ERROR : FR_SUCCESS;
1003}
1004
1008static int op_mailbox_list(struct IndexSharedData *shared,
1009 struct IndexPrivateData *priv, int op)
1010{
1012 return FR_SUCCESS;
1013}
1014
1018static int op_mail_key(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
1019{
1020 if (!(WithCrypto & APPLICATION_PGP))
1021 return FR_NOT_IMPL;
1022 int rc = mutt_send_message(SEND_KEY, NULL, NULL, NULL, NULL, shared->sub);
1024
1025 return (rc == -1) ? FR_ERROR : FR_SUCCESS;
1026}
1027
1031static int op_main_break_thread(struct IndexSharedData *shared,
1032 struct IndexPrivateData *priv, int op)
1033{
1034 struct Mailbox *m = shared->mailbox;
1035 /* L10N: CHECK_ACL */
1036 if (!check_acl(m, MUTT_ACL_WRITE, _("Can't break thread")))
1037 return FR_ERROR;
1038
1039 struct Email *e = shared->email;
1040 if (!e)
1041 return FR_NO_ACTION;
1042
1043 if (!mutt_using_threads())
1044 {
1045 mutt_warning(_("Threading is not enabled"));
1046 return FR_NO_ACTION;
1047 }
1048
1049 struct MailboxView *mv = shared->mailbox_view;
1051 {
1052 {
1054 mutt_sort_headers(mv, true);
1055 menu_set_index(priv->menu, e->vnum);
1056 }
1057
1058 m->changed = true;
1059 mutt_message(_("Thread broken"));
1060
1062 }
1063 else
1064 {
1065 mutt_error(_("Thread can't be broken, message is not part of a thread"));
1066 }
1067
1068 return FR_SUCCESS;
1069}
1070
1079static int op_main_change_folder(struct IndexSharedData *shared,
1080 struct IndexPrivateData *priv, int op)
1081{
1082 struct Buffer *folderbuf = buf_pool_get();
1083 buf_alloc(folderbuf, PATH_MAX);
1084
1085 char *cp = NULL;
1086 bool read_only;
1087 const bool c_read_only = cs_subset_bool(shared->sub, "read_only");
1088 if (shared->attach_msg || c_read_only || (op == OP_MAIN_CHANGE_FOLDER_READONLY))
1089 {
1090 cp = _("Open mailbox in read-only mode");
1091 read_only = true;
1092 }
1093 else
1094 {
1095 cp = _("Open mailbox");
1096 read_only = false;
1097 }
1098
1099 const bool c_change_folder_next = cs_subset_bool(shared->sub, "change_folder_next");
1100 if (c_change_folder_next && shared->mailbox && !buf_is_empty(&shared->mailbox->pathbuf))
1101 {
1102 buf_strcpy(folderbuf, mailbox_path(shared->mailbox));
1103 buf_pretty_mailbox(folderbuf);
1104 }
1105 /* By default, fill buf with the next mailbox that contains unread mail */
1106 mutt_mailbox_next(shared->mailbox_view ? shared->mailbox : NULL, folderbuf);
1107
1108 if (mw_enter_fname(cp, folderbuf, true, shared->mailbox, false, NULL, NULL,
1109 MUTT_SEL_NO_FLAGS) == -1)
1110 {
1111 goto changefoldercleanup;
1112 }
1113
1114 /* Selected directory is okay, let's save it. */
1116
1117 if (buf_is_empty(folderbuf))
1118 {
1119 msgwin_clear_text(NULL);
1120 goto changefoldercleanup;
1121 }
1122
1123 struct Mailbox *m = mx_mbox_find2(buf_string(folderbuf));
1124 if (m)
1125 {
1126 change_folder_mailbox(priv->menu, m, &priv->oldcount, shared, read_only);
1127 }
1128 else
1129 {
1130 change_folder_string(priv->menu, folderbuf, &priv->oldcount, shared, read_only);
1131 }
1132
1133changefoldercleanup:
1134 buf_pool_release(&folderbuf);
1136
1137 return FR_SUCCESS;
1138}
1139
1143static int op_main_collapse_all(struct IndexSharedData *shared,
1144 struct IndexPrivateData *priv, int op)
1145{
1146 if (!mutt_using_threads())
1147 {
1148 mutt_error(_("Threading is not enabled"));
1149 return FR_ERROR;
1150 }
1151 collapse_all(shared->mailbox_view, priv->menu, 1);
1152
1153 return FR_SUCCESS;
1154}
1155
1160 struct IndexPrivateData *priv, int op)
1161{
1162 if (!mutt_using_threads())
1163 {
1164 mutt_error(_("Threading is not enabled"));
1165 return FR_ERROR;
1166 }
1167
1168 if (!shared->email)
1169 return FR_NO_ACTION;
1170
1171 if (shared->email->collapsed)
1172 {
1173 int index = mutt_uncollapse_thread(shared->email);
1174 mutt_set_vnum(shared->mailbox);
1175 const bool c_uncollapse_jump = cs_subset_bool(shared->sub, "uncollapse_jump");
1176 if (c_uncollapse_jump)
1177 index = mutt_thread_next_unread(shared->email);
1178 menu_set_index(priv->menu, index);
1179 }
1180 else if (mutt_thread_can_collapse(shared->email))
1181 {
1183 mutt_set_vnum(shared->mailbox);
1184 }
1185 else
1186 {
1187 mutt_error(_("Thread contains unread or flagged messages"));
1188 return FR_ERROR;
1189 }
1190
1192
1193 return FR_SUCCESS;
1194}
1195
1199static int op_main_delete_pattern(struct IndexSharedData *shared,
1200 struct IndexPrivateData *priv, int op)
1201{
1202 /* L10N: CHECK_ACL */
1203 /* L10N: Due to the implementation details we do not know whether we
1204 delete zero, 1, 12, ... messages. So in English we use
1205 "messages". Your language might have other means to express this. */
1206 if (!check_acl(shared->mailbox, MUTT_ACL_DELETE, _("Can't delete messages")))
1207 return FR_ERROR;
1208
1209 mutt_pattern_func(shared->mailbox_view, MUTT_DELETE, _("Delete messages matching: "));
1211
1212 return FR_SUCCESS;
1213}
1214
1223static int op_main_limit(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
1224{
1225 const bool lmt = mview_has_limit(shared->mailbox_view);
1226 int old_index = shared->email ? shared->email->index : -1;
1227 if (op == OP_TOGGLE_READ)
1228 {
1229 char buf2[1024] = { 0 };
1230
1231 if (!lmt || !mutt_strn_equal(shared->mailbox_view->pattern, "!~R!~D~s", 8))
1232 {
1233 snprintf(buf2, sizeof(buf2), "!~R!~D~s%s", lmt ? shared->mailbox_view->pattern : ".*");
1234 }
1235 else
1236 {
1237 mutt_str_copy(buf2, shared->mailbox_view->pattern + 8, sizeof(buf2));
1238 if ((*buf2 == '\0') || mutt_strn_equal(buf2, ".*", 2))
1239 snprintf(buf2, sizeof(buf2), "~A");
1240 }
1241 mutt_str_replace(&shared->mailbox_view->pattern, buf2);
1243 }
1244
1245 if (((op == OP_LIMIT_CURRENT_THREAD) &&
1246 mutt_limit_current_thread(shared->mailbox_view, shared->email)) ||
1247 (op == OP_TOGGLE_READ) ||
1248 ((op == OP_MAIN_LIMIT) && (mutt_pattern_func(shared->mailbox_view, MUTT_LIMIT,
1249 _("Limit to messages matching: ")) == 0)))
1250 {
1251 priv->menu->max = shared->mailbox->vcount;
1252 menu_set_index(priv->menu, 0);
1253 if (old_index >= 0)
1254 {
1255 /* try to find what used to be the current message */
1256 for (size_t i = 0; i < shared->mailbox->vcount; i++)
1257 {
1258 struct Email *e = mutt_get_virt_email(shared->mailbox, i);
1259 if (!e)
1260 continue;
1261 if (e->index == old_index)
1262 {
1263 menu_set_index(priv->menu, i);
1264 break;
1265 }
1266 }
1267 }
1268
1269 if ((shared->mailbox->msg_count != 0) && mutt_using_threads())
1270 {
1271 const bool c_collapse_all = cs_subset_bool(shared->sub, "collapse_all");
1272 if (c_collapse_all)
1273 collapse_all(shared->mailbox_view, priv->menu, 0);
1275 }
1277 }
1278 if (lmt)
1279 mutt_message(_("To view all messages, limit to \"all\""));
1280
1281 return FR_SUCCESS;
1282}
1283
1287static int op_main_link_threads(struct IndexSharedData *shared,
1288 struct IndexPrivateData *priv, int op)
1289{
1290 struct Mailbox *m = shared->mailbox;
1291 /* L10N: CHECK_ACL */
1292 if (!check_acl(m, MUTT_ACL_WRITE, _("Can't link threads")))
1293 return FR_ERROR;
1294
1295 struct Email *e = shared->email;
1296 if (!e)
1297 return FR_NO_ACTION;
1298
1299 enum FunctionRetval rc = FR_ERROR;
1300
1301 if (!mutt_using_threads())
1302 {
1303 mutt_error(_("Threading is not enabled"));
1304 }
1305 else if (!e->env->message_id)
1306 {
1307 mutt_error(_("No Message-ID: header available to link thread"));
1308 }
1309 else
1310 {
1311 struct MailboxView *mv = shared->mailbox_view;
1312 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
1313 ea_add_tagged(&ea, mv, NULL, true);
1314
1315 if (mutt_link_threads(e, &ea, m))
1316 {
1317 mutt_sort_headers(mv, true);
1318 menu_set_index(priv->menu, e->vnum);
1319
1320 m->changed = true;
1321 mutt_message(_("Threads linked"));
1322 rc = FR_SUCCESS;
1323 }
1324 else
1325 {
1326 mutt_error(_("No thread linked"));
1327 rc = FR_NO_ACTION;
1328 }
1329
1330 ARRAY_FREE(&ea);
1331 }
1332
1334 return rc;
1335}
1336
1344static int op_main_modify_tags(struct IndexSharedData *shared,
1345 struct IndexPrivateData *priv, int op)
1346{
1347 int rc = FR_ERROR;
1348 struct Buffer *buf = NULL;
1349
1350 if (!shared->mailbox)
1351 goto done;
1352 struct Mailbox *m = shared->mailbox;
1353 if (!mx_tags_is_supported(m))
1354 {
1355 mutt_message(_("Folder doesn't support tagging, aborting"));
1356 goto done;
1357 }
1358 if (!shared->email)
1359 {
1360 rc = FR_NO_ACTION;
1361 goto done;
1362 }
1363
1364 struct Buffer *tags = buf_pool_get();
1365 if (!priv->tag_prefix)
1366 driver_tags_get_with_hidden(&shared->email->tags, tags);
1367 buf = buf_pool_get();
1368 int rc2 = mx_tags_edit(m, buf_string(tags), buf);
1369 buf_pool_release(&tags);
1370 if (rc2 < 0)
1371 {
1372 goto done;
1373 }
1374 else if (rc2 == 0)
1375 {
1376 mutt_message(_("No tag specified, aborting"));
1377 goto done;
1378 }
1379
1380 if (priv->tag_prefix)
1381 {
1382 struct Progress *progress = NULL;
1383
1384 if (m->verbose)
1385 {
1387 progress_set_message(progress, _("Update tags..."));
1388 }
1389
1390#ifdef USE_NOTMUCH
1391 if (m->type == MUTT_NOTMUCH)
1392 nm_db_longrun_init(m, true);
1393#endif
1394 for (int px = 0, i = 0; i < m->msg_count; i++)
1395 {
1396 struct Email *e = m->emails[i];
1397 if (!e)
1398 break;
1399 if (!message_is_tagged(e))
1400 continue;
1401
1402 progress_update(progress, ++px, -1);
1403 mx_tags_commit(m, e, buf_string(buf));
1404 e->attr_color = NULL;
1405 if (op == OP_MAIN_MODIFY_TAGS_THEN_HIDE)
1406 {
1407 bool still_queried = false;
1408#ifdef USE_NOTMUCH
1409 if (m->type == MUTT_NOTMUCH)
1410 still_queried = nm_message_is_still_queried(m, e);
1411#endif
1412 e->quasi_deleted = !still_queried;
1413 m->changed = true;
1414 }
1415 }
1416 progress_free(&progress);
1417#ifdef USE_NOTMUCH
1418 if (m->type == MUTT_NOTMUCH)
1420#endif
1422 }
1423 else
1424 {
1425 if (mx_tags_commit(m, shared->email, buf_string(buf)))
1426 {
1427 mutt_message(_("Failed to modify tags, aborting"));
1428 goto done;
1429 }
1430 shared->email->attr_color = NULL;
1431 if (op == OP_MAIN_MODIFY_TAGS_THEN_HIDE)
1432 {
1433 bool still_queried = false;
1434#ifdef USE_NOTMUCH
1435 if (m->type == MUTT_NOTMUCH)
1436 still_queried = nm_message_is_still_queried(m, shared->email);
1437#endif
1438 shared->email->quasi_deleted = !still_queried;
1439 m->changed = true;
1440 }
1441
1443 }
1444 rc = FR_SUCCESS;
1445
1446done:
1447 buf_pool_release(&buf);
1448 return rc;
1449}
1450
1462static int op_main_next_new(struct IndexSharedData *shared,
1463 struct IndexPrivateData *priv, int op)
1464{
1465 int first_unread = -1;
1466 int first_new = -1;
1467
1468 const int saved_current = menu_get_index(priv->menu);
1469 int mcur = saved_current;
1470 int index = -1;
1471 const bool threaded = mutt_using_threads();
1472 for (size_t i = 0; i != shared->mailbox->vcount; i++)
1473 {
1474 if ((op == OP_MAIN_NEXT_NEW) || (op == OP_MAIN_NEXT_UNREAD) ||
1475 (op == OP_MAIN_NEXT_NEW_THEN_UNREAD))
1476 {
1477 mcur++;
1478 if (mcur > (shared->mailbox->vcount - 1))
1479 {
1480 mcur = 0;
1481 }
1482 }
1483 else
1484 {
1485 mcur--;
1486 if (mcur < 0)
1487 {
1488 mcur = shared->mailbox->vcount - 1;
1489 }
1490 }
1491
1492 struct Email *e = mutt_get_virt_email(shared->mailbox, mcur);
1493 if (!e)
1494 break;
1495 if (e->collapsed && threaded)
1496 {
1497 int unread = mutt_thread_contains_unread(e);
1498 if ((unread != 0) && (first_unread == -1))
1499 first_unread = mcur;
1500 if ((unread == 1) && (first_new == -1))
1501 first_new = mcur;
1502 }
1503 else if (!e->deleted && !e->read)
1504 {
1505 if (first_unread == -1)
1506 first_unread = mcur;
1507 if (!e->old && (first_new == -1))
1508 first_new = mcur;
1509 }
1510
1511 if (((op == OP_MAIN_NEXT_UNREAD) || (op == OP_MAIN_PREV_UNREAD)) && (first_unread != -1))
1512 {
1513 break;
1514 }
1515 if (((op == OP_MAIN_NEXT_NEW) || (op == OP_MAIN_PREV_NEW) ||
1516 (op == OP_MAIN_NEXT_NEW_THEN_UNREAD) || (op == OP_MAIN_PREV_NEW_THEN_UNREAD)) &&
1517 (first_new != -1))
1518 {
1519 break;
1520 }
1521 }
1522 if (((op == OP_MAIN_NEXT_NEW) || (op == OP_MAIN_PREV_NEW) ||
1523 (op == OP_MAIN_NEXT_NEW_THEN_UNREAD) || (op == OP_MAIN_PREV_NEW_THEN_UNREAD)) &&
1524 (first_new != -1))
1525 {
1526 index = first_new;
1527 }
1528 else if (((op == OP_MAIN_NEXT_UNREAD) || (op == OP_MAIN_PREV_UNREAD) ||
1529 (op == OP_MAIN_NEXT_NEW_THEN_UNREAD) || (op == OP_MAIN_PREV_NEW_THEN_UNREAD)) &&
1530 (first_unread != -1))
1531 {
1532 index = first_unread;
1533 }
1534
1535 if (index == -1)
1536 {
1537 menu_set_index(priv->menu, saved_current);
1538 if ((op == OP_MAIN_NEXT_NEW) || (op == OP_MAIN_PREV_NEW))
1539 {
1540 if (mview_has_limit(shared->mailbox_view))
1541 mutt_error(_("No new messages in this limited view"));
1542 else
1543 mutt_error(_("No new messages"));
1544 }
1545 else
1546 {
1547 if (mview_has_limit(shared->mailbox_view))
1548 mutt_error(_("No unread messages in this limited view"));
1549 else
1550 mutt_error(_("No unread messages"));
1551 }
1552 notify_send(shared->notify, NT_INDEX, NT_INDEX_EMAIL, NULL);
1553 return FR_ERROR;
1554 }
1555 else
1556 {
1557 menu_set_index(priv->menu, index);
1558 }
1559
1560 index = menu_get_index(priv->menu);
1561 if ((op == OP_MAIN_NEXT_NEW) || (op == OP_MAIN_NEXT_UNREAD) ||
1562 (op == OP_MAIN_NEXT_NEW_THEN_UNREAD))
1563 {
1564 if (saved_current > index)
1565 {
1566 mutt_message(_("Search wrapped to top"));
1567 }
1568 }
1569 else if (saved_current < index)
1570 {
1571 mutt_message(_("Search wrapped to bottom"));
1572 }
1573
1574 return FR_SUCCESS;
1575}
1576
1586static int op_main_next_thread(struct IndexSharedData *shared,
1587 struct IndexPrivateData *priv, int op)
1588{
1589 int index = -1;
1590 switch (op)
1591 {
1592 case OP_MAIN_NEXT_THREAD:
1593 index = mutt_next_thread(shared->email);
1594 break;
1595
1596 case OP_MAIN_NEXT_SUBTHREAD:
1597 index = mutt_next_subthread(shared->email);
1598 break;
1599
1600 case OP_MAIN_PREV_THREAD:
1601 index = mutt_previous_thread(shared->email);
1602 break;
1603
1604 case OP_MAIN_PREV_SUBTHREAD:
1606 break;
1607 }
1608
1609 if (index != -1)
1610 menu_set_index(priv->menu, index);
1611
1612 if (index < 0)
1613 {
1614 if ((op == OP_MAIN_NEXT_THREAD) || (op == OP_MAIN_NEXT_SUBTHREAD))
1615 mutt_error(_("No more threads"));
1616 else
1617 mutt_error(_("You are on the first thread"));
1618
1619 notify_send(shared->notify, NT_INDEX, NT_INDEX_EMAIL, NULL);
1620 }
1621
1622 return FR_SUCCESS;
1623}
1624
1628static int op_main_next_undeleted(struct IndexSharedData *shared,
1629 struct IndexPrivateData *priv, int op)
1630{
1631 int index = menu_get_index(priv->menu);
1632 if (index >= (shared->mailbox->vcount - 1))
1633 {
1634 notify_send(shared->notify, NT_INDEX, NT_INDEX_EMAIL, NULL);
1635 mutt_message(_("You are on the last message"));
1636 return FR_ERROR;
1637 }
1638
1639 const bool uncollapse = mutt_using_threads() && !window_is_focused(priv->win_index);
1640
1641 index = find_next_undeleted(shared->mailbox_view, index, uncollapse);
1642 if (index != -1)
1643 {
1644 menu_set_index(priv->menu, index);
1645 if (uncollapse)
1647 }
1648
1649 if (index == -1)
1650 {
1651 notify_send(shared->notify, NT_INDEX, NT_INDEX_EMAIL, NULL);
1652 mutt_error(_("No undeleted messages"));
1653 }
1654
1655 return FR_SUCCESS;
1656}
1657
1662 struct IndexPrivateData *priv, int op)
1663{
1664 struct Mailbox *m = shared->mailbox;
1665
1666 struct Buffer *folderbuf = buf_pool_get();
1667 buf_strcpy(folderbuf, mailbox_path(m));
1668 m = mutt_mailbox_next_unread(m, folderbuf);
1669 buf_pool_release(&folderbuf);
1670
1671 if (!m)
1672 {
1673 mutt_error(_("No mailboxes have new mail"));
1674 return FR_ERROR;
1675 }
1676
1677 change_folder_mailbox(priv->menu, m, &priv->oldcount, shared, false);
1678 return FR_SUCCESS;
1679}
1680
1684static int op_main_prev_undeleted(struct IndexSharedData *shared,
1685 struct IndexPrivateData *priv, int op)
1686{
1687 int index = menu_get_index(priv->menu);
1688 if (index < 1)
1689 {
1690 notify_send(shared->notify, NT_INDEX, NT_INDEX_EMAIL, NULL);
1691 mutt_message(_("You are on the first message"));
1692 return FR_ERROR;
1693 }
1694
1695 const bool uncollapse = mutt_using_threads() && !window_is_focused(priv->win_index);
1696
1697 index = find_previous_undeleted(shared->mailbox_view, index, uncollapse);
1698 if (index != -1)
1699 {
1700 menu_set_index(priv->menu, index);
1701 if (uncollapse)
1703 }
1704
1705 if (index == -1)
1706 {
1707 mutt_error(_("No undeleted messages"));
1708 notify_send(shared->notify, NT_INDEX, NT_INDEX_EMAIL, NULL);
1709 }
1710
1711 return FR_SUCCESS;
1712}
1713
1717static int op_main_quasi_delete(struct IndexSharedData *shared,
1718 struct IndexPrivateData *priv, int op)
1719{
1720 if (priv->tag_prefix)
1721 {
1722 struct Mailbox *m = shared->mailbox;
1723 for (size_t i = 0; i < m->msg_count; i++)
1724 {
1725 struct Email *e = m->emails[i];
1726 if (!e)
1727 break;
1728 if (message_is_tagged(e))
1729 {
1730 e->quasi_deleted = true;
1731 m->changed = true;
1732 }
1733 }
1734 }
1735 else
1736 {
1737 if (!shared->email)
1738 return FR_NO_ACTION;
1739 shared->email->quasi_deleted = true;
1740 shared->mailbox->changed = true;
1741 }
1742
1743 return FR_SUCCESS;
1744}
1745
1753static int op_main_read_thread(struct IndexSharedData *shared,
1754 struct IndexPrivateData *priv, int op)
1755{
1756 /* L10N: CHECK_ACL */
1757 /* L10N: Due to the implementation details we do not know whether we
1758 mark zero, 1, 12, ... messages as read. So in English we use
1759 "messages". Your language might have other means to express this. */
1760 if (!check_acl(shared->mailbox, MUTT_ACL_SEEN, _("Can't mark messages as read")))
1761 return FR_ERROR;
1762
1763 int rc = mutt_thread_set_flag(shared->mailbox, shared->email, MUTT_READ, true,
1764 (op != OP_MAIN_READ_THREAD));
1765 if (rc != -1)
1766 {
1767 const enum ResolveMethod rm = (op == OP_MAIN_READ_THREAD) ? RESOLVE_NEXT_THREAD :
1769 resolve_email(priv, shared, rm);
1771 }
1772
1773 return FR_SUCCESS;
1774}
1775
1783static int op_main_root_message(struct IndexSharedData *shared,
1784 struct IndexPrivateData *priv, int op)
1785{
1786 int index = mutt_parent_message(shared->email, op == OP_MAIN_ROOT_MESSAGE);
1787 if (index != -1)
1788 menu_set_index(priv->menu, index);
1789
1790 return FR_SUCCESS;
1791}
1792
1800static int op_main_set_flag(struct IndexSharedData *shared,
1801 struct IndexPrivateData *priv, int op)
1802{
1803 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
1804 ea_add_tagged(&ea, shared->mailbox_view, shared->email, priv->tag_prefix);
1805
1806 if (mw_change_flag(shared->mailbox, &ea, (op == OP_MAIN_SET_FLAG)) == 0)
1807 {
1808 if (priv->tag_prefix)
1809 {
1811 }
1812 else
1813 {
1815 }
1816 }
1817 ARRAY_FREE(&ea);
1818
1819 return FR_SUCCESS;
1820}
1821
1825static int op_main_show_limit(struct IndexSharedData *shared,
1826 struct IndexPrivateData *priv, int op)
1827{
1828 if (mview_has_limit(shared->mailbox_view))
1829 {
1830 char buf2[256] = { 0 };
1831 /* L10N: ask for a limit to apply */
1832 snprintf(buf2, sizeof(buf2), _("Limit: %s"), shared->mailbox_view->pattern);
1833 mutt_message("%s", buf2);
1834 }
1835 else
1836 {
1837 mutt_message(_("No limit pattern is in effect"));
1838 }
1839
1840 return FR_SUCCESS;
1841}
1842
1846static int op_main_sync_folder(struct IndexSharedData *shared,
1847 struct IndexPrivateData *priv, int op)
1848{
1849 if (!shared->mailbox || (shared->mailbox->msg_count == 0) || shared->mailbox->readonly)
1850 return FR_NO_ACTION;
1851
1852 int ovc = shared->mailbox->vcount;
1853 int oc = shared->mailbox->msg_count;
1854 struct Email *e = NULL;
1855
1856 /* don't attempt to move the cursor if there are no visible messages in the current limit */
1857 int index = menu_get_index(priv->menu);
1858 if (index < shared->mailbox->vcount)
1859 {
1860 /* threads may be reordered, so figure out what header the cursor
1861 * should be on. */
1862 int newidx = index;
1863 if (!shared->email)
1864 return FR_NO_ACTION;
1865 if (shared->email->deleted)
1866 newidx = find_next_undeleted(shared->mailbox_view, index, false);
1867 if (newidx < 0)
1868 newidx = find_previous_undeleted(shared->mailbox_view, index, false);
1869 if (newidx >= 0)
1870 e = mutt_get_virt_email(shared->mailbox, newidx);
1871 }
1872
1873 enum MxStatus check = mx_mbox_sync(shared->mailbox);
1874 if (check == MX_STATUS_OK)
1875 {
1876 if (e && (shared->mailbox->vcount != ovc))
1877 {
1878 for (size_t i = 0; i < shared->mailbox->vcount; i++)
1879 {
1880 struct Email *e2 = mutt_get_virt_email(shared->mailbox, i);
1881 if (e2 == e)
1882 {
1883 menu_set_index(priv->menu, i);
1884 break;
1885 }
1886 }
1887 }
1889 }
1890 else if ((check == MX_STATUS_NEW_MAIL) || (check == MX_STATUS_REOPENED))
1891 {
1892 update_index(priv->menu, shared->mailbox_view, check, oc, shared);
1893 }
1894
1895 /* do a sanity check even if mx_mbox_sync failed. */
1896
1897 index = menu_get_index(priv->menu);
1898 if ((index < 0) || (shared->mailbox && (index >= shared->mailbox->vcount)))
1899 {
1901 }
1902
1903 /* check for a fatal error, or all messages deleted */
1904 if (shared->mailbox && buf_is_empty(&shared->mailbox->pathbuf))
1905 {
1906 mview_free(&shared->mailbox_view);
1907 }
1908
1909 priv->menu->max = shared->mailbox->vcount;
1911
1912 struct EventMailbox ev_m = { shared->mailbox };
1914
1915 return FR_SUCCESS;
1916}
1917
1921static int op_main_tag_pattern(struct IndexSharedData *shared,
1922 struct IndexPrivateData *priv, int op)
1923{
1924 mutt_pattern_func(shared->mailbox_view, MUTT_TAG, _("Tag messages matching: "));
1926
1927 return FR_SUCCESS;
1928}
1929
1934 struct IndexPrivateData *priv, int op)
1935{
1936 /* L10N: CHECK_ACL */
1937 /* L10N: Due to the implementation details we do not know whether we
1938 undelete zero, 1, 12, ... messages. So in English we use
1939 "messages". Your language might have other means to express this. */
1940 if (!check_acl(shared->mailbox, MUTT_ACL_DELETE, _("Can't undelete messages")))
1941 return FR_ERROR;
1942
1944 _("Undelete messages matching: ")) == 0)
1945 {
1947 }
1948
1949 return FR_SUCCESS;
1950}
1951
1955static int op_main_untag_pattern(struct IndexSharedData *shared,
1956 struct IndexPrivateData *priv, int op)
1957{
1958 if (mutt_pattern_func(shared->mailbox_view, MUTT_UNTAG, _("Untag messages matching: ")) == 0)
1960
1961 return FR_SUCCESS;
1962}
1963
1967static int op_mark_msg(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
1968{
1969 if (!shared->email)
1970 return FR_NO_ACTION;
1971
1972 int rc = FR_SUCCESS;
1973
1974 if (shared->email->env->message_id)
1975 {
1976 struct Buffer *buf = buf_pool_get();
1977
1978 /* L10N: This is the prompt for <mark-message>. Whatever they
1979 enter will be prefixed by $mark_macro_prefix and will become
1980 a macro hotkey to jump to the currently selected message. */
1981 if ((mw_get_field(_("Enter macro stroke: "), buf, MUTT_COMP_NO_FLAGS,
1982 HC_OTHER, NULL, NULL) == 0) &&
1983 !buf_is_empty(buf))
1984 {
1985 const char *const c_mark_macro_prefix = cs_subset_string(shared->sub, "mark_macro_prefix");
1986 char str[256] = { 0 };
1987 snprintf(str, sizeof(str), "%s%s", c_mark_macro_prefix, buf_string(buf));
1988
1989 struct Buffer *msg_id = buf_pool_get();
1990 mutt_file_sanitize_regex(msg_id, shared->email->env->message_id);
1991 char macro[256] = { 0 };
1992 snprintf(macro, sizeof(macro), "<search>~i '%s'\n", buf_string(msg_id));
1993 buf_pool_release(&msg_id);
1994
1995 /* L10N: "message hotkey" is the key bindings menu description of a
1996 macro created by <mark-message>. */
1997 km_bind(str, MENU_INDEX, OP_MACRO, macro, _("message hotkey"));
1998
1999 /* L10N: This is echoed after <mark-message> creates a new hotkey
2000 macro. %s is the hotkey string ($mark_macro_prefix followed
2001 by whatever they typed at the prompt.) */
2002 buf_printf(buf, _("Message bound to %s"), str);
2003 mutt_message("%s", buf_string(buf));
2004 mutt_debug(LL_DEBUG1, "Mark: %s => %s\n", str, macro);
2005 buf_pool_release(&buf);
2006 }
2007 }
2008 else
2009 {
2010 /* L10N: This error is printed if <mark-message> can't find a
2011 Message-ID for the currently selected message in the index. */
2012 mutt_error(_("No message ID to macro"));
2013 rc = FR_ERROR;
2014 }
2015
2016 return rc;
2017}
2018
2022static int op_next_entry(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2023{
2024 const int index = menu_get_index(priv->menu) + 1;
2025 if (index >= shared->mailbox->vcount)
2026 {
2027 mutt_message(_("You are on the last message"));
2028 notify_send(shared->notify, NT_INDEX, NT_INDEX_EMAIL, NULL);
2029 return FR_ERROR;
2030 }
2031 menu_set_index(priv->menu, index);
2032 return FR_SUCCESS;
2033}
2034
2038static int op_pipe(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2039{
2040 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
2041 ea_add_tagged(&ea, shared->mailbox_view, shared->email, priv->tag_prefix);
2042 mutt_pipe_message(shared->mailbox, &ea);
2043 ARRAY_FREE(&ea);
2044
2045 /* in an IMAP folder index with imap_peek=no, piping could change
2046 * new or old messages status to read. Redraw what's needed. */
2047 const bool c_imap_peek = cs_subset_bool(shared->sub, "imap_peek");
2048 if ((shared->mailbox->type == MUTT_IMAP) && !c_imap_peek)
2049 {
2051 }
2052
2053 return FR_SUCCESS;
2054}
2055
2059static int op_prev_entry(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2060{
2061 int index = menu_get_index(priv->menu);
2062 if (index < 1)
2063 {
2064 notify_send(shared->notify, NT_INDEX, NT_INDEX_EMAIL, NULL);
2065 mutt_message(_("You are on the first message"));
2066 return FR_ERROR;
2067 }
2068 menu_set_index(priv->menu, index - 1);
2069 return FR_SUCCESS;
2070}
2071
2075static int op_print(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2076{
2077 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
2078 ea_add_tagged(&ea, shared->mailbox_view, shared->email, priv->tag_prefix);
2079 mutt_print_message(shared->mailbox, &ea);
2080 ARRAY_FREE(&ea);
2081
2082 /* in an IMAP folder index with imap_peek=no, printing could change
2083 * new or old messages status to read. Redraw what's needed. */
2084 const bool c_imap_peek = cs_subset_bool(shared->sub, "imap_peek");
2085 if ((shared->mailbox->type == MUTT_IMAP) && !c_imap_peek)
2086 {
2088 }
2089
2090 return FR_SUCCESS;
2091}
2092
2096static int op_query(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2097{
2098 query_index(shared->mailbox, shared->sub);
2099 return FR_SUCCESS;
2100}
2101
2105static int op_quit(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2106{
2107 if (shared->attach_msg)
2108 return FR_DONE;
2109
2110 if (query_quadoption(_("Quit NeoMutt?"), shared->sub, "quit") == MUTT_YES)
2111 {
2112 priv->oldcount = shared->mailbox ? shared->mailbox->msg_count : 0;
2113
2115 mutt_debug(LL_NOTIFY, "NT_GLOBAL_SHUTDOWN\n");
2117
2118 enum MxStatus check = MX_STATUS_OK;
2119 if (!shared->mailbox_view || ((check = mx_mbox_close(shared->mailbox)) == MX_STATUS_OK))
2120 {
2121 mview_free(&shared->mailbox_view);
2122 mailbox_free(&shared->mailbox);
2123 return FR_DONE;
2124 }
2125
2126 if ((check == MX_STATUS_NEW_MAIL) || (check == MX_STATUS_REOPENED))
2127 {
2128 update_index(priv->menu, shared->mailbox_view, check, priv->oldcount, shared);
2129 }
2130
2131 menu_queue_redraw(priv->menu, MENU_REDRAW_FULL); /* new mail arrived? */
2133 }
2134
2135 return FR_NO_ACTION;
2136}
2137
2141static int op_recall_message(struct IndexSharedData *shared,
2142 struct IndexPrivateData *priv, int op)
2143{
2144 int rc = mutt_send_message(SEND_POSTPONED, NULL, NULL, shared->mailbox, NULL,
2145 shared->sub);
2147 return (rc == -1) ? FR_ERROR : FR_SUCCESS;
2148}
2149
2153static int op_reply(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2154{
2155 if (!shared->email)
2156 return FR_NO_ACTION;
2157 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
2158 ea_add_tagged(&ea, shared->mailbox_view, shared->email, priv->tag_prefix);
2159 const bool c_pgp_auto_decode = cs_subset_bool(shared->sub, "pgp_auto_decode");
2160 if (c_pgp_auto_decode &&
2161 (priv->tag_prefix || !(shared->email->security & PGP_TRADITIONAL_CHECKED)))
2162 {
2163 if (mutt_check_traditional_pgp(shared->mailbox, &ea))
2165 }
2166 int rc = mutt_send_message(SEND_REPLY, NULL, NULL, shared->mailbox, &ea,
2167 shared->sub);
2168 ARRAY_FREE(&ea);
2170
2171 return (rc == -1) ? FR_ERROR : FR_SUCCESS;
2172}
2173
2177static int op_resend(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2178{
2179 int rc = -1;
2180 if (priv->tag_prefix)
2181 {
2182 struct Mailbox *m = shared->mailbox;
2183 for (size_t i = 0; i < m->msg_count; i++)
2184 {
2185 struct Email *e = m->emails[i];
2186 if (!e)
2187 break;
2188 if (message_is_tagged(e))
2189 rc = mutt_resend_message(NULL, shared->mailbox, e, shared->sub);
2190 }
2191 }
2192 else
2193 {
2194 rc = mutt_resend_message(NULL, shared->mailbox, shared->email, shared->sub);
2195 }
2196
2198 return (rc == -1) ? FR_ERROR : FR_SUCCESS;
2199}
2200
2212static int op_save(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2213{
2214 if (((op == OP_DECRYPT_COPY) || (op == OP_DECRYPT_SAVE)) && !WithCrypto)
2215 return FR_NOT_IMPL;
2216
2217 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
2218 ea_add_tagged(&ea, shared->mailbox_view, shared->email, priv->tag_prefix);
2219
2220 const enum MessageSaveOpt save_opt = ((op == OP_SAVE) || (op == OP_DECODE_SAVE) ||
2221 (op == OP_DECRYPT_SAVE)) ?
2222 SAVE_MOVE :
2223 SAVE_COPY;
2224
2225 enum MessageTransformOpt transform_opt =
2226 ((op == OP_DECODE_SAVE) || (op == OP_DECODE_COPY)) ? TRANSFORM_DECODE :
2227 ((op == OP_DECRYPT_SAVE) || (op == OP_DECRYPT_COPY)) ? TRANSFORM_DECRYPT :
2229
2230 const int rc = mutt_save_message(shared->mailbox, &ea, save_opt, transform_opt);
2231 if ((rc == 0) && (save_opt == SAVE_MOVE))
2232 {
2234 }
2235 ARRAY_FREE(&ea);
2236
2237 if (priv->tag_prefix)
2239
2240 return (rc == -1) ? FR_ERROR : FR_SUCCESS;
2241}
2242
2252static int op_search(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2253{
2255 switch (op)
2256 {
2257 case OP_SEARCH:
2258 flags |= SEARCH_PROMPT;
2259 shared->search_state->reverse = false;
2260 break;
2261 case OP_SEARCH_REVERSE:
2262 flags |= SEARCH_PROMPT;
2263 shared->search_state->reverse = true;
2264 break;
2265 case OP_SEARCH_NEXT:
2266 break;
2267 case OP_SEARCH_OPPOSITE:
2268 flags |= SEARCH_OPPOSITE;
2269 break;
2270 }
2271
2272 // Initiating a search can happen on an empty mailbox, but
2273 // searching for next/previous/... needs to be on a message and
2274 // thus a non-empty mailbox
2275 int index = menu_get_index(priv->menu);
2276 index = mutt_search_command(shared->mailbox_view, priv->menu, index,
2277 shared->search_state, flags);
2278 if (index != -1)
2279 menu_set_index(priv->menu, index);
2280
2281 return FR_SUCCESS;
2282}
2283
2291static int op_sort(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2292{
2293 if (!mutt_select_sort(op == OP_SORT_REVERSE))
2294 return FR_ERROR;
2295
2296 if (shared->mailbox && (shared->mailbox->msg_count != 0))
2297 {
2298 resort_index(shared->mailbox_view, priv->menu);
2300 }
2301
2302 return FR_SUCCESS;
2303}
2304
2308static int op_tag(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2309{
2310 const bool c_auto_tag = cs_subset_bool(shared->sub, "auto_tag");
2311 if (priv->tag_prefix && !c_auto_tag)
2312 {
2313 struct Mailbox *m = shared->mailbox;
2314 for (size_t i = 0; i < m->msg_count; i++)
2315 {
2316 struct Email *e = m->emails[i];
2317 if (!e)
2318 break;
2319 if (e->visible)
2320 mutt_set_flag(m, e, MUTT_TAG, false, true);
2321 }
2323 return FR_SUCCESS;
2324 }
2325
2326 if (!shared->email)
2327 return FR_NO_ACTION;
2328
2329 mutt_set_flag(shared->mailbox, shared->email, MUTT_TAG, !shared->email->tagged, true);
2330
2331 resolve_email(priv, shared, RESOLVE_NEXT_EMAIL);
2332 return FR_SUCCESS;
2333}
2334
2342static int op_tag_thread(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2343{
2344 if (!shared->email)
2345 return FR_NO_ACTION;
2346
2347 int rc = mutt_thread_set_flag(shared->mailbox, shared->email, MUTT_TAG,
2348 !shared->email->tagged, (op != OP_TAG_THREAD));
2349 if (rc != -1)
2350 {
2351 const enum ResolveMethod rm = (op == OP_TAG_THREAD) ? RESOLVE_NEXT_THREAD :
2353 resolve_email(priv, shared, rm);
2355 }
2356
2357 return FR_SUCCESS;
2358}
2359
2363static int op_toggle_new(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2364{
2365 /* L10N: CHECK_ACL */
2366 if (!check_acl(shared->mailbox, MUTT_ACL_SEEN, _("Can't toggle new")))
2367 return FR_ERROR;
2368
2369 struct Mailbox *m = shared->mailbox;
2370 if (priv->tag_prefix)
2371 {
2372 for (size_t i = 0; i < m->msg_count; i++)
2373 {
2374 struct Email *e = m->emails[i];
2375 if (!e)
2376 break;
2377 if (!message_is_tagged(e))
2378 continue;
2379
2380 if (e->read || e->old)
2381 mutt_set_flag(m, e, MUTT_NEW, true, true);
2382 else
2383 mutt_set_flag(m, e, MUTT_READ, true, true);
2384 }
2386 }
2387 else
2388 {
2389 if (!shared->email)
2390 return FR_NO_ACTION;
2391 if (shared->email->read || shared->email->old)
2392 mutt_set_flag(m, shared->email, MUTT_NEW, true, true);
2393 else
2394 mutt_set_flag(m, shared->email, MUTT_READ, true, true);
2395
2397 }
2398
2399 return FR_SUCCESS;
2400}
2401
2405static int op_toggle_write(struct IndexSharedData *shared,
2406 struct IndexPrivateData *priv, int op)
2407{
2408 mx_toggle_write(shared->mailbox);
2409 return FR_SUCCESS;
2410}
2411
2415static int op_undelete(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2416{
2417 /* L10N: CHECK_ACL */
2418 if (!check_acl(shared->mailbox, MUTT_ACL_DELETE, _("Can't undelete message")))
2419 return FR_ERROR;
2420
2421 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
2422 ea_add_tagged(&ea, shared->mailbox_view, shared->email, priv->tag_prefix);
2423
2424 mutt_emails_set_flag(shared->mailbox, &ea, MUTT_DELETE, false);
2425 mutt_emails_set_flag(shared->mailbox, &ea, MUTT_PURGE, false);
2426 ARRAY_FREE(&ea);
2427
2428 if (priv->tag_prefix)
2429 {
2431 }
2432 else
2433 {
2434 resolve_email(priv, shared, RESOLVE_NEXT_EMAIL);
2435 }
2436
2437 return FR_SUCCESS;
2438}
2439
2447static int op_undelete_thread(struct IndexSharedData *shared,
2448 struct IndexPrivateData *priv, int op)
2449{
2450 /* L10N: CHECK_ACL */
2451 /* L10N: Due to the implementation details we do not know whether we
2452 undelete zero, 1, 12, ... messages. So in English we use
2453 "messages". Your language might have other means to express this. */
2454 if (!check_acl(shared->mailbox, MUTT_ACL_DELETE, _("Can't undelete messages")))
2455 return FR_ERROR;
2456
2457 int rc = mutt_thread_set_flag(shared->mailbox, shared->email, MUTT_DELETE,
2458 false, (op != OP_UNDELETE_THREAD));
2459 if (rc != -1)
2460 {
2461 rc = mutt_thread_set_flag(shared->mailbox, shared->email, MUTT_PURGE, false,
2462 (op != OP_UNDELETE_THREAD));
2463 }
2464 if (rc != -1)
2465 {
2466 const enum ResolveMethod rm = (op == OP_UNDELETE_THREAD) ? RESOLVE_NEXT_THREAD :
2468 resolve_email(priv, shared, rm);
2470 }
2471
2472 return FR_SUCCESS;
2473}
2474
2478static int op_view_attachments(struct IndexSharedData *shared,
2479 struct IndexPrivateData *priv, int op)
2480{
2481 if (!shared->email)
2482 return FR_NO_ACTION;
2483
2484 enum FunctionRetval rc = FR_ERROR;
2485 struct Message *msg = mx_msg_open(shared->mailbox, shared->email);
2486 if (msg)
2487 {
2488 dlg_attachment(NeoMutt->sub, shared->mailbox_view, shared->email, msg->fp,
2489 shared->attach_msg);
2490 if (shared->email->attach_del)
2491 {
2492 shared->mailbox->changed = true;
2493 }
2494 mx_msg_close(shared->mailbox, &msg);
2495 rc = FR_SUCCESS;
2496 }
2498 return rc;
2499}
2500
2501// -----------------------------------------------------------------------------
2502
2503#ifdef USE_AUTOCRYPT
2507static int op_autocrypt_acct_menu(struct IndexSharedData *shared,
2508 struct IndexPrivateData *priv, int op)
2509{
2510 dlg_autocrypt();
2511 return FR_SUCCESS;
2512}
2513#endif
2514
2518static int op_main_imap_fetch(struct IndexSharedData *shared,
2519 struct IndexPrivateData *priv, int op)
2520{
2521 if (!shared->mailbox || (shared->mailbox->type != MUTT_IMAP))
2522 return FR_NO_ACTION;
2523
2524 imap_check_mailbox(shared->mailbox, true);
2525 return FR_SUCCESS;
2526}
2527
2532 struct IndexPrivateData *priv, int op)
2533{
2534 if (shared->mailbox && (shared->mailbox->type == MUTT_IMAP))
2535 {
2536 const enum MxStatus check = mx_mbox_close(shared->mailbox);
2537 if (check == MX_STATUS_OK)
2538 {
2539 mview_free(&shared->mailbox_view);
2540 }
2541 else
2542 {
2543 if ((check == MX_STATUS_NEW_MAIL) || (check == MX_STATUS_REOPENED))
2544 {
2545 update_index(priv->menu, shared->mailbox_view, check, priv->oldcount, shared);
2546 }
2549 return FR_ERROR;
2550 }
2551 }
2553 mutt_message(_("Logged out of IMAP servers"));
2556
2557 return FR_SUCCESS;
2558}
2559
2563static int op_catchup(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2564{
2565 struct Mailbox *m = shared->mailbox;
2566 if (!m || (m->type != MUTT_NNTP))
2567 return FR_NO_ACTION;
2568
2569 struct NntpMboxData *mdata = m->mdata;
2570 if (mutt_newsgroup_catchup(m, mdata->adata, mdata->group))
2572
2573 return FR_SUCCESS;
2574}
2575
2583static int op_get_children(struct IndexSharedData *shared,
2584 struct IndexPrivateData *priv, int op)
2585{
2586 struct Mailbox *m = shared->mailbox;
2587 if (m->type != MUTT_NNTP)
2588 return FR_ERROR;
2589
2590 struct Email *e = shared->email;
2591 if (!e)
2592 return FR_NO_ACTION;
2593
2594 char buf[PATH_MAX] = { 0 };
2595 int oldmsgcount = m->msg_count;
2596 int oldindex = e->index;
2597 int rc = 0;
2598
2599 if (!e->env->message_id)
2600 {
2601 mutt_error(_("No Message-Id. Unable to perform operation."));
2602 return FR_ERROR;
2603 }
2604
2605 mutt_message(_("Fetching message headers..."));
2606 if (!m->id_hash)
2607 m->id_hash = mutt_make_id_hash(m);
2608 mutt_str_copy(buf, e->env->message_id, sizeof(buf));
2609
2610 /* trying to find msgid of the root message */
2611 if (op == OP_RECONSTRUCT_THREAD)
2612 {
2613 struct ListNode *ref = NULL;
2614 STAILQ_FOREACH(ref, &e->env->references, entries)
2615 {
2616 if (!mutt_hash_find(m->id_hash, ref->data))
2617 {
2618 rc = nntp_check_msgid(m, ref->data);
2619 if (rc < 0)
2620 return FR_ERROR;
2621 }
2622
2623 /* the last msgid in References is the root message */
2624 if (!STAILQ_NEXT(ref, entries))
2625 mutt_str_copy(buf, ref->data, sizeof(buf));
2626 }
2627 }
2628
2629 /* fetching all child messages */
2630 rc = nntp_check_children(m, buf);
2631
2632 /* at least one message has been loaded */
2633 if (m->msg_count > oldmsgcount)
2634 {
2635 bool verbose = m->verbose;
2636
2637 if (rc < 0)
2638 m->verbose = false;
2639
2640 struct MailboxView *mv = shared->mailbox_view;
2641 mutt_sort_headers(mv, (op == OP_RECONSTRUCT_THREAD));
2642 m->verbose = verbose;
2643
2644 /* if the root message was retrieved, move to it */
2645 struct Email *e2 = mutt_hash_find(m->id_hash, buf);
2646 if (e2)
2647 {
2648 menu_set_index(priv->menu, e2->vnum);
2649 }
2650 else
2651 {
2652 /* try to restore old position */
2653 for (int i = 0; i < m->msg_count; i++)
2654 {
2655 e2 = m->emails[i];
2656 if (!e2)
2657 break;
2658 if (e2->index == oldindex)
2659 {
2660 menu_set_index(priv->menu, e2->vnum);
2661 /* as an added courtesy, recenter the menu
2662 * with the current entry at the middle of the screen */
2664 }
2665 }
2666 }
2668 }
2669 else if (rc >= 0)
2670 {
2671 mutt_error(_("No deleted messages found in the thread"));
2672 }
2673
2674 return FR_SUCCESS;
2675}
2676
2684static int op_get_message(struct IndexSharedData *shared,
2685 struct IndexPrivateData *priv, int op)
2686{
2687 struct Mailbox *m = shared->mailbox;
2688 if (m->type != MUTT_NNTP)
2689 return FR_SUCCESS;
2690
2691 int rc = FR_ERROR;
2692 struct Buffer *buf = buf_pool_get();
2693
2694 if (op == OP_GET_MESSAGE)
2695 {
2696 if ((mw_get_field(_("Enter Message-Id: "), buf, MUTT_COMP_NO_FLAGS,
2697 HC_OTHER, NULL, NULL) != 0) ||
2698 buf_is_empty(buf))
2699 {
2700 goto done;
2701 }
2702 }
2703 else
2704 {
2705 struct Email *e = shared->email;
2706 if (!e || STAILQ_EMPTY(&e->env->references))
2707 {
2708 mutt_error(_("Article has no parent reference"));
2709 goto done;
2710 }
2711 buf_strcpy(buf, STAILQ_FIRST(&e->env->references)->data);
2712 }
2713
2714 if (!m->id_hash)
2715 m->id_hash = mutt_make_id_hash(m);
2716 struct Email *e = mutt_hash_find(m->id_hash, buf_string(buf));
2717 if (e)
2718 {
2719 if (e->vnum != -1)
2720 {
2721 menu_set_index(priv->menu, e->vnum);
2722 }
2723 else if (e->collapsed)
2724 {
2726 mutt_set_vnum(m);
2727 menu_set_index(priv->menu, e->vnum);
2728 }
2729 else
2730 {
2731 mutt_error(_("Message is not visible in limited view"));
2732 }
2733 }
2734 else
2735 {
2736 mutt_message(_("Fetching %s from server..."), buf_string(buf));
2737 int rc2 = nntp_check_msgid(m, buf_string(buf));
2738 if (rc2 == 0)
2739 {
2740 e = m->emails[m->msg_count - 1];
2741 struct MailboxView *mv = shared->mailbox_view;
2742 mutt_sort_headers(mv, false);
2743 menu_set_index(priv->menu, e->vnum);
2745 rc = FR_SUCCESS;
2746 }
2747 else if (rc2 > 0)
2748 {
2749 mutt_error(_("Article %s not found on the server"), buf_string(buf));
2750 }
2751 }
2752
2753done:
2754 buf_pool_release(&buf);
2755 return rc;
2756}
2757
2765static int op_main_change_group(struct IndexSharedData *shared,
2766 struct IndexPrivateData *priv, int op)
2767{
2768 struct Buffer *folderbuf = buf_pool_get();
2769 buf_alloc(folderbuf, PATH_MAX);
2770
2771 OptNews = false;
2772 bool read_only;
2773 char *cp = NULL;
2774 const bool c_read_only = cs_subset_bool(shared->sub, "read_only");
2775 if (shared->attach_msg || c_read_only || (op == OP_MAIN_CHANGE_GROUP_READONLY))
2776 {
2777 cp = _("Open newsgroup in read-only mode");
2778 read_only = true;
2779 }
2780 else
2781 {
2782 cp = _("Open newsgroup");
2783 read_only = false;
2784 }
2785
2786 const bool c_change_folder_next = cs_subset_bool(shared->sub, "change_folder_next");
2787 if (c_change_folder_next && shared->mailbox && !buf_is_empty(&shared->mailbox->pathbuf))
2788 {
2789 buf_strcpy(folderbuf, mailbox_path(shared->mailbox));
2790 buf_pretty_mailbox(folderbuf);
2791 }
2792
2793 OptNews = true;
2794 const char *const c_news_server = cs_subset_string(shared->sub, "news_server");
2795 if (!CurrentNewsSrv)
2796 CurrentNewsSrv = nntp_select_server(shared->mailbox, c_news_server, false);
2797 if (!CurrentNewsSrv)
2798 goto changefoldercleanup2;
2799
2800 nntp_mailbox(shared->mailbox, folderbuf->data, folderbuf->dsize);
2801
2802 if (mw_enter_fname(cp, folderbuf, true, shared->mailbox, false, NULL, NULL,
2803 MUTT_SEL_NO_FLAGS) == -1)
2804 {
2805 goto changefoldercleanup2;
2806 }
2807
2808 /* Selected directory is okay, let's save it. */
2810
2811 if (buf_is_empty(folderbuf))
2812 {
2813 msgwin_clear_text(NULL);
2814 goto changefoldercleanup2;
2815 }
2816
2817 struct Mailbox *m = mx_mbox_find2(buf_string(folderbuf));
2818 if (m)
2819 {
2820 change_folder_mailbox(priv->menu, m, &priv->oldcount, shared, read_only);
2821 }
2822 else
2823 {
2824 change_folder_string(priv->menu, folderbuf, &priv->oldcount, shared, read_only);
2825 }
2826 struct MuttWindow *dlg = dialog_find(priv->win_index);
2827 dlg->help_data = IndexNewsHelp;
2828
2829changefoldercleanup2:
2830 buf_pool_release(&folderbuf);
2831 return FR_SUCCESS;
2832}
2833
2841static int op_post(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2842{
2843 if (!shared->email)
2844 return FR_NO_ACTION;
2845
2846 if ((op != OP_FOLLOWUP) || !shared->email->env->followup_to ||
2847 !mutt_istr_equal(shared->email->env->followup_to, "poster") ||
2848 (query_quadoption(_("Reply by mail as poster prefers?"), shared->sub,
2849 "followup_to_poster") != MUTT_YES))
2850 {
2851 if (shared->mailbox && (shared->mailbox->type == MUTT_NNTP) &&
2852 !((struct NntpMboxData *) shared->mailbox->mdata)->allowed &&
2853 (query_quadoption(_("Posting to this group not allowed, may be moderated. Continue?"),
2854 shared->sub, "post_moderated") != MUTT_YES))
2855 {
2856 return FR_ERROR;
2857 }
2858 if (op == OP_POST)
2859 {
2860 mutt_send_message(SEND_NEWS, NULL, NULL, shared->mailbox, NULL, shared->sub);
2861 }
2862 else
2863 {
2864 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
2865 ea_add_tagged(&ea, shared->mailbox_view, shared->email, priv->tag_prefix);
2866 mutt_send_message(((op == OP_FOLLOWUP) ? SEND_REPLY : SEND_FORWARD) | SEND_NEWS,
2867 NULL, NULL, shared->mailbox, &ea, shared->sub);
2868 ARRAY_FREE(&ea);
2869 }
2871 return FR_SUCCESS;
2872 }
2873
2874 return op_reply(shared, priv, OP_REPLY);
2875}
2876
2877#ifdef USE_NOTMUCH
2881static int op_main_entire_thread(struct IndexSharedData *shared,
2882 struct IndexPrivateData *priv, int op)
2883{
2884 if (shared->mailbox->type != MUTT_NOTMUCH)
2885 {
2886 if (((shared->mailbox->type != MUTT_MH) && (shared->mailbox->type != MUTT_MAILDIR)) ||
2887 (!shared->email || !shared->email->env || !shared->email->env->message_id))
2888 {
2889 mutt_message(_("No virtual folder and no Message-Id, aborting"));
2890 return FR_ERROR;
2891 } // no virtual folder, but we have message-id, reconstruct thread on-the-fly
2892
2893 struct Buffer *buf = buf_pool_get();
2894 buf_alloc(buf, PATH_MAX);
2895 buf_addstr(buf, "id:");
2896
2897 int msg_id_offset = 0;
2898 if ((shared->email->env->message_id)[0] == '<')
2899 msg_id_offset = 1;
2900
2901 buf_addstr(buf, shared->email->env->message_id + msg_id_offset);
2902
2903 size_t len = buf_len(buf);
2904 if (buf->data[len - 1] == '>')
2905 buf->data[len - 1] = '\0';
2906
2907 change_folder_notmuch(priv->menu, buf->data, buf->dsize, &priv->oldcount, shared, false);
2908 buf_pool_release(&buf);
2909
2910 // If notmuch doesn't contain the message, we're left in an empty
2911 // vfolder. No messages are found, but nm_read_entire_thread assumes
2912 // a valid message-id and will throw a segfault.
2913 //
2914 // To prevent that, stay in the empty vfolder and print an error.
2915 if (shared->mailbox->msg_count == 0)
2916 {
2917 mutt_error(_("failed to find message in notmuch database. try running 'notmuch new'."));
2918 return FR_ERROR;
2919 }
2920 }
2921 priv->oldcount = shared->mailbox->msg_count;
2922 int index = menu_get_index(priv->menu);
2923 struct Email *e_oldcur = mutt_get_virt_email(shared->mailbox, index);
2924 if (!e_oldcur)
2925 return FR_ERROR;
2926
2927 if (nm_read_entire_thread(shared->mailbox, e_oldcur) < 0)
2928 {
2929 mutt_message(_("Failed to read thread, aborting"));
2930 return FR_ERROR;
2931 }
2932
2933 // nm_read_entire_thread() may modify msg_count and menu won't be updated.
2934 priv->menu->max = shared->mailbox->msg_count;
2935
2936 if (priv->oldcount < shared->mailbox->msg_count)
2937 {
2938 /* nm_read_entire_thread() triggers mutt_sort_headers() if necessary */
2939 index = e_oldcur->vnum;
2940 if (e_oldcur->collapsed || shared->mailbox_view->collapsed)
2941 {
2942 index = mutt_uncollapse_thread(e_oldcur);
2943 mutt_set_vnum(shared->mailbox);
2944 }
2945 menu_set_index(priv->menu, index);
2947 }
2948
2949 return FR_SUCCESS;
2950}
2951
2960 struct IndexPrivateData *priv, int op)
2961{
2962 int rc = FR_SUCCESS;
2963 struct Buffer *buf = buf_pool_get();
2964
2965 if ((mw_get_field("Query: ", buf, MUTT_COMP_NO_FLAGS, HC_OTHER,
2966 &CompleteNmQueryOps, NULL) != 0) ||
2967 buf_is_empty(buf))
2968 {
2969 mutt_message(_("No query, aborting"));
2970 rc = FR_NO_ACTION;
2971 goto done;
2972 }
2973
2974 // Keep copy of user's query to name the mailbox
2975 char *query_unencoded = buf_strdup(buf);
2976
2977 buf_alloc(buf, PATH_MAX);
2978 struct Mailbox *m_query = change_folder_notmuch(priv->menu, buf->data, buf->dsize,
2979 &priv->oldcount, shared,
2980 (op == OP_MAIN_VFOLDER_FROM_QUERY_READONLY));
2981 if (m_query)
2982 {
2983 FREE(&m_query->name);
2984 m_query->name = query_unencoded;
2985 query_unencoded = NULL;
2986 rc = FR_SUCCESS;
2987 }
2988 else
2989 {
2990 FREE(&query_unencoded);
2991 }
2992
2993done:
2994 buf_pool_release(&buf);
2995 return rc;
2996}
2997
3007 struct IndexPrivateData *priv, int op)
3008{
3009 // Common guard clauses.
3011 {
3012 mutt_message(_("Windowed queries disabled"));
3013 return FR_ERROR;
3014 }
3015 const char *const c_nm_query_window_current_search = cs_subset_string(shared->sub, "nm_query_window_current_search");
3016 if (!c_nm_query_window_current_search)
3017 {
3018 mutt_message(_("No notmuch vfolder currently loaded"));
3019 return FR_ERROR;
3020 }
3021
3022 // Call the specific operation.
3023 switch (op)
3024 {
3025 case OP_MAIN_WINDOWED_VFOLDER_BACKWARD:
3027 break;
3028 case OP_MAIN_WINDOWED_VFOLDER_FORWARD:
3030 break;
3031 case OP_MAIN_WINDOWED_VFOLDER_RESET:
3033 break;
3034 }
3035
3036 // Common query window folder change.
3037 char buf[PATH_MAX] = { 0 };
3038 mutt_str_copy(buf, c_nm_query_window_current_search, sizeof(buf));
3039 change_folder_notmuch(priv->menu, buf, sizeof(buf), &priv->oldcount, shared, false);
3040
3041 return FR_SUCCESS;
3042}
3043#endif
3044
3048static int op_main_fetch_mail(struct IndexSharedData *shared,
3049 struct IndexPrivateData *priv, int op)
3050{
3053 return FR_SUCCESS;
3054}
3055
3056// -----------------------------------------------------------------------------
3057
3065static bool prereq(struct IndexSharedData *shared, struct Menu *menu, CheckFlags checks)
3066{
3067 bool result = true;
3068 struct MailboxView *mv = shared->mailbox_view;
3069
3070 if (checks & (CHECK_MSGCOUNT | CHECK_VISIBLE | CHECK_READONLY))
3071 checks |= CHECK_IN_MAILBOX;
3072
3073 if ((checks & CHECK_IN_MAILBOX) && (!mv || !mv->mailbox))
3074 {
3075 mutt_error(_("No mailbox is open"));
3076 result = false;
3077 }
3078
3079 if (result && (checks & CHECK_MSGCOUNT) && (mv->mailbox->msg_count == 0))
3080 {
3081 mutt_error(_("There are no messages"));
3082 result = false;
3083 }
3084
3085 int index = menu_get_index(menu);
3086 if (result && (checks & CHECK_VISIBLE) &&
3087 ((index < 0) || (index >= mv->mailbox->vcount)))
3088 {
3089 mutt_error(_("No visible messages"));
3090 result = false;
3091 }
3092
3093 if (result && (checks & CHECK_READONLY) && mv->mailbox->readonly)
3094 {
3095 mutt_error(_("Mailbox is read-only"));
3096 result = false;
3097 }
3098
3099 if (result && (checks & CHECK_ATTACH) && shared->attach_msg)
3100 {
3101 mutt_error(_("Function not permitted in attach-message mode"));
3102 result = false;
3103 }
3104
3105 if (!result)
3106 mutt_flushinp();
3107
3108 return result;
3109}
3110
3114static const struct IndexFunction IndexFunctions[] = {
3115 // clang-format off
3116 { OP_ALIAS_DIALOG, op_alias_dialog, CHECK_NO_FLAGS },
3122 { OP_COPY_MESSAGE, op_save, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3123 { OP_CREATE_ALIAS, op_create_alias, CHECK_NO_FLAGS },
3124 { OP_DECODE_COPY, op_save, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3125 { OP_DECODE_SAVE, op_save, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3126 { OP_DECRYPT_COPY, op_save, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3127 { OP_DECRYPT_SAVE, op_save, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3135 { OP_EDIT_OR_VIEW_RAW_MESSAGE, op_edit_raw_message, CHECK_ATTACH | CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3137 { OP_END_COND, op_end_cond, CHECK_NO_FLAGS },
3138 { OP_EXIT, op_exit, CHECK_NO_FLAGS },
3142 { OP_FORGET_PASSPHRASE, op_forget_passphrase, CHECK_NO_FLAGS },
3144 { OP_FORWARD_TO_GROUP, op_post, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3148 { OP_GENERIC_SELECT_ENTRY, op_display_message, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3151 { OP_JUMP, op_jump, CHECK_IN_MAILBOX },
3152 { OP_JUMP_1, op_jump, CHECK_IN_MAILBOX },
3153 { OP_JUMP_2, op_jump, CHECK_IN_MAILBOX },
3154 { OP_JUMP_3, op_jump, CHECK_IN_MAILBOX },
3155 { OP_JUMP_4, op_jump, CHECK_IN_MAILBOX },
3156 { OP_JUMP_5, op_jump, CHECK_IN_MAILBOX },
3157 { OP_JUMP_6, op_jump, CHECK_IN_MAILBOX },
3158 { OP_JUMP_7, op_jump, CHECK_IN_MAILBOX },
3159 { OP_JUMP_8, op_jump, CHECK_IN_MAILBOX },
3160 { OP_JUMP_9, op_jump, CHECK_IN_MAILBOX },
3161 { OP_LIMIT_CURRENT_THREAD, op_main_limit, CHECK_IN_MAILBOX },
3165 { OP_MAIL, op_mail, CHECK_ATTACH },
3166 { OP_MAILBOX_LIST, op_mailbox_list, CHECK_NO_FLAGS },
3167 { OP_MAIL_KEY, op_mail_key, CHECK_ATTACH },
3169 { OP_MAIN_CHANGE_FOLDER, op_main_change_folder, CHECK_NO_FLAGS },
3170 { OP_MAIN_CHANGE_FOLDER_READONLY, op_main_change_folder, CHECK_NO_FLAGS },
3171 { OP_MAIN_CHANGE_GROUP, op_main_change_group, CHECK_NO_FLAGS },
3172 { OP_MAIN_CHANGE_GROUP_READONLY, op_main_change_group, CHECK_NO_FLAGS },
3174 { OP_MAIN_COLLAPSE_ALL, op_main_collapse_all, CHECK_IN_MAILBOX },
3175 { OP_MAIN_COLLAPSE_THREAD, op_main_collapse_thread, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3176 { OP_MAIN_DELETE_PATTERN, op_main_delete_pattern, CHECK_ATTACH | CHECK_IN_MAILBOX | CHECK_READONLY },
3177 { OP_MAIN_FETCH_MAIL, op_main_fetch_mail, CHECK_ATTACH },
3178 { OP_MAIN_IMAP_FETCH, op_main_imap_fetch, CHECK_NO_FLAGS },
3179 { OP_MAIN_IMAP_LOGOUT_ALL, op_main_imap_logout_all, CHECK_NO_FLAGS },
3180 { OP_MAIN_LIMIT, op_main_limit, CHECK_IN_MAILBOX },
3183 { OP_MAIN_MODIFY_TAGS_THEN_HIDE, op_main_modify_tags, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_READONLY | CHECK_VISIBLE },
3185 { OP_MAIN_NEXT_NEW_THEN_UNREAD, op_main_next_new, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3186 { OP_MAIN_NEXT_SUBTHREAD, op_main_next_thread, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3189 { OP_MAIN_NEXT_UNREAD, op_main_next_new, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3190 { OP_MAIN_NEXT_UNREAD_MAILBOX, op_main_next_unread_mailbox, CHECK_IN_MAILBOX },
3191 { OP_MAIN_PARENT_MESSAGE, op_main_root_message, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3193 { OP_MAIN_PREV_NEW_THEN_UNREAD, op_main_next_new, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3194 { OP_MAIN_PREV_SUBTHREAD, op_main_next_thread, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3197 { OP_MAIN_PREV_UNREAD, op_main_next_new, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3203 { OP_MAIN_SHOW_LIMIT, op_main_show_limit, CHECK_IN_MAILBOX },
3204 { OP_MAIN_SYNC_FOLDER, op_main_sync_folder, CHECK_NO_FLAGS },
3205 { OP_MAIN_TAG_PATTERN, op_main_tag_pattern, CHECK_IN_MAILBOX },
3206 { OP_MAIN_UNDELETE_PATTERN, op_main_undelete_pattern, CHECK_IN_MAILBOX | CHECK_READONLY },
3207 { OP_MAIN_UNTAG_PATTERN, op_main_untag_pattern, CHECK_IN_MAILBOX },
3211 { OP_POST, op_post, CHECK_ATTACH | CHECK_IN_MAILBOX },
3216 { OP_QUERY, op_query, CHECK_ATTACH },
3217 { OP_QUIT, op_quit, CHECK_NO_FLAGS },
3218 { OP_RECALL_MESSAGE, op_recall_message, CHECK_ATTACH },
3223 { OP_SEARCH, op_search, CHECK_IN_MAILBOX },
3224 { OP_SEARCH_NEXT, op_search, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3225 { OP_SEARCH_OPPOSITE, op_search, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3226 { OP_SEARCH_REVERSE, op_search, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3227 { OP_SORT, op_sort, CHECK_NO_FLAGS },
3228 { OP_SORT_REVERSE, op_sort, CHECK_NO_FLAGS },
3233 { OP_TOGGLE_READ, op_main_limit, CHECK_IN_MAILBOX },
3234 { OP_TOGGLE_WRITE, op_toggle_write, CHECK_IN_MAILBOX },
3240#ifdef USE_AUTOCRYPT
3241 { OP_AUTOCRYPT_ACCT_MENU, op_autocrypt_acct_menu, CHECK_NO_FLAGS },
3242#endif
3243#ifdef USE_NOTMUCH
3244 { OP_MAIN_CHANGE_VFOLDER, op_main_change_folder, CHECK_NO_FLAGS },
3246 { OP_MAIN_VFOLDER_FROM_QUERY, op_main_vfolder_from_query, CHECK_NO_FLAGS },
3247 { OP_MAIN_VFOLDER_FROM_QUERY_READONLY, op_main_vfolder_from_query, CHECK_NO_FLAGS },
3248 { OP_MAIN_WINDOWED_VFOLDER_BACKWARD, op_main_windowed_vfolder, CHECK_IN_MAILBOX },
3249 { OP_MAIN_WINDOWED_VFOLDER_FORWARD, op_main_windowed_vfolder, CHECK_IN_MAILBOX },
3250 { OP_MAIN_WINDOWED_VFOLDER_RESET, op_main_windowed_vfolder, CHECK_IN_MAILBOX },
3251#endif
3252 { 0, NULL, CHECK_NO_FLAGS },
3253 // clang-format on
3254};
3255
3260{
3261 // The Dispatcher may be called on any Window in the Dialog
3262 struct MuttWindow *dlg = dialog_find(win);
3263 if (!dlg || !dlg->wdata || !win->parent || !win->parent->wdata)
3264 return FR_ERROR;
3265
3266 struct IndexPrivateData *priv = win->parent->wdata;
3267 struct IndexSharedData *shared = dlg->wdata;
3268
3269 int rc = FR_UNKNOWN;
3270 for (size_t i = 0; IndexFunctions[i].op != OP_NULL; i++)
3271 {
3272 const struct IndexFunction *fn = &IndexFunctions[i];
3273 if (fn->op == op)
3274 {
3275 if (!prereq(shared, priv->menu, fn->flags))
3276 {
3277 rc = FR_ERROR;
3278 break;
3279 }
3280 rc = fn->function(shared, priv, op);
3281 break;
3282 }
3283 }
3284
3285 if (rc == FR_UNKNOWN) // Not our function
3286 return rc;
3287
3288 const char *result = dispatcher_get_retval_name(rc);
3289 mutt_debug(LL_DEBUG1, "Handled %s (%d) -> %s\n", opcodes_get_name(op), op, NONULL(result));
3290
3291 return rc;
3292}
Email Aliases.
void alias_create(struct AddressList *al, const struct ConfigSubset *sub)
Create a new Alias from an Address.
Definition: alias.c:367
struct AddressList * mutt_get_address(struct Envelope *env, const char **prefix)
Get an Address from an Envelope.
Definition: alias.c:327
#define ARRAY_FREE(head)
Release all memory.
Definition: array.h:204
#define ARRAY_HEAD_INITIALIZER
Static initializer for arrays.
Definition: array.h:58
GUI display the mailboxes in a side panel.
Autocrypt end-to-end encryption.
int bool_str_toggle(struct ConfigSubset *sub, const char *name, struct Buffer *err)
Toggle the value of a bool.
Definition: bool.c:224
Select a Mailbox from a list.
#define MUTT_SEL_NO_FLAGS
No flags are set.
Definition: lib.h:56
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:161
size_t buf_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:491
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:291
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:226
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:395
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:571
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:337
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:96
void mutt_pattern_free(struct PatternList **pat)
Free a Pattern.
Definition: compile.c:778
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:291
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.
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:89
@ NT_MAILBOX_CHANGE
Mailbox has been changed.
Definition: mailbox.h:185
#define MUTT_ACL_INSERT
Add/copy into the mailbox (used when editing a message)
Definition: mailbox.h:66
#define MUTT_ACL_DELETE
Delete a message.
Definition: mailbox.h:63
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
Definition: mailbox.h:223
#define MUTT_ACL_WRITE
Write to a message (for flagging or linking threads)
Definition: mailbox.h:71
@ MUTT_NOTMUCH
'Notmuch' (virtual) Mailbox type
Definition: mailbox.h:51
@ MUTT_MH
'MH' Mailbox type
Definition: mailbox.h:47
@ MUTT_NNTP
'NNTP' (Usenet) Mailbox type
Definition: mailbox.h:49
@ MUTT_IMAP
'IMAP' Mailbox type
Definition: mailbox.h:50
@ MUTT_MAILDIR
'Maildir' Mailbox type
Definition: mailbox.h:48
#define MUTT_ACL_SEEN
Change the 'seen' status of a message.
Definition: mailbox.h:70
void crypt_extract_keys_from_messages(struct Mailbox *m, struct EmailArray *ea)
Extract keys from a message.
Definition: crypt.c:858
void crypt_forget_passphrase(void)
Forget a passphrase and display a message.
Definition: crypt.c:90
int digit(const char *s)
void mutt_flushinp(void)
Empty all the keyboard buffers.
Definition: get.c:58
void mutt_unget_ch(int ch)
Return a keystroke to the input buffer.
Definition: get.c:115
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
FunctionRetval
Possible return values for NeoMutt functions.
Definition: dispatcher.h:32
@ 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
void alias_dialog(struct Mailbox *m, struct ConfigSubset *sub)
Open the aliases dialog.
Definition: dlg_alias.c:566
void mutt_browser_select_dir(const char *f)
Remember the last directory selected.
Definition: dlg_browser.c:1264
bool check_acl(struct Mailbox *m, AclFlags acl, const char *msg)
Check the ACLs for a function.
Definition: dlg_index.c:139
const struct Mapping IndexNewsHelp[]
Help Bar for the News Index dialog.
Definition: dlg_index.c:118
void change_folder_mailbox(struct Menu *menu, struct Mailbox *m, int *oldcount, struct IndexSharedData *shared, bool read_only)
Change to a different Mailbox by pointer.
Definition: dlg_index.c:612
struct Mailbox * change_folder_notmuch(struct Menu *menu, char *buf, int buflen, int *oldcount, struct IndexSharedData *shared, bool read_only)
Change to a different Notmuch Mailbox by string.
Definition: dlg_index.c:733
void update_index(struct Menu *menu, struct MailboxView *mv, enum MxStatus check, int oldcount, const struct IndexSharedData *shared)
Update the index.
Definition: dlg_index.c:543
int find_first_message(struct MailboxView *mv)
Get index of first new message.
Definition: dlg_index.c:310
void resort_index(struct MailboxView *mv, struct Menu *menu)
Resort the index.
Definition: dlg_index.c:370
int find_next_undeleted(struct MailboxView *mv, int msgno, bool uncollapse)
Find the next undeleted email.
Definition: dlg_index.c:242
void collapse_all(struct MailboxView *mv, struct Menu *menu, int toggle)
Collapse/uncollapse all threads.
Definition: dlg_index.c:166
void change_folder_string(struct Menu *menu, struct Buffer *buf, int *oldcount, struct IndexSharedData *shared, bool read_only)
Change to a different Mailbox by string.
Definition: dlg_index.c:758
int find_previous_undeleted(struct MailboxView *mv, int msgno, bool uncollapse)
Find the previous undeleted email.
Definition: dlg_index.c:276
void query_index(struct Mailbox *m, struct ConfigSubset *sub)
Perform an Alias Query and display the results.
Definition: dlg_query.c:556
int mutt_ev_message(struct Mailbox *m, struct EmailArray *ea, enum EvMessage action)
Edit or view a message.
Definition: editmsg.c:284
Edit a string.
Structs that make up an email.
void mutt_print_message(struct Mailbox *m, struct EmailArray *ea)
Print a message.
Definition: external.c:438
bool mutt_select_sort(bool reverse)
Ask the user for a sort method.
Definition: external.c:476
void mutt_pipe_message(struct Mailbox *m, struct EmailArray *ea)
Pipe a message.
Definition: external.c:407
bool mutt_check_traditional_pgp(struct Mailbox *m, struct EmailArray *ea)
Check if a message has inline PGP content.
Definition: external.c:1211
void index_bounce_message(struct Mailbox *m, struct EmailArray *ea)
Bounce an email.
Definition: external.c:90
int mutt_save_message(struct Mailbox *m, struct EmailArray *ea, enum MessageSaveOpt save_opt, enum MessageTransformOpt transform_opt)
Save an email.
Definition: external.c:778
bool mutt_edit_content_type(struct Email *e, struct Body *b, FILE *fp)
Edit the content type of an attachment.
Definition: external.c:1070
void mutt_display_address(struct Envelope *env)
Display the address of a message.
Definition: external.c:661
Manage where the email is piped to external commands.
MessageTransformOpt
Message transformation option.
Definition: external.h:41
@ TRANSFORM_NONE
No transformation.
Definition: external.h:42
@ TRANSFORM_DECODE
Decode message.
Definition: external.h:44
@ TRANSFORM_DECRYPT
Decrypt message.
Definition: external.h:43
MessageSaveOpt
Message save option.
Definition: external.h:51
@ SAVE_MOVE
Move message to another mailbox, removing the original.
Definition: external.h:53
@ SAVE_COPY
Copy message, making a duplicate in another mailbox.
Definition: external.h:52
int mutt_file_sanitize_regex(struct Buffer *dest, const char *src)
Escape any regex-magic characters in a string.
Definition: file.c:754
void mutt_set_flag(struct Mailbox *m, struct Email *e, enum MessageType flag, bool bf, bool upd_mbox)
Set a flag on an email.
Definition: flags.c:57
void mutt_emails_set_flag(struct Mailbox *m, struct EmailArray *ea, enum MessageType flag, bool bf)
Set flag on messages.
Definition: flags.c:361
int mutt_thread_set_flag(struct Mailbox *m, struct Email *e, enum MessageType flag, bool bf, bool subthread)
Set a flag on an entire thread.
Definition: flags.c:385
bool OptNews
(pseudo) used to change reader mode
Definition: globals.c:67
bool OptNeedResort
(pseudo) used to force a re-sort
Definition: globals.c:66
static int op_delete(struct AliasMenuData *mdata, int op)
delete the current entry - Implements alias_function_t -
Definition: functions.c:168
static int op_main_tag_pattern(struct AliasMenuData *mdata, int op)
Tag messages matching a pattern - Implements alias_function_t -.
Definition: functions.c:263
static int op_main_limit(struct AliasMenuData *mdata, int op)
show only messages matching a pattern - Implements alias_function_t -
Definition: functions.c:244
static int op_exit(struct AliasMenuData *mdata, int op)
exit this menu - Implements alias_function_t -
Definition: functions.c:200
static int op_main_untag_pattern(struct AliasMenuData *mdata, int op)
Untag messages matching a pattern - Implements alias_function_t -.
Definition: functions.c:279
static int op_query(struct AliasMenuData *mdata, int op)
query external program for addresses - Implements alias_function_t -
Definition: functions.c:299
static int op_search(struct AliasMenuData *mdata, int op)
search for a regular expression - Implements alias_function_t -
Definition: functions.c:352
static int op_create_alias(struct AliasMenuData *mdata, int op)
create an alias from a message sender - Implements alias_function_t -
Definition: functions.c:128
static int op_sort(struct AliasMenuData *mdata, int op)
sort aliases - Implements alias_function_t -
Definition: functions.c:389
static int op_forward_message(struct AttachPrivateData *priv, int op)
forward a message with comments - Implements attach_function_t -
Definition: functions.c:562
static int op_bounce_message(struct AttachPrivateData *priv, int op)
remail a message to another user - Implements attach_function_t -
Definition: functions.c:477
static int op_attachment_edit_type(struct AttachPrivateData *priv, int op)
edit attachment content type - Implements attach_function_t -
Definition: functions.c:343
static int op_extract_keys(struct AttachPrivateData *priv, int op)
extract supported public keys - Implements attach_function_t -
Definition: functions.c:539
static int op_reply(struct AttachPrivateData *priv, int op)
reply to a message - Implements attach_function_t -
Definition: functions.c:596
static int op_compose_to_sender(struct AttachPrivateData *priv, int op)
compose new message to the current message sender - Implements attach_function_t -
Definition: functions.c:505
static int op_forget_passphrase(struct AttachPrivateData *priv, int op)
wipe passphrases from memory - Implements attach_function_t -
Definition: functions.c:553
static int op_list_subscribe(struct AttachPrivateData *priv, int op)
subscribe to a mailing list - Implements attach_function_t -
Definition: functions.c:576
static int op_list_unsubscribe(struct AttachPrivateData *priv, int op)
unsubscribe from a mailing list - Implements attach_function_t -
Definition: functions.c:586
static int op_check_traditional(struct AttachPrivateData *priv, int op)
check for classic PGP - Implements attach_function_t -
Definition: functions.c:491
static int op_resend(struct AttachPrivateData *priv, int op)
use the current message as a template for a new one - Implements attach_function_t -
Definition: functions.c:619
static int op_catchup(struct BrowserPrivateData *priv, int op)
Mark all articles in newsgroup as read - Implements browser_function_t -.
Definition: functions.c:300
static int op_mailbox_list(struct BrowserPrivateData *priv, int op)
List mailboxes with new mail - Implements browser_function_t -.
Definition: functions.c:827
int index_function_dispatcher(struct MuttWindow *win, int op)
Perform an Index function - Implements function_dispatcher_t -.
Definition: functions.c:3259
void dlg_autocrypt(void)
Display the Autocrypt account Menu -.
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:540
int mw_change_flag(struct Mailbox *m, struct EmailArray *ea, bool bf)
Change the flag on a Message -.
Definition: flags.c:454
int mw_enter_fname(const char *prompt, struct Buffer *fname, bool mailbox, struct Mailbox *m, bool multiple, char ***files, int *numfiles, SelectFileFlags flags)
Ask the user to select a file -.
Definition: curs_lib.c:236
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:274
static int op_quit(struct HistoryData *hd, int op)
Quit this menu - Implements history_function_t -.
Definition: functions.c:55
static int op_main_link_threads(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Link tagged message to the current one - Implements index_function_t -.
Definition: functions.c:1287
static int op_main_break_thread(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Break the thread in two - Implements index_function_t -.
Definition: functions.c:1031
static int op_main_root_message(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Jump to root message in thread - Implements index_function_t -.
Definition: functions.c:1783
static int op_main_delete_pattern(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Delete messages matching a pattern - Implements index_function_t -.
Definition: functions.c:1199
static int op_toggle_new(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Toggle a message's 'new' flag - Implements index_function_t -.
Definition: functions.c:2363
static int op_mail_key(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Mail a PGP public key - Implements index_function_t -.
Definition: functions.c:1018
static int op_display_message(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Display a message - Implements index_function_t -.
Definition: functions.c:606
static int op_main_next_undeleted(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Move to the next undeleted message - Implements index_function_t -.
Definition: functions.c:1628
static int op_main_fetch_mail(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Retrieve mail from POP server - Implements index_function_t -.
Definition: functions.c:3048
static int op_list_reply(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Reply to specified mailing list - Implements index_function_t -.
Definition: functions.c:955
static int op_delete_thread(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Delete all messages in thread - Implements index_function_t -.
Definition: functions.c:554
static int op_main_next_unread_mailbox(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Open next mailbox with unread mail - Implements index_function_t -.
Definition: functions.c:1661
static int op_pipe(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Pipe message/attachment to a shell command - Implements index_function_t -.
Definition: functions.c:2038
static int op_main_prev_undeleted(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Move to the previous undeleted message - Implements index_function_t -.
Definition: functions.c:1684
static int op_prev_entry(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Move to the previous entry - Implements index_function_t -.
Definition: functions.c:2059
static int op_next_entry(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Move to the next entry - Implements index_function_t -.
Definition: functions.c:2022
static int op_main_modify_tags(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Modify (notmuch/imap) tags - Implements index_function_t -.
Definition: functions.c:1344
static int op_main_sync_folder(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Save changes to mailbox - Implements index_function_t -.
Definition: functions.c:1846
static int op_autocrypt_acct_menu(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Manage autocrypt accounts - Implements index_function_t -.
Definition: functions.c:2507
static int op_end_cond(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
End of conditional execution (noop) - Implements index_function_t -.
Definition: functions.c:754
static int op_edit_raw_message(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Edit the raw message (edit and edit-raw-message are synonyms) - Implements index_function_t -.
Definition: functions.c:709
static int op_get_message(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Get parent of the current message - Implements index_function_t -.
Definition: functions.c:2684
static int op_main_next_new(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Jump to the next new message - Implements index_function_t -.
Definition: functions.c:1462
static int op_main_change_group(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Open a different newsgroup - Implements index_function_t -.
Definition: functions.c:2765
static int op_view_attachments(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Show MIME attachments - Implements index_function_t -.
Definition: functions.c:2478
static int op_main_vfolder_from_query(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Generate virtual folder from query - Implements index_function_t -.
Definition: functions.c:2959
static int op_flag_message(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Toggle a message's 'important' flag - Implements index_function_t -.
Definition: functions.c:800
static int op_main_imap_logout_all(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Logout from all IMAP servers - Implements index_function_t -.
Definition: functions.c:2531
static int op_main_read_thread(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Mark the current thread as read - Implements index_function_t -.
Definition: functions.c:1753
static int op_recall_message(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Recall a postponed message - Implements index_function_t -.
Definition: functions.c:2141
static int op_get_children(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Get all children of the current message - Implements index_function_t -.
Definition: functions.c:2583
static int op_toggle_write(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Toggle whether the mailbox will be rewritten - Implements index_function_t -.
Definition: functions.c:2405
static int op_save(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Make decrypted copy - Implements index_function_t -.
Definition: functions.c:2212
static int op_undelete_thread(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Undelete all messages in thread - Implements index_function_t -.
Definition: functions.c:2447
static int op_edit_label(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Add, change, or delete a message's label - Implements index_function_t -.
Definition: functions.c:674
static int op_main_entire_thread(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Read entire thread of the current message - Implements index_function_t -.
Definition: functions.c:2881
static int op_display_address(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Display full address of sender - Implements index_function_t -.
Definition: functions.c:589
static int op_post(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Followup to newsgroup - Implements index_function_t -.
Definition: functions.c:2841
static int op_tag(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Tag the current entry - Implements index_function_t -.
Definition: functions.c:2308
static int op_tag_thread(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Tag the current thread - Implements index_function_t -.
Definition: functions.c:2342
static int op_main_collapse_thread(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Collapse/uncollapse current thread - Implements index_function_t -.
Definition: functions.c:1159
static int op_alias_dialog(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Open the aliases dialog - Implements index_function_t -.
Definition: functions.c:422
static int op_main_imap_fetch(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Force retrieval of mail from IMAP server - Implements index_function_t -.
Definition: functions.c:2518
static int op_main_quasi_delete(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Delete from NeoMutt, don't touch on disk - Implements index_function_t -.
Definition: functions.c:1717
static int op_undelete(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Undelete the current entry - Implements index_function_t -.
Definition: functions.c:2415
static int op_main_collapse_all(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Collapse/uncollapse all threads - Implements index_function_t -.
Definition: functions.c:1143
static int op_jump(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Jump to an index number - Implements index_function_t -.
Definition: functions.c:905
static int op_main_undelete_pattern(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Undelete messages matching a pattern - Implements index_function_t -.
Definition: functions.c:1933
static int op_mark_msg(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Create a hotkey macro for the current message - Implements index_function_t -.
Definition: functions.c:1967
static int op_main_windowed_vfolder(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Shifts virtual folder time window - Implements index_function_t -.
Definition: functions.c:3006
static int op_main_set_flag(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Set a status flag on a message - Implements index_function_t -.
Definition: functions.c:1800
static int op_main_next_thread(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Jump to the next thread - Implements index_function_t -.
Definition: functions.c:1586
static int op_group_reply(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Reply to all recipients - Implements index_function_t -.
Definition: functions.c:875
static int op_main_show_limit(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Show currently active limit pattern - Implements index_function_t -.
Definition: functions.c:1825
static int op_main_change_folder(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Open a different folder - Implements index_function_t -.
Definition: functions.c:1079
static int op_mail(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Compose a new mail message - Implements index_function_t -.
Definition: functions.c:997
static int op_print(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Print the current entry - Implements index_function_t -.
Definition: functions.c:2075
#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
Convenience wrapper for the gui headers.
void * mutt_hash_find(const struct HashTable *table, const char *strkey)
Find the HashElem data in a Hash Table element using a key.
Definition: hash.c:362
Read/write command history from/to a file.
@ HC_OTHER
Miscellaneous strings.
Definition: lib.h:59
void mutt_startup_shutdown_hook(HookFlags type)
Execute any startup/shutdown hooks.
Definition: hook.c:964
Parse and execute user-defined hooks.
#define MUTT_SHUTDOWN_HOOK
shutdown-hook: run when leaving NeoMutt
Definition: hook.h:55
IMAP network mailbox.
void imap_logout_all(void)
Close all open connections.
Definition: imap.c:554
enum MxStatus imap_check_mailbox(struct Mailbox *m, bool force)
Use the NOOP or IDLE command to poll for new mail.
Definition: imap.c:1032
const struct MenuFuncOp OpIndex[]
Functions for the Index Menu.
Definition: functions.c:91
bool index_next_undeleted(struct MuttWindow *win_index)
Select the next undeleted Email (if possible)
Definition: functions.c:391
static bool resolve_email(struct IndexPrivateData *priv, struct IndexSharedData *shared, enum ResolveMethod rm)
Pick the next Email to advance the cursor to.
Definition: functions.c:342
const struct MenuOpSeq IndexDefaultBindings[]
Key bindings for the Index Menu.
Definition: functions.c:236
static bool prereq(struct IndexSharedData *shared, struct Menu *menu, CheckFlags checks)
Check the pre-requisites for a function.
Definition: functions.c:3065
static const struct IndexFunction IndexFunctions[]
All the NeoMutt functions that the Index supports.
Definition: functions.c:3114
ResolveMethod
How to advance the cursor.
Definition: functions.c:328
@ RESOLVE_NEXT_SUBTHREAD
Next sibling sub-thread.
Definition: functions.c:332
@ RESOLVE_NEXT_UNDELETED
Next undeleted email.
Definition: functions.c:330
@ RESOLVE_NEXT_EMAIL
Next email, whatever its state.
Definition: functions.c:329
@ RESOLVE_NEXT_THREAD
Next top-level thread.
Definition: functions.c:331
uint8_t CheckFlags
Flags, e.g. CHECK_IN_MAILBOX.
Definition: lib.h:67
#define CHECK_NO_FLAGS
No flags are set.
Definition: lib.h:68
#define CHECK_ATTACH
Is the user in message-attach mode?
Definition: lib.h:73
#define CHECK_VISIBLE
Is the selected message visible in the index?
Definition: lib.h:71
#define CHECK_IN_MAILBOX
Is there a mailbox open?
Definition: lib.h:69
#define CHECK_READONLY
Is the mailbox readonly?
Definition: lib.h:72
#define CHECK_MSGCOUNT
Are there any messages?
Definition: lib.h:70
#define NT_INDEX_EMAIL
Email has changed.
Definition: lib.h:65
void index_shared_data_set_email(struct IndexSharedData *shared, struct Email *e)
Set the current Email for the Index and friends.
Definition: shared_data.c:235
Data shared between Index, Pager and Sidebar.
Manage keymappings.
enum CommandResult km_bind(char *s, enum MenuType menu, int op, char *macro, char *desc)
Bind a key to a macro.
Definition: parse.c:160
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43
@ LL_NOTIFY
Log of notifications.
Definition: logging2.h:48
#define FREE(x)
Definition: memory.h:55
GUI present the user with a selectable list.
#define MENU_REDRAW_FULL
Redraw everything.
Definition: lib.h:59
#define MENU_REDRAW_INDEX
Redraw the index.
Definition: lib.h:56
MenuRedrawFlags menu_current_middle(struct Menu *menu)
Move the current selection to the centre of the window.
Definition: move.c:464
void menu_queue_redraw(struct Menu *menu, MenuRedrawFlags redraw)
Queue a request for a redraw.
Definition: menu.c:184
int menu_get_index(struct Menu *menu)
Get the current selection in the Menu.
Definition: menu.c:160
#define MENU_REDRAW_CURRENT
Redraw the current line of the menu.
Definition: lib.h:58
MenuRedrawFlags menu_set_index(struct Menu *menu, int index)
Set the current selection in the Menu.
Definition: menu.c:174
void msgwin_clear_text(struct MuttWindow *win)
Clear the text in the Message Window.
Definition: msgwin.c:519
Convenience wrapper for the library headers.
#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_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:672
bool mutt_strn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings (to a maximum), safely.
Definition: string.c:425
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:581
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:280
Many unsorted constants and some structs.
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:56
@ MUTT_UNDELETE
Messages to be un-deleted.
Definition: mutt.h:76
@ MUTT_LIMIT
Messages in limited view.
Definition: mutt.h:82
@ MUTT_UNTAG
Messages to be un-tagged.
Definition: mutt.h:81
@ MUTT_READ
Messages that have been read.
Definition: mutt.h:73
@ MUTT_PURGE
Messages to be purged (bypass trash)
Definition: mutt.h:77
@ MUTT_TAG
Tagged messages.
Definition: mutt.h:80
@ MUTT_FLAG
Flagged messages.
Definition: mutt.h:79
@ MUTT_DELETE
Messages to be deleted.
Definition: mutt.h:75
@ MUTT_NEW
New messages.
Definition: mutt.h:70
#define PATH_MAX
Definition: mutt.h:42
int mutt_label_message(struct MailboxView *mv, struct EmailArray *ea)
Let the user label a message.
Definition: mutt_header.c:130
Representation of the email's header.
struct Mailbox * mutt_mailbox_next_unread(struct Mailbox *m_cur, struct Buffer *s)
Find next mailbox with unread mail.
Definition: mutt_mailbox.c:387
struct Mailbox * mutt_mailbox_next(struct Mailbox *m_cur, struct Buffer *s)
Incoming folders completion routine.
Definition: mutt_mailbox.c:361
bool mutt_mailbox_list(void)
Show a message with the list of mailboxes with new mail.
Definition: mutt_mailbox.c:248
Mailbox helper functions.
bool mutt_link_threads(struct Email *parent, struct EmailArray *children, struct Mailbox *m)
Forcibly link threads together.
Definition: mutt_thread.c:1750
void mutt_draw_tree(struct ThreadsContext *tctx)
Draw a tree of threaded emails.
Definition: mutt_thread.c:394
int mutt_messages_in_thread(struct Mailbox *m, struct Email *e, enum MessageInThread mit)
Count the messages in a thread.
Definition: mutt_thread.c:1660
off_t mutt_set_vnum(struct Mailbox *m)
Set the virtual index number of all the messages in a mailbox.
Definition: mutt_thread.c:1407
bool mutt_thread_can_collapse(struct Email *e)
Check whether a thread can be collapsed.
Definition: mutt_thread.c:1820
int mutt_parent_message(struct Email *e, bool find_root)
Find the parent of a message.
Definition: mutt_thread.c:1357
struct HashTable * mutt_make_id_hash(struct Mailbox *m)
Create a Hash Table for message-ids.
Definition: mutt_thread.c:1705
Create/manipulate threading in emails.
#define mutt_thread_next_unread(e)
Definition: mutt_thread.h:111
#define mutt_using_threads()
Definition: mutt_thread.h:114
#define mutt_previous_thread(e)
Definition: mutt_thread.h:121
#define mutt_uncollapse_thread(e)
Definition: mutt_thread.h:108
@ MIT_POSITION
Our position in the thread.
Definition: mutt_thread.h:90
#define mutt_next_subthread(e)
Definition: mutt_thread.h:122
#define mutt_thread_contains_unread(e)
Definition: mutt_thread.h:109
#define mutt_previous_subthread(e)
Definition: mutt_thread.h:123
#define mutt_next_thread(e)
Definition: mutt_thread.h:120
#define mutt_collapse_thread(e)
Definition: mutt_thread.h:107
bool window_is_focused(const struct MuttWindow *win)
Does the given Window have the focus?
Definition: mutt_window.c:653
struct MuttWindow * window_set_focus(struct MuttWindow *win)
Set the Window focus.
Definition: mutt_window.c:683
void buf_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using '~' or '='.
Definition: muttlib.c:519
Some miscellaneous functions.
struct Email * mutt_get_virt_email(struct Mailbox *m, int vnum)
Get a virtual Email.
Definition: mview.c:418
bool mutt_limit_current_thread(struct MailboxView *mv, struct Email *e)
Limit the email view to the current thread.
Definition: mview.c:481
void mview_free(struct MailboxView **ptr)
Free a MailboxView.
Definition: mview.c:50
int ea_add_tagged(struct EmailArray *ea, struct MailboxView *mv, struct Email *e, bool use_tagged)
Get an array of the tagged Emails.
Definition: mview.c:378
bool message_is_tagged(struct Email *e)
Is a message in the index tagged (and within limit)
Definition: mview.c:364
bool mview_has_limit(const struct MailboxView *mv)
Is a limit active?
Definition: mview.c:439
View of a Mailbox.
int mx_tags_edit(struct Mailbox *m, const char *tags, struct Buffer *buf)
Start the tag editor of the mailbox.
Definition: mx.c:1274
int mx_msg_close(struct Mailbox *m, struct Message **ptr)
Close a message.
Definition: mx.c:1180
void mx_fastclose_mailbox(struct Mailbox *m, bool keep_account)
Free up memory associated with the Mailbox.
Definition: mx.c:414
struct Mailbox * mx_mbox_find2(const char *path)
Find a Mailbox on an Account.
Definition: mx.c:1605
struct Message * mx_msg_open(struct Mailbox *m, struct Email *e)
Return a stream pointer for a message.
Definition: mx.c:1134
bool mx_tags_is_supported(struct Mailbox *m)
Return true if mailbox support tagging.
Definition: mx.c:1311
int mx_tags_commit(struct Mailbox *m, struct Email *e, const char *tags)
Save tags to the Mailbox - Wrapper for MxOps::tags_commit()
Definition: mx.c:1294
int mx_toggle_write(struct Mailbox *m)
Toggle the mailbox's readonly flag.
Definition: mx.c:1807
enum MxStatus mx_mbox_sync(struct Mailbox *m)
Save changes to mailbox.
Definition: mx.c:906
enum MxStatus mx_mbox_close(struct Mailbox *m)
Save changes and close mailbox.
Definition: mx.c:598
API for mailboxes.
MxStatus
Return values from mbox_check(), mbox_check_stats(), mbox_sync(), and mbox_close()
Definition: mxapi.h:63
@ MX_STATUS_OK
No changes.
Definition: mxapi.h:65
@ MX_STATUS_REOPENED
Mailbox was reopened.
Definition: mxapi.h:68
@ MX_STATUS_NEW_MAIL
New mail received in Mailbox.
Definition: mxapi.h:66
API for encryption/signing of emails.
#define PGP_TRADITIONAL_CHECKED
Email has a traditional (inline) signature.
Definition: lib.h:92
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:90
#define WithCrypto
Definition: lib.h:116
@ NT_GLOBAL_SHUTDOWN
NeoMutt is about to close.
Definition: neomutt.h:62
Usenet network mailbox type; talk to an NNTP server.
int nntp_check_msgid(struct Mailbox *m, const char *msgid)
Fetch article by Message-ID.
Definition: nntp.c:2215
int nntp_check_children(struct Mailbox *m, const char *msgid)
Fetch children of article with the Message-ID.
Definition: nntp.c:2286
void nntp_mailbox(struct Mailbox *m, char *buf, size_t buflen)
Get first newsgroup with new messages.
Definition: newsrc.c:1425
struct NntpMboxData * mutt_newsgroup_catchup(struct Mailbox *m, struct NntpAccountData *adata, char *group)
Catchup newsgroup.
Definition: newsrc.c:1343
struct NntpAccountData * CurrentNewsSrv
Current NNTP news server.
Definition: nntp.c:77
struct NntpAccountData * nntp_select_server(struct Mailbox *m, const char *server, bool leave_lock)
Open a connection to an NNTP server.
Definition: newsrc.c:1063
Nntp-specific Mailbox data.
@ NT_MAILBOX
Mailbox has changed, NotifyMailbox, EventMailbox.
Definition: notify_type.h:49
@ NT_INDEX
Index data has changed, NotifyIndex, IndexSharedData.
Definition: notify_type.h:48
@ NT_GLOBAL
Not object-related, NotifyGlobal.
Definition: notify_type.h:46
const struct CompleteOps CompleteNmQueryOps
Auto-Completion of NmQuerys.
Definition: complete.c:247
void nm_db_longrun_done(struct Mailbox *m)
Finish a long transaction.
Definition: db.c:379
void nm_db_longrun_init(struct Mailbox *m, bool writable)
Start a long transaction.
Definition: db.c:364
Notmuch virtual mailbox type.
void nm_query_window_reset(void)
Resets the vfolder window position to the present.
Definition: notmuch.c:1686
int nm_read_entire_thread(struct Mailbox *m, struct Email *e)
Get the entire thread of an email.
Definition: notmuch.c:1514
void nm_query_window_backward(void)
Function to move the current search window backward in time.
Definition: notmuch.c:1675
bool nm_query_window_available(void)
Are windowed queries enabled for use?
Definition: notmuch.c:1638
bool nm_message_is_still_queried(struct Mailbox *m, struct Email *e)
Is a message still visible in the query?
Definition: notmuch.c:1698
void nm_query_window_forward(void)
Function to move the current search window forward in time.
Definition: notmuch.c:1655
const char * opcodes_get_name(int op)
Get the name of an opcode.
Definition: opcodes.c:48
const char * pager_get_pager(struct ConfigSubset *sub)
Get the value of $pager.
Definition: config.c:108
GUI display a file/email/help in a viewport with paging.
int mutt_display_message(struct MuttWindow *win_index, struct IndexSharedData *shared)
Display a message in the pager.
Definition: message.c:448
int external_pager(struct MailboxView *mv, struct Email *e, const char *command)
Display a message in an external program.
Definition: message.c:301
Private state data for the Pager.
Match patterns to emails.
int mutt_search_command(struct MailboxView *mv, struct Menu *menu, int cur, struct SearchState *state, SearchFlags flags)
Perform a search.
Definition: pattern.c:478
int mutt_pattern_func(struct MailboxView *mv, int op, char *prompt)
Perform some Pattern matching.
Definition: pattern.c:311
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
POP network mailbox.
void pop_fetch_mail(void)
Fetch messages and save them in $spool_file.
Definition: pop.c:513
Progress Bar.
@ MUTT_PROGRESS_WRITE
Progress tracks elements, according to $write_inc
Definition: lib.h:83
struct Progress * progress_new(enum ProgressType type, size_t size)
Create a new Progress Bar.
Definition: progress.c:139
void progress_free(struct Progress **ptr)
Free a Progress Bar.
Definition: progress.c:110
void progress_set_message(struct Progress *progress, const char *fmt,...) __attribute__((__format__(__printf__
bool progress_update(struct Progress *progress, size_t pos, int percent)
Update the state of the progress bar.
Definition: progress.c:80
Prototypes for many functions.
@ EVM_VIEW
View the message.
Definition: protos.h:53
@ EVM_EDIT
Edit the message.
Definition: protos.h:54
@ MUTT_YES
User answered 'Yes', or assume 'Yes'.
Definition: quad.h:39
Ask the user a question.
enum QuadOption query_quadoption(const char *prompt, struct ConfigSubset *sub, const char *name)
Ask the user a quad-question.
Definition: question.c:379
#define STAILQ_FIRST(head)
Definition: queue.h:350
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
#define STAILQ_EMPTY(head)
Definition: queue.h:348
#define STAILQ_NEXT(elm, field)
Definition: queue.h:400
#define SEARCH_OPPOSITE
Search in the opposite direction.
Definition: search_state.h:46
uint8_t SearchFlags
Flags for a specific search, e.g. SEARCH_PROMPT.
Definition: search_state.h:43
#define SEARCH_NO_FLAGS
No flags are set.
Definition: search_state.h:44
#define SEARCH_PROMPT
Ask for search input.
Definition: search_state.h:45
Convenience wrapper for the send headers.
int mutt_resend_message(FILE *fp, struct Mailbox *m, struct Email *e_cur, struct ConfigSubset *sub)
Resend an email.
Definition: send.c:1617
bool mutt_send_list_unsubscribe(struct Mailbox *m, struct Email *e)
Send a mailing-list unsubscription email.
Definition: send.c:3042
int mutt_send_message(SendFlags flags, struct Email *e_templ, const char *tempfile, struct Mailbox *m, struct EmailArray *ea, struct ConfigSubset *sub)
Send an email.
Definition: send.c:2102
bool mutt_send_list_subscribe(struct Mailbox *m, struct Email *e)
Send a mailing-list subscription email.
Definition: send.c:3013
#define SEND_GROUP_CHAT_REPLY
Reply to all recipients preserving To/Cc.
Definition: send.h:54
uint32_t SendFlags
Flags for mutt_send_message(), e.g. SEND_REPLY.
Definition: send.h:40
#define SEND_GROUP_REPLY
Reply to all.
Definition: send.h:43
#define SEND_LIST_REPLY
Reply to mailing list.
Definition: send.h:44
#define SEND_KEY
Mail a PGP public key.
Definition: send.h:48
#define SEND_POSTPONED
Recall a postponed email.
Definition: send.h:46
#define SEND_TO_SENDER
Compose new email to sender.
Definition: send.h:53
#define SEND_NO_FLAGS
No flags are set.
Definition: send.h:41
#define SEND_REPLY
Reply to sender.
Definition: send.h:42
#define SEND_NEWS
Reply to a news article.
Definition: send.h:55
#define SEND_FORWARD
Forward email.
Definition: send.h:45
Sidebar functions.
void mutt_sort_headers(struct MailboxView *mv, bool init)
Sort emails by their headers.
Definition: sort.c:350
Assorted sorting methods.
Key value store.
#define NONULL(x)
Definition: string2.h:37
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
The envelope/body of an email.
Definition: email.h:39
bool read
Email is read.
Definition: email.h:50
bool visible
Is this message part of the view?
Definition: email.h:121
struct Envelope * env
Envelope information.
Definition: email.h:68
bool collapsed
Is this message part of a collapsed thread?
Definition: email.h:120
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib....
Definition: email.h:43
struct Body * body
List of MIME parts.
Definition: email.h:69
bool old
Email is seen, but unread.
Definition: email.h:49
bool attach_del
Has an attachment marked for deletion.
Definition: email.h:99
bool flagged
Marked important?
Definition: email.h:47
bool threaded
Used for threading.
Definition: email.h:108
const struct AttrColor * attr_color
Color-pair to use when displaying in the index.
Definition: email.h:112
int vnum
Virtual message number.
Definition: email.h:114
struct TagList tags
For drivers that support server tagging.
Definition: email.h:72
bool deleted
Email is deleted.
Definition: email.h:78
int index
The absolute (unsorted) message number.
Definition: email.h:110
bool quasi_deleted
Deleted from neomutt, but not modified on disk.
Definition: email.h:103
bool tagged
Email is tagged.
Definition: email.h:107
char * followup_to
List of 'followup-to' fields.
Definition: envelope.h:80
char * message_id
Message ID.
Definition: envelope.h:73
struct ListHead references
message references (in reverse order)
Definition: envelope.h:83
struct ListHead in_reply_to
in-reply-to header content
Definition: envelope.h:84
An Event that happened to a Mailbox.
Definition: mailbox.h:199
A NeoMutt function.
Definition: functions.h:49
int op
Op code, e.g. OP_MAIN_LIMIT.
Definition: functions.h:50
index_function_t function
Function to call.
Definition: functions.h:51
int flags
Prerequisites for the function, e.g. CHECK_IN_MAILBOX.
Definition: functions.h:52
Private state data for the Index.
Definition: private_data.h:35
struct MuttWindow * win_index
Window for the Index.
Definition: private_data.h:42
struct IndexSharedData * shared
Shared Index data.
Definition: private_data.h:40
bool tag_prefix
tag-prefix has been pressed
Definition: private_data.h:36
struct Menu * menu
Menu controlling the index.
Definition: private_data.h:41
int oldcount
Old count of mails in the mailbox.
Definition: private_data.h:37
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 ConfigSubset * sub
Config set to use.
Definition: shared_data.h:38
struct MailboxView * mailbox_view
Current Mailbox view.
Definition: shared_data.h:40
struct SearchState * search_state
State of the current search.
Definition: shared_data.h:45
struct Notify * notify
Notifications: NotifyIndex, IndexSharedData.
Definition: shared_data.h:44
A List node for strings.
Definition: list.h:37
char * data
String.
Definition: list.h:38
View of a Mailbox.
Definition: mview.h:40
bool collapsed
Are all threads collapsed?
Definition: mview.h:49
struct Menu * menu
Needed for pattern compilation.
Definition: mview.h:47
struct ThreadsContext * threads
Threads context.
Definition: mview.h:44
struct Mailbox * mailbox
Current Mailbox.
Definition: mview.h:51
char * pattern
Limit pattern string.
Definition: mview.h:42
A mailbox.
Definition: mailbox.h:79
int vcount
The number of virtual messages.
Definition: mailbox.h:99
bool changed
Mailbox has been modified.
Definition: mailbox.h:110
int msg_count
Total number of messages.
Definition: mailbox.h:88
AclFlags rights
ACL bits, see AclFlags.
Definition: mailbox.h:119
enum MailboxType type
Mailbox type.
Definition: mailbox.h:102
void * mdata
Driver specific data.
Definition: mailbox.h:132
struct Email ** emails
Array of Emails.
Definition: mailbox.h:96
char * name
A short name for the Mailbox.
Definition: mailbox.h:82
struct Notify * notify
Notifications: NotifyMailbox, EventMailbox.
Definition: mailbox.h:145
struct HashTable * id_hash
Hash Table: "message-id" -> Email.
Definition: mailbox.h:123
struct Buffer pathbuf
Path of the Mailbox.
Definition: mailbox.h:80
bool readonly
Don't allow changes to the mailbox.
Definition: mailbox.h:116
int msg_tagged
How many messages are tagged?
Definition: mailbox.h:94
bool verbose
Display status messages?
Definition: mailbox.h:117
Mapping between a function and an operation.
Definition: lib.h:101
Mapping between an operation and a key sequence.
Definition: lib.h:110
Definition: lib.h:79
int max
Number of entries in the menu.
Definition: lib.h:81
A local copy of an email.
Definition: message.h:34
FILE * fp
pointer to the message data
Definition: message.h:35
const struct Mapping * help_data
Data for the Help Bar.
Definition: mutt_window.h:141
void * wdata
Private data.
Definition: mutt_window.h:144
struct MuttWindow * parent
Parent Window.
Definition: mutt_window.h:134
Container for Accounts, Notifications.
Definition: neomutt.h:42
struct Notify * notify
Notifications handler.
Definition: neomutt.h:43
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:46
NNTP-specific Mailbox data -.
Definition: mdata.h:34
bool reverse
search backwards
Definition: search_state.h:40
struct PatternList * pattern
compiled search pattern
Definition: search_state.h:37
void driver_tags_get_with_hidden(struct TagList *tl, struct Buffer *tags)
Get all tags, also hidden ones, separated by space.
Definition: tags.c:174
void mutt_break_thread(struct Email *e)
Break the email Thread.
Definition: thread.c:229
@ MENU_INDEX
Index panel (list of emails)
Definition: type.h:51