NeoMutt  2021-02-05-666-ge300cd
Teaching an old dog new tricks
DOXYGEN
functions.c
Go to the documentation of this file.
1 
29 #include "config.h"
30 #include <ctype.h>
31 #include <limits.h>
32 #include <stdbool.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include "mutt/lib.h"
36 #include "config/lib.h"
37 #include "email/lib.h"
38 #include "core/lib.h"
39 #include "alias/lib.h"
40 #include "gui/lib.h"
41 #include "mutt.h"
42 #include "functions.h"
43 #include "lib.h"
44 #include "menu/lib.h"
45 #include "ncrypt/lib.h"
46 #include "pager/lib.h"
47 #include "pattern/lib.h"
48 #include "progress/lib.h"
49 #include "question/lib.h"
50 #include "send/lib.h"
51 #include "browser.h"
52 #include "commands.h"
53 #include "context.h"
54 #include "hook.h"
55 #include "keymap.h"
56 #include "mutt_header.h"
57 #include "mutt_mailbox.h"
58 #include "mutt_thread.h"
59 #include "muttlib.h"
60 #include "mx.h"
61 #include "opcodes.h"
62 #include "options.h"
63 #include "private_data.h"
64 #include "protos.h"
65 #include "recvattach.h"
66 #include "score.h"
67 #include "shared_data.h"
68 #include "sort.h"
69 #ifdef USE_AUTOCRYPT
70 #include "autocrypt/lib.h"
71 #endif
72 #ifdef USE_NOTMUCH
73 #include "notmuch/lib.h"
74 #endif
75 #ifdef USE_IMAP
76 #include "imap/lib.h"
77 #endif
78 #ifdef USE_SIDEBAR
79 #include "sidebar/lib.h"
80 #endif
81 #ifdef USE_NNTP
82 #include "nntp/lib.h"
83 #include "nntp/mdata.h" // IWYU pragma: keep
84 #endif
85 #ifdef USE_POP
86 #include "pop/lib.h"
87 #endif
88 
89 static const char *Not_available_in_this_menu =
90  N_("Not available in this menu");
91 
92 // -----------------------------------------------------------------------------
93 
97 static int op_bounce_message(struct IndexSharedData *shared,
98  struct IndexPrivateData *priv, int op)
99 {
100  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
101  el_add_tagged(&el, shared->ctx, shared->email, priv->tag);
102  ci_bounce_message(shared->mailbox, &el);
103  emaillist_clear(&el);
104 
105  return IR_SUCCESS;
106 }
107 
111 static int op_check_stats(struct IndexSharedData *shared,
112  struct IndexPrivateData *priv, int op)
113 {
114  mutt_check_stats(shared->mailbox);
115  return IR_SUCCESS;
116 }
117 
121 static int op_check_traditional(struct IndexSharedData *shared,
122  struct IndexPrivateData *priv, int op)
123 {
124  if (!(WithCrypto & APPLICATION_PGP))
125  return IR_NOT_IMPL;
126  if (!shared->email)
127  return IR_NO_ACTION;
128 
129  if (priv->tag || !(shared->email->security & PGP_TRADITIONAL_CHECKED))
130  {
131  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
132  el_add_tagged(&el, shared->ctx, shared->email, priv->tag);
133  if (mutt_check_traditional_pgp(shared->mailbox, &el))
135  emaillist_clear(&el);
136  }
137 
138  if (priv->in_pager)
139  return IR_CONTINUE;
140 
141  return IR_SUCCESS;
142 }
143 
147 static int op_compose_to_sender(struct IndexSharedData *shared,
148  struct IndexPrivateData *priv, int op)
149 {
150  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
151  el_add_tagged(&el, shared->ctx, shared->email, priv->tag);
152  int rc = mutt_send_message(SEND_TO_SENDER, NULL, NULL, shared->mailbox, &el,
153  shared->sub);
154  emaillist_clear(&el);
156 
157  return (rc == -1) ? IR_ERROR : IR_SUCCESS;
158 }
159 
163 static int op_create_alias(struct IndexSharedData *shared,
164  struct IndexPrivateData *priv, int op)
165 {
166  struct AddressList *al = NULL;
167  if (shared->email && shared->email->env)
168  al = mutt_get_address(shared->email->env, NULL);
169  alias_create(al, shared->sub);
171 
172  return IR_SUCCESS;
173 }
174 
178 static int op_delete(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
179 {
180  /* L10N: CHECK_ACL */
181  if (!check_acl(shared->mailbox, MUTT_ACL_DELETE, _("Can't delete message")))
182  return IR_ERROR;
183 
184  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
185  el_add_tagged(&el, shared->ctx, shared->email, priv->tag);
186 
187  mutt_emails_set_flag(shared->mailbox, &el, MUTT_DELETE, true);
188  mutt_emails_set_flag(shared->mailbox, &el, MUTT_PURGE, (op == OP_PURGE_MESSAGE));
189  const bool c_delete_untag = cs_subset_bool(shared->sub, "delete_untag");
190  if (c_delete_untag)
191  mutt_emails_set_flag(shared->mailbox, &el, MUTT_TAG, false);
192  emaillist_clear(&el);
193 
194  if (priv->tag)
195  {
197  }
198  else
199  {
200  const bool c_resolve = cs_subset_bool(shared->sub, "resolve");
201  if (c_resolve)
202  {
203  int index = menu_get_index(priv->menu);
204  index = ci_next_undeleted(shared->mailbox, index);
205  if (index != -1)
206  menu_set_index(priv->menu, index);
207 
208  if (index == -1)
209  {
211  }
212  else if (priv->in_pager)
213  {
214  return IR_CONTINUE;
215  }
216  }
217  else
219  }
221 
222  return IR_SUCCESS;
223 }
224 
228 static int op_delete_thread(struct IndexSharedData *shared,
229  struct IndexPrivateData *priv, int op)
230 {
231  /* L10N: CHECK_ACL */
232  /* L10N: Due to the implementation details we do not know whether we
233  delete zero, 1, 12, ... messages. So in English we use
234  "messages". Your language might have other means to express this. */
235  if (!check_acl(shared->mailbox, MUTT_ACL_DELETE, _("Can't delete messages")))
236  return IR_ERROR;
237  if (!shared->email)
238  return IR_NO_ACTION;
239 
240  int subthread = (op == OP_DELETE_SUBTHREAD);
241  int rc = mutt_thread_set_flag(shared->mailbox, shared->email, MUTT_DELETE, true, subthread);
242  if (rc == -1)
243  return IR_ERROR;
244  if (op == OP_PURGE_THREAD)
245  {
246  rc = mutt_thread_set_flag(shared->mailbox, shared->email, MUTT_PURGE, true, subthread);
247  if (rc == -1)
248  return IR_ERROR;
249  }
250 
251  const bool c_delete_untag = cs_subset_bool(shared->sub, "delete_untag");
252  if (c_delete_untag)
253  mutt_thread_set_flag(shared->mailbox, shared->email, MUTT_TAG, false, subthread);
254  const bool c_resolve = cs_subset_bool(shared->sub, "resolve");
255  if (c_resolve)
256  {
257  int index = menu_get_index(priv->menu);
258  index = ci_next_undeleted(shared->mailbox, index);
259  if (index != -1)
260  menu_set_index(priv->menu, index);
261  }
263  return IR_SUCCESS;
264 }
265 
269 static int op_display_address(struct IndexSharedData *shared,
270  struct IndexPrivateData *priv, int op)
271 {
272  if (!shared->email)
273  return IR_NO_ACTION;
274  mutt_display_address(shared->email->env);
275 
276  return IR_SUCCESS;
277 }
278 
282 static int op_display_message(struct IndexSharedData *shared,
283  struct IndexPrivateData *priv, int op)
284 {
285  if (!shared->email)
286  return IR_NO_ACTION;
287  /* toggle the weeding of headers so that a user can press the key
288  * again while reading the message. */
289  if (op == OP_DISPLAY_HEADERS)
290  bool_str_toggle(shared->sub, "weed", NULL);
291 
292  OptNeedResort = false;
293 
294  if (mutt_using_threads() && shared->email->collapsed)
295  {
296  mutt_uncollapse_thread(shared->email);
297  mutt_set_vnum(shared->mailbox);
298  const bool c_uncollapse_jump =
299  cs_subset_bool(shared->sub, "uncollapse_jump");
300  if (c_uncollapse_jump)
302  }
303 
304  const bool c_pgp_auto_decode = cs_subset_bool(shared->sub, "pgp_auto_decode");
305  if (c_pgp_auto_decode && (priv->tag || !(shared->email->security & PGP_TRADITIONAL_CHECKED)))
306  {
307  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
308  el_add_tagged(&el, shared->ctx, shared->email, priv->tag);
309  if (mutt_check_traditional_pgp(shared->mailbox, &el))
311  emaillist_clear(&el);
312  }
313  const int index = menu_get_index(priv->menu);
315 
316  op = mutt_display_message(priv->win_index, priv->win_ibar, priv->win_pager,
317  priv->win_pbar, shared->mailbox, shared->email);
319  if (op < 0)
320  {
321  OptNeedResort = false;
322  return IR_ERROR;
323  }
324 
325  /* This is used to redirect a single operation back here afterwards. If
326  * mutt_display_message() returns 0, then this flag and pager state will
327  * be cleaned up after this switch statement. */
328  priv->in_pager = true;
329  if (shared->mailbox)
330  {
331  update_index(priv->menu, shared->ctx, MX_STATUS_NEW_MAIL,
332  shared->mailbox->msg_count, shared);
333  }
334 
335  return op;
336 }
337 
341 static int op_edit_label(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
342 {
343  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
344  el_add_tagged(&el, shared->ctx, shared->email, priv->tag);
345  int num_changed = mutt_label_message(shared->mailbox, &el);
346  emaillist_clear(&el);
347 
348  if (num_changed > 0)
349  {
350  shared->mailbox->changed = true;
352  /* L10N: This is displayed when the x-label on one or more
353  messages is edited. */
354  mutt_message(ngettext("%d label changed", "%d labels changed", num_changed), num_changed);
355  return IR_SUCCESS;
356  }
357 
358  /* L10N: This is displayed when editing an x-label, but no messages
359  were updated. Possibly due to canceling at the prompt or if the new
360  label is the same as the old label. */
361  mutt_message(_("No labels changed"));
362  return IR_NO_ACTION;
363 }
364 
368 static int op_edit_raw_message(struct IndexSharedData *shared,
369  struct IndexPrivateData *priv, int op)
370 {
371  /* TODO split this into 3 cases? */
372  bool edit;
373  if (op == OP_EDIT_RAW_MESSAGE)
374  {
375  /* L10N: CHECK_ACL */
376  if (!check_acl(shared->mailbox, MUTT_ACL_INSERT, _("Can't edit message")))
377  return IR_ERROR;
378  edit = true;
379  }
380  else if (op == OP_EDIT_OR_VIEW_RAW_MESSAGE)
381  edit = !shared->mailbox->readonly && (shared->mailbox->rights & MUTT_ACL_INSERT);
382  else
383  edit = false;
384 
385  if (!shared->email)
386  return IR_NO_ACTION;
387  const bool c_pgp_auto_decode = cs_subset_bool(shared->sub, "pgp_auto_decode");
388  if (c_pgp_auto_decode && (priv->tag || !(shared->email->security & PGP_TRADITIONAL_CHECKED)))
389  {
390  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
391  el_add_tagged(&el, shared->ctx, shared->email, priv->tag);
392  if (mutt_check_traditional_pgp(shared->mailbox, &el))
394  emaillist_clear(&el);
395  }
396  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
397  el_add_tagged(&el, shared->ctx, shared->email, priv->tag);
398  mutt_ev_message(shared->mailbox, &el, edit ? EVM_EDIT : EVM_VIEW);
399  emaillist_clear(&el);
401 
402  return IR_SUCCESS;
403 }
404 
408 static int op_edit_type(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
409 {
410  if (!shared->email)
411  return IR_NO_ACTION;
412  mutt_edit_content_type(shared->email, shared->email->body, NULL);
413  /* if we were in the pager, redisplay the message */
414  if (priv->in_pager)
415  return IR_CONTINUE;
416 
418  return IR_SUCCESS;
419 }
420 
424 static int op_end_cond(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
425 {
426  return IR_SUCCESS;
427 }
428 
432 static int op_enter_command(struct IndexSharedData *shared,
433  struct IndexPrivateData *priv, int op)
434 {
436  mutt_check_rescore(shared->mailbox);
438 
439  return IR_SUCCESS;
440 }
441 
445 static int op_exit(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
446 {
447  if ((!priv->in_pager) && priv->attach_msg)
448  return IR_DONE;
449 
450  const enum QuadOption c_quit = cs_subset_quad(shared->sub, "quit");
451  if ((!priv->in_pager) &&
452  (query_quadoption(c_quit, _("Exit NeoMutt without saving?")) == MUTT_YES))
453  {
454  if (shared->ctx)
455  {
456  mx_fastclose_mailbox(shared->mailbox);
457  ctx_free(&shared->ctx);
458  }
459  return IR_DONE;
460  }
461 
462  return IR_NO_ACTION;
463 }
464 
468 static int op_extract_keys(struct IndexSharedData *shared,
469  struct IndexPrivateData *priv, int op)
470 {
471  if (!WithCrypto)
472  return IR_NOT_IMPL;
473  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
474  el_add_tagged(&el, shared->ctx, shared->email, priv->tag);
476  emaillist_clear(&el);
478 
479  return IR_SUCCESS;
480 }
481 
485 static int op_flag_message(struct IndexSharedData *shared,
486  struct IndexPrivateData *priv, int op)
487 {
488  /* L10N: CHECK_ACL */
489  if (!check_acl(shared->mailbox, MUTT_ACL_WRITE, _("Can't flag message")))
490  return IR_ERROR;
491 
492  struct Mailbox *m = shared->mailbox;
493  if (priv->tag)
494  {
495  for (size_t i = 0; i < m->msg_count; i++)
496  {
497  struct Email *e = m->emails[i];
498  if (!e)
499  break;
500  if (message_is_tagged(e))
501  mutt_set_flag(m, e, MUTT_FLAG, !e->flagged);
502  }
503 
505  }
506  else
507  {
508  if (!shared->email)
509  return IR_NO_ACTION;
510  mutt_set_flag(m, shared->email, MUTT_FLAG, !shared->email->flagged);
511  const bool c_resolve = cs_subset_bool(shared->sub, "resolve");
512  if (c_resolve)
513  {
514  int index = menu_get_index(priv->menu);
515  index = ci_next_undeleted(shared->mailbox, index);
516  if (index == -1)
517  {
519  }
520  else
521  {
522  menu_set_index(priv->menu, index);
523  }
524  }
525  else
527  }
529 
530  return IR_SUCCESS;
531 }
532 
536 static int op_forget_passphrase(struct IndexSharedData *shared,
537  struct IndexPrivateData *priv, int op)
538 {
540  return IR_SUCCESS;
541 }
542 
546 static int op_forward_message(struct IndexSharedData *shared,
547  struct IndexPrivateData *priv, int op)
548 {
549  if (!shared->email)
550  return IR_NO_ACTION;
551  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
552  el_add_tagged(&el, shared->ctx, shared->email, priv->tag);
553  const bool c_pgp_auto_decode = cs_subset_bool(shared->sub, "pgp_auto_decode");
554  if (c_pgp_auto_decode && (priv->tag || !(shared->email->security & PGP_TRADITIONAL_CHECKED)))
555  {
556  if (mutt_check_traditional_pgp(shared->mailbox, &el))
558  }
559  int rc =
560  mutt_send_message(SEND_FORWARD, NULL, NULL, shared->mailbox, &el, shared->sub);
561  emaillist_clear(&el);
563 
564  return (rc == -1) ? IR_ERROR : IR_SUCCESS;
565 }
566 
570 static int op_group_reply(struct IndexSharedData *shared,
571  struct IndexPrivateData *priv, int op)
572 {
573  SendFlags replyflags = SEND_REPLY;
574  if (op == OP_GROUP_REPLY)
575  replyflags |= SEND_GROUP_REPLY;
576  else
577  replyflags |= SEND_GROUP_CHAT_REPLY;
578  if (!shared->email)
579  return IR_NO_ACTION;
580  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
581  el_add_tagged(&el, shared->ctx, shared->email, priv->tag);
582  const bool c_pgp_auto_decode = cs_subset_bool(shared->sub, "pgp_auto_decode");
583  if (c_pgp_auto_decode && (priv->tag || !(shared->email->security & PGP_TRADITIONAL_CHECKED)))
584  {
585  if (mutt_check_traditional_pgp(shared->mailbox, &el))
587  }
588  int rc =
589  mutt_send_message(replyflags, NULL, NULL, shared->mailbox, &el, shared->sub);
590  emaillist_clear(&el);
592 
593  return (rc == -1) ? IR_ERROR : IR_SUCCESS;
594 }
595 
599 static int op_help(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
600 {
603  return IR_SUCCESS;
604 }
605 
609 static int op_jump(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
610 {
611  char buf[PATH_MAX] = { 0 };
612  int msg_num = 0;
613  if (isdigit(LastKey))
615  if ((mutt_get_field(_("Jump to message: "), buf, sizeof(buf),
616  MUTT_COMP_NO_FLAGS, false, NULL, NULL) != 0) ||
617  (buf[0] == '\0'))
618  {
619  mutt_error(_("Nothing to do"));
620  }
621  else if (mutt_str_atoi(buf, &msg_num) < 0)
622  mutt_error(_("Argument must be a message number"));
623  else if ((msg_num < 1) || (msg_num > shared->mailbox->msg_count))
624  mutt_error(_("Invalid message number"));
625  else if (!shared->mailbox->emails[msg_num - 1]->visible)
626  mutt_error(_("That message is not visible"));
627  else
628  {
629  struct Email *e = shared->mailbox->emails[msg_num - 1];
630 
631  if (mutt_messages_in_thread(shared->mailbox, e, MIT_POSITION) > 1)
632  {
634  mutt_set_vnum(shared->mailbox);
635  }
636  menu_set_index(priv->menu, e->vnum);
637  }
638 
639  if (priv->in_pager)
640  return IR_CONTINUE;
641 
643  return IR_SUCCESS;
644 }
645 
649 static int op_list_reply(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
650 {
651  if (!shared->email)
652  return IR_NO_ACTION;
653  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
654  el_add_tagged(&el, shared->ctx, shared->email, priv->tag);
655  const bool c_pgp_auto_decode = cs_subset_bool(shared->sub, "pgp_auto_decode");
656  if (c_pgp_auto_decode && (priv->tag || !(shared->email->security & PGP_TRADITIONAL_CHECKED)))
657  {
658  if (mutt_check_traditional_pgp(shared->mailbox, &el))
660  }
661  int rc = mutt_send_message(SEND_REPLY | SEND_LIST_REPLY, NULL, NULL,
662  shared->mailbox, &el, shared->sub);
663  emaillist_clear(&el);
665 
666  return (rc == -1) ? IR_ERROR : IR_SUCCESS;
667 }
668 
672 static int op_mail(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
673 {
674  int rc = mutt_send_message(SEND_NO_FLAGS, NULL, NULL, shared->mailbox, NULL,
675  shared->sub);
677  return (rc == -1) ? IR_ERROR : IR_SUCCESS;
678 }
679 
683 static int op_mailbox_list(struct IndexSharedData *shared,
684  struct IndexPrivateData *priv, int op)
685 {
687  return IR_SUCCESS;
688 }
689 
693 static int op_mail_key(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
694 {
695  if (!(WithCrypto & APPLICATION_PGP))
696  return IR_NOT_IMPL;
697  int rc = mutt_send_message(SEND_KEY, NULL, NULL, NULL, NULL, shared->sub);
699 
700  return (rc == -1) ? IR_ERROR : IR_SUCCESS;
701 }
702 
706 static int op_main_break_thread(struct IndexSharedData *shared,
707  struct IndexPrivateData *priv, int op)
708 {
709  /* L10N: CHECK_ACL */
710  if (!check_acl(shared->mailbox, MUTT_ACL_WRITE, _("Can't break thread")))
711  return IR_ERROR;
712  if (!shared->email)
713  return IR_NO_ACTION;
714 
715  if (!mutt_using_threads())
716  mutt_error(_("Threading is not enabled"));
717  else if (!STAILQ_EMPTY(&shared->email->env->in_reply_to) ||
718  !STAILQ_EMPTY(&shared->email->env->references))
719  {
720  {
721  mutt_break_thread(shared->email);
722  mutt_sort_headers(shared->mailbox, shared->ctx->threads, true,
723  &shared->ctx->vsize);
724  menu_set_index(priv->menu, shared->email->vnum);
725  }
726 
727  shared->mailbox->changed = true;
728  mutt_message(_("Thread broken"));
729 
730  if (priv->in_pager)
731  return IR_CONTINUE;
732 
734  }
735  else
736  {
737  mutt_error(_("Thread can't be broken, message is not part of a thread"));
738  }
739 
740  return IR_SUCCESS;
741 }
742 
746 static int op_main_change_folder(struct IndexSharedData *shared,
747  struct IndexPrivateData *priv, int op)
748 {
749  bool pager_return = true; /* return to display message in pager */
750  struct Buffer *folderbuf = mutt_buffer_pool_get();
751  mutt_buffer_alloc(folderbuf, PATH_MAX);
752 
753  char *cp = NULL;
754  bool read_only;
755  const bool c_read_only = cs_subset_bool(shared->sub, "read_only");
756  if (priv->attach_msg || c_read_only || (op == OP_MAIN_CHANGE_FOLDER_READONLY))
757  {
758  cp = _("Open mailbox in read-only mode");
759  read_only = true;
760  }
761  else
762  {
763  cp = _("Open mailbox");
764  read_only = false;
765  }
766 
767  const bool c_change_folder_next =
768  cs_subset_bool(shared->sub, "change_folder_next");
769  if (c_change_folder_next && shared->mailbox &&
771  {
772  mutt_buffer_strcpy(folderbuf, mailbox_path(shared->mailbox));
773  mutt_buffer_pretty_mailbox(folderbuf);
774  }
775  /* By default, fill buf with the next mailbox that contains unread mail */
776  mutt_mailbox_next(shared->ctx ? shared->mailbox : NULL, folderbuf);
777 
778  if (mutt_buffer_enter_fname(cp, folderbuf, true, shared->mailbox, false, NULL,
779  NULL, MUTT_SEL_NO_FLAGS) == -1)
780  {
781  goto changefoldercleanup;
782  }
783 
784  /* Selected directory is okay, let's save it. */
786 
787  if (mutt_buffer_is_empty(folderbuf))
788  {
790  goto changefoldercleanup;
791  }
792 
793  struct Mailbox *m = mx_mbox_find2(mutt_buffer_string(folderbuf));
794  if (m)
795  {
796  change_folder_mailbox(priv->menu, m, &priv->oldcount, shared, read_only);
797  pager_return = false;
798  }
799  else
800  {
801  change_folder_string(priv->menu, folderbuf->data, folderbuf->dsize,
802  &priv->oldcount, shared, &pager_return, read_only);
803  }
804 
805 changefoldercleanup:
806  mutt_buffer_pool_release(&folderbuf);
807  if (priv->in_pager && pager_return)
808  return IR_CONTINUE;
809 
811 
812  return IR_SUCCESS;
813 }
814 
818 static int op_main_collapse_all(struct IndexSharedData *shared,
819  struct IndexPrivateData *priv, int op)
820 {
821  if (!mutt_using_threads())
822  {
823  mutt_error(_("Threading is not enabled"));
824  return IR_ERROR;
825  }
826  collapse_all(shared->ctx, priv->menu, 1);
827 
828  return IR_SUCCESS;
829 }
830 
834 static int op_main_collapse_thread(struct IndexSharedData *shared,
835  struct IndexPrivateData *priv, int op)
836 {
837  if (!mutt_using_threads())
838  {
839  mutt_error(_("Threading is not enabled"));
840  return IR_ERROR;
841  }
842 
843  if (!shared->email)
844  return IR_NO_ACTION;
845 
846  if (shared->email->collapsed)
847  {
848  int index = mutt_uncollapse_thread(shared->email);
849  mutt_set_vnum(shared->mailbox);
850  const bool c_uncollapse_jump =
851  cs_subset_bool(shared->sub, "uncollapse_jump");
852  if (c_uncollapse_jump)
853  index = mutt_thread_next_unread(shared->email);
854  menu_set_index(priv->menu, index);
855  }
856  else if (mutt_thread_can_collapse(shared->email))
857  {
859  mutt_set_vnum(shared->mailbox);
860  }
861  else
862  {
863  mutt_error(_("Thread contains unread or flagged messages"));
864  return IR_ERROR;
865  }
866 
868 
869  return IR_SUCCESS;
870 }
871 
875 static int op_main_delete_pattern(struct IndexSharedData *shared,
876  struct IndexPrivateData *priv, int op)
877 {
878  /* L10N: CHECK_ACL */
879  /* L10N: Due to the implementation details we do not know whether we
880  delete zero, 1, 12, ... messages. So in English we use
881  "messages". Your language might have other means to express this. */
882  if (!check_acl(shared->mailbox, MUTT_ACL_DELETE, _("Can't delete messages")))
883  return IR_ERROR;
884 
885  mutt_pattern_func(shared->ctx, MUTT_DELETE, _("Delete messages matching: "));
887 
888  return IR_SUCCESS;
889 }
890 
894 static int op_main_limit(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
895 {
896  const bool lmt = ctx_has_limit(shared->ctx);
897  int old_index = shared->email ? shared->email->index : -1;
898  if (op == OP_TOGGLE_READ)
899  {
900  char buf2[1024];
901 
902  if (!lmt || !mutt_strn_equal(shared->ctx->pattern, "!~R!~D~s", 8))
903  {
904  snprintf(buf2, sizeof(buf2), "!~R!~D~s%s", lmt ? shared->ctx->pattern : ".*");
905  }
906  else
907  {
908  mutt_str_copy(buf2, shared->ctx->pattern + 8, sizeof(buf2));
909  if ((*buf2 == '\0') || mutt_strn_equal(buf2, ".*", 2))
910  snprintf(buf2, sizeof(buf2), "~A");
911  }
912  mutt_str_replace(&shared->ctx->pattern, buf2);
913  mutt_pattern_func(shared->ctx, MUTT_LIMIT, NULL);
914  }
915 
916  if (((op == OP_LIMIT_CURRENT_THREAD) &&
917  mutt_limit_current_thread(shared->ctx, shared->email)) ||
918  (op == OP_TOGGLE_READ) ||
919  ((op == OP_MAIN_LIMIT) &&
920  (mutt_pattern_func(shared->ctx, MUTT_LIMIT, _("Limit to messages matching: ")) == 0)))
921  {
922  int index = 0;
923  if (old_index >= 0)
924  {
925  /* try to find what used to be the current message */
926  for (size_t i = 0; i < shared->mailbox->vcount; i++)
927  {
928  struct Email *e = mutt_get_virt_email(shared->mailbox, i);
929  if (!e)
930  continue;
931  if (e->index == old_index)
932  {
933  index = i;
934  break;
935  }
936  }
937  }
938  menu_set_index(priv->menu, index);
939 
940  if ((shared->mailbox->msg_count != 0) && mutt_using_threads())
941  {
942  const bool c_collapse_all = cs_subset_bool(shared->sub, "collapse_all");
943  if (c_collapse_all)
944  collapse_all(shared->ctx, priv->menu, 0);
945  mutt_draw_tree(shared->ctx->threads);
946  }
948  }
949  if (lmt)
950  mutt_message(_("To view all messages, limit to \"all\""));
951 
952  return IR_SUCCESS;
953 }
954 
958 static int op_main_link_threads(struct IndexSharedData *shared,
959  struct IndexPrivateData *priv, int op)
960 {
961  /* L10N: CHECK_ACL */
962  if (!check_acl(shared->mailbox, MUTT_ACL_WRITE, _("Can't link threads")))
963  return IR_ERROR;
964  if (!shared->email)
965  return IR_NO_ACTION;
966 
967  enum IndexRetval rc = IR_ERROR;
968 
969  if (!mutt_using_threads())
970  mutt_error(_("Threading is not enabled"));
971  else if (!shared->email->env->message_id)
972  mutt_error(_("No Message-ID: header available to link thread"));
973  else
974  {
975  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
976  el_add_tagged(&el, shared->ctx, NULL, true);
977 
978  if (mutt_link_threads(shared->email, &el, shared->mailbox))
979  {
980  mutt_sort_headers(shared->mailbox, shared->ctx->threads, true,
981  &shared->ctx->vsize);
982  menu_set_index(priv->menu, shared->email->vnum);
983 
984  shared->mailbox->changed = true;
985  mutt_message(_("Threads linked"));
986  rc = IR_SUCCESS;
987  }
988  else
989  {
990  mutt_error(_("No thread linked"));
991  rc = IR_NO_ACTION;
992  }
993 
994  emaillist_clear(&el);
995  }
996 
997  if (priv->in_pager)
998  return IR_CONTINUE;
999 
1001  return rc;
1002 }
1003 
1007 static int op_main_modify_tags(struct IndexSharedData *shared,
1008  struct IndexPrivateData *priv, int op)
1009 {
1010  if (!shared->mailbox)
1011  return IR_ERROR;
1012  struct Mailbox *m = shared->mailbox;
1013  if (!mx_tags_is_supported(m))
1014  {
1015  mutt_message(_("Folder doesn't support tagging, aborting"));
1016  return IR_ERROR;
1017  }
1018  if (!shared->email)
1019  return IR_NO_ACTION;
1020  char *tags = NULL;
1021  if (!priv->tag)
1022  tags = driver_tags_get_with_hidden(&shared->email->tags);
1023  char buf[PATH_MAX] = { 0 };
1024  int rc = mx_tags_edit(m, tags, buf, sizeof(buf));
1025  FREE(&tags);
1026  if (rc < 0)
1027  return IR_ERROR;
1028  else if (rc == 0)
1029  {
1030  mutt_message(_("No tag specified, aborting"));
1031  return IR_ERROR;
1032  }
1033 
1034  if (priv->tag)
1035  {
1036  struct Progress *progress = NULL;
1037 
1038  if (m->verbose)
1039  {
1040  progress = progress_new(_("Update tags..."), MUTT_PROGRESS_WRITE, m->msg_tagged);
1041  }
1042 
1043 #ifdef USE_NOTMUCH
1044  if (m->type == MUTT_NOTMUCH)
1045  nm_db_longrun_init(m, true);
1046 #endif
1047  for (int px = 0, i = 0; i < m->msg_count; i++)
1048  {
1049  struct Email *e = m->emails[i];
1050  if (!e)
1051  break;
1052  if (!message_is_tagged(e))
1053  continue;
1054 
1055  if (m->verbose)
1056  progress_update(progress, ++px, -1);
1057  mx_tags_commit(m, e, buf);
1058  if (op == OP_MAIN_MODIFY_TAGS_THEN_HIDE)
1059  {
1060  bool still_queried = false;
1061 #ifdef USE_NOTMUCH
1062  if (m->type == MUTT_NOTMUCH)
1063  still_queried = nm_message_is_still_queried(m, e);
1064 #endif
1065  e->quasi_deleted = !still_queried;
1066  m->changed = true;
1067  }
1068  }
1069  progress_free(&progress);
1070 #ifdef USE_NOTMUCH
1071  if (m->type == MUTT_NOTMUCH)
1072  nm_db_longrun_done(m);
1073 #endif
1075  }
1076  else
1077  {
1078  if (mx_tags_commit(m, shared->email, buf))
1079  {
1080  mutt_message(_("Failed to modify tags, aborting"));
1081  return IR_ERROR;
1082  }
1083  if (op == OP_MAIN_MODIFY_TAGS_THEN_HIDE)
1084  {
1085  bool still_queried = false;
1086 #ifdef USE_NOTMUCH
1087  if (m->type == MUTT_NOTMUCH)
1088  still_queried = nm_message_is_still_queried(m, shared->email);
1089 #endif
1090  shared->email->quasi_deleted = !still_queried;
1091  m->changed = true;
1092  }
1093  if (priv->in_pager)
1094  return IR_CONTINUE;
1095 
1096  const bool c_resolve = cs_subset_bool(shared->sub, "resolve");
1097  if (c_resolve)
1098  {
1099  int index = menu_get_index(priv->menu);
1100  index = ci_next_undeleted(shared->mailbox, index);
1101  if (index == -1)
1102  {
1104  }
1105  else
1106  {
1107  menu_set_index(priv->menu, index);
1108  }
1109  }
1110  else
1112  }
1113 
1115  return IR_SUCCESS;
1116 }
1117 
1121 static int op_main_next_new(struct IndexSharedData *shared,
1122  struct IndexPrivateData *priv, int op)
1123 {
1124  int first_unread = -1;
1125  int first_new = -1;
1126 
1127  const int saved_current = menu_get_index(priv->menu);
1128  int mcur = saved_current;
1129  int index = -1;
1130  const bool threaded = mutt_using_threads();
1131  for (size_t i = 0; i != shared->mailbox->vcount; i++)
1132  {
1133  if ((op == OP_MAIN_NEXT_NEW) || (op == OP_MAIN_NEXT_UNREAD) ||
1134  (op == OP_MAIN_NEXT_NEW_THEN_UNREAD))
1135  {
1136  mcur++;
1137  if (mcur > (shared->mailbox->vcount - 1))
1138  {
1139  mcur = 0;
1140  }
1141  }
1142  else
1143  {
1144  mcur--;
1145  if (mcur < 0)
1146  {
1147  mcur = shared->mailbox->vcount - 1;
1148  }
1149  }
1150 
1151  struct Email *e = mutt_get_virt_email(shared->mailbox, mcur);
1152  if (!e)
1153  break;
1154  if (e->collapsed && threaded)
1155  {
1156  int unread = mutt_thread_contains_unread(e);
1157  if ((unread != 0) && (first_unread == -1))
1158  first_unread = mcur;
1159  if ((unread == 1) && (first_new == -1))
1160  first_new = mcur;
1161  }
1162  else if (!e->deleted && !e->read)
1163  {
1164  if (first_unread == -1)
1165  first_unread = mcur;
1166  if (!e->old && (first_new == -1))
1167  first_new = mcur;
1168  }
1169 
1170  if (((op == OP_MAIN_NEXT_UNREAD) || (op == OP_MAIN_PREV_UNREAD)) && (first_unread != -1))
1171  {
1172  break;
1173  }
1174  if (((op == OP_MAIN_NEXT_NEW) || (op == OP_MAIN_PREV_NEW) ||
1175  (op == OP_MAIN_NEXT_NEW_THEN_UNREAD) || (op == OP_MAIN_PREV_NEW_THEN_UNREAD)) &&
1176  (first_new != -1))
1177  {
1178  break;
1179  }
1180  }
1181  if (((op == OP_MAIN_NEXT_NEW) || (op == OP_MAIN_PREV_NEW) ||
1182  (op == OP_MAIN_NEXT_NEW_THEN_UNREAD) || (op == OP_MAIN_PREV_NEW_THEN_UNREAD)) &&
1183  (first_new != -1))
1184  {
1185  index = first_new;
1186  }
1187  else if (((op == OP_MAIN_NEXT_UNREAD) || (op == OP_MAIN_PREV_UNREAD) ||
1188  (op == OP_MAIN_NEXT_NEW_THEN_UNREAD) || (op == OP_MAIN_PREV_NEW_THEN_UNREAD)) &&
1189  (first_unread != -1))
1190  {
1191  index = first_unread;
1192  }
1193 
1194  if (index == -1)
1195  {
1196  menu_set_index(priv->menu, saved_current);
1197  if ((op == OP_MAIN_NEXT_NEW) || (op == OP_MAIN_PREV_NEW))
1198  {
1199  if (ctx_has_limit(shared->ctx))
1200  mutt_error(_("No new messages in this limited view"));
1201  else
1202  mutt_error(_("No new messages"));
1203  }
1204  else
1205  {
1206  if (ctx_has_limit(shared->ctx))
1207  mutt_error(_("No unread messages in this limited view"));
1208  else
1209  mutt_error(_("No unread messages"));
1210  }
1211  return IR_ERROR;
1212  }
1213  else
1214  {
1215  menu_set_index(priv->menu, index);
1216  }
1217 
1218  index = menu_get_index(priv->menu);
1219  if ((op == OP_MAIN_NEXT_NEW) || (op == OP_MAIN_NEXT_UNREAD) ||
1220  (op == OP_MAIN_NEXT_NEW_THEN_UNREAD))
1221  {
1222  if (saved_current > index)
1223  {
1224  mutt_message(_("Search wrapped to top"));
1225  }
1226  }
1227  else if (saved_current < index)
1228  {
1229  mutt_message(_("Search wrapped to bottom"));
1230  }
1231 
1232  if (priv->in_pager)
1233  return IR_CONTINUE;
1234 
1236  return IR_SUCCESS;
1237 }
1238 
1242 static int op_main_next_thread(struct IndexSharedData *shared,
1243  struct IndexPrivateData *priv, int op)
1244 {
1245  int index = -1;
1246  switch (op)
1247  {
1248  case OP_MAIN_NEXT_THREAD:
1249  index = mutt_next_thread(shared->email);
1250  break;
1251 
1252  case OP_MAIN_NEXT_SUBTHREAD:
1253  index = mutt_next_subthread(shared->email);
1254  break;
1255 
1256  case OP_MAIN_PREV_THREAD:
1257  index = mutt_previous_thread(shared->email);
1258  break;
1259 
1260  case OP_MAIN_PREV_SUBTHREAD:
1261  index = mutt_previous_subthread(shared->email);
1262  break;
1263  }
1264 
1265  if (index != -1)
1266  menu_set_index(priv->menu, index);
1267 
1268  if (index < 0)
1269  {
1270  if ((op == OP_MAIN_NEXT_THREAD) || (op == OP_MAIN_NEXT_SUBTHREAD))
1271  mutt_error(_("No more threads"));
1272  else
1273  mutt_error(_("You are on the first thread"));
1274  }
1275  else if (priv->in_pager)
1276  {
1277  return IR_CONTINUE;
1278  }
1279  else
1281 
1282  return IR_SUCCESS;
1283 }
1284 
1288 static int op_main_next_undeleted(struct IndexSharedData *shared,
1289  struct IndexPrivateData *priv, int op)
1290 {
1291  int index = menu_get_index(priv->menu);
1292  if (index >= (shared->mailbox->vcount - 1))
1293  {
1294  if (!priv->in_pager)
1295  mutt_message(_("You are on the last message"));
1296  return IR_ERROR;
1297  }
1298  index = ci_next_undeleted(shared->mailbox, index);
1299  if (index != -1)
1300  menu_set_index(priv->menu, index);
1301 
1302  if (index == -1)
1303  {
1304  if (!priv->in_pager)
1305  mutt_error(_("No undeleted messages"));
1306  }
1307  else if (priv->in_pager)
1308  {
1309  return IR_CONTINUE;
1310  }
1311  else
1313 
1314  return IR_SUCCESS;
1315 }
1316 
1321  struct IndexPrivateData *priv, int op)
1322 {
1323  struct Mailbox *m = shared->mailbox;
1324 
1325  struct Buffer *folderbuf = mutt_buffer_pool_get();
1326  mutt_buffer_strcpy(folderbuf, mailbox_path(m));
1327  m = mutt_mailbox_next(m, folderbuf);
1328  mutt_buffer_pool_release(&folderbuf);
1329 
1330  if (!m)
1331  {
1332  mutt_error(_("No mailboxes have new mail"));
1333  return IR_ERROR;
1334  }
1335 
1336  change_folder_mailbox(priv->menu, m, &priv->oldcount, shared, false);
1337  return IR_SUCCESS;
1338 }
1339 
1343 static int op_main_prev_undeleted(struct IndexSharedData *shared,
1344  struct IndexPrivateData *priv, int op)
1345 {
1346  int index = menu_get_index(priv->menu);
1347  if (index < 1)
1348  {
1349  mutt_message(_("You are on the first message"));
1350  return IR_ERROR;
1351  }
1352  index = ci_previous_undeleted(shared->mailbox, index);
1353  if (index != -1)
1354  menu_set_index(priv->menu, index);
1355 
1356  if (index == -1)
1357  {
1358  if (!priv->in_pager)
1359  mutt_error(_("No undeleted messages"));
1360  }
1361  else if (priv->in_pager)
1362  {
1363  return IR_CONTINUE;
1364  }
1365  else
1367 
1368  return IR_SUCCESS;
1369 }
1370 
1374 static int op_main_quasi_delete(struct IndexSharedData *shared,
1375  struct IndexPrivateData *priv, int op)
1376 {
1377  if (priv->tag)
1378  {
1379  struct Mailbox *m = shared->mailbox;
1380  for (size_t i = 0; i < m->msg_count; i++)
1381  {
1382  struct Email *e = m->emails[i];
1383  if (!e)
1384  break;
1385  if (message_is_tagged(e))
1386  {
1387  e->quasi_deleted = true;
1388  m->changed = true;
1389  }
1390  }
1391  }
1392  else
1393  {
1394  if (!shared->email)
1395  return IR_NO_ACTION;
1396  shared->email->quasi_deleted = true;
1397  shared->mailbox->changed = true;
1398  }
1399 
1400  return IR_SUCCESS;
1401 }
1402 
1406 static int op_main_read_thread(struct IndexSharedData *shared,
1407  struct IndexPrivateData *priv, int op)
1408 {
1409  /* L10N: CHECK_ACL */
1410  /* L10N: Due to the implementation details we do not know whether we
1411  mark zero, 1, 12, ... messages as read. So in English we use
1412  "messages". Your language might have other means to express this. */
1413  if (!check_acl(shared->mailbox, MUTT_ACL_SEEN, _("Can't mark messages as read")))
1414  return IR_ERROR;
1415 
1416  int rc = mutt_thread_set_flag(shared->mailbox, shared->email, MUTT_READ, true,
1417  (op != OP_MAIN_READ_THREAD));
1418  if (rc != -1)
1419  {
1420  const bool c_resolve = cs_subset_bool(shared->sub, "resolve");
1421  if (c_resolve)
1422  {
1423  int index = ((op == OP_MAIN_READ_THREAD) ? mutt_next_thread(shared->email) :
1424  mutt_next_subthread(shared->email));
1425  if (index != -1)
1426  menu_set_index(priv->menu, index);
1427 
1428  if (priv->in_pager)
1429  {
1430  return IR_CONTINUE;
1431  }
1432  }
1434  }
1435 
1436  return IR_SUCCESS;
1437 }
1438 
1442 static int op_main_root_message(struct IndexSharedData *shared,
1443  struct IndexPrivateData *priv, int op)
1444 {
1445  int index = mutt_parent_message(shared->email, op == OP_MAIN_ROOT_MESSAGE);
1446  if (index != -1)
1447  menu_set_index(priv->menu, index);
1448 
1449  if (priv->in_pager)
1450  {
1451  return IR_CONTINUE;
1452  }
1453  else
1455 
1456  return IR_SUCCESS;
1457 }
1458 
1462 static int op_main_set_flag(struct IndexSharedData *shared,
1463  struct IndexPrivateData *priv, int op)
1464 {
1465  /* check_acl(MUTT_ACL_WRITE); */
1466  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
1467  el_add_tagged(&el, shared->ctx, shared->email, priv->tag);
1468 
1469  if (mutt_change_flag(shared->mailbox, &el, (op == OP_MAIN_SET_FLAG)) == 0)
1470  {
1472  const bool c_resolve = cs_subset_bool(shared->sub, "resolve");
1473  if (priv->tag)
1475  else if (c_resolve)
1476  {
1477  int index = menu_get_index(priv->menu);
1478  index = ci_next_undeleted(shared->mailbox, index);
1479  if (index == -1)
1480  {
1482  }
1483  else
1484  {
1485  menu_set_index(priv->menu, index);
1486  }
1487  }
1488  else
1490  }
1491  emaillist_clear(&el);
1492 
1493  return IR_SUCCESS;
1494 }
1495 
1499 static int op_main_show_limit(struct IndexSharedData *shared,
1500  struct IndexPrivateData *priv, int op)
1501 {
1502  if (!ctx_has_limit(shared->ctx))
1503  mutt_message(_("No limit pattern is in effect"));
1504  else
1505  {
1506  char buf2[256];
1507  /* L10N: ask for a limit to apply */
1508  snprintf(buf2, sizeof(buf2), _("Limit: %s"), shared->ctx->pattern);
1509  mutt_message("%s", buf2);
1510  }
1511 
1512  return IR_SUCCESS;
1513 }
1514 
1518 static int op_main_sync_folder(struct IndexSharedData *shared,
1519  struct IndexPrivateData *priv, int op)
1520 {
1521  if (!shared->mailbox || (shared->mailbox->msg_count == 0) || shared->mailbox->readonly)
1522  return IR_NO_ACTION;
1523 
1524  int ovc = shared->mailbox->vcount;
1525  int oc = shared->mailbox->msg_count;
1526  struct Email *e = NULL;
1527 
1528  /* don't attempt to move the cursor if there are no visible messages in the current limit */
1529  int index = menu_get_index(priv->menu);
1530  if (index < shared->mailbox->vcount)
1531  {
1532  /* threads may be reordered, so figure out what header the cursor
1533  * should be on. */
1534  int newidx = index;
1535  if (!shared->email)
1536  return IR_NO_ACTION;
1537  if (shared->email->deleted)
1538  newidx = ci_next_undeleted(shared->mailbox, index);
1539  if (newidx < 0)
1540  newidx = ci_previous_undeleted(shared->mailbox, index);
1541  if (newidx >= 0)
1542  e = mutt_get_virt_email(shared->mailbox, newidx);
1543  }
1544 
1545  enum MxStatus check = mx_mbox_sync(shared->mailbox);
1546  if (check == MX_STATUS_OK)
1547  {
1548  if (e && (shared->mailbox->vcount != ovc))
1549  {
1550  for (size_t i = 0; i < shared->mailbox->vcount; i++)
1551  {
1552  struct Email *e2 = mutt_get_virt_email(shared->mailbox, i);
1553  if (e2 == e)
1554  {
1555  menu_set_index(priv->menu, i);
1556  break;
1557  }
1558  }
1559  }
1560  OptSearchInvalid = true;
1561  }
1562  else if ((check == MX_STATUS_NEW_MAIL) || (check == MX_STATUS_REOPENED))
1563  {
1564  update_index(priv->menu, shared->ctx, check, oc, shared);
1565  }
1566 
1567  /* do a sanity check even if mx_mbox_sync failed. */
1568 
1569  index = menu_get_index(priv->menu);
1570  if ((index < 0) || (shared->mailbox && (index >= shared->mailbox->vcount)))
1571  {
1572  menu_set_index(priv->menu, ci_first_message(shared->mailbox));
1573  }
1574 
1575  /* check for a fatal error, or all messages deleted */
1576  if (shared->mailbox && mutt_buffer_is_empty(&shared->mailbox->pathbuf))
1577  {
1578  ctx_free(&shared->ctx);
1579  }
1580 
1581  /* if we were in the pager, redisplay the message */
1582  if (priv->in_pager)
1583  {
1584  return IR_CONTINUE;
1585  }
1587 
1588  return IR_SUCCESS;
1589 }
1590 
1594 static int op_main_tag_pattern(struct IndexSharedData *shared,
1595  struct IndexPrivateData *priv, int op)
1596 {
1597  mutt_pattern_func(shared->ctx, MUTT_TAG, _("Tag messages matching: "));
1599 
1600  return IR_SUCCESS;
1601 }
1602 
1606 static int op_main_undelete_pattern(struct IndexSharedData *shared,
1607  struct IndexPrivateData *priv, int op)
1608 {
1609  /* L10N: CHECK_ACL */
1610  /* L10N: Due to the implementation details we do not know whether we
1611  undelete zero, 1, 12, ... messages. So in English we use
1612  "messages". Your language might have other means to express this. */
1613  if (!check_acl(shared->mailbox, MUTT_ACL_DELETE, _("Can't undelete messages")))
1614  return IR_ERROR;
1615 
1616  if (mutt_pattern_func(shared->ctx, MUTT_UNDELETE, _("Undelete messages matching: ")) == 0)
1617  {
1619  }
1620 
1621  return IR_SUCCESS;
1622 }
1623 
1627 static int op_main_untag_pattern(struct IndexSharedData *shared,
1628  struct IndexPrivateData *priv, int op)
1629 {
1630  if (mutt_pattern_func(shared->ctx, MUTT_UNTAG, _("Untag messages matching: ")) == 0)
1632 
1633  return IR_SUCCESS;
1634 }
1635 
1639 static int op_mark_msg(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
1640 {
1641  if (!shared->email)
1642  return IR_NO_ACTION;
1643  if (shared->email->env->message_id)
1644  {
1645  char buf2[128] = { 0 };
1646 
1647  /* L10N: This is the prompt for <mark-message>. Whatever they
1648  enter will be prefixed by $mark_macro_prefix and will become
1649  a macro hotkey to jump to the currently selected message. */
1650  if (!mutt_get_field(_("Enter macro stroke: "), buf2, sizeof(buf2),
1651  MUTT_COMP_NO_FLAGS, false, NULL, NULL) &&
1652  buf2[0])
1653  {
1654  const char *const c_mark_macro_prefix =
1655  cs_subset_string(shared->sub, "mark_macro_prefix");
1656  char str[256];
1657  snprintf(str, sizeof(str), "%s%s", c_mark_macro_prefix, buf2);
1658 
1659  struct Buffer *msg_id = mutt_buffer_pool_get();
1660  mutt_file_sanitize_regex(msg_id, shared->email->env->message_id);
1661  char macro[256];
1662  snprintf(macro, sizeof(macro), "<search>~i '%s'\n", mutt_buffer_string(msg_id));
1663  mutt_buffer_pool_release(&msg_id);
1664 
1665  /* L10N: "message hotkey" is the key bindings menu description of a
1666  macro created by <mark-message>. */
1667  km_bind(str, MENU_MAIN, OP_MACRO, macro, _("message hotkey"));
1668 
1669  /* L10N: This is echoed after <mark-message> creates a new hotkey
1670  macro. %s is the hotkey string ($mark_macro_prefix followed
1671  by whatever they typed at the prompt.) */
1672  snprintf(buf2, sizeof(buf2), _("Message bound to %s"), str);
1673  mutt_message(buf2);
1674  mutt_debug(LL_DEBUG1, "Mark: %s => %s\n", str, macro);
1675  }
1676  }
1677  else
1678  {
1679  /* L10N: This error is printed if <mark-message> can't find a
1680  Message-ID for the currently selected message in the index. */
1681  mutt_error(_("No message ID to macro"));
1682  return IR_ERROR;
1683  }
1684 
1685  return IR_SUCCESS;
1686 }
1687 
1691 static int op_menu_move(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
1692 {
1693  switch (op)
1694  {
1695  case OP_BOTTOM_PAGE:
1696  menu_bottom_page(priv->menu);
1697  return IR_SUCCESS;
1698  case OP_CURRENT_BOTTOM:
1699  menu_current_bottom(priv->menu);
1700  return IR_SUCCESS;
1701  case OP_CURRENT_MIDDLE:
1702  menu_current_middle(priv->menu);
1703  return IR_SUCCESS;
1704  case OP_CURRENT_TOP:
1705  menu_current_top(priv->menu);
1706  return IR_SUCCESS;
1707  case OP_FIRST_ENTRY:
1708  menu_first_entry(priv->menu);
1709  return IR_SUCCESS;
1710  case OP_HALF_DOWN:
1711  menu_half_down(priv->menu);
1712  return IR_SUCCESS;
1713  case OP_HALF_UP:
1714  menu_half_up(priv->menu);
1715  return IR_SUCCESS;
1716  case OP_LAST_ENTRY:
1717  menu_last_entry(priv->menu);
1718  return IR_SUCCESS;
1719  case OP_MIDDLE_PAGE:
1720  menu_middle_page(priv->menu);
1721  return IR_SUCCESS;
1722  case OP_NEXT_LINE:
1723  menu_next_line(priv->menu);
1724  return IR_SUCCESS;
1725  case OP_NEXT_PAGE:
1726  menu_next_page(priv->menu);
1727  return IR_SUCCESS;
1728  case OP_PREV_LINE:
1729  menu_prev_line(priv->menu);
1730  return IR_SUCCESS;
1731  case OP_PREV_PAGE:
1732  menu_prev_page(priv->menu);
1733  return IR_SUCCESS;
1734  case OP_TOP_PAGE:
1735  menu_top_page(priv->menu);
1736  return IR_SUCCESS;
1737  }
1738 
1739  return IR_ERROR;
1740 }
1741 
1745 static int op_next_entry(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
1746 {
1747  const int index = menu_get_index(priv->menu) + 1;
1748  if (index >= shared->mailbox->vcount)
1749  {
1750  if (!priv->in_pager)
1751  mutt_message(_("You are on the last message"));
1752  return IR_ERROR;
1753  }
1754  menu_set_index(priv->menu, index);
1755  if (priv->in_pager)
1756  return IR_CONTINUE;
1757 
1759  return IR_SUCCESS;
1760 }
1761 
1765 static int op_pipe(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
1766 {
1767  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
1768  el_add_tagged(&el, shared->ctx, shared->email, priv->tag);
1769  mutt_pipe_message(shared->mailbox, &el);
1770  emaillist_clear(&el);
1771 
1772 #ifdef USE_IMAP
1773  /* in an IMAP folder index with imap_peek=no, piping could change
1774  * new or old messages status to read. Redraw what's needed. */
1775  const bool c_imap_peek = cs_subset_bool(shared->sub, "imap_peek");
1776  if ((shared->mailbox->type == MUTT_IMAP) && !c_imap_peek)
1777  {
1780  }
1781 #endif
1782 
1783  return IR_SUCCESS;
1784 }
1785 
1789 static int op_prev_entry(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
1790 {
1791  int index = menu_get_index(priv->menu);
1792  if (index < 1)
1793  {
1794  if (!priv->in_pager)
1795  mutt_message(_("You are on the first message"));
1796  return IR_ERROR;
1797  }
1798  menu_set_index(priv->menu, index - 1);
1799  if (priv->in_pager)
1800  return IR_CONTINUE;
1801 
1803  return IR_SUCCESS;
1804 }
1805 
1809 static int op_print(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
1810 {
1811  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
1812  el_add_tagged(&el, shared->ctx, shared->email, priv->tag);
1813  mutt_print_message(shared->mailbox, &el);
1814  emaillist_clear(&el);
1815 
1816 #ifdef USE_IMAP
1817  /* in an IMAP folder index with imap_peek=no, printing could change
1818  * new or old messages status to read. Redraw what's needed. */
1819  const bool c_imap_peek = cs_subset_bool(shared->sub, "imap_peek");
1820  if ((shared->mailbox->type == MUTT_IMAP) && !c_imap_peek)
1821  {
1824  }
1825 #endif
1826 
1827  return IR_SUCCESS;
1828 }
1829 
1833 static int op_query(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
1834 {
1835  query_index(shared->sub);
1836  return IR_SUCCESS;
1837 }
1838 
1842 static int op_quit(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
1843 {
1844  if (priv->attach_msg)
1845  return IR_DONE;
1846 
1847  const enum QuadOption c_quit = cs_subset_quad(shared->sub, "quit");
1848  if (query_quadoption(c_quit, _("Quit NeoMutt?")) == MUTT_YES)
1849  {
1850  priv->oldcount = shared->mailbox ? shared->mailbox->msg_count : 0;
1851 
1853  mutt_debug(LL_NOTIFY, "NT_GLOBAL_SHUTDOWN\n");
1855 
1856  enum MxStatus check = MX_STATUS_OK;
1857  if (!shared->ctx || ((check = mx_mbox_close(shared->mailbox)) == MX_STATUS_OK))
1858  {
1859  ctx_free(&shared->ctx);
1860  return IR_DONE;
1861  }
1862 
1863  if ((check == MX_STATUS_NEW_MAIL) || (check == MX_STATUS_REOPENED))
1864  {
1865  update_index(priv->menu, shared->ctx, check, priv->oldcount, shared);
1866  }
1867 
1868  menu_queue_redraw(priv->menu, MENU_REDRAW_FULL); /* new mail arrived? */
1869  OptSearchInvalid = true;
1870  }
1871 
1872  return IR_NO_ACTION;
1873 }
1874 
1878 static int op_recall_message(struct IndexSharedData *shared,
1879  struct IndexPrivateData *priv, int op)
1880 {
1881  int rc = mutt_send_message(SEND_POSTPONED, NULL, NULL, shared->mailbox, NULL,
1882  shared->sub);
1884  return (rc == -1) ? IR_ERROR : IR_SUCCESS;
1885 }
1886 
1890 static int op_redraw(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
1891 {
1892  mutt_window_reflow(NULL);
1893  clearok(stdscr, true);
1895  return IR_SUCCESS;
1896 }
1897 
1901 static int op_reply(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
1902 {
1903  if (!shared->email)
1904  return IR_NO_ACTION;
1905  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
1906  el_add_tagged(&el, shared->ctx, shared->email, priv->tag);
1907  const bool c_pgp_auto_decode = cs_subset_bool(shared->sub, "pgp_auto_decode");
1908  if (c_pgp_auto_decode && (priv->tag || !(shared->email->security & PGP_TRADITIONAL_CHECKED)))
1909  {
1910  if (mutt_check_traditional_pgp(shared->mailbox, &el))
1912  }
1913  int rc =
1914  mutt_send_message(SEND_REPLY, NULL, NULL, shared->mailbox, &el, shared->sub);
1915  emaillist_clear(&el);
1917 
1918  return (rc == -1) ? IR_ERROR : IR_SUCCESS;
1919 }
1920 
1924 static int op_resend(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
1925 {
1926  int rc = -1;
1927  if (priv->tag)
1928  {
1929  struct Mailbox *m = shared->mailbox;
1930  for (size_t i = 0; i < m->msg_count; i++)
1931  {
1932  struct Email *e = m->emails[i];
1933  if (!e)
1934  break;
1935  if (message_is_tagged(e))
1936  rc = mutt_resend_message(NULL, shared->mailbox, e, shared->sub);
1937  }
1938  }
1939  else
1940  {
1941  rc = mutt_resend_message(NULL, shared->mailbox, shared->email, shared->sub);
1942  }
1943 
1945  return (rc == -1) ? IR_ERROR : IR_SUCCESS;
1946 }
1947 
1951 static int op_save(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
1952 {
1953  if (((op == OP_DECRYPT_COPY) || (op == OP_DECRYPT_SAVE)) && !WithCrypto)
1954  return IR_NOT_IMPL;
1955 
1956  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
1957  el_add_tagged(&el, shared->ctx, shared->email, priv->tag);
1958 
1959  const enum MessageSaveOpt save_opt =
1960  ((op == OP_SAVE) || (op == OP_DECODE_SAVE) || (op == OP_DECRYPT_SAVE)) ? SAVE_MOVE : SAVE_COPY;
1961 
1962  enum MessageTransformOpt transform_opt =
1963  ((op == OP_DECODE_SAVE) || (op == OP_DECODE_COPY)) ? TRANSFORM_DECODE :
1964  ((op == OP_DECRYPT_SAVE) || (op == OP_DECRYPT_COPY)) ? TRANSFORM_DECRYPT :
1966 
1967  const int rc = mutt_save_message(shared->mailbox, &el, save_opt, transform_opt);
1968  if ((rc == 0) && (save_opt == SAVE_MOVE))
1969  {
1971  const bool c_resolve = cs_subset_bool(shared->sub, "resolve");
1972  if (priv->tag)
1974  else if (c_resolve)
1975  {
1976  int index = menu_get_index(priv->menu);
1977  index = ci_next_undeleted(shared->mailbox, index);
1978  if (index == -1)
1979  {
1981  }
1982  else
1983  {
1984  menu_set_index(priv->menu, index);
1985  }
1986  }
1987  else
1989  }
1990  emaillist_clear(&el);
1991 
1992  return (rc == -1) ? IR_ERROR : IR_SUCCESS;
1993 }
1994 
1998 static int op_search(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
1999 {
2000  // Initiating a search can happen on an empty mailbox, but
2001  // searching for next/previous/... needs to be on a message and
2002  // thus a non-empty mailbox
2003  int index = menu_get_index(priv->menu);
2004  index = mutt_search_command(shared->mailbox, priv->menu, index, op);
2005  if (index != -1)
2006  menu_set_index(priv->menu, index);
2007  else
2009 
2010  return IR_SUCCESS;
2011 }
2012 
2016 static int op_shell_escape(struct IndexSharedData *shared,
2017  struct IndexPrivateData *priv, int op)
2018 {
2019  if (mutt_shell_escape())
2020  {
2022  }
2023 
2024  return IR_SUCCESS;
2025 }
2026 
2030 static int op_show_log_messages(struct IndexSharedData *shared,
2031  struct IndexPrivateData *priv, int op)
2032 {
2033  char tempfile[PATH_MAX];
2034  mutt_mktemp(tempfile, sizeof(tempfile));
2035 
2036  FILE *fp = mutt_file_fopen(tempfile, "a+");
2037  if (!fp)
2038  {
2039  mutt_perror("fopen");
2040  return IR_ERROR;
2041  }
2042 
2043  log_queue_save(fp);
2044  mutt_file_fclose(&fp);
2045 
2046  struct PagerData pdata = { 0 };
2047  struct PagerView pview = { &pdata };
2048 
2049  pdata.fname = tempfile;
2050 
2051  pview.banner = "messages";
2053  pview.mode = PAGER_MODE_OTHER;
2054 
2055  mutt_do_pager(&pview, NULL);
2056 
2057  return IR_SUCCESS;
2058 }
2059 
2063 static int op_sort(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2064 {
2065  if (!mutt_select_sort(op == OP_SORT_REVERSE))
2066  return IR_ERROR;
2067 
2068  if (shared->mailbox && (shared->mailbox->msg_count != 0))
2069  {
2070  resort_index(shared->ctx, priv->menu);
2071  OptSearchInvalid = true;
2072  }
2073  if (priv->in_pager)
2074  return IR_CONTINUE;
2075 
2077  return IR_SUCCESS;
2078 }
2079 
2083 static int op_tag(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2084 {
2085  const bool c_auto_tag = cs_subset_bool(shared->sub, "auto_tag");
2086  if (priv->tag && !c_auto_tag)
2087  {
2088  struct Mailbox *m = shared->mailbox;
2089  for (size_t i = 0; i < m->msg_count; i++)
2090  {
2091  struct Email *e = m->emails[i];
2092  if (!e)
2093  break;
2094  if (e->visible)
2095  mutt_set_flag(m, e, MUTT_TAG, false);
2096  }
2098  }
2099  else if (!shared->email)
2100  return IR_NO_ACTION;
2101 
2102  mutt_set_flag(shared->mailbox, shared->email, MUTT_TAG, !shared->email->tagged);
2103 
2105  const bool c_resolve = cs_subset_bool(shared->sub, "resolve");
2106  const int index = menu_get_index(priv->menu) + 1;
2107  if (c_resolve && (index < shared->mailbox->vcount))
2108  {
2109  menu_set_index(priv->menu, index);
2110  }
2111  else
2112  {
2114  }
2115 
2116  return IR_SUCCESS;
2117 }
2118 
2122 static int op_tag_thread(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2123 {
2124  if (!shared->email)
2125  return IR_NO_ACTION;
2126 
2127  int rc = mutt_thread_set_flag(shared->mailbox, shared->email, MUTT_TAG,
2128  !shared->email->tagged, (op != OP_TAG_THREAD));
2129  if (rc != -1)
2130  {
2131  const bool c_resolve = cs_subset_bool(shared->sub, "resolve");
2132  if (c_resolve)
2133  {
2134  int index;
2135  if (op == OP_TAG_THREAD)
2136  index = mutt_next_thread(shared->email);
2137  else
2138  index = mutt_next_subthread(shared->email);
2139 
2140  if (index != -1)
2141  menu_set_index(priv->menu, index);
2142  }
2144  }
2145 
2146  return IR_SUCCESS;
2147 }
2148 
2152 static int op_toggle_new(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2153 {
2154  /* L10N: CHECK_ACL */
2155  if (!check_acl(shared->mailbox, MUTT_ACL_SEEN, _("Can't toggle new")))
2156  return IR_ERROR;
2157 
2158  struct Mailbox *m = shared->mailbox;
2159  if (priv->tag)
2160  {
2161  for (size_t i = 0; i < m->msg_count; i++)
2162  {
2163  struct Email *e = m->emails[i];
2164  if (!e)
2165  break;
2166  if (!message_is_tagged(e))
2167  continue;
2168 
2169  if (e->read || e->old)
2170  mutt_set_flag(m, e, MUTT_NEW, true);
2171  else
2172  mutt_set_flag(m, e, MUTT_READ, true);
2173  }
2175  }
2176  else
2177  {
2178  if (!shared->email)
2179  return IR_NO_ACTION;
2180  if (shared->email->read || shared->email->old)
2181  mutt_set_flag(m, shared->email, MUTT_NEW, true);
2182  else
2183  mutt_set_flag(m, shared->email, MUTT_READ, true);
2184 
2185  const bool c_resolve = cs_subset_bool(shared->sub, "resolve");
2186  if (c_resolve)
2187  {
2188  int index = menu_get_index(priv->menu);
2189  index = ci_next_undeleted(shared->mailbox, index);
2190  if (index == -1)
2191  {
2193  }
2194  else
2195  {
2196  menu_set_index(priv->menu, index);
2197  }
2198  }
2199  else
2202  }
2203 
2204  return IR_SUCCESS;
2205 }
2206 
2210 static int op_toggle_write(struct IndexSharedData *shared,
2211  struct IndexPrivateData *priv, int op)
2212 {
2213  if (mx_toggle_write(shared->mailbox) == 0)
2214  {
2215  if (priv->in_pager)
2216  return IR_CONTINUE;
2218  }
2219 
2220  return IR_SUCCESS;
2221 }
2222 
2226 static int op_undelete(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2227 {
2228  /* L10N: CHECK_ACL */
2229  if (!check_acl(shared->mailbox, MUTT_ACL_DELETE, _("Can't undelete message")))
2230  return IR_ERROR;
2231 
2232  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
2233  el_add_tagged(&el, shared->ctx, shared->email, priv->tag);
2234 
2235  mutt_emails_set_flag(shared->mailbox, &el, MUTT_DELETE, false);
2236  mutt_emails_set_flag(shared->mailbox, &el, MUTT_PURGE, false);
2237  emaillist_clear(&el);
2238 
2239  if (priv->tag)
2240  {
2242  }
2243  else
2244  {
2245  const bool c_resolve = cs_subset_bool(shared->sub, "resolve");
2246  const int index = menu_get_index(priv->menu) + 1;
2247  if (c_resolve && (index < shared->mailbox->vcount))
2248  {
2249  menu_set_index(priv->menu, index);
2250  }
2251  else
2253  }
2254 
2256  return IR_SUCCESS;
2257 }
2258 
2262 static int op_undelete_thread(struct IndexSharedData *shared,
2263  struct IndexPrivateData *priv, int op)
2264 {
2265  /* L10N: CHECK_ACL */
2266  /* L10N: Due to the implementation details we do not know whether we
2267  undelete zero, 1, 12, ... messages. So in English we use
2268  "messages". Your language might have other means to express this. */
2269  if (!check_acl(shared->mailbox, MUTT_ACL_DELETE, _("Can't undelete messages")))
2270  return IR_ERROR;
2271 
2272  int rc = mutt_thread_set_flag(shared->mailbox, shared->email, MUTT_DELETE,
2273  false, (op != OP_UNDELETE_THREAD));
2274  if (rc != -1)
2275  {
2276  rc = mutt_thread_set_flag(shared->mailbox, shared->email, MUTT_PURGE, false,
2277  (op != OP_UNDELETE_THREAD));
2278  }
2279  if (rc != -1)
2280  {
2281  const bool c_resolve = cs_subset_bool(shared->sub, "resolve");
2282  if (c_resolve)
2283  {
2284  int index;
2285  if (op == OP_UNDELETE_THREAD)
2286  index = mutt_next_thread(shared->email);
2287  else
2288  index = mutt_next_subthread(shared->email);
2289 
2290  if (index != -1)
2291  menu_set_index(priv->menu, index);
2292  }
2294  }
2295 
2296  return IR_SUCCESS;
2297 }
2298 
2302 static int op_version(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2303 {
2305  return IR_SUCCESS;
2306 }
2307 
2311 static int op_view_attachments(struct IndexSharedData *shared,
2312  struct IndexPrivateData *priv, int op)
2313 {
2314  if (!shared->email)
2315  return IR_NO_ACTION;
2316 
2317  enum IndexRetval rc = IR_ERROR;
2318  struct Message *msg = mx_msg_open(shared->mailbox, shared->email->msgno);
2319  if (msg)
2320  {
2321  dlg_select_attachment(NeoMutt->sub, shared->mailbox, shared->email, msg->fp);
2322  if (shared->email->attach_del)
2323  {
2324  shared->mailbox->changed = true;
2325  }
2326  mx_msg_close(shared->mailbox, &msg);
2327  rc = IR_SUCCESS;
2328  }
2330  return rc;
2331 }
2332 
2336 static int op_what_key(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2337 {
2338  mutt_what_key();
2339  return IR_SUCCESS;
2340 }
2341 
2342 // -----------------------------------------------------------------------------
2343 
2344 #ifdef USE_AUTOCRYPT
2345 
2348 static int op_autocrypt_acct_menu(struct IndexSharedData *shared,
2349  struct IndexPrivateData *priv, int op)
2350 {
2352  return IR_SUCCESS;
2353 }
2354 #endif
2355 
2356 #ifdef USE_IMAP
2357 
2360 static int op_main_imap_fetch(struct IndexSharedData *shared,
2361  struct IndexPrivateData *priv, int op)
2362 {
2363  if (!shared->mailbox || (shared->mailbox->type != MUTT_IMAP))
2364  return IR_NO_ACTION;
2365 
2366  imap_check_mailbox(shared->mailbox, true);
2367  return IR_SUCCESS;
2368 }
2369 
2373 static int op_main_imap_logout_all(struct IndexSharedData *shared,
2374  struct IndexPrivateData *priv, int op)
2375 {
2376  if (shared->mailbox && (shared->mailbox->type == MUTT_IMAP))
2377  {
2378  const enum MxStatus check = mx_mbox_close(shared->mailbox);
2379  if (check == MX_STATUS_OK)
2380  {
2381  ctx_free(&shared->ctx);
2382  }
2383  else
2384  {
2385  if ((check == MX_STATUS_NEW_MAIL) || (check == MX_STATUS_REOPENED))
2386  {
2387  update_index(priv->menu, shared->ctx, check, priv->oldcount, shared);
2388  }
2389  OptSearchInvalid = true;
2391  return IR_ERROR;
2392  }
2393  }
2394  imap_logout_all();
2395  mutt_message(_("Logged out of IMAP servers"));
2396  OptSearchInvalid = true;
2398 
2399  return IR_SUCCESS;
2400 }
2401 #endif
2402 
2403 #ifdef USE_NNTP
2404 
2407 static int op_catchup(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2408 {
2409  if (!shared->mailbox || (shared->mailbox->type != MUTT_NNTP))
2410  return IR_NO_ACTION;
2411 
2412  struct NntpMboxData *mdata = shared->mailbox->mdata;
2413  if (mutt_newsgroup_catchup(shared->mailbox, mdata->adata, mdata->group))
2415 
2416  return IR_SUCCESS;
2417 }
2418 
2422 static int op_get_children(struct IndexSharedData *shared,
2423  struct IndexPrivateData *priv, int op)
2424 {
2425  if (shared->mailbox->type != MUTT_NNTP)
2426  return IR_ERROR;
2427 
2428  if (!shared->email)
2429  return IR_NO_ACTION;
2430 
2431  char buf[PATH_MAX] = { 0 };
2432  int oldmsgcount = shared->mailbox->msg_count;
2433  int oldindex = shared->email->index;
2434  int rc = 0;
2435 
2436  if (!shared->email->env->message_id)
2437  {
2438  mutt_error(_("No Message-Id. Unable to perform operation."));
2439  return IR_ERROR;
2440  }
2441 
2442  mutt_message(_("Fetching message headers..."));
2443  if (!shared->mailbox->id_hash)
2444  shared->mailbox->id_hash = mutt_make_id_hash(shared->mailbox);
2445  mutt_str_copy(buf, shared->email->env->message_id, sizeof(buf));
2446 
2447  /* trying to find msgid of the root message */
2448  if (op == OP_RECONSTRUCT_THREAD)
2449  {
2450  struct ListNode *ref = NULL;
2451  STAILQ_FOREACH(ref, &shared->email->env->references, entries)
2452  {
2453  if (!mutt_hash_find(shared->mailbox->id_hash, ref->data))
2454  {
2455  rc = nntp_check_msgid(shared->mailbox, ref->data);
2456  if (rc < 0)
2457  return IR_ERROR;
2458  }
2459 
2460  /* the last msgid in References is the root message */
2461  if (!STAILQ_NEXT(ref, entries))
2462  mutt_str_copy(buf, ref->data, sizeof(buf));
2463  }
2464  }
2465 
2466  /* fetching all child messages */
2467  rc = nntp_check_children(shared->mailbox, buf);
2468 
2469  /* at least one message has been loaded */
2470  if (shared->mailbox->msg_count > oldmsgcount)
2471  {
2472  const int index = menu_get_index(priv->menu);
2473  struct Email *e_oldcur = mutt_get_virt_email(shared->mailbox, index);
2474  bool verbose = shared->mailbox->verbose;
2475 
2476  if (rc < 0)
2477  shared->mailbox->verbose = false;
2478  mutt_sort_headers(shared->mailbox, shared->ctx->threads,
2479  (op == OP_RECONSTRUCT_THREAD), &shared->ctx->vsize);
2480  shared->mailbox->verbose = verbose;
2481 
2482  /* Similar to OP_MAIN_ENTIRE_THREAD, keep displaying the old message, but
2483  * update the index */
2484  if (priv->in_pager)
2485  {
2486  menu_set_index(priv->menu, e_oldcur->vnum);
2488  return IR_CONTINUE;
2489  }
2490 
2491  /* if the root message was retrieved, move to it */
2492  struct Email *e = mutt_hash_find(shared->mailbox->id_hash, buf);
2493  if (e)
2494  menu_set_index(priv->menu, e->vnum);
2495  else
2496  {
2497  /* try to restore old position */
2498  for (int i = 0; i < shared->mailbox->msg_count; i++)
2499  {
2500  e = shared->mailbox->emails[i];
2501  if (!e)
2502  break;
2503  if (e->index == oldindex)
2504  {
2505  menu_set_index(priv->menu, e->vnum);
2506  /* as an added courtesy, recenter the menu
2507  * with the current entry at the middle of the screen */
2508  menu_current_middle(priv->menu);
2509  }
2510  }
2511  }
2513  }
2514  else if (rc >= 0)
2515  {
2516  mutt_error(_("No deleted messages found in the thread"));
2517  /* Similar to OP_MAIN_ENTIRE_THREAD, keep displaying the old message, but
2518  * update the index */
2519  if (priv->in_pager)
2520  {
2521  return IR_CONTINUE;
2522  }
2523  }
2524 
2525  return IR_SUCCESS;
2526 }
2527 
2531 static int op_get_message(struct IndexSharedData *shared,
2532  struct IndexPrivateData *priv, int op)
2533 {
2534  if (shared->mailbox->type != MUTT_NNTP)
2535  return IR_SUCCESS;
2536 
2537  char buf[PATH_MAX] = { 0 };
2538  if (op == OP_GET_MESSAGE)
2539  {
2540  if ((mutt_get_field(_("Enter Message-Id: "), buf, sizeof(buf),
2541  MUTT_COMP_NO_FLAGS, false, NULL, NULL) != 0) ||
2542  (buf[0] == '\0'))
2543  {
2544  return IR_ERROR;
2545  }
2546  }
2547  else
2548  {
2549  if (!shared->email || STAILQ_EMPTY(&shared->email->env->references))
2550  {
2551  mutt_error(_("Article has no parent reference"));
2552  return IR_ERROR;
2553  }
2554  mutt_str_copy(buf, STAILQ_FIRST(&shared->email->env->references)->data, sizeof(buf));
2555  }
2556 
2557  if (!shared->mailbox->id_hash)
2558  shared->mailbox->id_hash = mutt_make_id_hash(shared->mailbox);
2559  struct Email *e = mutt_hash_find(shared->mailbox->id_hash, buf);
2560  if (e)
2561  {
2562  if (e->vnum != -1)
2563  {
2564  menu_set_index(priv->menu, e->vnum);
2565  }
2566  else if (e->collapsed)
2567  {
2569  mutt_set_vnum(shared->mailbox);
2570  menu_set_index(priv->menu, e->vnum);
2571  }
2572  else
2573  mutt_error(_("Message is not visible in limited view"));
2574  }
2575  else
2576  {
2577  mutt_message(_("Fetching %s from server..."), buf);
2578  int rc = nntp_check_msgid(shared->mailbox, buf);
2579  if (rc == 0)
2580  {
2581  e = shared->mailbox->emails[shared->mailbox->msg_count - 1];
2582  mutt_sort_headers(shared->mailbox, shared->ctx->threads, false,
2583  &shared->ctx->vsize);
2584  menu_set_index(priv->menu, e->vnum);
2586  }
2587  else if (rc > 0)
2588  mutt_error(_("Article %s not found on the server"), buf);
2589  }
2590 
2591  return IR_SUCCESS;
2592 }
2593 
2597 static int op_main_change_group(struct IndexSharedData *shared,
2598  struct IndexPrivateData *priv, int op)
2599 {
2600  bool pager_return = true; /* return to display message in pager */
2601  struct Buffer *folderbuf = mutt_buffer_pool_get();
2602  mutt_buffer_alloc(folderbuf, PATH_MAX);
2603 
2604  OptNews = false;
2605  bool read_only;
2606  char *cp = NULL;
2607  const bool c_read_only = cs_subset_bool(shared->sub, "read_only");
2608  if (priv->attach_msg || c_read_only || (op == OP_MAIN_CHANGE_GROUP_READONLY))
2609  {
2610  cp = _("Open newsgroup in read-only mode");
2611  read_only = true;
2612  }
2613  else
2614  {
2615  cp = _("Open newsgroup");
2616  read_only = false;
2617  }
2618 
2619  const bool c_change_folder_next =
2620  cs_subset_bool(shared->sub, "change_folder_next");
2621  if (c_change_folder_next && shared->mailbox &&
2622  !mutt_buffer_is_empty(&shared->mailbox->pathbuf))
2623  {
2624  mutt_buffer_strcpy(folderbuf, mailbox_path(shared->mailbox));
2625  mutt_buffer_pretty_mailbox(folderbuf);
2626  }
2627 
2628  OptNews = true;
2629  const char *const c_news_server =
2630  cs_subset_string(shared->sub, "news_server");
2631  CurrentNewsSrv = nntp_select_server(shared->mailbox, c_news_server, false);
2632  if (!CurrentNewsSrv)
2633  goto changefoldercleanup2;
2634 
2635  nntp_mailbox(shared->mailbox, folderbuf->data, folderbuf->dsize);
2636 
2637  if (mutt_buffer_enter_fname(cp, folderbuf, true, shared->mailbox, false, NULL,
2638  NULL, MUTT_SEL_NO_FLAGS) == -1)
2639  {
2640  goto changefoldercleanup2;
2641  }
2642 
2643  /* Selected directory is okay, let's save it. */
2645 
2646  if (mutt_buffer_is_empty(folderbuf))
2647  {
2649  goto changefoldercleanup2;
2650  }
2651 
2652  struct Mailbox *m = mx_mbox_find2(mutt_buffer_string(folderbuf));
2653  if (m)
2654  {
2655  change_folder_mailbox(priv->menu, m, &priv->oldcount, shared, read_only);
2656  pager_return = false;
2657  }
2658  else
2659  {
2660  change_folder_string(priv->menu, folderbuf->data, folderbuf->dsize,
2661  &priv->oldcount, shared, &pager_return, read_only);
2662  }
2663  struct MuttWindow *dlg = dialog_find(priv->win_index);
2664  dlg->help_data = IndexNewsHelp;
2665 
2666 changefoldercleanup2:
2667  mutt_buffer_pool_release(&folderbuf);
2668  if (priv->in_pager && pager_return)
2669  return IR_CONTINUE;
2670 
2671  return IR_SUCCESS;
2672 }
2673 
2677 static int op_post(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
2678 {
2679  if (!shared->email)
2680  return IR_NO_ACTION;
2681 
2682  const enum QuadOption c_followup_to_poster =
2683  cs_subset_quad(shared->sub, "followup_to_poster");
2684  if ((op != OP_FOLLOWUP) || !shared->email->env->followup_to ||
2685  !mutt_istr_equal(shared->email->env->followup_to, "poster") ||
2686  (query_quadoption(c_followup_to_poster,
2687  _("Reply by mail as poster prefers?")) != MUTT_YES))
2688  {
2689  const enum QuadOption c_post_moderated =
2690  cs_subset_quad(shared->sub, "post_moderated");
2691  if (shared->mailbox && (shared->mailbox->type == MUTT_NNTP) &&
2692  !((struct NntpMboxData *) shared->mailbox->mdata)->allowed && (query_quadoption(c_post_moderated, _("Posting to this group not allowed, may be moderated. Continue?")) != MUTT_YES))
2693  {
2694  return IR_ERROR;
2695  }
2696  if (op == OP_POST)
2697  mutt_send_message(SEND_NEWS, NULL, NULL, shared->mailbox, NULL, shared->sub);
2698  else
2699  {
2700  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
2701  el_add_tagged(&el, shared->ctx, shared->email, priv->tag);
2702  mutt_send_message(((op == OP_FOLLOWUP) ? SEND_REPLY : SEND_FORWARD) | SEND_NEWS,
2703  NULL, NULL, shared->mailbox, &el, shared->sub);
2704  emaillist_clear(&el);
2705  }
2707  return IR_SUCCESS;
2708  }
2709 
2710  return op_reply(shared, priv, OP_REPLY);
2711 }
2712 #endif
2713 
2714 #ifdef USE_NOTMUCH
2715 
2718 static int op_main_entire_thread(struct IndexSharedData *shared,
2719  struct IndexPrivateData *priv, int op)
2720 {
2721  char buf[PATH_MAX] = { 0 };
2722  if (shared->mailbox->type != MUTT_NOTMUCH)
2723  {
2724  if (((shared->mailbox->type != MUTT_MH) && (shared->mailbox->type != MUTT_MAILDIR)) ||
2725  (!shared->email || !shared->email->env || !shared->email->env->message_id))
2726  {
2727  mutt_message(_("No virtual folder and no Message-Id, aborting"));
2728  return IR_ERROR;
2729  } // no virtual folder, but we have message-id, reconstruct thread on-the-fly
2730  strncpy(buf, "id:", sizeof(buf));
2731  int msg_id_offset = 0;
2732  if ((shared->email->env->message_id)[0] == '<')
2733  msg_id_offset = 1;
2734  mutt_str_cat(buf, sizeof(buf), (shared->email->env->message_id) + msg_id_offset);
2735  if (buf[strlen(buf) - 1] == '>')
2736  buf[strlen(buf) - 1] = '\0';
2737 
2738  change_folder_notmuch(priv->menu, buf, sizeof(buf), &priv->oldcount, shared, false);
2739 
2740  // If notmuch doesn't contain the message, we're left in an empty
2741  // vfolder. No messages are found, but nm_read_entire_thread assumes
2742  // a valid message-id and will throw a segfault.
2743  //
2744  // To prevent that, stay in the empty vfolder and print an error.
2745  if (shared->mailbox->msg_count == 0)
2746  {
2747  mutt_error(_("failed to find message in notmuch database. try "
2748  "running 'notmuch new'."));
2749  return IR_ERROR;
2750  }
2751  }
2752  priv->oldcount = shared->mailbox->msg_count;
2753  int index = menu_get_index(priv->menu);
2754  struct Email *e_oldcur = mutt_get_virt_email(shared->mailbox, index);
2755  if (nm_read_entire_thread(shared->mailbox, e_oldcur) < 0)
2756  {
2757  mutt_message(_("Failed to read thread, aborting"));
2758  return IR_ERROR;
2759  }
2760  if (priv->oldcount < shared->mailbox->msg_count)
2761  {
2762  /* nm_read_entire_thread() triggers mutt_sort_headers() if necessary */
2763  index = e_oldcur->vnum;
2764  if (e_oldcur->collapsed || shared->ctx->collapsed)
2765  {
2766  index = mutt_uncollapse_thread(e_oldcur);
2767  mutt_set_vnum(shared->mailbox);
2768  }
2769  menu_set_index(priv->menu, index);
2771  }
2772  if (priv->in_pager)
2773  return IR_CONTINUE;
2774 
2775  return IR_SUCCESS;
2776 }
2777 
2782  struct IndexPrivateData *priv, int op)
2783 {
2784  char buf[PATH_MAX] = { 0 };
2785  if ((mutt_get_field("Query: ", buf, sizeof(buf), MUTT_NM_QUERY, false, NULL, NULL) != 0) ||
2786  (buf[0] == '\0'))
2787  {
2788  mutt_message(_("No query, aborting"));
2789  return IR_NO_ACTION;
2790  }
2791 
2792  // Keep copy of user's query to name the mailbox
2793  char *query_unencoded = mutt_str_dup(buf);
2794 
2795  struct Mailbox *m_query =
2796  change_folder_notmuch(priv->menu, buf, sizeof(buf), &priv->oldcount,
2797  shared, (op == OP_MAIN_VFOLDER_FROM_QUERY_READONLY));
2798  if (m_query)
2799  {
2800  m_query->name = query_unencoded;
2801  query_unencoded = NULL;
2802  }
2803  else
2804  {
2805  FREE(&query_unencoded);
2806  }
2807 
2808  return IR_SUCCESS;
2809 }
2810 
2814 static int op_main_windowed_vfolder(struct IndexSharedData *shared,
2815  struct IndexPrivateData *priv, int op)
2816 {
2817  // Common guard clauses.
2819  {
2820  mutt_message(_("Windowed queries disabled"));
2821  return IR_ERROR;
2822  }
2823  const char *const c_nm_query_window_current_search =
2824  cs_subset_string(shared->sub, "nm_query_window_current_search");
2825  if (!c_nm_query_window_current_search)
2826  {
2827  mutt_message(_("No notmuch vfolder currently loaded"));
2828  return IR_ERROR;
2829  }
2830 
2831  // Call the specific operation.
2832  switch (op)
2833  {
2834  case OP_MAIN_WINDOWED_VFOLDER_BACKWARD:
2836  break;
2837  case OP_MAIN_WINDOWED_VFOLDER_FORWARD:
2839  break;
2840  case OP_MAIN_WINDOWED_VFOLDER_RESET:
2842  break;
2843  }
2844 
2845  // Common query window folder change.
2846  char buf[PATH_MAX] = { 0 };
2847  mutt_str_copy(buf, c_nm_query_window_current_search, sizeof(buf));
2848  change_folder_notmuch(priv->menu, buf, sizeof(buf), &priv->oldcount, shared, false);
2849 
2850  return IR_SUCCESS;
2851 }
2852 #endif
2853 
2854 #ifdef USE_POP
2855 
2858 static int op_main_fetch_mail(struct IndexSharedData *shared,
2859  struct IndexPrivateData *priv, int op)
2860 {
2861  pop_fetch_mail();
2863  return IR_SUCCESS;
2864 }
2865 #endif
2866 
2867 #ifdef USE_SIDEBAR
2868 
2871 static int op_sidebar_next(struct IndexSharedData *shared,
2872  struct IndexPrivateData *priv, int op)
2873 {
2874  struct MuttWindow *dlg = dialog_find(priv->win_index);
2875  struct MuttWindow *win_sidebar = window_find_child(dlg, WT_SIDEBAR);
2876  sb_change_mailbox(win_sidebar, op);
2877  return IR_SUCCESS;
2878 }
2879 
2883 static int op_sidebar_open(struct IndexSharedData *shared,
2884  struct IndexPrivateData *priv, int op)
2885 {
2886  struct MuttWindow *dlg = dialog_find(priv->win_index);
2887  struct MuttWindow *win_sidebar = window_find_child(dlg, WT_SIDEBAR);
2888  change_folder_mailbox(priv->menu, sb_get_highlight(win_sidebar),
2889  &priv->oldcount, shared, false);
2890  return IR_SUCCESS;
2891 }
2892 
2896 static int op_sidebar_toggle_visible(struct IndexSharedData *shared,
2897  struct IndexPrivateData *priv, int op)
2898 {
2899  bool_str_toggle(shared->sub, "sidebar_visible", NULL);
2900  mutt_window_reflow(NULL);
2901  return IR_SUCCESS;
2902 }
2903 #endif
2904 
2905 // -----------------------------------------------------------------------------
2906 
2914 bool prereq(struct Context *ctx, struct Menu *menu, CheckFlags checks)
2915 {
2916  bool result = true;
2917 
2918  if (checks & (CHECK_MSGCOUNT | CHECK_VISIBLE | CHECK_READONLY))
2919  checks |= CHECK_IN_MAILBOX;
2920 
2921  if ((checks & CHECK_IN_MAILBOX) && (!ctx || !ctx->mailbox))
2922  {
2923  mutt_error(_("No mailbox is open"));
2924  result = false;
2925  }
2926 
2927  if (result && (checks & CHECK_MSGCOUNT) && (ctx->mailbox->msg_count == 0))
2928  {
2929  mutt_error(_("There are no messages"));
2930  result = false;
2931  }
2932 
2933  int index = menu_get_index(menu);
2934  if (result && (checks & CHECK_VISIBLE) && (index >= ctx->mailbox->vcount))
2935  {
2936  mutt_error(_("No visible messages"));
2937  result = false;
2938  }
2939 
2940  if (result && (checks & CHECK_READONLY) && ctx->mailbox->readonly)
2941  {
2942  mutt_error(_("Mailbox is read-only"));
2943  result = false;
2944  }
2945 
2946  if (result && (checks & CHECK_ATTACH) && OptAttachMsg)
2947  {
2948  mutt_error(_("Function not permitted in attach-message mode"));
2949  result = false;
2950  }
2951 
2952  if (!result)
2953  mutt_flushinp();
2954 
2955  return result;
2956 }
2957 
2964 int index_function_dispatcher(struct MuttWindow *win_index, int op)
2965 {
2966  if (!win_index)
2967  {
2969  return IR_ERROR;
2970  }
2971 
2972  struct IndexPrivateData *priv = win_index->parent->wdata;
2973  if (!priv)
2974  return IR_ERROR;
2975 
2976  struct MuttWindow *dlg = dialog_find(win_index);
2977  if (!dlg || !dlg->wdata)
2978  return IR_ERROR;
2979 
2980  struct IndexSharedData *shared = dlg->wdata;
2981 
2982  int rc = IR_UNKNOWN;
2983  for (size_t i = 0; IndexFunctions[i].op != OP_NULL; i++)
2984  {
2985  const struct IndexFunction *fn = &IndexFunctions[i];
2986  if (fn->op == op)
2987  {
2988  if (!prereq(shared->ctx, priv->menu, fn->flags))
2989  {
2990  rc = IR_ERROR;
2991  break;
2992  }
2993  rc = fn->function(shared, priv, op);
2994  break;
2995  }
2996  }
2997 
2998  return rc;
2999 }
3000 
3004 struct IndexFunction IndexFunctions[] = {
3005  // clang-format off
3006  { OP_BOTTOM_PAGE, op_menu_move, CHECK_NO_FLAGS },
3008  { OP_CHECK_STATS, op_check_stats, CHECK_NO_FLAGS },
3009  { OP_CHECK_TRADITIONAL, op_check_traditional, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3011  { OP_COPY_MESSAGE, op_save, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3012  { OP_CREATE_ALIAS, op_create_alias, CHECK_NO_FLAGS },
3013  { OP_CURRENT_BOTTOM, op_menu_move, CHECK_NO_FLAGS },
3014  { OP_CURRENT_MIDDLE, op_menu_move, CHECK_NO_FLAGS },
3015  { OP_CURRENT_TOP, op_menu_move, CHECK_NO_FLAGS },
3016  { OP_DECODE_COPY, op_save, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3017  { OP_DECODE_SAVE, op_save, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3018  { OP_DECRYPT_COPY, op_save, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3019  { OP_DECRYPT_SAVE, op_save, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3023  { OP_DISPLAY_ADDRESS, op_display_address, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3024  { OP_DISPLAY_HEADERS, op_display_message, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3025  { OP_DISPLAY_MESSAGE, op_display_message, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3027  { OP_EDIT_OR_VIEW_RAW_MESSAGE, op_edit_raw_message, CHECK_ATTACH | CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3030  { OP_END_COND, op_end_cond, CHECK_NO_FLAGS },
3031  { OP_ENTER_COMMAND, op_enter_command, CHECK_NO_FLAGS },
3032  { OP_EXIT, op_exit, CHECK_NO_FLAGS },
3034  { OP_FIRST_ENTRY, op_menu_move, CHECK_NO_FLAGS },
3036  { OP_FORGET_PASSPHRASE, op_forget_passphrase, CHECK_NO_FLAGS },
3040  { OP_HALF_DOWN, op_menu_move, CHECK_NO_FLAGS },
3041  { OP_HALF_UP, op_menu_move, CHECK_NO_FLAGS },
3042  { OP_HELP, op_help, CHECK_NO_FLAGS },
3043  { OP_JUMP, op_jump, CHECK_IN_MAILBOX },
3044  { OP_LAST_ENTRY, op_menu_move, CHECK_NO_FLAGS },
3045  { OP_LIMIT_CURRENT_THREAD, op_main_limit, CHECK_IN_MAILBOX },
3046  { OP_LIST_REPLY, op_list_reply, CHECK_ATTACH | CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3047  { OP_MAIL, op_mail, CHECK_ATTACH },
3048  { OP_MAILBOX_LIST, op_mailbox_list, CHECK_NO_FLAGS },
3049  { OP_MAIL_KEY, op_mail_key, CHECK_ATTACH },
3050  { OP_MAIN_BREAK_THREAD, op_main_break_thread, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_READONLY | CHECK_VISIBLE },
3051  { OP_MAIN_CHANGE_FOLDER, op_main_change_folder, CHECK_NO_FLAGS },
3052  { OP_MAIN_CHANGE_FOLDER_READONLY, op_main_change_folder, CHECK_NO_FLAGS },
3053  { OP_MAIN_CLEAR_FLAG, op_main_set_flag, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_READONLY | CHECK_VISIBLE },
3054  { OP_MAIN_COLLAPSE_ALL, op_main_collapse_all, CHECK_IN_MAILBOX },
3055  { OP_MAIN_COLLAPSE_THREAD, op_main_collapse_thread, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3056  { OP_MAIN_DELETE_PATTERN, op_main_delete_pattern, CHECK_ATTACH | CHECK_IN_MAILBOX | CHECK_READONLY },
3057  { OP_MAIN_LIMIT, op_main_limit, CHECK_IN_MAILBOX },
3058  { OP_MAIN_LINK_THREADS, op_main_link_threads, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_READONLY | CHECK_VISIBLE },
3059  { OP_MAIN_MODIFY_TAGS, op_main_modify_tags, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_READONLY | CHECK_VISIBLE },
3060  { OP_MAIN_MODIFY_TAGS_THEN_HIDE, op_main_modify_tags, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_READONLY | CHECK_VISIBLE },
3061  { OP_MAIN_NEXT_NEW, op_main_next_new, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3062  { OP_MAIN_NEXT_NEW_THEN_UNREAD, op_main_next_new, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3063  { OP_MAIN_NEXT_SUBTHREAD, op_main_next_thread, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3064  { OP_MAIN_NEXT_THREAD, op_main_next_thread, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3065  { OP_MAIN_NEXT_UNDELETED, op_main_next_undeleted, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3066  { OP_MAIN_NEXT_UNREAD, op_main_next_new, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3067  { OP_MAIN_NEXT_UNREAD_MAILBOX, op_main_next_unread_mailbox, CHECK_IN_MAILBOX },
3068  { OP_MAIN_PARENT_MESSAGE, op_main_root_message, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3069  { OP_MAIN_PREV_NEW, op_main_next_new, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3070  { OP_MAIN_PREV_NEW_THEN_UNREAD, op_main_next_new, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3071  { OP_MAIN_PREV_SUBTHREAD, op_main_next_thread, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3072  { OP_MAIN_PREV_THREAD, op_main_next_thread, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3073  { OP_MAIN_PREV_UNDELETED, op_main_prev_undeleted, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3074  { OP_MAIN_PREV_UNREAD, op_main_next_new, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3075  { OP_MAIN_QUASI_DELETE, op_main_quasi_delete, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3076  { OP_MAIN_READ_SUBTHREAD, op_main_read_thread, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_READONLY | CHECK_VISIBLE },
3077  { OP_MAIN_READ_THREAD, op_main_read_thread, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_READONLY | CHECK_VISIBLE },
3078  { OP_MAIN_ROOT_MESSAGE, op_main_root_message, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3079  { OP_MAIN_SET_FLAG, op_main_set_flag, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_READONLY | CHECK_VISIBLE },
3080  { OP_MAIN_SHOW_LIMIT, op_main_show_limit, CHECK_IN_MAILBOX },
3081  { OP_MAIN_SYNC_FOLDER, op_main_sync_folder, CHECK_NO_FLAGS },
3082  { OP_MAIN_TAG_PATTERN, op_main_tag_pattern, CHECK_IN_MAILBOX },
3083  { OP_MAIN_UNDELETE_PATTERN, op_main_undelete_pattern, CHECK_IN_MAILBOX | CHECK_READONLY },
3084  { OP_MAIN_UNTAG_PATTERN, op_main_untag_pattern, CHECK_IN_MAILBOX },
3085  { OP_MARK_MSG, op_mark_msg, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3086  { OP_MIDDLE_PAGE, op_menu_move, CHECK_NO_FLAGS },
3087  { OP_NEXT_ENTRY, op_next_entry, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3088  { OP_NEXT_LINE, op_menu_move, CHECK_NO_FLAGS },
3089  { OP_NEXT_PAGE, op_menu_move, CHECK_NO_FLAGS },
3090  { OP_PIPE, op_pipe, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3091  { OP_PREV_ENTRY, op_prev_entry, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3092  { OP_PREV_LINE, op_menu_move, CHECK_NO_FLAGS },
3093  { OP_PREV_PAGE, op_menu_move, CHECK_NO_FLAGS },
3094  { OP_PRINT, op_print, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3095  { OP_PURGE_MESSAGE, op_delete, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_READONLY | CHECK_VISIBLE },
3096  { OP_PURGE_THREAD, op_delete_thread, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_READONLY | CHECK_VISIBLE },
3097  { OP_QUERY, op_query, CHECK_ATTACH },
3098  { OP_QUIT, op_quit, CHECK_NO_FLAGS },
3099  { OP_RECALL_MESSAGE, op_recall_message, CHECK_ATTACH },
3100  { OP_REDRAW, op_redraw, CHECK_NO_FLAGS },
3101  { OP_REPLY, op_reply, CHECK_ATTACH | CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3102  { OP_RESEND, op_resend, CHECK_ATTACH | CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3103  { OP_SAVE, op_save, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3104  { OP_SEARCH, op_search, CHECK_IN_MAILBOX },
3105  { OP_SEARCH_NEXT, op_search, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3106  { OP_SEARCH_OPPOSITE, op_search, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3107  { OP_SEARCH_REVERSE, op_search, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3108  { OP_SHELL_ESCAPE, op_shell_escape, CHECK_NO_FLAGS },
3109  { OP_SHOW_LOG_MESSAGES, op_show_log_messages, CHECK_NO_FLAGS },
3110  { OP_SORT, op_sort, CHECK_NO_FLAGS },
3111  { OP_SORT_REVERSE, op_sort, CHECK_NO_FLAGS },
3112  { OP_TAG, op_tag, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3113  { OP_TAG_SUBTHREAD, op_tag_thread, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3114  { OP_TAG_THREAD, op_tag_thread, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3115  { OP_TOGGLE_NEW, op_toggle_new, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_READONLY | CHECK_VISIBLE },
3116  { OP_TOGGLE_READ, op_main_limit, CHECK_IN_MAILBOX },
3117  { OP_TOGGLE_WRITE, op_toggle_write, CHECK_IN_MAILBOX },
3118  { OP_TOP_PAGE, op_menu_move, CHECK_NO_FLAGS },
3119  { OP_UNDELETE, op_undelete, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_READONLY | CHECK_VISIBLE },
3120  { OP_UNDELETE_SUBTHREAD, op_undelete_thread, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_READONLY | CHECK_VISIBLE },
3121  { OP_UNDELETE_THREAD, op_undelete_thread, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_READONLY | CHECK_VISIBLE },
3122  { OP_VERSION, op_version, CHECK_NO_FLAGS },
3123  { OP_VIEW_ATTACHMENTS, op_view_attachments, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3124  { OP_VIEW_RAW_MESSAGE, op_edit_raw_message, CHECK_ATTACH | CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3125  { OP_WHAT_KEY, op_what_key, CHECK_NO_FLAGS },
3126 #ifdef USE_AUTOCRYPT
3127  { OP_AUTOCRYPT_ACCT_MENU, op_autocrypt_acct_menu, CHECK_NO_FLAGS },
3128 #endif
3129 #ifdef USE_IMAP
3130  { OP_MAIN_IMAP_FETCH, op_main_imap_fetch, CHECK_NO_FLAGS },
3131  { OP_MAIN_IMAP_LOGOUT_ALL, op_main_imap_logout_all, CHECK_NO_FLAGS },
3132 #endif
3133 #ifdef USE_NNTP
3134  { OP_CATCHUP, op_catchup, CHECK_ATTACH | CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_READONLY },
3135  { OP_FOLLOWUP, op_post, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3136  { OP_FORWARD_TO_GROUP, op_post, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3137  { OP_GET_CHILDREN, op_get_children, CHECK_ATTACH | CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_READONLY | CHECK_VISIBLE },
3138  { OP_GET_MESSAGE, op_get_message, CHECK_ATTACH | CHECK_IN_MAILBOX | CHECK_READONLY },
3139  { OP_GET_PARENT, op_get_message, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3140  { OP_MAIN_CHANGE_GROUP, op_main_change_group, CHECK_NO_FLAGS },
3141  { OP_MAIN_CHANGE_GROUP_READONLY, op_main_change_group, CHECK_NO_FLAGS },
3142  { OP_POST, op_post, CHECK_ATTACH | CHECK_IN_MAILBOX },
3143  { OP_RECONSTRUCT_THREAD, op_get_children, CHECK_ATTACH | CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_READONLY | CHECK_VISIBLE },
3144 #endif
3145 #ifdef USE_NOTMUCH
3146  { OP_MAIN_CHANGE_VFOLDER, op_main_change_folder, CHECK_NO_FLAGS },
3147  { OP_MAIN_ENTIRE_THREAD, op_main_entire_thread, CHECK_IN_MAILBOX | CHECK_MSGCOUNT | CHECK_VISIBLE },
3148  { OP_MAIN_VFOLDER_FROM_QUERY, op_main_vfolder_from_query, CHECK_NO_FLAGS },
3149  { OP_MAIN_VFOLDER_FROM_QUERY_READONLY, op_main_vfolder_from_query, CHECK_NO_FLAGS },
3150  { OP_MAIN_WINDOWED_VFOLDER_BACKWARD, op_main_windowed_vfolder, CHECK_IN_MAILBOX },
3151  { OP_MAIN_WINDOWED_VFOLDER_FORWARD, op_main_windowed_vfolder, CHECK_IN_MAILBOX },
3152  { OP_MAIN_WINDOWED_VFOLDER_RESET, op_main_windowed_vfolder, CHECK_IN_MAILBOX },
3153 #endif
3154 #ifdef USE_POP
3155  { OP_MAIN_FETCH_MAIL, op_main_fetch_mail, CHECK_ATTACH },
3156 #endif
3157 #ifdef USE_SIDEBAR
3158  { OP_SIDEBAR_FIRST, op_sidebar_next, CHECK_NO_FLAGS },
3159  { OP_SIDEBAR_LAST, op_sidebar_next, CHECK_NO_FLAGS },
3160  { OP_SIDEBAR_NEXT, op_sidebar_next, CHECK_NO_FLAGS },
3161  { OP_SIDEBAR_NEXT_NEW, op_sidebar_next, CHECK_NO_FLAGS },
3162  { OP_SIDEBAR_OPEN, op_sidebar_open, CHECK_NO_FLAGS },
3163  { OP_SIDEBAR_PAGE_DOWN, op_sidebar_next, CHECK_NO_FLAGS },
3164  { OP_SIDEBAR_PAGE_UP, op_sidebar_next, CHECK_NO_FLAGS },
3165  { OP_SIDEBAR_PREV, op_sidebar_next, CHECK_NO_FLAGS },
3166  { OP_SIDEBAR_PREV_NEW, op_sidebar_next, CHECK_NO_FLAGS },
3167  { OP_SIDEBAR_TOGGLE_VISIBLE, op_sidebar_toggle_visible, CHECK_NO_FLAGS },
3168 #endif
3169  // clang-format on
3170  { 0, NULL, CHECK_NO_FLAGS },
3171 };
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:1499
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:1765
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:354
struct Email ** emails
Array of Emails.
Definition: mailbox.h:99
Convenience wrapper for the gui headers.
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:1639
The "current" mailbox.
Definition: context.h:37
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox&#39;s path string.
Definition: mailbox.h:215
void nm_query_window_forward(void)
Function to move the current search window forward in time.
Definition: notmuch.c:1640
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:693
struct MuttWindow * window_find_child(struct MuttWindow *win, enum WindowType type)
Recursively find a child Window of a given type.
Definition: mutt_window.c:550
static int op_edit_label(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
add, change, or delete a message&#39;s label - Implements index_function_t -
Definition: functions.c:341
static int op_mailbox_list(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
list mailboxes with new mail - Implements index_function_t -
Definition: functions.c:683
static int op_print(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
print the current entry - Implements index_function_t -
Definition: functions.c:1809
static int op_exit(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
exit this menu - Implements index_function_t -
Definition: functions.c:445
static int op_catchup(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
mark all articles in newsgroup as read - Implements index_function_t -
Definition: functions.c:2407
Manage keymappings.
enum MailboxType type
Mailbox type.
Definition: mailbox.h:105
Decrypt message.
Definition: commands.h:42
bool mutt_mailbox_list(void)
List the mailboxes with new mail.
Definition: mutt_mailbox.c:222
Valid function - successfully performed.
Definition: functions.h:41
int msg_count
Total number of messages.
Definition: mailbox.h:91
#define mutt_set_flag(m, e, flag, bf)
Definition: protos.h:66
static int op_quit(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
save changes to mailbox and quit - Implements index_function_t -
Definition: functions.c:1842
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
Representation of the email&#39;s header.
#define WithCrypto
Definition: lib.h:113
int mutt_str_atoi(const char *str, int *dst)
Convert ASCII string to an integer.
Definition: string.c:252
#define SEND_TO_SENDER
Compose new email to sender.
Definition: send.h:51
IMAP network mailbox.
void mutt_pipe_message(struct Mailbox *m, struct EmailList *el)
Pipe a message.
Definition: commands.c:760
The envelope/body of an email.
Definition: email.h:37
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:228
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
struct Email * mutt_get_virt_email(struct Mailbox *m, int vnum)
Get a virtual Email.
Definition: context.c:412
bool nm_query_window_available(void)
Are windowed queries enabled for use?
Definition: notmuch.c:1621
static int op_check_traditional(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
check for classic PGP - Implements index_function_t -
Definition: functions.c:121
static int op_bounce_message(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
remail a message to another user - Implements index_function_t -
Definition: functions.c:97
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:695
#define MUTT_SHUTDOWN_HOOK
shutdown-hook: run when leaving NeoMutt
Definition: hook.h:59
Definition: lib.h:67
struct Body * body
List of MIME parts.
Definition: email.h:91
void nm_query_window_backward(void)
Function to move the current search window backward in time.
Definition: notmuch.c:1661
Log of notifications.
Definition: logging.h:45
&#39;NNTP&#39; (Usenet) Mailbox type
Definition: mailbox.h:52
Structs that make up an email.
struct Email * email
Currently selected Email.
Definition: shared_data.h:42
struct Menu * menu
Menu controlling the index.
Definition: private_data.h:44
static int op_help(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
this screen - Implements index_function_t -
Definition: functions.c:599
#define mutt_error(...)
Definition: logging.h:88
The "currently-open" mailbox.
#define mutt_uncollapse_thread(e)
Definition: mutt_thread.h:89
Autocrypt end-to-end encryption.
Convenience wrapper for the send headers.
#define mutt_collapse_thread(e)
Definition: mutt_thread.h:88
bool tag
tag-prefix has been pressed
Definition: private_data.h:36
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:1462
#define CHECK_VISIBLE
Is the selected message visible in the index?
Definition: lib.h:71
void mutt_emails_set_flag(struct Mailbox *m, struct EmailList *el, enum MessageType flag, bool bf)
Set flag on messages.
Definition: flags.c:352
void update_index(struct Menu *menu, struct Context *ctx, enum MxStatus check, int oldcount, const struct IndexSharedData *shared)
Update the index.
Definition: dlg_index.c:496
void mutt_check_rescore(struct Mailbox *m)
Do the emails need to have their scores recalculated?
Definition: score.c:65
Private state data for the Index.
Definition: private_data.h:34
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:2531
void mutt_sort_headers(struct Mailbox *m, struct ThreadsContext *threads, bool init, off_t *vsize)
Sort emails by their headers.
Definition: sort.c:356
int mutt_get_field(const char *field, char *buf, size_t buflen, CompletionFlags complete, bool multiple, char ***files, int *numfiles)
Ask the user for a string.
Definition: curs_lib.c:335
void mutt_display_address(struct Envelope *env)
Display the address of a message.
Definition: commands.c:1026
struct ConfigSubset * sub
Config set to use.
Definition: shared_data.h:38
struct NntpAccountData * adata
Definition: mdata.h:47
bool mutt_shell_escape(void)
invoke a command in a subshell
Definition: commands.c:943
Messages in limited view.
Definition: mutt.h:101
struct MuttWindow * win_pbar
Window for the Pager Bar.
Definition: private_data.h:48
struct HashTable * mutt_make_id_hash(struct Mailbox *m)
Create a Hash Table for message-ids.
Definition: mutt_thread.c:1658
void mutt_flushinp(void)
Empty all the keyboard buffers.
Definition: curs_lib.c:668
const struct Mapping IndexNewsHelp[]
Help Bar for the News Index dialog.
Definition: dlg_index.c:122
bool attach_del
Has an attachment marked for deletion.
Definition: email.h:49
#define SEND_FORWARD
Forward email.
Definition: send.h:43
void collapse_all(struct Context *ctx, struct Menu *menu, int toggle)
Collapse/uncollapse all threads.
Definition: dlg_index.c:171
bool mutt_check_traditional_pgp(struct Mailbox *m, struct EmailList *el)
Check if a message has inline PGP content.
Definition: commands.c:1574
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
WHERE bool OptNeedResort
(pseudo) used to force a re-sort
Definition: options.h:42
static int op_undelete(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
undelete the current entry - Implements index_function_t -
Definition: functions.c:2226
struct ThreadsContext * threads
Threads context.
Definition: context.h:42
#define mutt_next_subthread(e)
Definition: mutt_thread.h:103
void crypt_forget_passphrase(void)
Forget a passphrase and display a message.
Definition: crypt.c:93
bool mutt_link_threads(struct Email *parent, struct EmailList *children, struct Mailbox *m)
Forcibly link threads together.
Definition: mutt_thread.c:1703
No transformation.
Definition: commands.h:41
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:818
#define MUTT_NM_QUERY
Notmuch query mode.
Definition: mutt.h:62
bool mutt_limit_current_thread(struct Context *ctx, struct Email *e)
Limit the email view to the current thread.
Definition: pattern.c:192
void mutt_enter_command(void)
enter a neomutt command
Definition: commands.c:978
bool threaded
Used for threading.
Definition: email.h:56
String manipulation buffer.
Definition: buffer.h:33
#define MUTT_ACL_INSERT
Add/copy into the mailbox (used when editing a message)
Definition: mailbox.h:69
static int op_jump(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
jump to an index number - Implements index_function_t -
Definition: functions.c:609
static int op_toggle_new(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
toggle a message&#39;s &#39;new&#39; flag - Implements index_function_t -
Definition: functions.c:2152
static int op_display_message(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
display a message - Implements index_function_t -
Definition: functions.c:282
int nntp_check_msgid(struct Mailbox *m, const char *msgid)
Fetch article by Message-ID.
Definition: nntp.c:2141
New mail received in Mailbox.
Definition: mxapi.h:79
int oldcount
Old count of Emails in the Mailbox.
Definition: private_data.h:37
struct MuttWindow * window_set_focus(struct MuttWindow *win)
Set the Window focus.
Definition: mutt_window.c:680
bool ctx_has_limit(const struct Context *ctx)
Is a limit active?
Definition: context.c:433
Messages to be un-deleted.
Definition: mutt.h:95
Paged view into some data.
Definition: lib.h:154
Flagged messages.
Definition: mutt.h:98
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
void mutt_unget_event(int ch, int op)
Return a keystroke to the input buffer.
Definition: curs_lib.c:583
int ci_previous_undeleted(struct Mailbox *m, int msgno)
Find the previous undeleted email.
Definition: dlg_index.c:250
#define _(a)
Definition: message.h:28
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:875
Private state data for the Index.
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:834
static int op_redraw(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
clear and redraw the screen - Implements index_function_t -
Definition: functions.c:1890
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:424
enum MxStatus mx_mbox_sync(struct Mailbox *m)
Save changes to mailbox.
Definition: mx.c:916
static int op_forward_message(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
forward a message with comments - Implements index_function_t -
Definition: functions.c:546
Data shared between Index, Pager and Sidebar.
Definition: shared_data.h:36
#define MUTT_SEL_NO_FLAGS
No flags are set.
Definition: browser.h:36
Index functions.
Messages to be purged (bypass trash)
Definition: mutt.h:96
void nm_db_longrun_init(struct Mailbox *m, bool writable)
Start a long transaction.
Definition: db.c:314
int mx_toggle_write(struct Mailbox *m)
Toggle the mailbox&#39;s readonly flag.
Definition: mx.c:1830
int attach_msg
Are we in "attach message" mode?
Definition: private_data.h:40
void emaillist_clear(struct EmailList *el)
Drop a private list of Emails.
Definition: email.c:138
static int op_forget_passphrase(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
wipe passphrases from memory - Implements index_function_t -
Definition: functions.c:536
Copy message, making a duplicate in another mailbox.
Definition: commands.h:51
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:958
static int op_recall_message(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
recall a postponed message - Implements index_function_t -
Definition: functions.c:1878
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:1121
struct Mailbox * mutt_mailbox_next(struct Mailbox *m_cur, struct Buffer *s)
incoming folders completion routine
Definition: mutt_mailbox.c:314
static const char * Not_available_in_this_menu
Definition: functions.c:89
enum MxStatus mx_mbox_close(struct Mailbox *m)
Save changes and close mailbox.
Definition: mx.c:610
uint16_t SendFlags
Flags for mutt_send_message(), e.g. SEND_REPLY.
Definition: send.h:36
static int op_main_untag_pattern(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
untag messages matching a pattern - Implements index_function_t -
Definition: functions.c:1627
struct Mailbox * mx_mbox_find2(const char *path)
Find a Mailbox on an Account.
Definition: mx.c:1640
All user-callable functions.
#define SEND_POSTPONED
Recall a postponed email.
Definition: send.h:44
void mutt_help(enum MenuType menu)
Display the help menu.
Definition: help.c:389
void msgwin_clear_text(void)
Clear the text in the Message Window.
Definition: msgwin.c:242
#define mutt_perror(...)
Definition: logging.h:89
Container for Accounts, Notifications.
Definition: neomutt.h:36
A Progress Bar.
Definition: progress.c:47
void mutt_buffer_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:603
#define MUTT_ACL_DELETE
Delete a message.
Definition: mailbox.h:66
int vcount
The number of virtual messages.
Definition: mailbox.h:102
Mailbox was reopened.
Definition: mxapi.h:81
QuadOption
Possible values for a quad-option.
Definition: quad.h:35
Convenience wrapper for the config headers.
GUI component for displaying/selecting items from a list.
static int op_mail(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
compose a new mail message - Implements index_function_t -
Definition: functions.c:672
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:1007
static int op_compose_to_sender(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
compose new message to the current message sender - Implements index_function_t - ...
Definition: functions.c:147
static int op_tag_thread(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
tag the current thread - Implements index_function_t -
Definition: functions.c:2122
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:1242
void imap_logout_all(void)
close all open connections
Definition: imap.c:564
static int op_save(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
make decrypted copy - Implements index_function_t -
Definition: functions.c:1951
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:2718
Assorted sorting methods.
void mutt_print_message(struct Mailbox *m, struct EmailList *el)
Print a message.
Definition: commands.c:791
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
#define SEND_NO_FLAGS
No flags are set.
Definition: send.h:39
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:2210
Some miscellaneous functions.
Progress bar.
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1186
#define mutt_previous_thread(e)
Definition: mutt_thread.h:102
static int op_resend(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
use the current message as a template for a new one - Implements index_function_t - ...
Definition: functions.c:1924
size_t dsize
Length of data.
Definition: buffer.h:37
bool tagged
Email is tagged.
Definition: email.h:44
bool read
Email is read.
Definition: email.h:51
char * name
A short name for the Mailbox.
Definition: mailbox.h:85
Data to be displayed by PagerView.
Definition: lib.h:143
void mutt_startup_shutdown_hook(HookFlags type)
Execute any startup/shutdown hooks.
Definition: hook.c:863
struct ListHead in_reply_to
in-reply-to header content
Definition: envelope.h:82
char * message_id
Message ID.
Definition: envelope.h:69
#define MUTT_PAGER_BOTTOM
Start at the bottom.
Definition: lib.h:69
static int op_extract_keys(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
extract supported public keys - Implements index_function_t -
Definition: functions.c:468
struct Mailbox * mailbox
Definition: context.h:49
struct HashTable * id_hash
Hash Table by msg id.
Definition: mailbox.h:127
Parse and execute user-defined hooks.
uint8_t CheckFlags
Flags, e.g. CHECK_IN_MAILBOX.
Definition: lib.h:67
Many unsorted constants and some structs.
API for mailboxes.
bool old
Email is seen, but unread.
Definition: email.h:50
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:228
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:52
void change_folder_string(struct Menu *menu, char *buf, size_t buflen, int *oldcount, struct IndexSharedData *shared, bool *pager_return, bool read_only)
Change to a different Mailbox by string.
Definition: dlg_index.c:720
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:1606
bool readonly
Don&#39;t allow changes to the mailbox.
Definition: mailbox.h:119
void resort_index(struct Context *ctx, struct Menu *menu)
Resort the index.
Definition: dlg_index.c:330
bool nm_message_is_still_queried(struct Mailbox *m, struct Email *e)
Is a message still visible in the query?
Definition: notmuch.c:1685
int ci_first_message(struct Mailbox *m)
Get index of first new message.
Definition: dlg_index.c:274
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
#define mutt_thread_next_unread(e)
Definition: mutt_thread.h:92
void mutt_what_key(void)
Ask the user to press a key.
Definition: keymap.c:1718
static int op_autocrypt_acct_menu(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
manage autocrypt accounts - Implements index_function_t -
Definition: functions.c:2348
bool message_is_tagged(struct Email *e)
Is a message in the index tagged (and within limit)
Definition: context.c:350
struct Envelope * env
Envelope information.
Definition: email.h:90
int LastKey
contains the last key the user pressed
Definition: keymap.c:123
Convenience wrapper for the core headers.
static int op_reply(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
reply to a message - Implements index_function_t -
Definition: functions.c:1901
int mx_tags_commit(struct Mailbox *m, struct Email *e, char *tags)
Save tags to the Mailbox - Wrapper for MxOps::tags_commit()
Definition: mx.c:1290
void alias_create(struct AddressList *al, const struct ConfigSubset *sub)
Create a new Alias from an Address.
Definition: alias.c:372
int mutt_send_message(SendFlags flags, struct Email *e_templ, const char *tempfile, struct Mailbox *m, struct EmailList *el, struct ConfigSubset *sub)
Send an email.
Definition: send.c:2125
void mx_fastclose_mailbox(struct Mailbox *m)
free up memory associated with the Mailbox
Definition: mx.c:429
static int op_search(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
search for a regular expression - Implements index_function_t -
Definition: functions.c:1998
static int op_main_tag_pattern(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
tag messages matching a pattern - Implements index_function_t -
Definition: functions.c:1594
char * group
Definition: mdata.h:34
#define mutt_thread_contains_unread(e)
Definition: mutt_thread.h:90
static int op_group_reply(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
reply to all recipients - Implements index_function_t -
Definition: functions.c:570
int mutt_display_message(struct MuttWindow *win_index, struct MuttWindow *win_ibar, struct MuttWindow *win_pager, struct MuttWindow *win_pbar, struct Mailbox *m, struct Email *e)
Display a message in the pager.
Definition: commands.c:207
void mutt_break_thread(struct Email *e)
Break the email Thread.
Definition: thread.c:233
int bool_str_toggle(struct ConfigSubset *sub, const char *name, struct Buffer *err)
Toggle the value of a bool.
Definition: bool.c:214
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:1406
enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
Ask the user a quad-question.
Definition: question.c:347
static int op_show_log_messages(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
show log (and debug) messages - Implements index_function_t -
Definition: functions.c:2030
#define SEND_LIST_REPLY
Reply to mailing list.
Definition: send.h:42
int nntp_check_children(struct Mailbox *m, const char *msgid)
Fetch children of article with the Message-ID.
Definition: nntp.c:2211
int mutt_pattern_func(struct Context *ctx, int op, char *prompt)
Perform some Pattern matching.
Definition: pattern.c:342
Email Aliases.
static int op_sidebar_open(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
open highlighted mailbox - Implements index_function_t -
Definition: functions.c:2883
MessageTransformOpt
Message transformation option.
Definition: commands.h:39
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:706
void * mdata
Driver specific data.
Definition: mailbox.h:136
static int op_post(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
followup to newsgroup - Implements index_function_t -
Definition: functions.c:2677
struct NntpAccountData * nntp_select_server(struct Mailbox *m, const char *server, bool leave_lock)
Open a connection to an NNTP server.
Definition: newsrc.c:1017
#define MUTT_ACL_WRITE
Write to a message (for flagging or linking threads)
Definition: mailbox.h:74
struct TagList tags
For drivers that support server tagging.
Definition: email.h:109
&#39;Maildir&#39; Mailbox type
Definition: mailbox.h:51
Usenet network mailbox type; talk to an NNTP server.
bool check_acl(struct Mailbox *m, AclFlags acl, const char *msg)
Check the ACLs for a function.
Definition: dlg_index.c:144
bool quasi_deleted
Deleted from neomutt, but not modified on disk.
Definition: email.h:47
#define SEND_KEY
Mail a PGP public key.
Definition: send.h:46
bool mutt_select_sort(bool reverse)
Ask the user for a sort method.
Definition: commands.c:835
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:916
struct Context * ctx
Current Mailbox view.
Definition: shared_data.h:39
enum PagerMode mode
Pager mode.
Definition: lib.h:157
off_t vsize
Size (in bytes) of the messages shown.
Definition: context.h:39
int mutt_file_sanitize_regex(struct Buffer *dest, const char *src)
Escape any regex-magic characters in a string.
Definition: file.c:637
View the message.
Definition: protos.h:55
int mutt_save_message(struct Mailbox *m, struct EmailList *el, enum MessageSaveOpt save_opt, enum MessageTransformOpt transform_opt)
Save an email.
Definition: commands.c:1144
Side panel containing Accounts or groups of data.
Definition: mutt_window.h:101
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:2858
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:2597
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:2781
Prototypes for many functions.
Edit the message.
Definition: protos.h:56
bool visible
Is this message part of the view?
Definition: email.h:74
static int op_view_attachments(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
show MIME attachments - Implements index_function_t -
Definition: functions.c:2311
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:2373
Notmuch virtual mailbox type.
#define mutt_mktemp(buf, buflen)
Definition: muttlib.h:71
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:87
WHERE bool OptAttachMsg
(pseudo) used by attach-message
Definition: options.h:31
struct AddressList * mutt_get_address(struct Envelope *env, const char **prefix)
Get an Address from an Envelope.
Definition: alias.c:332
A local copy of an email.
Definition: mxapi.h:41
#define CHECK_IN_MAILBOX
Is there a mailbox open?
Definition: lib.h:69
void dlg_select_attachment(struct ConfigSubset *sub, struct Mailbox *m, struct Email *e, FILE *fp)
Show the attachments in a Menu.
Definition: recvattach.c:1713
Create/manipulate threading in emails.
Return to the Pager.
Definition: functions.h:36
Messages to be deleted.
Definition: mutt.h:94
A mailbox.
Definition: mailbox.h:81
#define PATH_MAX
Definition: mutt.h:40
int mutt_mailbox_check(struct Mailbox *m_cur, int force)
Check all all Mailboxes for new mail.
Definition: mutt_mailbox.c:137
static int op_what_key(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
display the keycode for a key press - Implements index_function_t -
Definition: functions.c:2336
int ci_next_undeleted(struct Mailbox *m, int msgno)
Find the next undeleted email.
Definition: dlg_index.c:227
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:1343
int log_queue_save(FILE *fp)
Save the contents of the queue to a temporary file.
Definition: logging.c:369
void pop_fetch_mail(void)
Fetch messages and save them in $spool_file.
Definition: pop.c:515
static int op_create_alias(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
create an alias from a message sender - Implements index_function_t -
Definition: functions.c:163
Manage where the email is piped to external commands.
No changes.
Definition: mxapi.h:78
enum CommandResult km_bind(char *s, enum MenuType mtype, int op, char *macro, char *desc)
Bind a key to a macro.
Definition: keymap.c:455
int nm_read_entire_thread(struct Mailbox *m, struct Email *e)
Get the entire thread of an email.
Definition: notmuch.c:1497
int op
Op code, e.g. OP_MAIN_LIMIT.
Definition: functions.h:61
int mutt_do_pager(struct PagerView *pview, struct Email *e)
Display some page-able text to the user (help or attachment)
Definition: do_pager.c:120
#define CHECK_READONLY
Is the mailbox readonly?
Definition: lib.h:72
const struct Mapping * help_data
Data for the Help Bar.
Definition: mutt_window.h:142
Match patterns to emails.
Tagged messages.
Definition: mutt.h:99
char * data
Pointer to data.
Definition: buffer.h:35
int mutt_parent_message(struct Email *e, bool find_root)
Find the parent of a message.
Definition: mutt_thread.c:1320
Nntp-specific Mailbox data.
bool prereq(struct Context *ctx, struct Menu *menu, CheckFlags checks)
Check the pre-requisites for a function.
Definition: functions.c:2914
#define mutt_next_thread(e)
Definition: mutt_thread.h:101
Exit the Index.
Definition: functions.h:37
static int op_flag_message(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
toggle a message&#39;s &#39;important&#39; flag - Implements index_function_t -
Definition: functions.c:485
void nm_db_longrun_done(struct Mailbox *m)
Finish a long transaction.
Definition: db.c:329
POP network mailbox.
New messages.
Definition: mutt.h:89
Messages that have been read.
Definition: mutt.h:92
Not object-related, NotifyGlobal.
Definition: notify_type.h:45
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
API for encryption/signing of emails.
&#39;MH&#39; Mailbox type
Definition: mailbox.h:50
bool collapsed
Is this message part of a collapsed thread?
Definition: email.h:73
static int op_enter_command(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
enter a neomuttrc command - Implements index_function_t -
Definition: functions.c:432
bool verbose
Display status messages?
Definition: mailbox.h:118
Ask the user a question.
static int op_shell_escape(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
invoke a command in a subshell - Implements index_function_t -
Definition: functions.c:2016
static int op_tag(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
tag the current entry - Implements index_function_t -
Definition: functions.c:2083
int mx_tags_edit(struct Mailbox *m, const char *tags, char *buf, size_t buflen)
start the tag editor of the mailbox
Definition: mx.c:1270
static int op_main_quasi_delete(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
delete from NeoMutt, don&#39;t touch on disk - Implements index_function_t -
Definition: functions.c:1374
int msg_tagged
How many messages are tagged?
Definition: mailbox.h:97
int vnum
Virtual message number.
Definition: email.h:88
Index panel (list of emails)
Definition: type.h:50
#define SEND_NEWS
Reply to a news article.
Definition: send.h:53
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:2814
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:368
WHERE bool OptSearchInvalid
(pseudo) used to invalidate the search pattern
Definition: options.h:51
AclFlags rights
ACL bits, see AclFlags.
Definition: mailbox.h:121
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
PagerFlags flags
Additional settings to tweak pager&#39;s function.
Definition: lib.h:158
struct Notify * notify
Notifications handler.
Definition: neomutt.h:38
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
#define MUTT_PAGER_LOGS
Logview mode.
Definition: lib.h:68
#define STAILQ_NEXT(elm, field)
Definition: queue.h:400
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib...
Definition: email.h:39
#define SEND_REPLY
Reply to sender.
Definition: send.h:40
static int op_version(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
show the NeoMutt version number and date - Implements index_function_t -
Definition: functions.c:2302
NNTP-specific Mailbox data -.
Definition: mdata.h:32
enum QuadOption cs_subset_quad(const struct ConfigSubset *sub, const char *name)
Get a quad-value config item by name.
Definition: helpers.c:218
int mutt_messages_in_thread(struct Mailbox *m, struct Email *e, enum MessageInThread mit)
Count the messages in a thread.
Definition: mutt_thread.c:1615
void progress_free(struct Progress **ptr)
Free a Progress Bar.
Definition: progress.c:228
Routines for adding user scores to emails.
void progress_update(struct Progress *progress, size_t pos, int percent)
Update the state of the progress bar.
Definition: progress.c:175
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
#define MUTT_MAILBOX_CHECK_FORCE
Definition: mutt_mailbox.h:32
&#39;Notmuch&#39; (virtual) Mailbox type
Definition: mailbox.h:54
#define mutt_using_threads()
Definition: mutt_thread.h:95
char * mutt_str_cat(char *buf, size_t buflen, const char *s)
Concatenate two strings.
Definition: string.c:385
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:2262
#define CHECK_ATTACH
Is the user in message-attach mode?
Definition: lib.h:73
enum MxStatus imap_check_mailbox(struct Mailbox *m, bool force)
use the NOOP or IDLE command to poll for new mail
Definition: imap.c:1103
void ci_bounce_message(struct Mailbox *m, struct EmailList *el)
Bounce an email.
Definition: commands.c:434
A NeoMutt function.
Definition: functions.h:59
char * driver_tags_get_with_hidden(struct TagList *list)
Get tags with hiddens.
Definition: tags.c:158
#define SEND_GROUP_REPLY
Reply to all.
Definition: send.h:41
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:649
char * data
String.
Definition: list.h:36
Unknown key.
Definition: functions.h:35
int mutt_buffer_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:513
static int op_check_stats(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
calculate message statistics for all mailboxes - Implements index_function_t -
Definition: functions.c:111
int mutt_label_message(struct Mailbox *m, struct EmailList *el)
Let the user label a message.
Definition: mutt_header.c:124
Move message to another mailbox, removing the original.
Definition: commands.h:52
struct MuttWindow * win_index
Window for the Index.
Definition: private_data.h:45
Routines for managing attachments.
Log at debug level 1.
Definition: logging.h:40
IndexRetval
Possible return values for Index functions.
Definition: functions.h:33
void query_index(struct ConfigSubset *sub)
Perform an Alias Query and display the results.
Definition: dlgquery.c:737
bool flagged
Marked important?
Definition: email.h:43
void mutt_browser_select_dir(const char *f)
Remember the last directory selected.
Definition: browser.c:1234
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:749
static int op_query(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
query external program for addresses - Implements index_function_t -
Definition: functions.c:1833
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:593
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:446
bool collapsed
Are all threads collapsed?
Definition: context.h:47
Progress tracks elements, according to $write_inc
Definition: lib.h:47
bool deleted
Email is deleted.
Definition: email.h:45
void mutt_window_reflow(struct MuttWindow *win)
Resize a Window and its children.
Definition: mutt_window.c:361
struct Progress * progress_new(const char *msg, enum ProgressType type, size_t size)
Create a new Progress Bar.
Definition: progress.c:246
struct MuttWindow * parent
Parent Window.
Definition: mutt_window.h:135
struct MuttWindow * win_ibar
Window for the Index Bar (status)
Definition: private_data.h:46
char * followup_to
List of &#39;followup-to&#39; fields.
Definition: envelope.h:77
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:1745
bool in_pager
Is the Pager active?
Definition: private_data.h:41
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:746
NeoMutt is about to close.
Definition: neomutt.h:51
FILE * fp
pointer to the message data
Definition: mxapi.h:43
MessageSaveOpt
Message save option.
Definition: commands.h:49
void mutt_check_stats(struct Mailbox *m)
Forcibly update mailbox stats.
Definition: commands.c:1590
Invalid function - feature not enabled.
Definition: functions.h:38
int index
The absolute (unsorted) message number.
Definition: email.h:86
#define mutt_message(...)
Definition: logging.h:87
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:1288
#define FREE(x)
Definition: memory.h:40
#define CHECK_MSGCOUNT
Are there any messages?
Definition: lib.h:70
int index_function_dispatcher(struct MuttWindow *win_index, int op)
Perform an Index function.
Definition: functions.c:2964
#define MUTT_ACL_SEEN
Change the &#39;seen&#39; status of a message.
Definition: mailbox.h:73
void crypt_extract_keys_from_messages(struct Mailbox *m, struct EmailList *el)
Extract keys from a message.
Definition: crypt.c:858
#define STAILQ_EMPTY(head)
Definition: queue.h:348
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:324
void mutt_draw_tree(struct ThreadsContext *tctx)
Draw a tree of threaded emails.
Definition: mutt_thread.c:388
Decode message.
Definition: commands.h:43
struct NntpAccountData * CurrentNewsSrv
Current NNTP news server.
Definition: nntp.c:78
static int op_delete(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
delete the current entry - Implements index_function_t -
Definition: functions.c:178
static int op_sidebar_toggle_visible(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
make the sidebar (in)visible - Implements index_function_t -
Definition: functions.c:2896
static int op_main_limit(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
limit view to current thread - Implements index_function_t -
Definition: functions.c:894
void nm_query_window_reset(void)
Resets the vfolder window position to the present.
Definition: notmuch.c:1673
#define PGP_TRADITIONAL_CHECKED
Email has a traditional (inline) signature.
Definition: lib.h:89
#define CHECK_NO_FLAGS
No flags are set.
Definition: lib.h:68
Messages to be un-tagged.
Definition: mutt.h:100
bool changed
Mailbox has been modified.
Definition: mailbox.h:114
int mutt_change_flag(struct Mailbox *m, struct EmailList *el, bool bf)
Change the flag on a Message.
Definition: flags.c:434
void ctx_free(struct Context **ptr)
Free a Context.
Definition: context.c:49
Handling of global boolean variables.
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
bool mx_tags_is_supported(struct Mailbox *m)
return true if mailbox support tagging
Definition: mx.c:1307
int mutt_resend_message(FILE *fp, struct Mailbox *m, struct Email *e_cur, struct ConfigSubset *sub)
Resend an email.
Definition: send.c:1632
index_function_t function
Function to call.
Definition: functions.h:62
const char * fname
Name of the file to read.
Definition: lib.h:148
#define SEND_GROUP_CHAT_REPLY
Reply to all recipients preserving To/Cc.
Definition: send.h:52
struct Mailbox * mailbox
Current Mailbox.
Definition: shared_data.h:41
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:269
off_t mutt_set_vnum(struct Mailbox *m)
Set the virtual index number of all the messages in a mailbox.
Definition: mutt_thread.c:1370
bool mutt_edit_content_type(struct Email *e, struct Body *b, FILE *fp)
Edit the content type of an attachment.
Definition: commands.c:1433
int el_add_tagged(struct EmailList *el, struct Context *ctx, struct Email *e, bool use_tagged)
Get a list of the tagged Emails.
Definition: context.c:364
struct NntpMboxData * mutt_newsgroup_catchup(struct Mailbox *m, struct NntpAccountData *adata, char *group)
Catchup newsgroup.
Definition: newsrc.c:1308
struct Buffer pathbuf
Definition: mailbox.h:83
Convenience wrapper for the library headers.
bool mutt_thread_can_collapse(struct Email *e)
Check whether a thread can be collapsed.
Definition: mutt_thread.c:1772
Valid function - error occurred.
Definition: functions.h:40
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:589
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:1518
struct ListHead references
message references (in reverse order)
Definition: envelope.h:81
A List node for strings.
Definition: list.h:34
Valid function - no action performed.
Definition: functions.h:39
const char * banner
Title to display in status bar.
Definition: lib.h:159
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:577
GUI display a file/email/help in a viewport with paging.
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:1789
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
void * wdata
Private data.
Definition: mutt_window.h:145
Pager is invoked via 3rd path. Non-email content is likely to be shown.
Definition: lib.h:135
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:2422
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
char * pattern
Limit pattern string.
Definition: context.h:40
#define N_(a)
Definition: message.h:32
#define STAILQ_FIRST(head)
Definition: queue.h:350
struct MuttWindow * dialog_find(struct MuttWindow *win)
Find the parent Dialog of a Window.
Definition: dialog.c:85
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:44
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:2360
MxStatus
Return values from mbox_check(), mbox_check_stats(), mbox_snc(), and mbox_close() ...
Definition: mxapi.h:75
int mutt_ev_message(struct Mailbox *m, struct EmailList *el, enum EvMessage action)
Edit or view a message.
Definition: editmsg.c:276
Mailbox helper functions.
struct Message * mx_msg_open(struct Mailbox *m, int msgno)
return a stream pointer for a message
Definition: mx.c:1140
static int op_sort(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
sort messages - Implements index_function_t -
Definition: functions.c:2063
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:375
static int op_edit_type(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
edit attachment content type - Implements index_function_t -
Definition: functions.c:408
static int op_menu_move(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
move to the bottom of the page - Implements index_function_t -
Definition: functions.c:1691
static int op_main_next_unread_mailbox(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
open next mailbox with new mail - Implements index_function_t -
Definition: functions.c:1320
int msgno
Number displayed to the user.
Definition: email.h:87
#define mutt_previous_subthread(e)
Definition: mutt_thread.h:104
const char * mutt_make_version(void)
Generate the NeoMutt version string.
Definition: muttlib.c:1476
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:1442
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
void mutt_buffer_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:265
void dlg_select_autocrypt_account(struct Mailbox *m)
Display the Autocrypt account Menu.
Definition: dlgautocrypt.c:344
struct MuttWindow * win_pager
Window for the Pager.
Definition: private_data.h:47
int mutt_search_command(struct Mailbox *m, struct Menu *menu, int cur, int op)
Perform a search.
Definition: pattern.c:496
void nntp_mailbox(struct Mailbox *m, char *buf, size_t buflen)
Get first newsgroup with new messages.
Definition: newsrc.c:1390
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition: notify.c:171
int flags
Prerequisites for the function, e.g. CHECK_IN_MAILBOX.
Definition: functions.h:63
Data shared between Index, Pager and Sidebar.
static int op_sidebar_next(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
move the highlight to the first mailbox - Implements index_function_t -
Definition: functions.c:2871