NeoMutt  2025-09-05-7-geaa2bd
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#ifdef USE_AUTOCRYPT
76#include "autocrypt/lib.h"
77#endif
78#ifdef USE_NOTMUCH
79#include "notmuch/lib.h"
80#endif
81#ifdef ENABLE_NLS
82#include <libintl.h>
83#endif
84#endif
85
86// clang-format off
90const struct MenuFuncOp OpIndex[] = { /* map: index */
91 { "alias-dialog", OP_ALIAS_DIALOG },
92#ifdef USE_AUTOCRYPT
93 { "autocrypt-acct-menu", OP_AUTOCRYPT_ACCT_MENU },
94#endif
95 { "bounce-message", OP_BOUNCE_MESSAGE },
96 { "break-thread", OP_MAIN_BREAK_THREAD },
97 { "catchup", OP_CATCHUP },
98 { "change-folder", OP_MAIN_CHANGE_FOLDER },
99 { "change-folder-readonly", OP_MAIN_CHANGE_FOLDER_READONLY },
100 { "change-newsgroup", OP_MAIN_CHANGE_GROUP },
101 { "change-newsgroup-readonly", OP_MAIN_CHANGE_GROUP_READONLY },
102#ifdef USE_NOTMUCH
103 { "change-vfolder", OP_MAIN_CHANGE_VFOLDER },
104#endif
105 { "check-traditional-pgp", OP_CHECK_TRADITIONAL },
106 { "clear-flag", OP_MAIN_CLEAR_FLAG },
107 { "collapse-all", OP_MAIN_COLLAPSE_ALL },
108 { "collapse-thread", OP_MAIN_COLLAPSE_THREAD },
109 { "compose-to-sender", OP_COMPOSE_TO_SENDER },
110 { "copy-message", OP_COPY_MESSAGE },
111 { "create-alias", OP_CREATE_ALIAS },
112 { "decode-copy", OP_DECODE_COPY },
113 { "decode-save", OP_DECODE_SAVE },
114 { "decrypt-copy", OP_DECRYPT_COPY },
115 { "decrypt-save", OP_DECRYPT_SAVE },
116 { "delete-message", OP_DELETE },
117 { "delete-pattern", OP_MAIN_DELETE_PATTERN },
118 { "delete-subthread", OP_DELETE_SUBTHREAD },
119 { "delete-thread", OP_DELETE_THREAD },
120 { "display-address", OP_DISPLAY_ADDRESS },
121 { "display-message", OP_DISPLAY_MESSAGE },
122 { "display-toggle-weed", OP_DISPLAY_HEADERS },
123 { "edit", OP_EDIT_RAW_MESSAGE },
124 { "edit-label", OP_EDIT_LABEL },
125 { "edit-or-view-raw-message", OP_EDIT_OR_VIEW_RAW_MESSAGE },
126 { "edit-raw-message", OP_EDIT_RAW_MESSAGE },
127 { "edit-type", OP_ATTACHMENT_EDIT_TYPE },
128#ifdef USE_NOTMUCH
129 { "entire-thread", OP_MAIN_ENTIRE_THREAD },
130#endif
131 { "exit", OP_EXIT },
132 { "extract-keys", OP_EXTRACT_KEYS },
133 { "fetch-mail", OP_MAIN_FETCH_MAIL },
134 { "flag-message", OP_FLAG_MESSAGE },
135 { "followup-message", OP_FOLLOWUP },
136 { "forget-passphrase", OP_FORGET_PASSPHRASE },
137 { "forward-message", OP_FORWARD_MESSAGE },
138 { "forward-to-group", OP_FORWARD_TO_GROUP },
139 { "get-children", OP_GET_CHILDREN },
140 { "get-message", OP_GET_MESSAGE },
141 { "get-parent", OP_GET_PARENT },
142 { "group-chat-reply", OP_GROUP_CHAT_REPLY },
143 { "group-reply", OP_GROUP_REPLY },
144 { "imap-fetch-mail", OP_MAIN_IMAP_FETCH },
145 { "imap-logout-all", OP_MAIN_IMAP_LOGOUT_ALL },
146 { "limit", OP_MAIN_LIMIT },
147 { "limit-current-thread", OP_LIMIT_CURRENT_THREAD },
148 { "link-threads", OP_MAIN_LINK_THREADS },
149 { "list-reply", OP_LIST_REPLY },
150 { "list-subscribe", OP_LIST_SUBSCRIBE },
151 { "list-unsubscribe", OP_LIST_UNSUBSCRIBE },
152 { "mail", OP_MAIL },
153 { "mail-key", OP_MAIL_KEY },
154 { "mailbox-list", OP_MAILBOX_LIST },
155 { "mark-message", OP_MARK_MSG },
156 { "modify-labels", OP_MAIN_MODIFY_TAGS },
157 { "modify-labels-then-hide", OP_MAIN_MODIFY_TAGS_THEN_HIDE },
158 { "modify-tags", OP_MAIN_MODIFY_TAGS },
159 { "modify-tags-then-hide", OP_MAIN_MODIFY_TAGS_THEN_HIDE },
160 { "next-new", OP_MAIN_NEXT_NEW },
161 { "next-new-then-unread", OP_MAIN_NEXT_NEW_THEN_UNREAD },
162 { "next-subthread", OP_MAIN_NEXT_SUBTHREAD },
163 { "next-thread", OP_MAIN_NEXT_THREAD },
164 { "next-undeleted", OP_MAIN_NEXT_UNDELETED },
165 { "next-unread", OP_MAIN_NEXT_UNREAD },
166 { "next-unread-mailbox", OP_MAIN_NEXT_UNREAD_MAILBOX },
167 { "parent-message", OP_MAIN_PARENT_MESSAGE },
168 { "pipe-entry", OP_PIPE },
169 { "pipe-message", OP_PIPE },
170 { "post-message", OP_POST },
171 { "previous-new", OP_MAIN_PREV_NEW },
172 { "previous-new-then-unread", OP_MAIN_PREV_NEW_THEN_UNREAD },
173 { "previous-subthread", OP_MAIN_PREV_SUBTHREAD },
174 { "previous-thread", OP_MAIN_PREV_THREAD },
175 { "previous-undeleted", OP_MAIN_PREV_UNDELETED },
176 { "previous-unread", OP_MAIN_PREV_UNREAD },
177 { "print-message", OP_PRINT },
178 { "purge-message", OP_PURGE_MESSAGE },
179 { "purge-thread", OP_PURGE_THREAD },
180 { "quasi-delete", OP_MAIN_QUASI_DELETE },
181 { "query", OP_QUERY },
182 { "quit", OP_QUIT },
183 { "read-subthread", OP_MAIN_READ_SUBTHREAD },
184 { "read-thread", OP_MAIN_READ_THREAD },
185 { "recall-message", OP_RECALL_MESSAGE },
186 { "reconstruct-thread", OP_RECONSTRUCT_THREAD },
187 { "reply", OP_REPLY },
188 { "resend-message", OP_RESEND },
189 { "root-message", OP_MAIN_ROOT_MESSAGE },
190 { "save-message", OP_SAVE },
191 { "set-flag", OP_MAIN_SET_FLAG },
192 { "show-limit", OP_MAIN_SHOW_LIMIT },
193 { "sidebar-first", OP_SIDEBAR_FIRST },
194 { "sidebar-last", OP_SIDEBAR_LAST },
195 { "sidebar-next", OP_SIDEBAR_NEXT },
196 { "sidebar-next-new", OP_SIDEBAR_NEXT_NEW },
197 { "sidebar-open", OP_SIDEBAR_OPEN },
198 { "sidebar-page-down", OP_SIDEBAR_PAGE_DOWN },
199 { "sidebar-page-up", OP_SIDEBAR_PAGE_UP },
200 { "sidebar-prev", OP_SIDEBAR_PREV },
201 { "sidebar-prev-new", OP_SIDEBAR_PREV_NEW },
202 { "sidebar-toggle-virtual", OP_SIDEBAR_TOGGLE_VIRTUAL },
203 { "sidebar-toggle-visible", OP_SIDEBAR_TOGGLE_VISIBLE },
204 { "sort-mailbox", OP_SORT },
205 { "sort-reverse", OP_SORT_REVERSE },
206 { "sync-mailbox", OP_MAIN_SYNC_FOLDER },
207 { "tag-pattern", OP_MAIN_TAG_PATTERN },
208 { "tag-subthread", OP_TAG_SUBTHREAD },
209 { "tag-thread", OP_TAG_THREAD },
210 { "toggle-new", OP_TOGGLE_NEW },
211 { "toggle-read", OP_TOGGLE_READ },
212 { "toggle-write", OP_TOGGLE_WRITE },
213 { "undelete-message", OP_UNDELETE },
214 { "undelete-pattern", OP_MAIN_UNDELETE_PATTERN },
215 { "undelete-subthread", OP_UNDELETE_SUBTHREAD },
216 { "undelete-thread", OP_UNDELETE_THREAD },
217 { "untag-pattern", OP_MAIN_UNTAG_PATTERN },
218#ifdef USE_NOTMUCH
219 { "vfolder-from-query", OP_MAIN_VFOLDER_FROM_QUERY },
220 { "vfolder-from-query-readonly", OP_MAIN_VFOLDER_FROM_QUERY_READONLY },
221 { "vfolder-window-backward", OP_MAIN_WINDOWED_VFOLDER_BACKWARD },
222 { "vfolder-window-forward", OP_MAIN_WINDOWED_VFOLDER_FORWARD },
223 { "vfolder-window-reset", OP_MAIN_WINDOWED_VFOLDER_RESET },
224#endif
225 { "view-attachments", OP_VIEW_ATTACHMENTS },
226 { "view-raw-message", OP_VIEW_RAW_MESSAGE },
227 // Deprecated
228 { "buffy-list", OP_MAILBOX_LIST },
229 { NULL, 0 },
230};
231
235const struct MenuOpSeq IndexDefaultBindings[] = { /* map: index */
236 { OP_ATTACHMENT_EDIT_TYPE, "\005" }, // <Ctrl-E>
237#ifdef USE_AUTOCRYPT
238 { OP_AUTOCRYPT_ACCT_MENU, "A" },
239#endif
240 { OP_BOUNCE_MESSAGE, "b" },
241 { OP_CHECK_TRADITIONAL, "\033P" }, // <Alt-P>
242 { OP_COPY_MESSAGE, "C" },
243 { OP_CREATE_ALIAS, "a" },
244 { OP_DECODE_COPY, "\033C" }, // <Alt-C>
245 { OP_DECODE_SAVE, "\033s" }, // <Alt-s>
246 { OP_DELETE, "d" },
247 { OP_DELETE_SUBTHREAD, "\033d" }, // <Alt-d>
248 { OP_DELETE_THREAD, "\004" }, // <Ctrl-D>
249 { OP_DISPLAY_ADDRESS, "@" },
250 { OP_DISPLAY_HEADERS, "h" },
251 { OP_DISPLAY_MESSAGE, " " }, // <Space>
252 { OP_DISPLAY_MESSAGE, "<keypadenter>" },
253 { OP_DISPLAY_MESSAGE, "\n" }, // <Enter>
254 { OP_DISPLAY_MESSAGE, "\r" }, // <Return>
255 { OP_EDIT_LABEL, "Y" },
256 { OP_EDIT_OR_VIEW_RAW_MESSAGE, "e" },
257 { OP_EXIT, "x" },
258 { OP_EXTRACT_KEYS, "\013" }, // <Ctrl-K>
259 { OP_FLAG_MESSAGE, "F" },
260 { OP_FORGET_PASSPHRASE, "\006" }, // <Ctrl-F>
261 { OP_FORWARD_MESSAGE, "f" },
262 { OP_GROUP_REPLY, "g" },
263 { OP_LIST_REPLY, "L" },
264 { OP_MAIL, "m" },
265 { OP_MAILBOX_LIST, "." },
266 { OP_MAIL_KEY, "\033k" }, // <Alt-k>
267 { OP_MAIN_BREAK_THREAD, "#" },
268 { OP_MAIN_CHANGE_FOLDER, "c" },
269 { OP_MAIN_CHANGE_FOLDER_READONLY, "\033c" }, // <Alt-c>
270 { OP_MAIN_CHANGE_GROUP, "i" },
271 { OP_MAIN_CHANGE_GROUP_READONLY, "\033i" }, // <Alt-i>
272 { OP_MAIN_CLEAR_FLAG, "W" },
273 { OP_MAIN_COLLAPSE_ALL, "\033V" }, // <Alt-V>
274 { OP_MAIN_COLLAPSE_THREAD, "\033v" }, // <Alt-v>
275 { OP_MAIN_DELETE_PATTERN, "D" },
276 { OP_MAIN_FETCH_MAIL, "G" },
277 { OP_MAIN_LIMIT, "l" },
278 { OP_MAIN_LINK_THREADS, "&" },
279 { OP_MAIN_NEXT_NEW_THEN_UNREAD, "\t" }, // <Tab>
280 { OP_MAIN_NEXT_SUBTHREAD, "\033n" }, // <Alt-n>
281 { OP_MAIN_NEXT_THREAD, "\016" }, // <Ctrl-N>
282 { OP_MAIN_NEXT_UNDELETED, "<down>" },
283 { OP_MAIN_NEXT_UNDELETED, "j" },
284 { OP_MAIN_PARENT_MESSAGE, "P" },
285 { OP_MAIN_PREV_NEW_THEN_UNREAD, "\033\t" }, // <Alt->
286 { OP_MAIN_PREV_SUBTHREAD, "\033p" }, // <Alt-p>
287 { OP_MAIN_PREV_THREAD, "\020" }, // <Ctrl-P>
288 { OP_MAIN_PREV_UNDELETED, "<up>" },
289 { OP_MAIN_PREV_UNDELETED, "k" },
290 { OP_MAIN_READ_SUBTHREAD, "\033r" }, // <Alt-r>
291 { OP_MAIN_READ_THREAD, "\022" }, // <Ctrl-R>
292 { OP_MAIN_SET_FLAG, "w" },
293 { OP_MAIN_SHOW_LIMIT, "\033l" }, // <Alt-l>
294 { OP_MAIN_SYNC_FOLDER, "$" },
295 { OP_MAIN_TAG_PATTERN, "T" },
296 { OP_MAIN_UNDELETE_PATTERN, "U" },
297 { OP_MAIN_UNTAG_PATTERN, "\024" }, // <Ctrl-T>
298 { OP_MARK_MSG, "~" },
299 { OP_NEXT_ENTRY, "J" },
300 { OP_PIPE, "|" },
301 { OP_PREV_ENTRY, "K" },
302 { OP_PRINT, "p" },
303 { OP_QUERY, "Q" },
304 { OP_QUIT, "q" },
305 { OP_RECALL_MESSAGE, "R" },
306 { OP_REPLY, "r" },
307 { OP_RESEND, "\033e" }, // <Alt-e>
308 { OP_SAVE, "s" },
309 { OP_SHOW_LOG_MESSAGES, "M" },
310 { OP_SORT, "o" },
311 { OP_SORT_REVERSE, "O" },
312 { OP_TAG_THREAD, "\033t" }, // <Alt-t>
313 { OP_TOGGLE_NEW, "N" },
314 { OP_TOGGLE_WRITE, "%" },
315 { OP_UNDELETE, "u" },
316 { OP_UNDELETE_SUBTHREAD, "\033u" }, // <Alt-u>
317 { OP_UNDELETE_THREAD, "\025" }, // <Ctrl-U>
318 { OP_VIEW_ATTACHMENTS, "v" },
319 { 0, NULL },
320};
321// clang-format on
322
327{
332};
333
341static bool resolve_email(struct IndexPrivateData *priv,
342 struct IndexSharedData *shared, enum ResolveMethod rm)
343{
344 if (!priv || !priv->menu || !shared || !shared->mailbox || !shared->email)
345 return false;
346
347 const bool c_resolve = cs_subset_bool(shared->sub, "resolve");
348 if (!c_resolve)
349 return false;
350
351 int index = -1;
352 switch (rm)
353 {
355 index = menu_get_index(priv->menu) + 1;
356 break;
357
359 {
360 const bool uncollapse = mutt_using_threads() && !window_is_focused(priv->win_index);
361 index = find_next_undeleted(shared->mailbox_view, menu_get_index(priv->menu), uncollapse);
362 break;
363 }
364
366 index = mutt_next_thread(shared->email);
367 break;
368
370 index = mutt_next_subthread(shared->email);
371 break;
372 }
373
374 if ((index < 0) || (index >= shared->mailbox->vcount))
375 {
376 // Resolve failed
377 notify_send(shared->notify, NT_INDEX, NT_INDEX_EMAIL, NULL);
378 return false;
379 }
380
381 menu_set_index(priv->menu, index);
382 return true;
383}
384
390bool index_next_undeleted(struct MuttWindow *win_index)
391{
392 struct MuttWindow *dlg = dialog_find(win_index);
393 if (!dlg)
394 return false;
395
396 struct Menu *menu = win_index->wdata;
397 struct IndexSharedData *shared = dlg->wdata;
398 if (!shared)
399 return false;
400
401 struct IndexPrivateData *priv = win_index->parent->wdata;
402 const bool uncollapse = mutt_using_threads() && !window_is_focused(priv->win_index);
403
404 int index = find_next_undeleted(shared->mailbox_view, menu_get_index(menu), uncollapse);
405 if ((index < 0) || (index >= shared->mailbox->vcount))
406 {
407 // Selection failed
409 return false;
410 }
411
412 menu_set_index(menu, index);
413 return true;
414}
415
416// -----------------------------------------------------------------------------
417
422 struct IndexPrivateData *priv, int op)
423{
425 return FR_SUCCESS;
426}
427
432 struct IndexPrivateData *priv, int op)
433{
434 if (!shared->email)
435 return FR_NO_ACTION;
437
439 return FR_SUCCESS;
440}
441
446 struct IndexPrivateData *priv, int op)
447{
448 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
449 ea_add_tagged(&ea, shared->mailbox_view, shared->email, priv->tag_prefix);
450 index_bounce_message(shared->mailbox, &ea);
451 ARRAY_FREE(&ea);
452
453 return FR_SUCCESS;
454}
455
459static int op_check_traditional(struct IndexSharedData *shared,
460 struct IndexPrivateData *priv, int op)
461{
463 return FR_NOT_IMPL;
464 if (!shared->email)
465 return FR_NO_ACTION;
466
467 if (priv->tag_prefix || !(shared->email->security & PGP_TRADITIONAL_CHECKED))
468 {
469 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
470 ea_add_tagged(&ea, shared->mailbox_view, shared->email, priv->tag_prefix);
471 if (mutt_check_traditional_pgp(shared->mailbox, &ea))
473 ARRAY_FREE(&ea);
474 }
475
476 return FR_SUCCESS;
477}
478
482static int op_compose_to_sender(struct IndexSharedData *shared,
483 struct IndexPrivateData *priv, int op)
484{
485 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
486 ea_add_tagged(&ea, shared->mailbox_view, shared->email, priv->tag_prefix);
487 int rc = mutt_send_message(SEND_TO_SENDER, NULL, NULL, shared->mailbox, &ea,
488 shared->sub);
489 ARRAY_FREE(&ea);
491
492 return (rc == -1) ? FR_ERROR : FR_SUCCESS;
493}
494
498static int op_create_alias(struct IndexSharedData *shared,
499 struct IndexPrivateData *priv, int op)
500{
501 struct AddressList *al = NULL;
502 if (shared->email && shared->email->env)
503 al = mutt_get_address(shared->email->env, NULL);
504 alias_create(al, shared->sub);
506
507 return FR_SUCCESS;
508}
509
517static int op_delete(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
518{
519 /* L10N: CHECK_ACL */
520 if (!check_acl(shared->mailbox, MUTT_ACL_DELETE, _("Can't delete message")))
521 return FR_ERROR;
522
523 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
524 ea_add_tagged(&ea, shared->mailbox_view, shared->email, priv->tag_prefix);
525
526 mutt_emails_set_flag(shared->mailbox, &ea, MUTT_DELETE, true);
527 mutt_emails_set_flag(shared->mailbox, &ea, MUTT_PURGE, (op == OP_PURGE_MESSAGE));
528 const bool c_delete_untag = cs_subset_bool(shared->sub, "delete_untag");
529 if (c_delete_untag)
530 mutt_emails_set_flag(shared->mailbox, &ea, MUTT_TAG, false);
531 ARRAY_FREE(&ea);
532
533 if (priv->tag_prefix)
534 {
536 }
537 else
538 {
540 }
541
542 return FR_SUCCESS;
543}
544
553static int op_delete_thread(struct IndexSharedData *shared,
554 struct IndexPrivateData *priv, int op)
555{
556 /* L10N: CHECK_ACL */
557 /* L10N: Due to the implementation details we do not know whether we
558 delete zero, 1, 12, ... messages. So in English we use
559 "messages". Your language might have other means to express this. */
560 if (!check_acl(shared->mailbox, MUTT_ACL_DELETE, _("Can't delete messages")))
561 return FR_ERROR;
562 if (!shared->email)
563 return FR_NO_ACTION;
564
565 int subthread = (op == OP_DELETE_SUBTHREAD);
566 int rc = mutt_thread_set_flag(shared->mailbox, shared->email, MUTT_DELETE, true, subthread);
567 if (rc == -1)
568 return FR_ERROR;
569 if (op == OP_PURGE_THREAD)
570 {
571 rc = mutt_thread_set_flag(shared->mailbox, shared->email, MUTT_PURGE, true, subthread);
572 if (rc == -1)
573 return FR_ERROR;
574 }
575
576 const bool c_delete_untag = cs_subset_bool(shared->sub, "delete_untag");
577 if (c_delete_untag)
578 mutt_thread_set_flag(shared->mailbox, shared->email, MUTT_TAG, false, subthread);
579
582 return FR_SUCCESS;
583}
584
588static int op_display_address(struct IndexSharedData *shared,
589 struct IndexPrivateData *priv, int op)
590{
591 if (!shared->email)
592 return FR_NO_ACTION;
594
595 return FR_SUCCESS;
596}
597
605static int op_display_message(struct IndexSharedData *shared,
606 struct IndexPrivateData *priv, int op)
607{
608 if (!shared->email)
609 return FR_NO_ACTION;
610 /* toggle the weeding of headers so that a user can press the key
611 * again while reading the message. */
612 if (op == OP_DISPLAY_HEADERS)
613 {
614 bool_str_toggle(shared->sub, "weed", NULL);
615 notify_send(shared->notify, NT_INDEX, NT_INDEX_EMAIL, shared);
616 if (!window_is_focused(priv->win_index))
617 return FR_SUCCESS;
618 }
619
620 OptNeedResort = false;
621
622 if (mutt_using_threads() && shared->email->collapsed)
623 {
625 mutt_set_vnum(shared->mailbox);
626 const bool c_uncollapse_jump = cs_subset_bool(shared->sub, "uncollapse_jump");
627 if (c_uncollapse_jump)
629 }
630
631 const bool c_pgp_auto_decode = cs_subset_bool(shared->sub, "pgp_auto_decode");
632 if (c_pgp_auto_decode &&
633 (priv->tag_prefix || !(shared->email->security & PGP_TRADITIONAL_CHECKED)))
634 {
635 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
636 ea_add_tagged(&ea, shared->mailbox_view, shared->email, priv->tag_prefix);
637 if (mutt_check_traditional_pgp(shared->mailbox, &ea))
639 ARRAY_FREE(&ea);
640 }
641 const int index = menu_get_index(priv->menu);
643
644 const char *const c_pager = pager_get_pager(NeoMutt->sub);
645 if (c_pager)
646 {
647 op = external_pager(shared->mailbox_view, shared->email, c_pager);
648 }
649 else
650 {
651 op = mutt_display_message(priv->win_index, shared);
652 }
653
655 if (op < OP_NULL)
656 {
657 OptNeedResort = false;
658 return FR_ERROR;
659 }
660
661 if (shared->mailbox)
662 {
664 shared->mailbox->msg_count, shared);
665 }
666
667 return op;
668}
669
673static int op_edit_label(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
674{
675 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
676 ea_add_tagged(&ea, shared->mailbox_view, shared->email, priv->tag_prefix);
677 int num_changed = mutt_label_message(shared->mailbox_view, &ea);
678 ARRAY_FREE(&ea);
679
680 if (num_changed > 0)
681 {
682 shared->mailbox->changed = true;
684 /* L10N: This is displayed when the x-label on one or more
685 messages is edited. */
686 mutt_message(ngettext("%d label changed", "%d labels changed", num_changed), num_changed);
687
688 if (!priv->tag_prefix)
690 return FR_SUCCESS;
691 }
692
693 /* L10N: This is displayed when editing an x-label, but no messages
694 were updated. Possibly due to canceling at the prompt or if the new
695 label is the same as the old label. */
696 mutt_message(_("No labels changed"));
697 return FR_NO_ACTION;
698}
699
708static int op_edit_raw_message(struct IndexSharedData *shared,
709 struct IndexPrivateData *priv, int op)
710{
711 /* TODO split this into 3 cases? */
712 bool edit;
713 if (op == OP_EDIT_RAW_MESSAGE)
714 {
715 /* L10N: CHECK_ACL */
716 if (!check_acl(shared->mailbox, MUTT_ACL_INSERT, _("Can't edit message")))
717 return FR_ERROR;
718 edit = true;
719 }
720 else if (op == OP_EDIT_OR_VIEW_RAW_MESSAGE)
721 {
722 edit = !shared->mailbox->readonly && (shared->mailbox->rights & MUTT_ACL_INSERT);
723 }
724 else
725 {
726 edit = false;
727 }
728
729 if (!shared->email)
730 return FR_NO_ACTION;
731 const bool c_pgp_auto_decode = cs_subset_bool(shared->sub, "pgp_auto_decode");
732 if (c_pgp_auto_decode &&
733 (priv->tag_prefix || !(shared->email->security & PGP_TRADITIONAL_CHECKED)))
734 {
735 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
736 ea_add_tagged(&ea, shared->mailbox_view, shared->email, priv->tag_prefix);
737 if (mutt_check_traditional_pgp(shared->mailbox, &ea))
739 ARRAY_FREE(&ea);
740 }
741 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
742 ea_add_tagged(&ea, shared->mailbox_view, shared->email, priv->tag_prefix);
743 mutt_ev_message(shared->mailbox, &ea, edit ? EVM_EDIT : EVM_VIEW);
744 ARRAY_FREE(&ea);
746
747 return FR_SUCCESS;
748}
749
753static int op_end_cond(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
754{
755 return FR_SUCCESS;
756}
757
761static int op_exit(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
762{
763 if (shared->attach_msg)
764 return FR_DONE;
765
766 if (query_quadoption(_("Exit NeoMutt without saving?"), shared->sub, "quit") == MUTT_YES)
767 {
768 if (shared->mailbox_view)
769 {
770 mx_fastclose_mailbox(shared->mailbox, false);
771 mview_free(&shared->mailbox_view);
772 }
773 return FR_DONE;
774 }
775
776 return FR_NO_ACTION;
777}
778
782static int op_extract_keys(struct IndexSharedData *shared,
783 struct IndexPrivateData *priv, int op)
784{
785 if (!WithCrypto)
786 return FR_NOT_IMPL;
787 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
788 ea_add_tagged(&ea, shared->mailbox_view, shared->email, priv->tag_prefix);
790 ARRAY_FREE(&ea);
792
793 return FR_SUCCESS;
794}
795
799static int op_flag_message(struct IndexSharedData *shared,
800 struct IndexPrivateData *priv, int op)
801{
802 /* L10N: CHECK_ACL */
803 if (!check_acl(shared->mailbox, MUTT_ACL_WRITE, _("Can't flag message")))
804 return FR_ERROR;
805
806 struct Mailbox *m = shared->mailbox;
807 if (priv->tag_prefix)
808 {
809 for (size_t i = 0; i < m->msg_count; i++)
810 {
811 struct Email *e = m->emails[i];
812 if (!e)
813 break;
814 if (message_is_tagged(e))
815 mutt_set_flag(m, e, MUTT_FLAG, !e->flagged, true);
816 }
817
819 }
820 else
821 {
822 if (!shared->email)
823 return FR_NO_ACTION;
824 mutt_set_flag(m, shared->email, MUTT_FLAG, !shared->email->flagged, true);
825
827 }
828
829 return FR_SUCCESS;
830}
831
835static int op_forget_passphrase(struct IndexSharedData *shared,
836 struct IndexPrivateData *priv, int op)
837{
839 return FR_SUCCESS;
840}
841
845static int op_forward_message(struct IndexSharedData *shared,
846 struct IndexPrivateData *priv, int op)
847{
848 if (!shared->email)
849 return FR_NO_ACTION;
850 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
851 ea_add_tagged(&ea, shared->mailbox_view, shared->email, priv->tag_prefix);
852 const bool c_pgp_auto_decode = cs_subset_bool(shared->sub, "pgp_auto_decode");
853 if (c_pgp_auto_decode &&
854 (priv->tag_prefix || !(shared->email->security & PGP_TRADITIONAL_CHECKED)))
855 {
856 if (mutt_check_traditional_pgp(shared->mailbox, &ea))
858 }
859 int rc = mutt_send_message(SEND_FORWARD, NULL, NULL, shared->mailbox, &ea,
860 shared->sub);
861 ARRAY_FREE(&ea);
863
864 return (rc == -1) ? FR_ERROR : FR_SUCCESS;
865}
866
874static int op_group_reply(struct IndexSharedData *shared,
875 struct IndexPrivateData *priv, int op)
876{
877 SendFlags replyflags = SEND_REPLY;
878 if (op == OP_GROUP_REPLY)
879 replyflags |= SEND_GROUP_REPLY;
880 else
881 replyflags |= SEND_GROUP_CHAT_REPLY;
882 if (!shared->email)
883 return FR_NO_ACTION;
884 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
885 ea_add_tagged(&ea, shared->mailbox_view, shared->email, priv->tag_prefix);
886 const bool c_pgp_auto_decode = cs_subset_bool(shared->sub, "pgp_auto_decode");
887 if (c_pgp_auto_decode &&
888 (priv->tag_prefix || !(shared->email->security & PGP_TRADITIONAL_CHECKED)))
889 {
890 if (mutt_check_traditional_pgp(shared->mailbox, &ea))
892 }
893 int rc = mutt_send_message(replyflags, NULL, NULL, shared->mailbox, &ea,
894 shared->sub);
895 ARRAY_FREE(&ea);
897
898 return (rc == -1) ? FR_ERROR : FR_SUCCESS;
899}
900
904static int op_jump(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
905{
906 int rc = FR_ERROR;
907 struct Buffer *buf = buf_pool_get();
908
909 const int digit = op - OP_JUMP;
910 if ((digit > 0) && (digit < 10))
911 {
912 mutt_unget_ch('0' + digit);
913 }
914
915 int msg_num = 0;
916 if ((mw_get_field(_("Jump to message: "), buf, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0) ||
917 buf_is_empty(buf))
918 {
919 mutt_message(_("Nothing to do"));
920 rc = FR_NO_ACTION;
921 }
922 else if (!mutt_str_atoi_full(buf_string(buf), &msg_num))
923 {
924 mutt_warning(_("Argument must be a message number"));
925 }
926 else if ((msg_num < 1) || (msg_num > shared->mailbox->msg_count))
927 {
928 mutt_warning(_("Invalid message number"));
929 }
930 else if (!shared->mailbox->emails[msg_num - 1]->visible)
931 {
932 mutt_warning(_("That message is not visible"));
933 }
934 else
935 {
936 struct Email *e = shared->mailbox->emails[msg_num - 1];
937
938 if (mutt_messages_in_thread(shared->mailbox, e, MIT_POSITION) > 1)
939 {
941 mutt_set_vnum(shared->mailbox);
942 }
943 menu_set_index(priv->menu, e->vnum);
944 rc = FR_SUCCESS;
945 }
946
947 buf_pool_release(&buf);
948 return rc;
949}
950
954static int op_list_reply(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
955{
956 if (!shared->email)
957 return FR_NO_ACTION;
958 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
959 ea_add_tagged(&ea, shared->mailbox_view, shared->email, priv->tag_prefix);
960 const bool c_pgp_auto_decode = cs_subset_bool(shared->sub, "pgp_auto_decode");
961 if (c_pgp_auto_decode &&
962 (priv->tag_prefix || !(shared->email->security & PGP_TRADITIONAL_CHECKED)))
963 {
964 if (mutt_check_traditional_pgp(shared->mailbox, &ea))
966 }
967 int rc = mutt_send_message(SEND_REPLY | SEND_LIST_REPLY, NULL, NULL,
968 shared->mailbox, &ea, shared->sub);
969 ARRAY_FREE(&ea);
971
972 return (rc == -1) ? FR_ERROR : FR_SUCCESS;
973}
974
978static int op_list_subscribe(struct IndexSharedData *shared,
979 struct IndexPrivateData *priv, int op)
980{
981 return mutt_send_list_subscribe(shared->mailbox, shared->email) ? FR_SUCCESS : FR_NO_ACTION;
982}
983
987static int op_list_unsubscribe(struct IndexSharedData *shared,
988 struct IndexPrivateData *priv, int op)
989{
991}
992
996static int op_mail(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
997{
998 int rc = mutt_send_message(SEND_NO_FLAGS, NULL, NULL, shared->mailbox, NULL,
999 shared->sub);
1001 return (rc == -1) ? FR_ERROR : FR_SUCCESS;
1002}
1003
1007static int op_mailbox_list(struct IndexSharedData *shared,
1008 struct IndexPrivateData *priv, int op)
1009{
1011 return FR_SUCCESS;
1012}
1013
1017static int op_mail_key(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
1018{
1019 if (!(WithCrypto & APPLICATION_PGP))
1020 return FR_NOT_IMPL;
1021 int rc = mutt_send_message(SEND_KEY, NULL, NULL, NULL, NULL, shared->sub);
1023
1024 return (rc == -1) ? FR_ERROR : FR_SUCCESS;
1025}
1026
1030static int op_main_break_thread(struct IndexSharedData *shared,
1031 struct IndexPrivateData *priv, int op)
1032{
1033 struct Mailbox *m = shared->mailbox;
1034 /* L10N: CHECK_ACL */
1035 if (!check_acl(m, MUTT_ACL_WRITE, _("Can't break thread")))
1036 return FR_ERROR;
1037
1038 struct Email *e = shared->email;
1039 if (!e)
1040 return FR_NO_ACTION;
1041
1042 if (!mutt_using_threads())
1043 {
1044 mutt_warning(_("Threading is not enabled"));
1045 return FR_NO_ACTION;
1046 }
1047
1048 struct MailboxView *mv = shared->mailbox_view;
1050 {
1051 {
1053 mutt_sort_headers(mv, true);
1054 menu_set_index(priv->menu, e->vnum);
1055 }
1056
1057 m->changed = true;
1058 mutt_message(_("Thread broken"));
1059
1061 }
1062 else
1063 {
1064 mutt_error(_("Thread can't be broken, message is not part of a thread"));
1065 }
1066
1067 return FR_SUCCESS;
1068}
1069
1078static int op_main_change_folder(struct IndexSharedData *shared,
1079 struct IndexPrivateData *priv, int op)
1080{
1081 struct Buffer *folderbuf = buf_pool_get();
1082 buf_alloc(folderbuf, PATH_MAX);
1083
1084 char *cp = NULL;
1085 bool read_only;
1086 const bool c_read_only = cs_subset_bool(shared->sub, "read_only");
1087 if (shared->attach_msg || c_read_only || (op == OP_MAIN_CHANGE_FOLDER_READONLY))
1088 {
1089 cp = _("Open mailbox in read-only mode");
1090 read_only = true;
1091 }
1092 else
1093 {
1094 cp = _("Open mailbox");
1095 read_only = false;
1096 }
1097
1098 const bool c_change_folder_next = cs_subset_bool(shared->sub, "change_folder_next");
1099 if (c_change_folder_next && shared->mailbox && !buf_is_empty(&shared->mailbox->pathbuf))
1100 {
1101 buf_strcpy(folderbuf, mailbox_path(shared->mailbox));
1102 buf_pretty_mailbox(folderbuf);
1103 }
1104 /* By default, fill buf with the next mailbox that contains unread mail */
1105 mutt_mailbox_next(shared->mailbox_view ? shared->mailbox : NULL, folderbuf);
1106
1107 if (mw_enter_fname(cp, folderbuf, true, shared->mailbox, false, NULL, NULL,
1108 MUTT_SEL_NO_FLAGS) == -1)
1109 {
1110 goto changefoldercleanup;
1111 }
1112
1113 /* Selected directory is okay, let's save it. */
1115
1116 if (buf_is_empty(folderbuf))
1117 {
1118 msgwin_clear_text(NULL);
1119 goto changefoldercleanup;
1120 }
1121
1122 struct Mailbox *m = mx_mbox_find2(buf_string(folderbuf));
1123 if (m)
1124 {
1125 change_folder_mailbox(priv->menu, m, &priv->oldcount, shared, read_only);
1126 }
1127 else
1128 {
1129 change_folder_string(priv->menu, folderbuf, &priv->oldcount, shared, read_only);
1130 }
1131
1132changefoldercleanup:
1133 buf_pool_release(&folderbuf);
1135
1136 return FR_SUCCESS;
1137}
1138
1142static int op_main_collapse_all(struct IndexSharedData *shared,
1143 struct IndexPrivateData *priv, int op)
1144{
1145 if (!mutt_using_threads())
1146 {
1147 mutt_error(_("Threading is not enabled"));
1148 return FR_ERROR;
1149 }
1150 collapse_all(shared->mailbox_view, priv->menu, 1);
1151 notify_send(shared->notify, NT_INDEX, NT_INDEX_EMAIL, NULL);
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 notify_send(shared->notify, NT_INDEX, NT_INDEX_EMAIL, NULL);
1193
1194 return FR_SUCCESS;
1195}
1196
1200static int op_main_delete_pattern(struct IndexSharedData *shared,
1201 struct IndexPrivateData *priv, int op)
1202{
1203 /* L10N: CHECK_ACL */
1204 /* L10N: Due to the implementation details we do not know whether we
1205 delete zero, 1, 12, ... messages. So in English we use
1206 "messages". Your language might have other means to express this. */
1207 if (!check_acl(shared->mailbox, MUTT_ACL_DELETE, _("Can't delete messages")))
1208 return FR_ERROR;
1209
1210 mutt_pattern_func(shared->mailbox_view, MUTT_DELETE, _("Delete messages matching: "));
1212
1213 return FR_SUCCESS;
1214}
1215
1224static int op_main_limit(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
1225{
1226 const bool lmt = mview_has_limit(shared->mailbox_view);
1227 int old_index = shared->email ? shared->email->index : -1;
1228 if (op == OP_TOGGLE_READ)
1229 {
1230 char buf2[1024] = { 0 };
1231
1232 if (!lmt || !mutt_strn_equal(shared->mailbox_view->pattern, "!~R!~D~s", 8))
1233 {
1234 snprintf(buf2, sizeof(buf2), "!~R!~D~s%s", lmt ? shared->mailbox_view->pattern : ".*");
1235 }
1236 else
1237 {
1238 mutt_str_copy(buf2, shared->mailbox_view->pattern + 8, sizeof(buf2));
1239 if ((*buf2 == '\0') || mutt_strn_equal(buf2, ".*", 2))
1240 snprintf(buf2, sizeof(buf2), "~A");
1241 }
1242 mutt_str_replace(&shared->mailbox_view->pattern, buf2);
1244 }
1245
1246 if (((op == OP_LIMIT_CURRENT_THREAD) &&
1247 mutt_limit_current_thread(shared->mailbox_view, shared->email)) ||
1248 (op == OP_TOGGLE_READ) ||
1249 ((op == OP_MAIN_LIMIT) && (mutt_pattern_func(shared->mailbox_view, MUTT_LIMIT,
1250 _("Limit to messages matching: ")) == 0)))
1251 {
1252 priv->menu->max = shared->mailbox->vcount;
1253 menu_set_index(priv->menu, 0);
1254 if (old_index >= 0)
1255 {
1256 /* try to find what used to be the current message */
1257 for (size_t i = 0; i < shared->mailbox->vcount; i++)
1258 {
1259 struct Email *e = mutt_get_virt_email(shared->mailbox, i);
1260 if (!e)
1261 continue;
1262 if (e->index == old_index)
1263 {
1264 menu_set_index(priv->menu, i);
1265 break;
1266 }
1267 }
1268 }
1269
1270 if ((shared->mailbox->msg_count != 0) && mutt_using_threads())
1271 {
1272 const bool c_collapse_all = cs_subset_bool(shared->sub, "collapse_all");
1273 if (c_collapse_all)
1274 collapse_all(shared->mailbox_view, priv->menu, 0);
1276 }
1277 notify_send(shared->notify, NT_INDEX, NT_INDEX_EMAIL, NULL);
1279 }
1280 if (lmt)
1281 mutt_message(_("To view all messages, limit to \"all\""));
1282
1283 return FR_SUCCESS;
1284}
1285
1289static int op_main_link_threads(struct IndexSharedData *shared,
1290 struct IndexPrivateData *priv, int op)
1291{
1292 struct Mailbox *m = shared->mailbox;
1293 /* L10N: CHECK_ACL */
1294 if (!check_acl(m, MUTT_ACL_WRITE, _("Can't link threads")))
1295 return FR_ERROR;
1296
1297 struct Email *e = shared->email;
1298 if (!e)
1299 return FR_NO_ACTION;
1300
1301 enum FunctionRetval rc = FR_ERROR;
1302
1303 if (!mutt_using_threads())
1304 {
1305 mutt_error(_("Threading is not enabled"));
1306 }
1307 else if (!e->env->message_id)
1308 {
1309 mutt_error(_("No Message-ID: header available to link thread"));
1310 }
1311 else
1312 {
1313 struct MailboxView *mv = shared->mailbox_view;
1314 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
1315 ea_add_tagged(&ea, mv, NULL, true);
1316
1317 if (mutt_link_threads(e, &ea, m))
1318 {
1319 mutt_sort_headers(mv, true);
1320 menu_set_index(priv->menu, e->vnum);
1321
1322 m->changed = true;
1323 mutt_message(_("Threads linked"));
1324 rc = FR_SUCCESS;
1325 }
1326 else
1327 {
1328 mutt_error(_("No thread linked"));
1329 rc = FR_NO_ACTION;
1330 }
1331
1332 ARRAY_FREE(&ea);
1333 }
1334
1336 return rc;
1337}
1338
1346static int op_main_modify_tags(struct IndexSharedData *shared,
1347 struct IndexPrivateData *priv, int op)
1348{
1349 int rc = FR_ERROR;
1350 struct Buffer *buf = NULL;
1351
1352 if (!shared->mailbox)
1353 goto done;
1354 struct Mailbox *m = shared->mailbox;
1355 if (!mx_tags_is_supported(m))
1356 {
1357 mutt_message(_("Folder doesn't support tagging, aborting"));
1358 goto done;
1359 }
1360 if (!shared->email)
1361 {
1362 rc = FR_NO_ACTION;
1363 goto done;
1364 }
1365
1366 struct Buffer *tags = buf_pool_get();
1367 if (!priv->tag_prefix)
1368 driver_tags_get_with_hidden(&shared->email->tags, tags);
1369 buf = buf_pool_get();
1370 int rc2 = mx_tags_edit(m, buf_string(tags), buf);
1371 buf_pool_release(&tags);
1372 if (rc2 < 0)
1373 {
1374 goto done;
1375 }
1376 else if (rc2 == 0)
1377 {
1378 mutt_message(_("No tag specified, aborting"));
1379 goto done;
1380 }
1381
1382 if (priv->tag_prefix)
1383 {
1384 struct Progress *progress = NULL;
1385
1386 if (m->verbose)
1387 {
1389 progress_set_message(progress, _("Update tags..."));
1390 }
1391
1392#ifdef USE_NOTMUCH
1393 if (m->type == MUTT_NOTMUCH)
1394 nm_db_longrun_init(m, true);
1395#endif
1396 for (int px = 0, i = 0; i < m->msg_count; i++)
1397 {
1398 struct Email *e = m->emails[i];
1399 if (!e)
1400 break;
1401 if (!message_is_tagged(e))
1402 continue;
1403
1404 progress_update(progress, ++px, -1);
1405 mx_tags_commit(m, e, buf_string(buf));
1406 e->attr_color = NULL;
1407 if (op == OP_MAIN_MODIFY_TAGS_THEN_HIDE)
1408 {
1409 bool still_queried = false;
1410#ifdef USE_NOTMUCH
1411 if (m->type == MUTT_NOTMUCH)
1412 still_queried = nm_message_is_still_queried(m, e);
1413#endif
1414 e->quasi_deleted = !still_queried;
1415 m->changed = true;
1416 }
1417 }
1418 progress_free(&progress);
1419#ifdef USE_NOTMUCH
1420 if (m->type == MUTT_NOTMUCH)
1422#endif
1424 }
1425 else
1426 {
1427 if (mx_tags_commit(m, shared->email, buf_string(buf)))
1428 {
1429 mutt_message(_("Failed to modify tags, aborting"));
1430 goto done;
1431 }
1432 shared->email->attr_color = NULL;
1433 if (op == OP_MAIN_MODIFY_TAGS_THEN_HIDE)
1434 {
1435 bool still_queried = false;
1436#ifdef USE_NOTMUCH
1437 if (m->type == MUTT_NOTMUCH)
1438 still_queried = nm_message_is_still_queried(m, shared->email);
1439#endif
1440 shared->email->quasi_deleted = !still_queried;
1441 m->changed = true;
1442 }
1443
1445 }
1446 rc = FR_SUCCESS;
1447
1448done:
1449 buf_pool_release(&buf);
1450 return rc;
1451}
1452
1464static int op_main_next_new(struct IndexSharedData *shared,
1465 struct IndexPrivateData *priv, int op)
1466{
1467 int first_unread = -1;
1468 int first_new = -1;
1469
1470 const int saved_current = menu_get_index(priv->menu);
1471 int mcur = saved_current;
1472 int index = -1;
1473 const bool threaded = mutt_using_threads();
1474 for (size_t i = 0; i != shared->mailbox->vcount; i++)
1475 {
1476 if ((op == OP_MAIN_NEXT_NEW) || (op == OP_MAIN_NEXT_UNREAD) ||
1477 (op == OP_MAIN_NEXT_NEW_THEN_UNREAD))
1478 {
1479 mcur++;
1480 if (mcur > (shared->mailbox->vcount - 1))
1481 {
1482 mcur = 0;
1483 }
1484 }
1485 else
1486 {
1487 mcur--;
1488 if (mcur < 0)
1489 {
1490 mcur = shared->mailbox->vcount - 1;
1491 }
1492 }
1493
1494 struct Email *e = mutt_get_virt_email(shared->mailbox, mcur);
1495 if (!e)
1496 break;
1497 if (e->collapsed && threaded)
1498 {
1499 int unread = mutt_thread_contains_unread(e);
1500 if ((unread != 0) && (first_unread == -1))
1501 first_unread = mcur;
1502 if ((unread == 1) && (first_new == -1))
1503 first_new = mcur;
1504 }
1505 else if (!e->deleted && !e->read)
1506 {
1507 if (first_unread == -1)
1508 first_unread = mcur;
1509 if (!e->old && (first_new == -1))
1510 first_new = mcur;
1511 }
1512
1513 if (((op == OP_MAIN_NEXT_UNREAD) || (op == OP_MAIN_PREV_UNREAD)) && (first_unread != -1))
1514 {
1515 break;
1516 }
1517 if (((op == OP_MAIN_NEXT_NEW) || (op == OP_MAIN_PREV_NEW) ||
1518 (op == OP_MAIN_NEXT_NEW_THEN_UNREAD) || (op == OP_MAIN_PREV_NEW_THEN_UNREAD)) &&
1519 (first_new != -1))
1520 {
1521 break;
1522 }
1523 }
1524 if (((op == OP_MAIN_NEXT_NEW) || (op == OP_MAIN_PREV_NEW) ||
1525 (op == OP_MAIN_NEXT_NEW_THEN_UNREAD) || (op == OP_MAIN_PREV_NEW_THEN_UNREAD)) &&
1526 (first_new != -1))
1527 {
1528 index = first_new;
1529 }
1530 else if (((op == OP_MAIN_NEXT_UNREAD) || (op == OP_MAIN_PREV_UNREAD) ||
1531 (op == OP_MAIN_NEXT_NEW_THEN_UNREAD) || (op == OP_MAIN_PREV_NEW_THEN_UNREAD)) &&
1532 (first_unread != -1))
1533 {
1534 index = first_unread;
1535 }
1536
1537 if (index == -1)
1538 {
1539 menu_set_index(priv->menu, saved_current);
1540 if ((op == OP_MAIN_NEXT_NEW) || (op == OP_MAIN_PREV_NEW))
1541 {
1542 if (mview_has_limit(shared->mailbox_view))
1543 mutt_error(_("No new messages in this limited view"));
1544 else
1545 mutt_error(_("No new messages"));
1546 }
1547 else
1548 {
1549 if (mview_has_limit(shared->mailbox_view))
1550 mutt_error(_("No unread messages in this limited view"));
1551 else
1552 mutt_error(_("No unread messages"));
1553 }
1554 notify_send(shared->notify, NT_INDEX, NT_INDEX_EMAIL, NULL);
1555 return FR_ERROR;
1556 }
1557 else
1558 {
1559 menu_set_index(priv->menu, index);
1560 }
1561
1562 index = menu_get_index(priv->menu);
1563 if ((op == OP_MAIN_NEXT_NEW) || (op == OP_MAIN_NEXT_UNREAD) ||
1564 (op == OP_MAIN_NEXT_NEW_THEN_UNREAD))
1565 {
1566 if (saved_current > index)
1567 {
1568 mutt_message(_("Search wrapped to top"));
1569 }
1570 }
1571 else if (saved_current < index)
1572 {
1573 mutt_message(_("Search wrapped to bottom"));
1574 }
1575
1576 return FR_SUCCESS;
1577}
1578
1588static int op_main_next_thread(struct IndexSharedData *shared,
1589 struct IndexPrivateData *priv, int op)
1590{
1591 int index = -1;
1592 switch (op)
1593 {
1594 case OP_MAIN_NEXT_THREAD:
1595 index = mutt_next_thread(shared->email);
1596 break;
1597
1598 case OP_MAIN_NEXT_SUBTHREAD:
1599 index = mutt_next_subthread(shared->email);
1600 break;
1601
1602 case OP_MAIN_PREV_THREAD:
1603 index = mutt_previous_thread(shared->email);
1604 break;
1605
1606 case OP_MAIN_PREV_SUBTHREAD:
1608 break;
1609 }
1610
1611 if (index != -1)
1612 menu_set_index(priv->menu, index);
1613
1614 if (index < 0)
1615 {
1616 if ((op == OP_MAIN_NEXT_THREAD) || (op == OP_MAIN_NEXT_SUBTHREAD))
1617 mutt_error(_("No more threads"));
1618 else
1619 mutt_error(_("You are on the first thread"));
1620
1621 notify_send(shared->notify, NT_INDEX, NT_INDEX_EMAIL, NULL);
1622 }
1623
1624 return FR_SUCCESS;
1625}
1626
1630static int op_main_next_undeleted(struct IndexSharedData *shared,
1631 struct IndexPrivateData *priv, int op)
1632{
1633 int index = menu_get_index(priv->menu);
1634 if (index >= (shared->mailbox->vcount - 1))
1635 {
1636 notify_send(shared->notify, NT_INDEX, NT_INDEX_EMAIL, NULL);
1637 mutt_message(_("You are on the last message"));
1638 return FR_ERROR;
1639 }
1640
1641 const bool uncollapse = mutt_using_threads() && !window_is_focused(priv->win_index);
1642
1643 index = find_next_undeleted(shared->mailbox_view, index, uncollapse);
1644 if (index != -1)
1645 {
1646 menu_set_index(priv->menu, index);
1647 if (uncollapse)
1649 }
1650
1651 if (index == -1)
1652 {
1653 notify_send(shared->notify, NT_INDEX, NT_INDEX_EMAIL, NULL);
1654 mutt_error(_("No undeleted messages"));
1655 }
1656
1657 return FR_SUCCESS;
1658}
1659
1664 struct IndexPrivateData *priv, int op)
1665{
1666 struct Mailbox *m = shared->mailbox;
1667
1668 struct Buffer *folderbuf = buf_pool_get();
1669 buf_strcpy(folderbuf, mailbox_path(m));
1670 m = mutt_mailbox_next_unread(m, folderbuf);
1671 buf_pool_release(&folderbuf);
1672
1673 if (!m)
1674 {
1675 mutt_error(_("No mailboxes have new mail"));
1676 return FR_ERROR;
1677 }
1678
1679 change_folder_mailbox(priv->menu, m, &priv->oldcount, shared, false);
1680 return FR_SUCCESS;
1681}
1682
1686static int op_main_prev_undeleted(struct IndexSharedData *shared,
1687 struct IndexPrivateData *priv, int op)
1688{
1689 int index = menu_get_index(priv->menu);
1690 if (index < 1)
1691 {
1692 notify_send(shared->notify, NT_INDEX, NT_INDEX_EMAIL, NULL);
1693 mutt_message(_("You are on the first message"));
1694 return FR_ERROR;
1695 }
1696
1697 const bool uncollapse = mutt_using_threads() && !window_is_focused(priv->win_index);
1698
1699 index = find_previous_undeleted(shared->mailbox_view, index, uncollapse);
1700 if (index != -1)
1701 {
1702 menu_set_index(priv->menu, index);
1703 if (uncollapse)
1705 }
1706
1707 if (index == -1)
1708 {
1709 mutt_error(_("No undeleted messages"));
1710 notify_send(shared->notify, NT_INDEX, NT_INDEX_EMAIL, NULL);
1711 }
1712
1713 return FR_SUCCESS;
1714}
1715
1719static int op_main_quasi_delete(struct IndexSharedData *shared,
1720 struct IndexPrivateData *priv, int op)
1721{
1722 if (priv->tag_prefix)
1723 {
1724 struct Mailbox *m = shared->mailbox;
1725 for (size_t i = 0; i < m->msg_count; i++)
1726 {
1727 struct Email *e = m->emails[i];
1728 if (!e)
1729 break;
1730 if (message_is_tagged(e))
1731 {
1732 e->quasi_deleted = true;
1733 m->changed = true;
1734 }
1735 }
1736 }
1737 else
1738 {
1739 if (!shared->email)
1740 return FR_NO_ACTION;
1741 shared->email->quasi_deleted = true;
1742 shared->mailbox->changed = true;
1743 }
1744
1745 return FR_SUCCESS;
1746}
1747
1755static int op_main_read_thread(struct IndexSharedData *shared,
1756 struct IndexPrivateData *priv, int op)
1757{
1758 /* L10N: CHECK_ACL */
1759 /* L10N: Due to the implementation details we do not know whether we
1760 mark zero, 1, 12, ... messages as read. So in English we use
1761 "messages". Your language might have other means to express this. */
1762 if (!check_acl(shared->mailbox, MUTT_ACL_SEEN, _("Can't mark messages as read")))
1763 return FR_ERROR;
1764
1765 int rc = mutt_thread_set_flag(shared->mailbox, shared->email, MUTT_READ, true,
1766 (op != OP_MAIN_READ_THREAD));
1767 if (rc != -1)
1768 {
1769 const enum ResolveMethod rm = (op == OP_MAIN_READ_THREAD) ? RESOLVE_NEXT_THREAD :
1771 resolve_email(priv, shared, rm);
1773 }
1774
1775 return FR_SUCCESS;
1776}
1777
1785static int op_main_root_message(struct IndexSharedData *shared,
1786 struct IndexPrivateData *priv, int op)
1787{
1788 int index = mutt_parent_message(shared->email, op == OP_MAIN_ROOT_MESSAGE);
1789 if (index != -1)
1790 menu_set_index(priv->menu, index);
1791
1792 return FR_SUCCESS;
1793}
1794
1802static int op_main_set_flag(struct IndexSharedData *shared,
1803 struct IndexPrivateData *priv, int op)
1804{
1805 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
1806 ea_add_tagged(&ea, shared->mailbox_view, shared->email, priv->tag_prefix);
1807
1808 if (mw_change_flag(shared->mailbox, &ea, (op == OP_MAIN_SET_FLAG)) == 0)
1809 {
1810 if (priv->tag_prefix)
1811 {
1813 }
1814 else
1815 {
1817 }
1818 }
1819 ARRAY_FREE(&ea);
1820
1821 return FR_SUCCESS;
1822}
1823
1827static int op_main_show_limit(struct IndexSharedData *shared,
1828 struct IndexPrivateData *priv, int op)
1829{
1830 if (mview_has_limit(shared->mailbox_view))
1831 {
1832 char buf2[256] = { 0 };
1833 /* L10N: ask for a limit to apply */
1834 snprintf(buf2, sizeof(buf2), _("Limit: %s"), shared->mailbox_view->pattern);
1835 mutt_message("%s", buf2);
1836 }
1837 else
1838 {
1839 mutt_message(_("No limit pattern is in effect"));
1840 }
1841
1842 return FR_SUCCESS;
1843}
1844
1848static int op_main_sync_folder(struct IndexSharedData *shared,
1849 struct IndexPrivateData *priv, int op)
1850{
1851 if (!shared->mailbox || (shared->mailbox->msg_count == 0) || shared->mailbox->readonly)
1852 return FR_NO_ACTION;
1853
1854 int ovc = shared->mailbox->vcount;
1855 int oc = shared->mailbox->msg_count;
1856 struct Email *e = NULL;
1857
1858 /* don't attempt to move the cursor if there are no visible messages in the current limit */
1859 int index = menu_get_index(priv->menu);
1860 if (index < shared->mailbox->vcount)
1861 {
1862 /* threads may be reordered, so figure out what header the cursor
1863 * should be on. */
1864 int newidx = index;
1865 if (!shared->email)
1866 return FR_NO_ACTION;
1867 if (shared->email->deleted)
1868 newidx = find_next_undeleted(shared->mailbox_view, index, false);
1869 if (newidx < 0)
1870 newidx = find_previous_undeleted(shared->mailbox_view, index, false);
1871 if (newidx >= 0)
1872 e = mutt_get_virt_email(shared->mailbox, newidx);
1873 }
1874
1875 enum MxStatus check = mx_mbox_sync(shared->mailbox);
1876 if (check == MX_STATUS_OK)
1877 {
1878 if (e && (shared->mailbox->vcount != ovc))
1879 {
1880 for (size_t i = 0; i < shared->mailbox->vcount; i++)
1881 {
1882 struct Email *e2 = mutt_get_virt_email(shared->mailbox, i);
1883 if (e2 == e)
1884 {
1885 menu_set_index(priv->menu, i);
1886 break;
1887 }
1888 }
1889 }
1891 }
1892 else if ((check == MX_STATUS_NEW_MAIL) || (check == MX_STATUS_REOPENED))
1893 {
1894 update_index(priv->menu, shared->mailbox_view, check, oc, shared);
1895 }
1896
1897 /* do a sanity check even if mx_mbox_sync failed. */
1898
1899 index = menu_get_index(priv->menu);
1900 if ((index < 0) || (shared->mailbox && (index >= shared->mailbox->vcount)))
1901 {
1903 }
1904
1905 /* check for a fatal error, or all messages deleted */
1906 if (shared->mailbox && buf_is_empty(&shared->mailbox->pathbuf))
1907 {
1908 mview_free(&shared->mailbox_view);
1909 }
1910
1911 priv->menu->max = shared->mailbox->vcount;
1913
1914 struct EventMailbox ev_m = { shared->mailbox };
1916
1917 return FR_SUCCESS;
1918}
1919
1923static int op_main_tag_pattern(struct IndexSharedData *shared,
1924 struct IndexPrivateData *priv, int op)
1925{
1926 mutt_pattern_func(shared->mailbox_view, MUTT_TAG, _("Tag messages matching: "));
1928
1929 return FR_SUCCESS;
1930}
1931
1936 struct IndexPrivateData *priv, int op)
1937{
1938 /* L10N: CHECK_ACL */
1939 /* L10N: Due to the implementation details we do not know whether we
1940 undelete zero, 1, 12, ... messages. So in English we use
1941 "messages". Your language might have other means to express this. */
1942 if (!check_acl(shared->mailbox, MUTT_ACL_DELETE, _("Can't undelete messages")))
1943 return FR_ERROR;
1944
1946 _("Undelete messages matching: ")) == 0)
1947 {
1949 }
1950
1951 return FR_SUCCESS;
1952}
1953
1957static int op_main_untag_pattern(struct IndexSharedData *shared,
1958 struct IndexPrivateData *priv, int op)
1959{
1960 if (mutt_pattern_func(shared->mailbox_view, MUTT_UNTAG, _("Untag messages matching: ")) == 0)
1962
1963 return FR_SUCCESS;
1964}
1965
1969static int op_mark_msg(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
1970{
1971 if (!shared->email)
1972 return FR_NO_ACTION;
1973
1974 int rc = FR_SUCCESS;
1975
1976 if (shared->email->env->message_id)
1977 {
1978 struct Buffer *buf = buf_pool_get();
1979
1980 /* L10N: This is the prompt for <mark-message>. Whatever they
1981 enter will be prefixed by $mark_macro_prefix and will become
1982 a macro hotkey to jump to the currently selected message. */
1983 if ((mw_get_field(_("Enter macro stroke: "), buf, MUTT_COMP_NO_FLAGS,
1984 HC_OTHER, NULL, NULL) == 0) &&
1985 !buf_is_empty(buf))
1986 {
1987 const char *const c_mark_macro_prefix = cs_subset_string(shared->sub, "mark_macro_prefix");
1988 char str[256] = { 0 };
1989 snprintf(str, sizeof(str), "%s%s", c_mark_macro_prefix, buf_string(buf));
1990
1991 struct Buffer *msg_id = buf_pool_get();
1992 mutt_file_sanitize_regex(msg_id, shared->email->env->message_id);
1993 char macro[256] = { 0 };
1994 snprintf(macro, sizeof(macro), "<search>~i '%s'\n", buf_string(msg_id));
1995 buf_pool_release(&msg_id);
1996
1997 /* L10N: "message hotkey" is the key bindings menu description of a
1998 macro created by <mark-message>. */
1999 km_bind(str, MENU_INDEX, OP_MACRO, macro, _("message hotkey"));
2000
2001 /* L10N: This is echoed after <mark-message> creates a new hotkey
2002 macro. %s is the hotkey string ($mark_macro_prefix followed
2003 by whatever they typed at the prompt.) */
2004 buf_printf(buf, _("Message bound to %s"), str);
2005 mutt_message("%s", buf_string(buf));
2006 mutt_debug(LL_DEBUG1, "Mark: %s => %s\n", str, macro);
2007 buf_pool_release(&buf);
2008 }
2009 }
2010 else
2011 {
2012 /* L10N: This error is printed if <mark-message> can't find a
2013 Message-ID for the currently selected message in the index. */
2014 mutt_error(_("No message ID to macro"));
2015 rc = FR_ERROR;
2016 }
2017
2018 return rc;
2019}
2020
2024static int op_next_entry(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2025{
2026 const int index = menu_get_index(priv->menu) + 1;
2027 if (index >= shared->mailbox->vcount)
2028 {
2029 mutt_message(_("You are on the last message"));
2030 notify_send(shared->notify, NT_INDEX, NT_INDEX_EMAIL, NULL);
2031 return FR_ERROR;
2032 }
2033 menu_set_index(priv->menu, index);
2034 return FR_SUCCESS;
2035}
2036
2040static int op_pipe(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2041{
2042 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
2043 ea_add_tagged(&ea, shared->mailbox_view, shared->email, priv->tag_prefix);
2044 mutt_pipe_message(shared->mailbox, &ea);
2045 ARRAY_FREE(&ea);
2046
2047 /* in an IMAP folder index with imap_peek=no, piping could change
2048 * new or old messages status to read. Redraw what's needed. */
2049 const bool c_imap_peek = cs_subset_bool(shared->sub, "imap_peek");
2050 if ((shared->mailbox->type == MUTT_IMAP) && !c_imap_peek)
2051 {
2053 }
2054
2055 return FR_SUCCESS;
2056}
2057
2061static int op_prev_entry(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2062{
2063 int index = menu_get_index(priv->menu);
2064 if (index < 1)
2065 {
2066 notify_send(shared->notify, NT_INDEX, NT_INDEX_EMAIL, NULL);
2067 mutt_message(_("You are on the first message"));
2068 return FR_ERROR;
2069 }
2070 menu_set_index(priv->menu, index - 1);
2071 return FR_SUCCESS;
2072}
2073
2077static int op_print(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2078{
2079 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
2080 ea_add_tagged(&ea, shared->mailbox_view, shared->email, priv->tag_prefix);
2081 mutt_print_message(shared->mailbox, &ea);
2082 ARRAY_FREE(&ea);
2083
2084 /* in an IMAP folder index with imap_peek=no, printing could change
2085 * new or old messages status to read. Redraw what's needed. */
2086 const bool c_imap_peek = cs_subset_bool(shared->sub, "imap_peek");
2087 if ((shared->mailbox->type == MUTT_IMAP) && !c_imap_peek)
2088 {
2090 }
2091
2092 return FR_SUCCESS;
2093}
2094
2098static int op_query(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2099{
2100 query_index(shared->mailbox, shared->sub);
2101 return FR_SUCCESS;
2102}
2103
2107static int op_quit(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2108{
2109 if (shared->attach_msg)
2110 return FR_DONE;
2111
2112 if (query_quadoption(_("Quit NeoMutt?"), shared->sub, "quit") == MUTT_YES)
2113 {
2114 priv->oldcount = shared->mailbox ? shared->mailbox->msg_count : 0;
2115
2117 mutt_debug(LL_NOTIFY, "NT_GLOBAL_SHUTDOWN\n");
2119
2120 enum MxStatus check = MX_STATUS_OK;
2121 if (!shared->mailbox_view || ((check = mx_mbox_close(shared->mailbox)) == MX_STATUS_OK))
2122 {
2123 mview_free(&shared->mailbox_view);
2124 mailbox_free(&shared->mailbox);
2125 return FR_DONE;
2126 }
2127
2128 if ((check == MX_STATUS_NEW_MAIL) || (check == MX_STATUS_REOPENED))
2129 {
2130 update_index(priv->menu, shared->mailbox_view, check, priv->oldcount, shared);
2131 }
2132
2133 menu_queue_redraw(priv->menu, MENU_REDRAW_FULL); /* new mail arrived? */
2135 }
2136
2137 return FR_NO_ACTION;
2138}
2139
2143static int op_recall_message(struct IndexSharedData *shared,
2144 struct IndexPrivateData *priv, int op)
2145{
2146 int rc = mutt_send_message(SEND_POSTPONED, NULL, NULL, shared->mailbox, NULL,
2147 shared->sub);
2149 return (rc == -1) ? FR_ERROR : FR_SUCCESS;
2150}
2151
2155static int op_reply(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2156{
2157 if (!shared->email)
2158 return FR_NO_ACTION;
2159 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
2160 ea_add_tagged(&ea, shared->mailbox_view, shared->email, priv->tag_prefix);
2161 const bool c_pgp_auto_decode = cs_subset_bool(shared->sub, "pgp_auto_decode");
2162 if (c_pgp_auto_decode &&
2163 (priv->tag_prefix || !(shared->email->security & PGP_TRADITIONAL_CHECKED)))
2164 {
2165 if (mutt_check_traditional_pgp(shared->mailbox, &ea))
2167 }
2168 int rc = mutt_send_message(SEND_REPLY, NULL, NULL, shared->mailbox, &ea,
2169 shared->sub);
2170 ARRAY_FREE(&ea);
2172
2173 return (rc == -1) ? FR_ERROR : FR_SUCCESS;
2174}
2175
2179static int op_resend(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2180{
2181 int rc = -1;
2182 if (priv->tag_prefix)
2183 {
2184 struct Mailbox *m = shared->mailbox;
2185 for (size_t i = 0; i < m->msg_count; i++)
2186 {
2187 struct Email *e = m->emails[i];
2188 if (!e)
2189 break;
2190 if (message_is_tagged(e))
2191 rc = mutt_resend_message(NULL, shared->mailbox, e, shared->sub);
2192 }
2193 }
2194 else
2195 {
2196 rc = mutt_resend_message(NULL, shared->mailbox, shared->email, shared->sub);
2197 }
2198
2200 return (rc == -1) ? FR_ERROR : FR_SUCCESS;
2201}
2202
2214static int op_save(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2215{
2216 if (((op == OP_DECRYPT_COPY) || (op == OP_DECRYPT_SAVE)) && !WithCrypto)
2217 return FR_NOT_IMPL;
2218
2219 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
2220 ea_add_tagged(&ea, shared->mailbox_view, shared->email, priv->tag_prefix);
2221
2222 const enum MessageSaveOpt save_opt = ((op == OP_SAVE) || (op == OP_DECODE_SAVE) ||
2223 (op == OP_DECRYPT_SAVE)) ?
2224 SAVE_MOVE :
2225 SAVE_COPY;
2226
2227 enum MessageTransformOpt transform_opt =
2228 ((op == OP_DECODE_SAVE) || (op == OP_DECODE_COPY)) ? TRANSFORM_DECODE :
2229 ((op == OP_DECRYPT_SAVE) || (op == OP_DECRYPT_COPY)) ? TRANSFORM_DECRYPT :
2231
2232 const int rc = mutt_save_message(shared->mailbox, &ea, save_opt, transform_opt);
2233 if ((rc == 0) && (save_opt == SAVE_MOVE))
2234 {
2236 }
2237 ARRAY_FREE(&ea);
2238
2239 if (priv->tag_prefix)
2241
2242 return (rc == -1) ? FR_ERROR : FR_SUCCESS;
2243}
2244
2254static int op_search(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2255{
2257 switch (op)
2258 {
2259 case OP_SEARCH:
2260 flags |= SEARCH_PROMPT;
2261 shared->search_state->reverse = false;
2262 break;
2263 case OP_SEARCH_REVERSE:
2264 flags |= SEARCH_PROMPT;
2265 shared->search_state->reverse = true;
2266 break;
2267 case OP_SEARCH_NEXT:
2268 break;
2269 case OP_SEARCH_OPPOSITE:
2270 flags |= SEARCH_OPPOSITE;
2271 break;
2272 }
2273
2274 // Initiating a search can happen on an empty mailbox, but
2275 // searching for next/previous/... needs to be on a message and
2276 // thus a non-empty mailbox
2277 int index = menu_get_index(priv->menu);
2278 index = mutt_search_command(shared->mailbox_view, priv->menu, index,
2279 shared->search_state, flags);
2280 if (index != -1)
2281 menu_set_index(priv->menu, index);
2282
2283 return FR_SUCCESS;
2284}
2285
2293static int op_sort(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2294{
2295 if (!mutt_select_sort(op == OP_SORT_REVERSE))
2296 return FR_ERROR;
2297
2298 if (shared->mailbox && (shared->mailbox->msg_count != 0))
2299 {
2300 resort_index(shared->mailbox_view, priv->menu);
2302 }
2303
2304 return FR_SUCCESS;
2305}
2306
2310static int op_tag(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2311{
2312 const bool c_auto_tag = cs_subset_bool(shared->sub, "auto_tag");
2313 if (priv->tag_prefix && !c_auto_tag)
2314 {
2315 struct Mailbox *m = shared->mailbox;
2316 for (size_t i = 0; i < m->msg_count; i++)
2317 {
2318 struct Email *e = m->emails[i];
2319 if (!e)
2320 break;
2321 if (e->visible)
2322 mutt_set_flag(m, e, MUTT_TAG, false, true);
2323 }
2325 return FR_SUCCESS;
2326 }
2327
2328 if (!shared->email)
2329 return FR_NO_ACTION;
2330
2331 mutt_set_flag(shared->mailbox, shared->email, MUTT_TAG, !shared->email->tagged, true);
2332
2333 resolve_email(priv, shared, RESOLVE_NEXT_EMAIL);
2334 return FR_SUCCESS;
2335}
2336
2344static int op_tag_thread(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2345{
2346 if (!shared->email)
2347 return FR_NO_ACTION;
2348
2349 int rc = mutt_thread_set_flag(shared->mailbox, shared->email, MUTT_TAG,
2350 !shared->email->tagged, (op != OP_TAG_THREAD));
2351 if (rc != -1)
2352 {
2353 const enum ResolveMethod rm = (op == OP_TAG_THREAD) ? RESOLVE_NEXT_THREAD :
2355 resolve_email(priv, shared, rm);
2357 }
2358
2359 return FR_SUCCESS;
2360}
2361
2365static int op_toggle_new(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2366{
2367 /* L10N: CHECK_ACL */
2368 if (!check_acl(shared->mailbox, MUTT_ACL_SEEN, _("Can't toggle new")))
2369 return FR_ERROR;
2370
2371 struct Mailbox *m = shared->mailbox;
2372 if (priv->tag_prefix)
2373 {
2374 for (size_t i = 0; i < m->msg_count; i++)
2375 {
2376 struct Email *e = m->emails[i];
2377 if (!e)
2378 break;
2379 if (!message_is_tagged(e))
2380 continue;
2381
2382 if (e->read || e->old)
2383 mutt_set_flag(m, e, MUTT_NEW, true, true);
2384 else
2385 mutt_set_flag(m, e, MUTT_READ, true, true);
2386 }
2388 }
2389 else
2390 {
2391 if (!shared->email)
2392 return FR_NO_ACTION;
2393 if (shared->email->read || shared->email->old)
2394 mutt_set_flag(m, shared->email, MUTT_NEW, true, true);
2395 else
2396 mutt_set_flag(m, shared->email, MUTT_READ, true, true);
2397
2399 }
2400
2401 return FR_SUCCESS;
2402}
2403
2407static int op_toggle_write(struct IndexSharedData *shared,
2408 struct IndexPrivateData *priv, int op)
2409{
2410 mx_toggle_write(shared->mailbox);
2411 return FR_SUCCESS;
2412}
2413
2417static int op_undelete(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2418{
2419 /* L10N: CHECK_ACL */
2420 if (!check_acl(shared->mailbox, MUTT_ACL_DELETE, _("Can't undelete message")))
2421 return FR_ERROR;
2422
2423 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
2424 ea_add_tagged(&ea, shared->mailbox_view, shared->email, priv->tag_prefix);
2425
2426 mutt_emails_set_flag(shared->mailbox, &ea, MUTT_DELETE, false);
2427 mutt_emails_set_flag(shared->mailbox, &ea, MUTT_PURGE, false);
2428 ARRAY_FREE(&ea);
2429
2430 if (priv->tag_prefix)
2431 {
2433 }
2434 else
2435 {
2436 resolve_email(priv, shared, RESOLVE_NEXT_EMAIL);
2437 }
2438
2439 return FR_SUCCESS;
2440}
2441
2449static int op_undelete_thread(struct IndexSharedData *shared,
2450 struct IndexPrivateData *priv, int op)
2451{
2452 /* L10N: CHECK_ACL */
2453 /* L10N: Due to the implementation details we do not know whether we
2454 undelete zero, 1, 12, ... messages. So in English we use
2455 "messages". Your language might have other means to express this. */
2456 if (!check_acl(shared->mailbox, MUTT_ACL_DELETE, _("Can't undelete messages")))
2457 return FR_ERROR;
2458
2459 int rc = mutt_thread_set_flag(shared->mailbox, shared->email, MUTT_DELETE,
2460 false, (op != OP_UNDELETE_THREAD));
2461 if (rc != -1)
2462 {
2463 rc = mutt_thread_set_flag(shared->mailbox, shared->email, MUTT_PURGE, false,
2464 (op != OP_UNDELETE_THREAD));
2465 }
2466 if (rc != -1)
2467 {
2468 const enum ResolveMethod rm = (op == OP_UNDELETE_THREAD) ? RESOLVE_NEXT_THREAD :
2470 resolve_email(priv, shared, rm);
2472 }
2473
2474 return FR_SUCCESS;
2475}
2476
2480static int op_view_attachments(struct IndexSharedData *shared,
2481 struct IndexPrivateData *priv, int op)
2482{
2483 if (!shared->email)
2484 return FR_NO_ACTION;
2485
2486 enum FunctionRetval rc = FR_ERROR;
2487 struct Message *msg = mx_msg_open(shared->mailbox, shared->email);
2488 if (msg)
2489 {
2490 dlg_attachment(NeoMutt->sub, shared->mailbox_view, shared->email, msg->fp,
2491 shared->attach_msg);
2492 if (shared->email->attach_del)
2493 {
2494 shared->mailbox->changed = true;
2495 }
2496 mx_msg_close(shared->mailbox, &msg);
2497 rc = FR_SUCCESS;
2498 }
2500 return rc;
2501}
2502
2503// -----------------------------------------------------------------------------
2504
2505#ifdef USE_AUTOCRYPT
2509static int op_autocrypt_acct_menu(struct IndexSharedData *shared,
2510 struct IndexPrivateData *priv, int op)
2511{
2512 dlg_autocrypt();
2513 return FR_SUCCESS;
2514}
2515#endif
2516
2520static int op_main_imap_fetch(struct IndexSharedData *shared,
2521 struct IndexPrivateData *priv, int op)
2522{
2523 if (!shared->mailbox || (shared->mailbox->type != MUTT_IMAP))
2524 return FR_NO_ACTION;
2525
2526 imap_check_mailbox(shared->mailbox, true);
2527 return FR_SUCCESS;
2528}
2529
2534 struct IndexPrivateData *priv, int op)
2535{
2536 if (shared->mailbox && (shared->mailbox->type == MUTT_IMAP))
2537 {
2538 const enum MxStatus check = mx_mbox_close(shared->mailbox);
2539 if (check == MX_STATUS_OK)
2540 {
2541 mview_free(&shared->mailbox_view);
2542 }
2543 else
2544 {
2545 if ((check == MX_STATUS_NEW_MAIL) || (check == MX_STATUS_REOPENED))
2546 {
2547 update_index(priv->menu, shared->mailbox_view, check, priv->oldcount, shared);
2548 }
2551 return FR_ERROR;
2552 }
2553 }
2555 mutt_message(_("Logged out of IMAP servers"));
2558
2559 return FR_SUCCESS;
2560}
2561
2565static int op_catchup(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2566{
2567 struct Mailbox *m = shared->mailbox;
2568 if (!m || (m->type != MUTT_NNTP))
2569 return FR_NO_ACTION;
2570
2571 struct NntpMboxData *mdata = m->mdata;
2572 if (mutt_newsgroup_catchup(m, mdata->adata, mdata->group))
2574
2575 return FR_SUCCESS;
2576}
2577
2585static int op_get_children(struct IndexSharedData *shared,
2586 struct IndexPrivateData *priv, int op)
2587{
2588 struct Mailbox *m = shared->mailbox;
2589 if (m->type != MUTT_NNTP)
2590 return FR_ERROR;
2591
2592 struct Email *e = shared->email;
2593 if (!e)
2594 return FR_NO_ACTION;
2595
2596 char buf[PATH_MAX] = { 0 };
2597 int oldmsgcount = m->msg_count;
2598 int oldindex = e->index;
2599 int rc = 0;
2600
2601 if (!e->env->message_id)
2602 {
2603 mutt_error(_("No Message-Id. Unable to perform operation."));
2604 return FR_ERROR;
2605 }
2606
2607 mutt_message(_("Fetching message headers..."));
2608 if (!m->id_hash)
2609 m->id_hash = mutt_make_id_hash(m);
2610 mutt_str_copy(buf, e->env->message_id, sizeof(buf));
2611
2612 /* trying to find msgid of the root message */
2613 if (op == OP_RECONSTRUCT_THREAD)
2614 {
2615 struct ListNode *ref = NULL;
2616 STAILQ_FOREACH(ref, &e->env->references, entries)
2617 {
2618 if (!mutt_hash_find(m->id_hash, ref->data))
2619 {
2620 rc = nntp_check_msgid(m, ref->data);
2621 if (rc < 0)
2622 return FR_ERROR;
2623 }
2624
2625 /* the last msgid in References is the root message */
2626 if (!STAILQ_NEXT(ref, entries))
2627 mutt_str_copy(buf, ref->data, sizeof(buf));
2628 }
2629 }
2630
2631 /* fetching all child messages */
2632 rc = nntp_check_children(m, buf);
2633
2634 /* at least one message has been loaded */
2635 if (m->msg_count > oldmsgcount)
2636 {
2637 bool verbose = m->verbose;
2638
2639 if (rc < 0)
2640 m->verbose = false;
2641
2642 struct MailboxView *mv = shared->mailbox_view;
2643 mutt_sort_headers(mv, (op == OP_RECONSTRUCT_THREAD));
2644 m->verbose = verbose;
2645
2646 /* if the root message was retrieved, move to it */
2647 struct Email *e2 = mutt_hash_find(m->id_hash, buf);
2648 if (e2)
2649 {
2650 menu_set_index(priv->menu, e2->vnum);
2651 }
2652 else
2653 {
2654 /* try to restore old position */
2655 for (int i = 0; i < m->msg_count; i++)
2656 {
2657 e2 = m->emails[i];
2658 if (!e2)
2659 break;
2660 if (e2->index == oldindex)
2661 {
2662 menu_set_index(priv->menu, e2->vnum);
2663 /* as an added courtesy, recenter the menu
2664 * with the current entry at the middle of the screen */
2666 }
2667 }
2668 }
2670 }
2671 else if (rc >= 0)
2672 {
2673 mutt_error(_("No deleted messages found in the thread"));
2674 }
2675
2676 return FR_SUCCESS;
2677}
2678
2686static int op_get_message(struct IndexSharedData *shared,
2687 struct IndexPrivateData *priv, int op)
2688{
2689 struct Mailbox *m = shared->mailbox;
2690 if (m->type != MUTT_NNTP)
2691 return FR_SUCCESS;
2692
2693 int rc = FR_ERROR;
2694 struct Buffer *buf = buf_pool_get();
2695
2696 if (op == OP_GET_MESSAGE)
2697 {
2698 if ((mw_get_field(_("Enter Message-Id: "), buf, MUTT_COMP_NO_FLAGS,
2699 HC_OTHER, NULL, NULL) != 0) ||
2700 buf_is_empty(buf))
2701 {
2702 goto done;
2703 }
2704 }
2705 else
2706 {
2707 struct Email *e = shared->email;
2708 if (!e || STAILQ_EMPTY(&e->env->references))
2709 {
2710 mutt_error(_("Article has no parent reference"));
2711 goto done;
2712 }
2713 buf_strcpy(buf, STAILQ_FIRST(&e->env->references)->data);
2714 }
2715
2716 if (!m->id_hash)
2717 m->id_hash = mutt_make_id_hash(m);
2718 struct Email *e = mutt_hash_find(m->id_hash, buf_string(buf));
2719 if (e)
2720 {
2721 if (e->vnum != -1)
2722 {
2723 menu_set_index(priv->menu, e->vnum);
2724 }
2725 else if (e->collapsed)
2726 {
2728 mutt_set_vnum(m);
2729 menu_set_index(priv->menu, e->vnum);
2730 }
2731 else
2732 {
2733 mutt_error(_("Message is not visible in limited view"));
2734 }
2735 }
2736 else
2737 {
2738 mutt_message(_("Fetching %s from server..."), buf_string(buf));
2739 int rc2 = nntp_check_msgid(m, buf_string(buf));
2740 if (rc2 == 0)
2741 {
2742 e = m->emails[m->msg_count - 1];
2743 struct MailboxView *mv = shared->mailbox_view;
2744 mutt_sort_headers(mv, false);
2745 menu_set_index(priv->menu, e->vnum);
2747 rc = FR_SUCCESS;
2748 }
2749 else if (rc2 > 0)
2750 {
2751 mutt_error(_("Article %s not found on the server"), buf_string(buf));
2752 }
2753 }
2754
2755done:
2756 buf_pool_release(&buf);
2757 return rc;
2758}
2759
2767static int op_main_change_group(struct IndexSharedData *shared,
2768 struct IndexPrivateData *priv, int op)
2769{
2770 struct Buffer *folderbuf = buf_pool_get();
2771 buf_alloc(folderbuf, PATH_MAX);
2772
2773 OptNews = false;
2774 bool read_only;
2775 char *cp = NULL;
2776 const bool c_read_only = cs_subset_bool(shared->sub, "read_only");
2777 if (shared->attach_msg || c_read_only || (op == OP_MAIN_CHANGE_GROUP_READONLY))
2778 {
2779 cp = _("Open newsgroup in read-only mode");
2780 read_only = true;
2781 }
2782 else
2783 {
2784 cp = _("Open newsgroup");
2785 read_only = false;
2786 }
2787
2788 const bool c_change_folder_next = cs_subset_bool(shared->sub, "change_folder_next");
2789 if (c_change_folder_next && shared->mailbox && !buf_is_empty(&shared->mailbox->pathbuf))
2790 {
2791 buf_strcpy(folderbuf, mailbox_path(shared->mailbox));
2792 buf_pretty_mailbox(folderbuf);
2793 }
2794
2795 OptNews = true;
2796 const char *const c_news_server = cs_subset_string(shared->sub, "news_server");
2797 if (!CurrentNewsSrv)
2798 CurrentNewsSrv = nntp_select_server(shared->mailbox, c_news_server, false);
2799 if (!CurrentNewsSrv)
2800 goto changefoldercleanup2;
2801
2802 nntp_mailbox(shared->mailbox, folderbuf->data, folderbuf->dsize);
2803
2804 if (mw_enter_fname(cp, folderbuf, true, shared->mailbox, false, NULL, NULL,
2805 MUTT_SEL_NO_FLAGS) == -1)
2806 {
2807 goto changefoldercleanup2;
2808 }
2809
2810 /* Selected directory is okay, let's save it. */
2812
2813 if (buf_is_empty(folderbuf))
2814 {
2815 msgwin_clear_text(NULL);
2816 goto changefoldercleanup2;
2817 }
2818
2819 struct Mailbox *m = mx_mbox_find2(buf_string(folderbuf));
2820 if (m)
2821 {
2822 change_folder_mailbox(priv->menu, m, &priv->oldcount, shared, read_only);
2823 }
2824 else
2825 {
2826 change_folder_string(priv->menu, folderbuf, &priv->oldcount, shared, read_only);
2827 }
2828 struct MuttWindow *dlg = dialog_find(priv->win_index);
2829 dlg->help_data = IndexNewsHelp;
2830
2831changefoldercleanup2:
2832 buf_pool_release(&folderbuf);
2833 return FR_SUCCESS;
2834}
2835
2843static int op_post(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2844{
2845 if (!shared->email)
2846 return FR_NO_ACTION;
2847
2848 if ((op != OP_FOLLOWUP) || !shared->email->env->followup_to ||
2849 !mutt_istr_equal(shared->email->env->followup_to, "poster") ||
2850 (query_quadoption(_("Reply by mail as poster prefers?"), shared->sub,
2851 "followup_to_poster") != MUTT_YES))
2852 {
2853 if (shared->mailbox && (shared->mailbox->type == MUTT_NNTP) &&
2854 !((struct NntpMboxData *) shared->mailbox->mdata)->allowed &&
2855 (query_quadoption(_("Posting to this group not allowed, may be moderated. Continue?"),
2856 shared->sub, "post_moderated") != MUTT_YES))
2857 {
2858 return FR_ERROR;
2859 }
2860 if (op == OP_POST)
2861 {
2862 mutt_send_message(SEND_NEWS, NULL, NULL, shared->mailbox, NULL, shared->sub);
2863 }
2864 else
2865 {
2866 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
2867 ea_add_tagged(&ea, shared->mailbox_view, shared->email, priv->tag_prefix);
2868 mutt_send_message(((op == OP_FOLLOWUP) ? SEND_REPLY : SEND_FORWARD) | SEND_NEWS,
2869 NULL, NULL, shared->mailbox, &ea, shared->sub);
2870 ARRAY_FREE(&ea);
2871 }
2873 return FR_SUCCESS;
2874 }
2875
2876 return op_reply(shared, priv, OP_REPLY);
2877}
2878
2879#ifdef USE_NOTMUCH
2883static int op_main_entire_thread(struct IndexSharedData *shared,
2884 struct IndexPrivateData *priv, int op)
2885{
2886 if (shared->mailbox->type != MUTT_NOTMUCH)
2887 {
2888 if (((shared->mailbox->type != MUTT_MH) && (shared->mailbox->type != MUTT_MAILDIR)) ||
2889 (!shared->email || !shared->email->env || !shared->email->env->message_id))
2890 {
2891 mutt_message(_("No virtual folder and no Message-Id, aborting"));
2892 return FR_ERROR;
2893 } // no virtual folder, but we have message-id, reconstruct thread on-the-fly
2894
2895 struct Buffer *buf = buf_pool_get();
2896 buf_alloc(buf, PATH_MAX);
2897 buf_addstr(buf, "id:");
2898
2899 int msg_id_offset = 0;
2900 if ((shared->email->env->message_id)[0] == '<')
2901 msg_id_offset = 1;
2902
2903 buf_addstr(buf, shared->email->env->message_id + msg_id_offset);
2904
2905 size_t len = buf_len(buf);
2906 ASSERT(len > 0);
2907 if (buf->data[len - 1] == '>')
2908 buf->data[len - 1] = '\0';
2909
2910 change_folder_notmuch(priv->menu, buf->data, buf->dsize, &priv->oldcount, shared, false);
2911 buf_pool_release(&buf);
2912
2913 // If notmuch doesn't contain the message, we're left in an empty
2914 // vfolder. No messages are found, but nm_read_entire_thread assumes
2915 // a valid message-id and will throw a segfault.
2916 //
2917 // To prevent that, stay in the empty vfolder and print an error.
2918 if (shared->mailbox->msg_count == 0)
2919 {
2920 mutt_error(_("failed to find message in notmuch database. try running 'notmuch new'."));
2921 return FR_ERROR;
2922 }
2923 }
2924 priv->oldcount = shared->mailbox->msg_count;
2925 int index = menu_get_index(priv->menu);
2926 struct Email *e_oldcur = mutt_get_virt_email(shared->mailbox, index);
2927 if (!e_oldcur)
2928 return FR_ERROR;
2929
2930 if (nm_read_entire_thread(shared->mailbox, e_oldcur) < 0)
2931 {
2932 mutt_message(_("Failed to read thread, aborting"));
2933 return FR_ERROR;
2934 }
2935
2936 // nm_read_entire_thread() may modify msg_count and menu won't be updated.
2937 priv->menu->max = shared->mailbox->msg_count;
2938
2939 if (priv->oldcount < shared->mailbox->msg_count)
2940 {
2941 /* nm_read_entire_thread() triggers mutt_sort_headers() if necessary */
2942 index = e_oldcur->vnum;
2943 if (e_oldcur->collapsed || shared->mailbox_view->collapsed)
2944 {
2945 index = mutt_uncollapse_thread(e_oldcur);
2946 mutt_set_vnum(shared->mailbox);
2947 }
2948 menu_set_index(priv->menu, index);
2950 }
2951
2952 return FR_SUCCESS;
2953}
2954
2963 struct IndexPrivateData *priv, int op)
2964{
2965 int rc = FR_SUCCESS;
2966 struct Buffer *buf = buf_pool_get();
2967
2968 if ((mw_get_field("Query: ", buf, MUTT_COMP_NO_FLAGS, HC_OTHER,
2969 &CompleteNmQueryOps, NULL) != 0) ||
2970 buf_is_empty(buf))
2971 {
2972 mutt_message(_("No query, aborting"));
2973 rc = FR_NO_ACTION;
2974 goto done;
2975 }
2976
2977 // Keep copy of user's query to name the mailbox
2978 char *query_unencoded = buf_strdup(buf);
2979
2980 buf_alloc(buf, PATH_MAX);
2981 struct Mailbox *m_query = change_folder_notmuch(priv->menu, buf->data, buf->dsize,
2982 &priv->oldcount, shared,
2983 (op == OP_MAIN_VFOLDER_FROM_QUERY_READONLY));
2984 if (m_query)
2985 {
2986 FREE(&m_query->name);
2987 m_query->name = query_unencoded;
2988 query_unencoded = NULL;
2989 rc = FR_SUCCESS;
2990 }
2991 else
2992 {
2993 FREE(&query_unencoded);
2994 }
2995
2996done:
2997 buf_pool_release(&buf);
2998 return rc;
2999}
3000
3010 struct IndexPrivateData *priv, int op)
3011{
3012 // Common guard clauses.
3014 {
3015 mutt_message(_("Windowed queries disabled"));
3016 return FR_ERROR;
3017 }
3018 const char *const c_nm_query_window_current_search = cs_subset_string(shared->sub, "nm_query_window_current_search");
3019 if (!c_nm_query_window_current_search)
3020 {
3021 mutt_message(_("No notmuch vfolder currently loaded"));
3022 return FR_ERROR;
3023 }
3024
3025 // Call the specific operation.
3026 switch (op)
3027 {
3028 case OP_MAIN_WINDOWED_VFOLDER_BACKWARD:
3030 break;
3031 case OP_MAIN_WINDOWED_VFOLDER_FORWARD:
3033 break;
3034 case OP_MAIN_WINDOWED_VFOLDER_RESET:
3036 break;
3037 }
3038
3039 // Common query window folder change.
3040 char buf[PATH_MAX] = { 0 };
3041 mutt_str_copy(buf, c_nm_query_window_current_search, sizeof(buf));
3042 change_folder_notmuch(priv->menu, buf, sizeof(buf), &priv->oldcount, shared, false);
3043
3044 return FR_SUCCESS;
3045}
3046#endif
3047
3051static int op_main_fetch_mail(struct IndexSharedData *shared,
3052 struct IndexPrivateData *priv, int op)
3053{
3056 return FR_SUCCESS;
3057}
3058
3059// -----------------------------------------------------------------------------
3060
3068static bool prereq(struct IndexSharedData *shared, struct Menu *menu, CheckFlags checks)
3069{
3070 bool result = true;
3071 struct MailboxView *mv = shared->mailbox_view;
3072
3073 if (checks & (CHECK_MSGCOUNT | CHECK_VISIBLE | CHECK_READONLY))
3074 checks |= CHECK_IN_MAILBOX;
3075
3076 if ((checks & CHECK_IN_MAILBOX) && (!mv || !mv->mailbox))
3077 {
3078 mutt_error(_("No mailbox is open"));
3079 result = false;
3080 }
3081
3082 if (result && (checks & CHECK_MSGCOUNT) && (mv->mailbox->msg_count == 0))
3083 {
3084 mutt_error(_("There are no messages"));
3085 result = false;
3086 }
3087
3088 int index = menu_get_index(menu);
3089 if (result && (checks & CHECK_VISIBLE) &&
3090 ((index < 0) || (index >= mv->mailbox->vcount)))
3091 {
3092 mutt_error(_("No visible messages"));
3093 result = false;
3094 }
3095
3096 if (result && (checks & CHECK_READONLY) && mv->mailbox->readonly)
3097 {
3098 mutt_error(_("Mailbox is read-only"));
3099 result = false;
3100 }
3101
3102 if (result && (checks & CHECK_ATTACH) && shared->attach_msg)
3103 {
3104 mutt_error(_("Function not permitted in attach-message mode"));
3105 result = false;
3106 }
3107
3108 if (!result)
3109 mutt_flushinp();
3110
3111 return result;
3112}
3113
3117static const struct IndexFunction IndexFunctions[] = {
3118 // clang-format off
3119 { OP_ALIAS_DIALOG, op_alias_dialog, CHECK_NO_FLAGS },
3125 { OP_COPY_MESSAGE, op_save, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3126 { OP_CREATE_ALIAS, op_create_alias, CHECK_NO_FLAGS },
3127 { OP_DECODE_COPY, op_save, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3128 { OP_DECODE_SAVE, op_save, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3129 { OP_DECRYPT_COPY, op_save, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3130 { OP_DECRYPT_SAVE, op_save, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3138 { OP_EDIT_OR_VIEW_RAW_MESSAGE, op_edit_raw_message, CHECK_ATTACH | CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3140 { OP_END_COND, op_end_cond, CHECK_NO_FLAGS },
3141 { OP_EXIT, op_exit, CHECK_NO_FLAGS },
3145 { OP_FORGET_PASSPHRASE, op_forget_passphrase, CHECK_NO_FLAGS },
3147 { OP_FORWARD_TO_GROUP, op_post, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3151 { OP_GENERIC_SELECT_ENTRY, op_display_message, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3154 { OP_JUMP, op_jump, CHECK_IN_MAILBOX },
3155 { OP_JUMP_1, op_jump, CHECK_IN_MAILBOX },
3156 { OP_JUMP_2, op_jump, CHECK_IN_MAILBOX },
3157 { OP_JUMP_3, op_jump, CHECK_IN_MAILBOX },
3158 { OP_JUMP_4, op_jump, CHECK_IN_MAILBOX },
3159 { OP_JUMP_5, op_jump, CHECK_IN_MAILBOX },
3160 { OP_JUMP_6, op_jump, CHECK_IN_MAILBOX },
3161 { OP_JUMP_7, op_jump, CHECK_IN_MAILBOX },
3162 { OP_JUMP_8, op_jump, CHECK_IN_MAILBOX },
3163 { OP_JUMP_9, op_jump, CHECK_IN_MAILBOX },
3164 { OP_LIMIT_CURRENT_THREAD, op_main_limit, CHECK_IN_MAILBOX },
3168 { OP_MAIL, op_mail, CHECK_ATTACH },
3169 { OP_MAILBOX_LIST, op_mailbox_list, CHECK_NO_FLAGS },
3170 { OP_MAIL_KEY, op_mail_key, CHECK_ATTACH },
3172 { OP_MAIN_CHANGE_FOLDER, op_main_change_folder, CHECK_NO_FLAGS },
3173 { OP_MAIN_CHANGE_FOLDER_READONLY, op_main_change_folder, CHECK_NO_FLAGS },
3174 { OP_MAIN_CHANGE_GROUP, op_main_change_group, CHECK_NO_FLAGS },
3175 { OP_MAIN_CHANGE_GROUP_READONLY, op_main_change_group, CHECK_NO_FLAGS },
3177 { OP_MAIN_COLLAPSE_ALL, op_main_collapse_all, CHECK_IN_MAILBOX },
3178 { OP_MAIN_COLLAPSE_THREAD, op_main_collapse_thread, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3179 { OP_MAIN_DELETE_PATTERN, op_main_delete_pattern, CHECK_ATTACH | CHECK_IN_MAILBOX | CHECK_READONLY },
3180 { OP_MAIN_FETCH_MAIL, op_main_fetch_mail, CHECK_ATTACH },
3181 { OP_MAIN_IMAP_FETCH, op_main_imap_fetch, CHECK_NO_FLAGS },
3182 { OP_MAIN_IMAP_LOGOUT_ALL, op_main_imap_logout_all, CHECK_NO_FLAGS },
3183 { OP_MAIN_LIMIT, op_main_limit, CHECK_IN_MAILBOX },
3186 { OP_MAIN_MODIFY_TAGS_THEN_HIDE, op_main_modify_tags, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_READONLY | CHECK_VISIBLE },
3188 { OP_MAIN_NEXT_NEW_THEN_UNREAD, op_main_next_new, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3189 { OP_MAIN_NEXT_SUBTHREAD, op_main_next_thread, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3192 { OP_MAIN_NEXT_UNREAD, op_main_next_new, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3193 { OP_MAIN_NEXT_UNREAD_MAILBOX, op_main_next_unread_mailbox, CHECK_IN_MAILBOX },
3194 { OP_MAIN_PARENT_MESSAGE, op_main_root_message, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3196 { OP_MAIN_PREV_NEW_THEN_UNREAD, op_main_next_new, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3197 { OP_MAIN_PREV_SUBTHREAD, op_main_next_thread, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3200 { OP_MAIN_PREV_UNREAD, op_main_next_new, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3206 { OP_MAIN_SHOW_LIMIT, op_main_show_limit, CHECK_IN_MAILBOX },
3207 { OP_MAIN_SYNC_FOLDER, op_main_sync_folder, CHECK_NO_FLAGS },
3208 { OP_MAIN_TAG_PATTERN, op_main_tag_pattern, CHECK_IN_MAILBOX },
3209 { OP_MAIN_UNDELETE_PATTERN, op_main_undelete_pattern, CHECK_IN_MAILBOX | CHECK_READONLY },
3210 { OP_MAIN_UNTAG_PATTERN, op_main_untag_pattern, CHECK_IN_MAILBOX },
3214 { OP_POST, op_post, CHECK_ATTACH | CHECK_IN_MAILBOX },
3219 { OP_QUERY, op_query, CHECK_ATTACH },
3220 { OP_QUIT, op_quit, CHECK_NO_FLAGS },
3221 { OP_RECALL_MESSAGE, op_recall_message, CHECK_ATTACH },
3226 { OP_SEARCH, op_search, CHECK_IN_MAILBOX },
3227 { OP_SEARCH_NEXT, op_search, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3228 { OP_SEARCH_OPPOSITE, op_search, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3229 { OP_SEARCH_REVERSE, op_search, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3230 { OP_SORT, op_sort, CHECK_NO_FLAGS },
3231 { OP_SORT_REVERSE, op_sort, CHECK_NO_FLAGS },
3236 { OP_TOGGLE_READ, op_main_limit, CHECK_IN_MAILBOX },
3237 { OP_TOGGLE_WRITE, op_toggle_write, CHECK_IN_MAILBOX },
3243#ifdef USE_AUTOCRYPT
3244 { OP_AUTOCRYPT_ACCT_MENU, op_autocrypt_acct_menu, CHECK_NO_FLAGS },
3245#endif
3246#ifdef USE_NOTMUCH
3247 { OP_MAIN_CHANGE_VFOLDER, op_main_change_folder, CHECK_NO_FLAGS },
3249 { OP_MAIN_VFOLDER_FROM_QUERY, op_main_vfolder_from_query, CHECK_NO_FLAGS },
3250 { OP_MAIN_VFOLDER_FROM_QUERY_READONLY, op_main_vfolder_from_query, CHECK_NO_FLAGS },
3251 { OP_MAIN_WINDOWED_VFOLDER_BACKWARD, op_main_windowed_vfolder, CHECK_IN_MAILBOX },
3252 { OP_MAIN_WINDOWED_VFOLDER_FORWARD, op_main_windowed_vfolder, CHECK_IN_MAILBOX },
3253 { OP_MAIN_WINDOWED_VFOLDER_RESET, op_main_windowed_vfolder, CHECK_IN_MAILBOX },
3254#endif
3255 { 0, NULL, CHECK_NO_FLAGS },
3256 // clang-format on
3257};
3258
3263{
3264 // The Dispatcher may be called on any Window in the Dialog
3265 struct MuttWindow *dlg = dialog_find(win);
3266 if (!dlg || !dlg->wdata || !win->parent || !win->parent->wdata)
3267 return FR_ERROR;
3268
3269 struct IndexPrivateData *priv = win->parent->wdata;
3270 struct IndexSharedData *shared = dlg->wdata;
3271
3272 int rc = FR_UNKNOWN;
3273 for (size_t i = 0; IndexFunctions[i].op != OP_NULL; i++)
3274 {
3275 const struct IndexFunction *fn = &IndexFunctions[i];
3276 if (fn->op == op)
3277 {
3278 if (!prereq(shared, priv->menu, fn->flags))
3279 {
3280 rc = FR_ERROR;
3281 break;
3282 }
3283 rc = fn->function(shared, priv, op);
3284 break;
3285 }
3286 }
3287
3288 if (rc == FR_UNKNOWN) // Not our function
3289 return rc;
3290
3291 const char *result = dispatcher_get_retval_name(rc);
3292 mutt_debug(LL_DEBUG1, "Handled %s (%d) -> %s\n", opcodes_get_name(op), op, NONULL(result));
3293
3294 return rc;
3295}
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:229
Select a Mailbox from a list.
#define MUTT_SEL_NO_FLAGS
No flags are set.
Definition: lib.h:57
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:776
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:859
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:460
void mutt_browser_select_dir(const char *f)
Remember the last directory selected.
Definition: dlg_browser.c:830
bool check_acl(struct Mailbox *m, AclFlags acl, const char *msg)
Check the ACLs for a function.
Definition: dlg_index.c:138
const struct Mapping IndexNewsHelp[]
Help Bar for the News Index dialog.
Definition: dlg_index.c:117
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:611
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:732
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:542
int find_first_message(struct MailboxView *mv)
Get index of first new message.
Definition: dlg_index.c:309
void resort_index(struct MailboxView *mv, struct Menu *menu)
Resort the index.
Definition: dlg_index.c:369
int find_next_undeleted(struct MailboxView *mv, int msgno, bool uncollapse)
Find the next undeleted email.
Definition: dlg_index.c:241
void collapse_all(struct MailboxView *mv, struct Menu *menu, int toggle)
Collapse/uncollapse all threads.
Definition: dlg_index.c:165
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:757
int find_previous_undeleted(struct MailboxView *mv, int msgno, bool uncollapse)
Find the previous undeleted email.
Definition: dlg_index.c:275
void query_index(struct Mailbox *m, struct ConfigSubset *sub)
Perform an Alias Query and display the results.
Definition: dlg_query.c:481
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_sort_headers(struct MailboxView *mv, bool init)
Sort emails by their headers.
Definition: sort.c:355
bool OptNeedResort
(pseudo) used to force a re-sort
Definition: globals.c:62
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:631
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:63
static int op_delete(struct AliasMenuData *mdata, int op)
delete the current entry - Implements alias_function_t -
Definition: functions.c:169
static int op_main_tag_pattern(struct AliasMenuData *mdata, int op)
Tag messages matching a pattern - Implements alias_function_t -.
Definition: functions.c:264
static int op_main_limit(struct AliasMenuData *mdata, int op)
show only messages matching a pattern - Implements alias_function_t -
Definition: functions.c:245
static int op_exit(struct AliasMenuData *mdata, int op)
exit this menu - Implements alias_function_t -
Definition: functions.c:201
static int op_main_untag_pattern(struct AliasMenuData *mdata, int op)
Untag messages matching a pattern - Implements alias_function_t -.
Definition: functions.c:280
static int op_query(struct AliasMenuData *mdata, int op)
query external program for addresses - Implements alias_function_t -
Definition: functions.c:300
static int op_search(struct AliasMenuData *mdata, int op)
search for a regular expression - Implements alias_function_t -
Definition: functions.c:353
static int op_create_alias(struct AliasMenuData *mdata, int op)
create an alias from a message sender - Implements alias_function_t -
Definition: functions.c:129
static int op_sort(struct AliasMenuData *mdata, int op)
sort aliases - Implements alias_function_t -
Definition: functions.c:390
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:301
static int op_mailbox_list(struct BrowserPrivateData *priv, int op)
List mailboxes with new mail - Implements browser_function_t -.
Definition: functions.c:832
int index_function_dispatcher(struct MuttWindow *win, int op)
Perform an Index function - Implements function_dispatcher_t -.
Definition: functions.c:3262
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:208
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:237
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:273
static int op_quit(struct HistoryData *hd, int op)
Quit this menu - Implements history_function_t -.
Definition: functions.c:56
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:1289
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:1030
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:1785
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:1200
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:2365
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:1017
static int op_display_message(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Display a message - Implements index_function_t -.
Definition: functions.c:605
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:1630
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:3051
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:954
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:553
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:1663
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:2040
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:1686
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:2061
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:2024
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:1346
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:1848
static int op_autocrypt_acct_menu(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Manage autocrypt accounts - Implements index_function_t -.
Definition: functions.c:2509
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:753
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:708
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:2686
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:1464
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:2767
static int op_view_attachments(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Show MIME attachments - Implements index_function_t -.
Definition: functions.c:2480
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:2962
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:799
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:2533
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:1755
static int op_recall_message(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Recall a postponed message - Implements index_function_t -.
Definition: functions.c:2143
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:2585
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:2407
static int op_save(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Make decrypted copy - Implements index_function_t -.
Definition: functions.c:2214
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:2449
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:673
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:2883
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:588
static int op_post(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Followup to newsgroup - Implements index_function_t -.
Definition: functions.c:2843
static int op_tag(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Tag the current entry - Implements index_function_t -.
Definition: functions.c:2310
static int op_tag_thread(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Tag the current thread - Implements index_function_t -.
Definition: functions.c:2344
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:421
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:2520
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:1719
static int op_undelete(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Undelete the current entry - Implements index_function_t -.
Definition: functions.c:2417
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:1142
static int op_jump(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Jump to an index number - Implements index_function_t -.
Definition: functions.c:904
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:1935
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:1969
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:3009
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:1802
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:1588
static int op_group_reply(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Reply to all recipients - Implements index_function_t -.
Definition: functions.c:874
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:1827
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:1078
static int op_mail(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Compose a new mail message - Implements index_function_t -.
Definition: functions.c:996
static int op_print(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Print the current entry - Implements index_function_t -.
Definition: functions.c:2077
#define mutt_warning(...)
Definition: logging2.h:91
#define mutt_error(...)
Definition: logging2.h:93
#define mutt_message(...)
Definition: logging2.h:92
#define mutt_debug(LEVEL,...)
Definition: logging2.h:90
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:58
void mutt_startup_shutdown_hook(HookFlags type)
Execute any startup/shutdown hooks.
Definition: hook.c:965
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:556
enum MxStatus imap_check_mailbox(struct Mailbox *m, bool force)
Use the NOOP or IDLE command to poll for new mail.
Definition: imap.c:1034
const struct MenuFuncOp OpIndex[]
Functions for the Index Menu.
Definition: functions.c:90
bool index_next_undeleted(struct MuttWindow *win_index)
Select the next undeleted Email (if possible)
Definition: functions.c:390
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:341
const struct MenuOpSeq IndexDefaultBindings[]
Key bindings for the Index Menu.
Definition: functions.c:235
static bool prereq(struct IndexSharedData *shared, struct Menu *menu, CheckFlags checks)
Check the pre-requisites for a function.
Definition: functions.c:3068
static const struct IndexFunction IndexFunctions[]
All the NeoMutt functions that the Index supports.
Definition: functions.c:3117
ResolveMethod
How to advance the cursor.
Definition: functions.c:327
@ RESOLVE_NEXT_SUBTHREAD
Next sibling sub-thread.
Definition: functions.c:331
@ RESOLVE_NEXT_UNDELETED
Next undeleted email.
Definition: functions.c:329
@ RESOLVE_NEXT_EMAIL
Next email, whatever its state.
Definition: functions.c:328
@ RESOLVE_NEXT_THREAD
Next top-level thread.
Definition: functions.c:330
uint8_t CheckFlags
Flags, e.g. CHECK_IN_MAILBOX.
Definition: lib.h:74
#define CHECK_NO_FLAGS
No flags are set.
Definition: lib.h:75
#define CHECK_ATTACH
Is the user in message-attach mode?
Definition: lib.h:80
#define CHECK_VISIBLE
Is the selected message visible in the index?
Definition: lib.h:78
#define CHECK_IN_MAILBOX
Is there a mailbox open?
Definition: lib.h:76
#define CHECK_READONLY
Is the mailbox readonly?
Definition: lib.h:79
#define CHECK_MSGCOUNT
Are there any messages?
Definition: lib.h:77
#define NT_INDEX_EMAIL
Email has changed.
Definition: lib.h:72
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:165
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:44
@ LL_NOTIFY
Log of notifications.
Definition: logging2.h:49
#define FREE(x)
Definition: memory.h:62
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:671
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:426
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:580
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:281
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:1747
void mutt_draw_tree(struct ThreadsContext *tctx)
Draw a tree of threaded emails.
Definition: mutt_thread.c:392
int mutt_messages_in_thread(struct Mailbox *m, struct Email *e, enum MessageInThread mit)
Count the messages in a thread.
Definition: mutt_thread.c:1657
off_t mutt_set_vnum(struct Mailbox *m)
Set the virtual index number of all the messages in a mailbox.
Definition: mutt_thread.c:1404
bool mutt_thread_can_collapse(struct Email *e)
Check whether a thread can be collapsed.
Definition: mutt_thread.c:1817
int mutt_parent_message(struct Email *e, bool find_root)
Find the parent of a message.
Definition: mutt_thread.c:1354
struct HashTable * mutt_make_id_hash(struct Mailbox *m)
Create a Hash Table for message-ids.
Definition: mutt_thread.c:1702
Create/manipulate threading in emails.
#define mutt_thread_next_unread(e)
Definition: mutt_thread.h:110
#define mutt_using_threads()
Definition: mutt_thread.h:113
#define mutt_previous_thread(e)
Definition: mutt_thread.h:119
#define mutt_uncollapse_thread(e)
Definition: mutt_thread.h:107
@ MIT_POSITION
Our position in the thread.
Definition: mutt_thread.h:89
#define mutt_next_subthread(e)
Definition: mutt_thread.h:120
#define mutt_thread_contains_unread(e)
Definition: mutt_thread.h:108
#define mutt_previous_subthread(e)
Definition: mutt_thread.h:121
#define mutt_next_thread(e)
Definition: mutt_thread.h:118
#define mutt_collapse_thread(e)
Definition: mutt_thread.h:106
bool window_is_focused(const struct MuttWindow *win)
Does the given Window have the focus?
Definition: mutt_window.c:619
struct MuttWindow * window_set_focus(struct MuttWindow *win)
Set the Window focus.
Definition: mutt_window.c:649
void buf_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using '~' or '='.
Definition: muttlib.c:518
Some miscellaneous functions.
struct Email * mutt_get_virt_email(struct Mailbox *m, int vnum)
Get a virtual Email.
Definition: mview.c:417
bool mutt_limit_current_thread(struct MailboxView *mv, struct Email *e)
Limit the email view to the current thread.
Definition: mview.c:480
void mview_free(struct MailboxView **ptr)
Free a MailboxView.
Definition: mview.c:49
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:377
bool message_is_tagged(struct Email *e)
Is a message in the index tagged (and within limit)
Definition: mview.c:363
bool mview_has_limit(const struct MailboxView *mv)
Is a limit active?
Definition: mview.c:438
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:1279
int mx_msg_close(struct Mailbox *m, struct Message **ptr)
Close a message.
Definition: mx.c:1185
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:1610
struct Message * mx_msg_open(struct Mailbox *m, struct Email *e)
Return a stream pointer for a message.
Definition: mx.c:1139
bool mx_tags_is_supported(struct Mailbox *m)
Return true if mailbox support tagging.
Definition: mx.c:1316
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:1299
int mx_toggle_write(struct Mailbox *m)
Toggle the mailbox's readonly flag.
Definition: mx.c:1812
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:60
@ MX_STATUS_OK
No changes.
Definition: mxapi.h:62
@ MX_STATUS_REOPENED
Mailbox was reopened.
Definition: mxapi.h:65
@ MX_STATUS_NEW_MAIL
New mail received in Mailbox.
Definition: mxapi.h:63
API for encryption/signing of emails.
#define PGP_TRADITIONAL_CHECKED
Email has a traditional (inline) signature.
Definition: lib.h:98
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:96
#define WithCrypto
Definition: lib.h:122
@ NT_GLOBAL_SHUTDOWN
NeoMutt is about to close.
Definition: neomutt.h:68
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:2214
int nntp_check_children(struct Mailbox *m, const char *msgid)
Fetch children of article with the Message-ID.
Definition: nntp.c:2285
void nntp_mailbox(struct Mailbox *m, char *buf, size_t buflen)
Get first newsgroup with new messages.
Definition: newsrc.c:1308
struct NntpMboxData * mutt_newsgroup_catchup(struct Mailbox *m, struct NntpAccountData *adata, char *group)
Catchup newsgroup.
Definition: newsrc.c:1226
struct NntpAccountData * CurrentNewsSrv
Current NNTP news server.
Definition: nntp.c:76
struct NntpAccountData * nntp_select_server(struct Mailbox *m, const char *server, bool leave_lock)
Open a connection to an NNTP server.
Definition: newsrc.c:945
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:1708
int nm_read_entire_thread(struct Mailbox *m, struct Email *e)
Get the entire thread of an email.
Definition: notmuch.c:1536
void nm_query_window_backward(void)
Function to move the current search window backward in time.
Definition: notmuch.c:1697
bool nm_query_window_available(void)
Are windowed queries enabled for use?
Definition: notmuch.c:1660
bool nm_message_is_still_queried(struct Mailbox *m, struct Email *e)
Is a message still visible in the query?
Definition: notmuch.c:1720
void nm_query_window_forward(void)
Function to move the current search window forward in time.
Definition: notmuch.c:1677
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:111
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:447
int external_pager(struct MailboxView *mv, struct Email *e, const char *command)
Display a message in an external program.
Definition: message.c:300
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:475
int mutt_pattern_func(struct MailboxView *mv, int op, char *prompt)
Perform some Pattern matching.
Definition: pattern.c:308
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:82
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:96
POP network mailbox.
void pop_fetch_mail(void)
Fetch messages and save them in $spool_file.
Definition: pop.c:512
Progress Bar.
@ MUTT_PROGRESS_WRITE
Progress tracks elements, according to $write_inc
Definition: lib.h:84
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:54
@ EVM_EDIT
Edit the message.
Definition: protos.h:55
@ 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:378
#define STAILQ_FIRST(head)
Definition: queue.h:388
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:390
#define STAILQ_EMPTY(head)
Definition: queue.h:382
#define STAILQ_NEXT(elm, field)
Definition: queue.h:439
#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:1549
bool mutt_send_list_unsubscribe(struct Mailbox *m, struct Email *e)
Send a mailing-list unsubscription email.
Definition: send.c:2981
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:2034
bool mutt_send_list_subscribe(struct Mailbox *m, struct Email *e)
Send a mailing-list subscription email.
Definition: send.c:2952
#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.
#define ASSERT(COND)
Definition: signal2.h:60
Key value store.
#define NONULL(x)
Definition: string2.h:36
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:112
Mapping between an operation and a key sequence.
Definition: lib.h:121
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:142
void * wdata
Private data.
Definition: mutt_window.h:145
struct MuttWindow * parent
Parent Window.
Definition: mutt_window.h:135
Container for Accounts, Notifications.
Definition: neomutt.h:43
struct Notify * notify
Notifications handler.
Definition: neomutt.h:44
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:47
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:47