NeoMutt  2019-12-07-168-gc45f47
Teaching an old dog new tricks
DOXYGEN
menu.c
Go to the documentation of this file.
1 
29 #include "config.h"
30 #include <regex.h>
31 #include <stdbool.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <wchar.h>
35 #include "mutt/lib.h"
36 #include "config/lib.h"
37 #include "email/lib.h"
38 #include "core/lib.h"
39 #include "gui/lib.h"
40 #include "mutt.h"
41 #include "commands.h"
42 #include "context.h"
43 #include "globals.h"
44 #include "keymap.h"
45 #include "mutt_logging.h"
46 #include "mutt_menu.h"
47 #include "muttlib.h"
48 #include "opcodes.h"
49 #include "options.h"
50 #include "pattern.h"
51 #include "protos.h"
52 #ifdef USE_SIDEBAR
53 #include "sidebar.h"
54 #endif
55 
56 /* These Config Variables are only used in menu.c */
60 
62 
63 /* These are used to track the active menus, for redraw operations. */
64 static size_t MenuStackCount = 0;
65 static size_t MenuStackLen = 0;
66 static struct Menu **MenuStack = NULL;
67 
68 #define DIRECTION ((neg * 2) + 1)
69 
70 #define MUTT_SEARCH_UP 1
71 #define MUTT_SEARCH_DOWN 2
72 
82 static int get_color(int index, unsigned char *s)
83 {
84  struct ColorLineList *color = NULL;
85  struct ColorLine *np = NULL;
86  struct Email *e = mutt_get_virt_email(Context->mailbox, index);
87  int type = *s;
88 
89  switch (type)
90  {
92  color = &Colors->index_author_list;
93  break;
95  color = &Colors->index_flags_list;
96  break;
98  color = &Colors->index_subject_list;
99  break;
100  case MT_COLOR_INDEX_TAG:
101  STAILQ_FOREACH(np, &Colors->index_tag_list, entries)
102  {
103  if (strncmp((const char *) (s + 1), np->pattern, strlen(np->pattern)) == 0)
104  return np->pair;
105  const char *transform = mutt_hash_find(TagTransforms, np->pattern);
106  if (transform &&
107  (strncmp((const char *) (s + 1), transform, strlen(transform)) == 0))
108  {
109  return np->pair;
110  }
111  }
112  return 0;
113  default:
114  return Colors->defs[type];
115  }
116 
117  STAILQ_FOREACH(np, color, entries)
118  {
121  return np->pair;
122  }
123 
124  return 0;
125 }
126 
134 static void print_enriched_string(int index, int attr, unsigned char *s, bool do_color)
135 {
136  wchar_t wc;
137  size_t k;
138  size_t n = mutt_str_strlen((char *) s);
139  mbstate_t mbstate;
140 
141  memset(&mbstate, 0, sizeof(mbstate));
142  while (*s)
143  {
144  if (*s < MUTT_TREE_MAX)
145  {
146  if (do_color)
147 #if defined(HAVE_COLOR) && defined(HAVE_USE_DEFAULT_COLORS)
148  /* Combining tree fg color and another bg color requires
149  * having use_default_colors, because the other bg color
150  * may be undefined. */
152 #else
154 #endif
155 
156  while (*s && (*s < MUTT_TREE_MAX))
157  {
158  switch (*s)
159  {
160  case MUTT_TREE_LLCORNER:
161  if (C_AsciiChars)
162  mutt_window_addch('`');
163 #ifdef WACS_LLCORNER
164  else
165  add_wch(WACS_LLCORNER);
166 #else
167  else if (CharsetIsUtf8)
168  mutt_window_addstr("\342\224\224"); /* WACS_LLCORNER */
169  else
170  mutt_window_addch(ACS_LLCORNER);
171 #endif
172  break;
173  case MUTT_TREE_ULCORNER:
174  if (C_AsciiChars)
175  mutt_window_addch(',');
176 #ifdef WACS_ULCORNER
177  else
178  add_wch(WACS_ULCORNER);
179 #else
180  else if (CharsetIsUtf8)
181  mutt_window_addstr("\342\224\214"); /* WACS_ULCORNER */
182  else
183  mutt_window_addch(ACS_ULCORNER);
184 #endif
185  break;
186  case MUTT_TREE_LTEE:
187  if (C_AsciiChars)
188  mutt_window_addch('|');
189 #ifdef WACS_LTEE
190  else
191  add_wch(WACS_LTEE);
192 #else
193  else if (CharsetIsUtf8)
194  mutt_window_addstr("\342\224\234"); /* WACS_LTEE */
195  else
196  mutt_window_addch(ACS_LTEE);
197 #endif
198  break;
199  case MUTT_TREE_HLINE:
200  if (C_AsciiChars)
201  mutt_window_addch('-');
202 #ifdef WACS_HLINE
203  else
204  add_wch(WACS_HLINE);
205 #else
206  else if (CharsetIsUtf8)
207  mutt_window_addstr("\342\224\200"); /* WACS_HLINE */
208  else
209  mutt_window_addch(ACS_HLINE);
210 #endif
211  break;
212  case MUTT_TREE_VLINE:
213  if (C_AsciiChars)
214  mutt_window_addch('|');
215 #ifdef WACS_VLINE
216  else
217  add_wch(WACS_VLINE);
218 #else
219  else if (CharsetIsUtf8)
220  mutt_window_addstr("\342\224\202"); /* WACS_VLINE */
221  else
222  mutt_window_addch(ACS_VLINE);
223 #endif
224  break;
225  case MUTT_TREE_TTEE:
226  if (C_AsciiChars)
227  mutt_window_addch('-');
228 #ifdef WACS_TTEE
229  else
230  add_wch(WACS_TTEE);
231 #else
232  else if (CharsetIsUtf8)
233  mutt_window_addstr("\342\224\254"); /* WACS_TTEE */
234  else
235  mutt_window_addch(ACS_TTEE);
236 #endif
237  break;
238  case MUTT_TREE_BTEE:
239  if (C_AsciiChars)
240  mutt_window_addch('-');
241 #ifdef WACS_BTEE
242  else
243  add_wch(WACS_BTEE);
244 #else
245  else if (CharsetIsUtf8)
246  mutt_window_addstr("\342\224\264"); /* WACS_BTEE */
247  else
248  mutt_window_addch(ACS_BTEE);
249 #endif
250  break;
251  case MUTT_TREE_SPACE:
252  mutt_window_addch(' ');
253  break;
254  case MUTT_TREE_RARROW:
255  mutt_window_addch('>');
256  break;
257  case MUTT_TREE_STAR:
258  mutt_window_addch('*'); /* fake thread indicator */
259  break;
260  case MUTT_TREE_HIDDEN:
261  mutt_window_addch('&');
262  break;
263  case MUTT_TREE_EQUALS:
264  mutt_window_addch('=');
265  break;
266  case MUTT_TREE_MISSING:
267  mutt_window_addch('?');
268  break;
269  }
270  s++;
271  n--;
272  }
273  if (do_color)
274  mutt_curses_set_attr(attr);
275  }
276  else if (*s == MUTT_SPECIAL_INDEX)
277  {
278  s++;
279  if (do_color)
280  {
281  if (*s == MT_COLOR_INDEX)
282  {
283  attrset(attr);
284  }
285  else
286  {
287  if (get_color(index, s) == 0)
288  {
289  attron(attr);
290  }
291  else
292  {
293  attron(get_color(index, s));
294  }
295  }
296  }
297  s++;
298  n -= 2;
299  }
300  else if ((k = mbrtowc(&wc, (char *) s, n, &mbstate)) > 0)
301  {
302  mutt_window_addnstr((char *) s, k);
303  s += k;
304  n -= k;
305  }
306  else
307  break;
308  }
309 }
310 
318 static void menu_make_entry(char *buf, size_t buflen, struct Menu *menu, int i)
319 {
320  if (menu->dialog)
321  {
322  mutt_str_strfcpy(buf, NONULL(menu->dialog[i]), buflen);
323  menu->current = -1; /* hide menubar */
324  }
325  else
326  menu->menu_make_entry(buf, buflen, menu, i);
327 }
328 
337 static void menu_pad_string(struct Menu *menu, char *buf, size_t buflen)
338 {
339  char *scratch = mutt_str_strdup(buf);
340  int shift = C_ArrowCursor ? 3 : 0;
341  int cols = menu->win_index->state.cols - shift;
342 
343  mutt_simple_format(buf, buflen, cols, cols, JUSTIFY_LEFT, ' ', scratch,
344  mutt_str_strlen(scratch), true);
345  buf[buflen - 1] = '\0';
346  FREE(&scratch);
347 }
348 
353 void menu_redraw_full(struct Menu *menu)
354 {
356  /* clear() doesn't optimize screen redraws */
357  mutt_window_move_abs(0, 0);
359 
360  if (C_Help)
361  {
366  }
367  menu->offset = 0;
368  menu->pagelen = menu->win_index->state.rows;
369 
370  mutt_show_error();
371 
373 #ifdef USE_SIDEBAR
374  menu->redraw |= REDRAW_SIDEBAR;
375 #endif
376 }
377 
382 void menu_redraw_status(struct Menu *menu)
383 {
384  char buf[256];
385 
386  snprintf(buf, sizeof(buf), "-- NeoMutt: %s", menu->title);
388  mutt_window_move(menu->win_ibar, 0, 0);
389  mutt_paddstr(menu->win_ibar->state.cols, buf);
391  menu->redraw &= ~REDRAW_STATUS;
392 }
393 
394 #ifdef USE_SIDEBAR
395 
399 void menu_redraw_sidebar(struct Menu *menu)
400 {
401  menu->redraw &= ~REDRAW_SIDEBAR;
402  struct MuttWindow *dlg = mutt_window_dialog(menu->win_index);
403  struct MuttWindow *sidebar = mutt_window_find(dlg, WT_SIDEBAR);
404  mutt_sb_draw(sidebar);
405 }
406 #endif
407 
412 void menu_redraw_index(struct Menu *menu)
413 {
414  char buf[1024];
415  bool do_color;
416  int attr;
417 
418  for (int i = menu->top; i < menu->top + menu->pagelen; i++)
419  {
420  if (i < menu->max)
421  {
422  attr = menu->menu_color(i);
423 
424  menu_make_entry(buf, sizeof(buf), menu, i);
425  menu_pad_string(menu, buf, sizeof(buf));
426 
427  mutt_curses_set_attr(attr);
428  mutt_window_move(menu->win_index, i - menu->top + menu->offset, 0);
429  do_color = true;
430 
431  if (i == menu->current)
432  {
434  if (C_ArrowCursor)
435  {
436  mutt_window_addstr("->");
437  mutt_curses_set_attr(attr);
438  mutt_window_addch(' ');
439  }
440  else
441  do_color = false;
442  }
443  else if (C_ArrowCursor)
444  mutt_window_addstr(" ");
445 
446  print_enriched_string(i, attr, (unsigned char *) buf, do_color);
447  }
448  else
449  {
451  mutt_window_clearline(menu->win_index, i - menu->top + menu->offset);
452  }
453  }
455  menu->redraw = 0;
456 }
457 
462 void menu_redraw_motion(struct Menu *menu)
463 {
464  char buf[1024];
465 
466  if (menu->dialog)
467  {
468  menu->redraw &= ~REDRAW_MOTION;
469  return;
470  }
471 
472  /* Note: menu->color() for the index can end up retrieving a message
473  * over imap (if matching against ~h for instance). This can
474  * generate status messages. So we want to call it *before* we
475  * position the cursor for drawing. */
476  const int old_color = menu->menu_color(menu->oldcurrent);
477  mutt_window_move(menu->win_index, menu->oldcurrent + menu->offset - menu->top, 0);
478  mutt_curses_set_attr(old_color);
479 
480  if (C_ArrowCursor)
481  {
482  /* clear the pointer */
483  mutt_window_addstr(" ");
484 
485  if (menu->redraw & REDRAW_MOTION_RESYNC)
486  {
487  menu_make_entry(buf, sizeof(buf), menu, menu->oldcurrent);
488  menu_pad_string(menu, buf, sizeof(buf));
489  mutt_window_move(menu->win_index, menu->oldcurrent + menu->offset - menu->top, 3);
490  print_enriched_string(menu->oldcurrent, old_color, (unsigned char *) buf, true);
491  }
492 
493  /* now draw it in the new location */
495  mutt_window_mvaddstr(menu->win_index, menu->current + menu->offset - menu->top, 0, "->");
496  }
497  else
498  {
499  /* erase the current indicator */
500  menu_make_entry(buf, sizeof(buf), menu, menu->oldcurrent);
501  menu_pad_string(menu, buf, sizeof(buf));
502  print_enriched_string(menu->oldcurrent, old_color, (unsigned char *) buf, true);
503 
504  /* now draw the new one to reflect the change */
505  const int cur_color = menu->menu_color(menu->current);
506  menu_make_entry(buf, sizeof(buf), menu, menu->current);
507  menu_pad_string(menu, buf, sizeof(buf));
509  mutt_window_move(menu->win_index, menu->current + menu->offset - menu->top, 0);
510  print_enriched_string(menu->current, cur_color, (unsigned char *) buf, false);
511  }
512  menu->redraw &= REDRAW_STATUS;
514 }
515 
520 void menu_redraw_current(struct Menu *menu)
521 {
522  char buf[1024];
523  int attr = menu->menu_color(menu->current);
524 
525  mutt_window_move(menu->win_index, menu->current + menu->offset - menu->top, 0);
526  menu_make_entry(buf, sizeof(buf), menu, menu->current);
527  menu_pad_string(menu, buf, sizeof(buf));
528 
530  if (C_ArrowCursor)
531  {
532  mutt_window_addstr("->");
533  mutt_curses_set_attr(attr);
534  mutt_window_addch(' ');
535  menu_pad_string(menu, buf, sizeof(buf));
536  print_enriched_string(menu->current, attr, (unsigned char *) buf, true);
537  }
538  else
539  print_enriched_string(menu->current, attr, (unsigned char *) buf, false);
540  menu->redraw &= REDRAW_STATUS;
542 }
543 
548 static void menu_redraw_prompt(struct Menu *menu)
549 {
550  if (!menu || !menu->dialog)
551  return;
552 
553  if (OptMsgErr)
554  {
555  mutt_sleep(1);
556  OptMsgErr = false;
557  }
558 
559  if (ErrorBufMessage)
561 
564 }
565 
570 void menu_check_recenter(struct Menu *menu)
571 {
572  int c = MIN(C_MenuContext, menu->pagelen / 2);
573  int old_top = menu->top;
574 
575  if (!C_MenuMoveOff && (menu->max <= menu->pagelen)) /* less entries than lines */
576  {
577  if (menu->top != 0)
578  {
579  menu->top = 0;
580  menu->redraw |= REDRAW_INDEX;
581  }
582  }
583  else
584  {
585  if (C_MenuScroll || (menu->pagelen <= 0) || (c < C_MenuContext))
586  {
587  if (menu->current < menu->top + c)
588  menu->top = menu->current - c;
589  else if (menu->current >= menu->top + menu->pagelen - c)
590  menu->top = menu->current - menu->pagelen + c + 1;
591  }
592  else
593  {
594  if (menu->current < menu->top + c)
595  {
596  menu->top -= (menu->pagelen - c) * ((menu->top + menu->pagelen - 1 - menu->current) /
597  (menu->pagelen - c)) -
598  c;
599  }
600  else if ((menu->current >= menu->top + menu->pagelen - c))
601  {
602  menu->top +=
603  (menu->pagelen - c) * ((menu->current - menu->top) / (menu->pagelen - c)) - c;
604  }
605  }
606  }
607 
608  if (!C_MenuMoveOff) /* make entries stick to bottom */
609  menu->top = MIN(menu->top, menu->max - menu->pagelen);
610  menu->top = MAX(menu->top, 0);
611 
612  if (menu->top != old_top)
613  menu->redraw |= REDRAW_INDEX;
614 }
615 
622 static void menu_jump(struct Menu *menu)
623 {
624  int n;
625 
626  if (menu->max)
627  {
629  char buf[128];
630  buf[0] = '\0';
631  if ((mutt_get_field(_("Jump to: "), buf, sizeof(buf), MUTT_COMP_NO_FLAGS) == 0) && buf[0])
632  {
633  if ((mutt_str_atoi(buf, &n) == 0) && (n > 0) && (n < menu->max + 1))
634  {
635  n--; /* msg numbers are 0-based */
636  menu->current = n;
637  menu->redraw = REDRAW_MOTION;
638  }
639  else
640  mutt_error(_("Invalid index number"));
641  }
642  }
643  else
644  mutt_error(_("No entries"));
645 }
646 
651 void menu_next_line(struct Menu *menu)
652 {
653  if (menu->max)
654  {
655  int c = MIN(C_MenuContext, menu->pagelen / 2);
656 
657  if ((menu->top + 1 < menu->max - c) &&
658  (C_MenuMoveOff ||
659  ((menu->max > menu->pagelen) && (menu->top < menu->max - menu->pagelen))))
660  {
661  menu->top++;
662  if ((menu->current < menu->top + c) && (menu->current < menu->max - 1))
663  menu->current++;
664  menu->redraw = REDRAW_INDEX;
665  }
666  else
667  mutt_message(_("You can't scroll down farther"));
668  }
669  else
670  mutt_error(_("No entries"));
671 }
672 
677 void menu_prev_line(struct Menu *menu)
678 {
679  if (menu->top > 0)
680  {
681  int c = MIN(C_MenuContext, menu->pagelen / 2);
682 
683  menu->top--;
684  if ((menu->current >= menu->top + menu->pagelen - c) && (menu->current > 1))
685  menu->current--;
686  menu->redraw = REDRAW_INDEX;
687  }
688  else
689  mutt_message(_("You can't scroll up farther"));
690 }
691 
702 static void menu_length_jump(struct Menu *menu, int jumplen)
703 {
704  const int neg = (jumplen >= 0) ? 0 : -1;
705  const int c = MIN(C_MenuContext, menu->pagelen / 2);
706 
707  if (menu->max)
708  {
709  /* possible to scroll? */
710  int tmp;
711  if (DIRECTION * menu->top <
712  (tmp = (neg ? 0 : (menu->max /* -1 */) - (menu->pagelen /* -1 */))))
713  {
714  menu->top += jumplen;
715 
716  /* jumped too long? */
717  if ((neg || !C_MenuMoveOff) && (DIRECTION * menu->top > tmp))
718  menu->top = tmp;
719 
720  /* need to move the cursor? */
721  if ((DIRECTION *
722  (tmp = (menu->current - (menu->top + (neg ? (menu->pagelen - 1) - c : c))))) < 0)
723  {
724  menu->current -= tmp;
725  }
726 
727  menu->redraw = REDRAW_INDEX;
728  }
729  else if ((menu->current != (neg ? 0 : menu->max - 1)) && !menu->dialog)
730  {
731  menu->current += jumplen;
732  menu->redraw = REDRAW_MOTION;
733  }
734  else
735  {
736  mutt_message(neg ? _("You are on the first page") : _("You are on the last page"));
737  }
738 
739  menu->current = MIN(menu->current, menu->max - 1);
740  menu->current = MAX(menu->current, 0);
741  }
742  else
743  mutt_error(_("No entries"));
744 }
745 
750 void menu_next_page(struct Menu *menu)
751 {
752  menu_length_jump(menu, MAX(menu->pagelen /* - MenuOverlap */, 0));
753 }
754 
759 void menu_prev_page(struct Menu *menu)
760 {
761  menu_length_jump(menu, 0 - MAX(menu->pagelen /* - MenuOverlap */, 0));
762 }
763 
768 void menu_half_down(struct Menu *menu)
769 {
770  menu_length_jump(menu, menu->pagelen / 2);
771 }
772 
777 void menu_half_up(struct Menu *menu)
778 {
779  menu_length_jump(menu, 0 - menu->pagelen / 2);
780 }
781 
786 void menu_top_page(struct Menu *menu)
787 {
788  if (menu->current == menu->top)
789  return;
790 
791  menu->current = menu->top;
792  menu->redraw = REDRAW_MOTION;
793 }
794 
799 void menu_bottom_page(struct Menu *menu)
800 {
801  if (menu->max)
802  {
803  menu->current = menu->top + menu->pagelen - 1;
804  if (menu->current > menu->max - 1)
805  menu->current = menu->max - 1;
806  menu->redraw = REDRAW_MOTION;
807  }
808  else
809  mutt_error(_("No entries"));
810 }
811 
816 void menu_middle_page(struct Menu *menu)
817 {
818  if (menu->max)
819  {
820  int i = menu->top + menu->pagelen;
821  if (i > menu->max - 1)
822  i = menu->max - 1;
823  menu->current = menu->top + (i - menu->top) / 2;
824  menu->redraw = REDRAW_MOTION;
825  }
826  else
827  mutt_error(_("No entries"));
828 }
829 
834 void menu_first_entry(struct Menu *menu)
835 {
836  if (menu->max)
837  {
838  menu->current = 0;
839  menu->redraw = REDRAW_MOTION;
840  }
841  else
842  mutt_error(_("No entries"));
843 }
844 
849 void menu_last_entry(struct Menu *menu)
850 {
851  if (menu->max)
852  {
853  menu->current = menu->max - 1;
854  menu->redraw = REDRAW_MOTION;
855  }
856  else
857  mutt_error(_("No entries"));
858 }
859 
864 void menu_current_top(struct Menu *menu)
865 {
866  if (menu->max)
867  {
868  menu->top = menu->current;
869  menu->redraw = REDRAW_INDEX;
870  }
871  else
872  mutt_error(_("No entries"));
873 }
874 
879 void menu_current_middle(struct Menu *menu)
880 {
881  if (menu->max)
882  {
883  menu->top = menu->current - menu->pagelen / 2;
884  if (menu->top < 0)
885  menu->top = 0;
886  menu->redraw = REDRAW_INDEX;
887  }
888  else
889  mutt_error(_("No entries"));
890 }
891 
896 void menu_current_bottom(struct Menu *menu)
897 {
898  if (menu->max)
899  {
900  menu->top = menu->current - menu->pagelen + 1;
901  if (menu->top < 0)
902  menu->top = 0;
903  menu->redraw = REDRAW_INDEX;
904  }
905  else
906  mutt_error(_("No entries"));
907 }
908 
913 static void menu_next_entry(struct Menu *menu)
914 {
915  if (menu->current < menu->max - 1)
916  {
917  menu->current++;
918  menu->redraw = REDRAW_MOTION;
919  }
920  else
921  mutt_message(_("You are on the last entry"));
922 }
923 
928 static void menu_prev_entry(struct Menu *menu)
929 {
930  if (menu->current)
931  {
932  menu->current--;
933  menu->redraw = REDRAW_MOTION;
934  }
935  else
936  mutt_message(_("You are on the first entry"));
937 }
938 
942 static int default_color(int line)
943 {
944  return Colors->defs[MT_COLOR_NORMAL];
945 }
946 
950 static int generic_search(struct Menu *menu, regex_t *rx, int line)
951 {
952  char buf[1024];
953 
954  menu_make_entry(buf, sizeof(buf), menu, line);
955  return regexec(rx, buf, 0, NULL, 0);
956 }
957 
961 void mutt_menu_init(void)
962 {
963  for (int i = 0; i < MENU_MAX; i++)
964  SearchBuffers[i] = NULL;
965 }
966 
973 {
974  struct Menu *menu = mutt_mem_calloc(1, sizeof(struct Menu));
975 
976  menu->type = type;
977  menu->current = 0;
978  menu->top = 0;
979  menu->offset = 0;
980  menu->redraw = REDRAW_FULL;
981  menu->menu_color = default_color;
982  menu->menu_search = generic_search;
983 
984  return menu;
985 }
986 
991 void mutt_menu_free(struct Menu **ptr)
992 {
993  if (!ptr || !*ptr)
994  return;
995 
996  struct Menu *m = *ptr;
997  if (m->dialog)
998  {
999  for (int i = 0; i < m->max; i++)
1000  FREE(&m->dialog[i]);
1001 
1002  FREE(&m->dialog);
1003  }
1004 
1005  FREE(ptr);
1006 }
1007 
1013 void mutt_menu_add_dialog_row(struct Menu *menu, const char *row)
1014 {
1015  if (menu->dsize <= menu->max)
1016  {
1017  menu->dsize += 10;
1018  mutt_mem_realloc(&menu->dialog, menu->dsize * sizeof(char *));
1019  }
1020  menu->dialog[menu->max++] = mutt_str_strdup(row);
1021 }
1022 
1027 static struct Menu *get_current_menu(void)
1028 {
1029  return MenuStackCount ? MenuStack[MenuStackCount - 1] : NULL;
1030 }
1031 
1038 void mutt_menu_push_current(struct Menu *menu)
1039 {
1041  {
1042  MenuStackLen += 5;
1043  mutt_mem_realloc(&MenuStack, MenuStackLen * sizeof(struct Menu *));
1044  }
1045 
1046  MenuStack[MenuStackCount++] = menu;
1047  CurrentMenu = menu->type;
1048 }
1049 
1056 void mutt_menu_pop_current(struct Menu *menu)
1057 {
1058  struct Menu *prev_menu = NULL;
1059 
1060  if (!MenuStackCount || (MenuStack[MenuStackCount - 1] != menu))
1061  {
1062  mutt_debug(LL_DEBUG1, "called with inactive menu\n");
1063  return;
1064  }
1065 
1066  MenuStackCount--;
1067  prev_menu = get_current_menu();
1068  if (prev_menu)
1069  {
1070  CurrentMenu = prev_menu->type;
1071  prev_menu->redraw = REDRAW_FULL;
1072  }
1073  else
1074  {
1076  /* Clearing when NeoMutt exits would be an annoying change in behavior for
1077  * those who have disabled alternative screens. The option is currently
1078  * set by autocrypt initialization which mixes menus and prompts outside of
1079  * the normal menu system state. */
1081  {
1082  mutt_window_move_abs(0, 0);
1084  }
1085  }
1086 }
1087 
1093 {
1094  struct Menu *current_menu = get_current_menu();
1095  if (current_menu)
1096  current_menu->redraw |= redraw;
1097 }
1098 
1103 {
1104  struct Menu *current_menu = get_current_menu();
1105  if (current_menu)
1106  current_menu->redraw = REDRAW_FULL;
1107 }
1108 
1117 {
1118  if (CurrentMenu == menu)
1120 }
1121 
1129 {
1130  if (CurrentMenu == menu)
1132 }
1133 
1138 {
1139  struct Menu *current_menu = get_current_menu();
1140  if (current_menu)
1141  {
1142  if (menu_redraw(current_menu) == OP_REDRAW)
1143  {
1144  /* On a REDRAW_FULL with a non-customized redraw, menu_redraw()
1145  * will return OP_REDRAW to give the calling menu-loop a chance to
1146  * customize output. */
1147  menu_redraw(current_menu);
1148  }
1149  }
1150 }
1151 
1159 static int menu_search(struct Menu *menu, int op)
1160 {
1161  int rc = 0, wrap = 0;
1162  int search_dir;
1163  regex_t re;
1164  char buf[128];
1165  char *search_buf = ((menu->type < MENU_MAX)) ? SearchBuffers[menu->type] : NULL;
1166 
1167  if (!(search_buf && *search_buf) || ((op != OP_SEARCH_NEXT) && (op != OP_SEARCH_OPPOSITE)))
1168  {
1169  mutt_str_strfcpy(buf, search_buf && (search_buf[0] != '\0') ? search_buf : "",
1170  sizeof(buf));
1171  if ((mutt_get_field(((op == OP_SEARCH) || (op == OP_SEARCH_NEXT)) ?
1172  _("Search for: ") :
1173  _("Reverse search for: "),
1174  buf, sizeof(buf), MUTT_CLEAR) != 0) ||
1175  !buf[0])
1176  {
1177  return -1;
1178  }
1179  if (menu->type < MENU_MAX)
1180  {
1181  mutt_str_replace(&SearchBuffers[menu->type], buf);
1182  search_buf = SearchBuffers[menu->type];
1183  }
1184  menu->search_dir =
1185  ((op == OP_SEARCH) || (op == OP_SEARCH_NEXT)) ? MUTT_SEARCH_DOWN : MUTT_SEARCH_UP;
1186  }
1187 
1188  search_dir = (menu->search_dir == MUTT_SEARCH_UP) ? -1 : 1;
1189  if (op == OP_SEARCH_OPPOSITE)
1190  search_dir = -search_dir;
1191 
1192  if (search_buf)
1193  {
1194  int flags = mutt_mb_is_lower(search_buf) ? REG_ICASE : 0;
1195  rc = REG_COMP(&re, search_buf, REG_NOSUB | flags);
1196  }
1197 
1198  if (rc != 0)
1199  {
1200  regerror(rc, &re, buf, sizeof(buf));
1201  mutt_error("%s", buf);
1202  return -1;
1203  }
1204 
1205  rc = menu->current + search_dir;
1206 search_next:
1207  if (wrap)
1208  mutt_message(_("Search wrapped to top"));
1209  while ((rc >= 0) && (rc < menu->max))
1210  {
1211  if (menu->menu_search(menu, &re, rc) == 0)
1212  {
1213  regfree(&re);
1214  return rc;
1215  }
1216 
1217  rc += search_dir;
1218  }
1219 
1220  if (C_WrapSearch && (wrap++ == 0))
1221  {
1222  rc = (search_dir == 1) ? 0 : menu->max - 1;
1223  goto search_next;
1224  }
1225  regfree(&re);
1226  mutt_error(_("Not found"));
1227  return -1;
1228 }
1229 
1235 static int menu_dialog_translate_op(int i)
1236 {
1237  switch (i)
1238  {
1239  case OP_NEXT_ENTRY:
1240  return OP_NEXT_LINE;
1241  case OP_PREV_ENTRY:
1242  return OP_PREV_LINE;
1243  case OP_CURRENT_TOP:
1244  case OP_FIRST_ENTRY:
1245  return OP_TOP_PAGE;
1246  case OP_CURRENT_BOTTOM:
1247  case OP_LAST_ENTRY:
1248  return OP_BOTTOM_PAGE;
1249  case OP_CURRENT_MIDDLE:
1250  return OP_MIDDLE_PAGE;
1251  }
1252 
1253  return i;
1254 }
1255 
1263 static int menu_dialog_dokey(struct Menu *menu, int *ip)
1264 {
1265  struct KeyEvent ch;
1266  char *p = NULL;
1267 
1268  do
1269  {
1270  ch = mutt_getch();
1271  } while (ch.ch == -2);
1272 
1273  if (ch.ch < 0)
1274  {
1275  *ip = -1;
1276  return 0;
1277  }
1278 
1279  if (ch.ch && (p = strchr(menu->keys, ch.ch)))
1280  {
1281  *ip = OP_MAX + (p - menu->keys + 1);
1282  return 0;
1283  }
1284  else
1285  {
1286  if (ch.op == OP_NULL)
1287  mutt_unget_event(ch.ch, 0);
1288  else
1289  mutt_unget_event(0, ch.op);
1290  return -1;
1291  }
1292 }
1293 
1300 int menu_redraw(struct Menu *menu)
1301 {
1302  if (menu->menu_custom_redraw)
1303  {
1304  menu->menu_custom_redraw(menu);
1305  return OP_NULL;
1306  }
1307 
1308  /* See if all or part of the screen needs to be updated. */
1309  if (menu->redraw & REDRAW_FULL)
1310  {
1311  menu_redraw_full(menu);
1312  /* allow the caller to do any local configuration */
1313  return OP_REDRAW;
1314  }
1315 
1316  if (!menu->dialog)
1317  menu_check_recenter(menu);
1318 
1319  if (menu->redraw & REDRAW_STATUS)
1320  menu_redraw_status(menu);
1321 #ifdef USE_SIDEBAR
1322  if (menu->redraw & REDRAW_SIDEBAR)
1323  menu_redraw_sidebar(menu);
1324 #endif
1325  if (menu->redraw & REDRAW_INDEX)
1326  menu_redraw_index(menu);
1327  else if (menu->redraw & (REDRAW_MOTION | REDRAW_MOTION_RESYNC))
1328  menu_redraw_motion(menu);
1329  else if (menu->redraw == REDRAW_CURRENT)
1330  menu_redraw_current(menu);
1331 
1332  if (menu->dialog)
1333  menu_redraw_prompt(menu);
1334 
1335  return OP_NULL;
1336 }
1337 
1343 int mutt_menu_loop(struct Menu *menu)
1344 {
1345  static int last_position = -1;
1346  int i = OP_NULL;
1347 
1348  if (menu->max && menu->is_mailbox_list)
1349  {
1350  if (last_position > (menu->max - 1))
1351  last_position = -1;
1352  else if (last_position >= 0)
1353  menu->current = last_position;
1354  }
1355 
1356  while (true)
1357  {
1358  if (OptMenuCaller)
1359  {
1360  OptMenuCaller = false;
1361  return OP_NULL;
1362  }
1363 
1364  /* Clear the tag prefix unless we just started it. Don't clear
1365  * the prefix on a timeout (i==-2), but do clear on an abort (i==-1) */
1366  if (menu->tagprefix && (i != OP_TAG_PREFIX) && (i != OP_TAG_PREFIX_COND) && (i != -2))
1367  menu->tagprefix = false;
1368 
1370 
1371  if (menu_redraw(menu) == OP_REDRAW)
1372  return OP_REDRAW;
1373 
1374  /* give visual indication that the next command is a tag- command */
1375  if (menu->tagprefix)
1376  {
1377  mutt_window_mvaddstr(MuttMessageWindow, 0, 0, "tag-");
1379  }
1380 
1381  menu->oldcurrent = menu->current;
1382 
1383  /* move the cursor out of the way */
1384  if (C_ArrowCursor)
1385  mutt_window_move(menu->win_index, menu->current - menu->top + menu->offset, 2);
1386  else if (C_BrailleFriendly)
1387  mutt_window_move(menu->win_index, menu->current - menu->top + menu->offset, 0);
1388  else
1389  {
1390  mutt_window_move(menu->win_index, menu->current - menu->top + menu->offset,
1391  menu->win_index->state.cols - 1);
1392  }
1393 
1394  mutt_refresh();
1395 
1396  /* try to catch dialog keys before ops */
1397  if (menu->dialog && (menu_dialog_dokey(menu, &i) == 0))
1398  return i;
1399 
1400  i = km_dokey(menu->type);
1401  if ((i == OP_TAG_PREFIX) || (i == OP_TAG_PREFIX_COND))
1402  {
1403  if (menu->tagprefix)
1404  {
1405  menu->tagprefix = false;
1407  continue;
1408  }
1409 
1410  if (menu->tagged)
1411  {
1412  menu->tagprefix = true;
1413  continue;
1414  }
1415  else if (i == OP_TAG_PREFIX)
1416  {
1417  mutt_error(_("No tagged entries"));
1418  i = -1;
1419  }
1420  else /* None tagged, OP_TAG_PREFIX_COND */
1421  {
1423  mutt_message(_("Nothing to do"));
1424  i = -1;
1425  }
1426  }
1427  else if (menu->tagged && C_AutoTag)
1428  menu->tagprefix = true;
1429 
1431 
1432  if (SigWinch)
1433  {
1434  SigWinch = 0;
1436  clearok(stdscr, true); /* force complete redraw */
1437  }
1438 
1439  if (i < 0)
1440  {
1441  if (menu->tagprefix)
1443  continue;
1444  }
1445 
1446  if (!menu->dialog)
1447  mutt_clear_error();
1448 
1449  /* Convert menubar movement to scrolling */
1450  if (menu->dialog)
1451  i = menu_dialog_translate_op(i);
1452 
1453  switch (i)
1454  {
1455  case OP_NEXT_ENTRY:
1456  menu_next_entry(menu);
1457  break;
1458  case OP_PREV_ENTRY:
1459  menu_prev_entry(menu);
1460  break;
1461  case OP_HALF_DOWN:
1462  menu_half_down(menu);
1463  break;
1464  case OP_HALF_UP:
1465  menu_half_up(menu);
1466  break;
1467  case OP_NEXT_PAGE:
1468  menu_next_page(menu);
1469  break;
1470  case OP_PREV_PAGE:
1471  menu_prev_page(menu);
1472  break;
1473  case OP_NEXT_LINE:
1474  menu_next_line(menu);
1475  break;
1476  case OP_PREV_LINE:
1477  menu_prev_line(menu);
1478  break;
1479  case OP_FIRST_ENTRY:
1480  menu_first_entry(menu);
1481  break;
1482  case OP_LAST_ENTRY:
1483  menu_last_entry(menu);
1484  break;
1485  case OP_TOP_PAGE:
1486  menu_top_page(menu);
1487  break;
1488  case OP_MIDDLE_PAGE:
1489  menu_middle_page(menu);
1490  break;
1491  case OP_BOTTOM_PAGE:
1492  menu_bottom_page(menu);
1493  break;
1494  case OP_CURRENT_TOP:
1495  menu_current_top(menu);
1496  break;
1497  case OP_CURRENT_MIDDLE:
1498  menu_current_middle(menu);
1499  break;
1500  case OP_CURRENT_BOTTOM:
1501  menu_current_bottom(menu);
1502  break;
1503  case OP_SEARCH:
1504  case OP_SEARCH_REVERSE:
1505  case OP_SEARCH_NEXT:
1506  case OP_SEARCH_OPPOSITE:
1507  if (menu->menu_search && !menu->dialog) /* Searching dialogs won't work */
1508  {
1509  menu->oldcurrent = menu->current;
1510  menu->current = menu_search(menu, i);
1511  if (menu->current != -1)
1512  menu->redraw = REDRAW_MOTION;
1513  else
1514  menu->current = menu->oldcurrent;
1515  }
1516  else
1517  mutt_error(_("Search is not implemented for this menu"));
1518  break;
1519 
1520  case OP_JUMP:
1521  if (menu->dialog)
1522  mutt_error(_("Jumping is not implemented for dialogs"));
1523  else
1524  menu_jump(menu);
1525  break;
1526 
1527  case OP_ENTER_COMMAND:
1529  break;
1530 
1531  case OP_TAG:
1532  if (menu->menu_tag && !menu->dialog)
1533  {
1534  if (menu->tagprefix && !C_AutoTag)
1535  {
1536  for (i = 0; i < menu->max; i++)
1537  menu->tagged += menu->menu_tag(menu, i, 0);
1538  menu->redraw |= REDRAW_INDEX;
1539  }
1540  else if (menu->max)
1541  {
1542  int j = menu->menu_tag(menu, menu->current, -1);
1543  menu->tagged += j;
1544  if (j && C_Resolve && (menu->current < menu->max - 1))
1545  {
1546  menu->current++;
1547  menu->redraw |= REDRAW_MOTION_RESYNC;
1548  }
1549  else
1550  menu->redraw |= REDRAW_CURRENT;
1551  }
1552  else
1553  mutt_error(_("No entries"));
1554  }
1555  else
1556  mutt_error(_("Tagging is not supported"));
1557  break;
1558 
1559  case OP_SHELL_ESCAPE:
1561  break;
1562 
1563  case OP_WHAT_KEY:
1564  mutt_what_key();
1565  break;
1566 
1567  case OP_CHECK_STATS:
1568  mutt_check_stats();
1569  break;
1570 
1571  case OP_REDRAW:
1572  clearok(stdscr, true);
1573  menu->redraw = REDRAW_FULL;
1574  break;
1575 
1576  case OP_HELP:
1577  mutt_help(menu->type, menu->win_index->state.cols);
1578  menu->redraw = REDRAW_FULL;
1579  break;
1580 
1581  case OP_NULL:
1582  km_error_key(menu->type);
1583  break;
1584 
1585  case OP_END_COND:
1586  break;
1587 
1588  default:
1589  if (menu->is_mailbox_list)
1590  last_position = menu->current;
1591  return i;
1592  }
1593  }
1594  /* not reached */
1595 }
1596 
1601 {
1602  if (!nc->event_data)
1603  return -1;
1604  if (nc->event_type != NT_CONFIG)
1605  return 0;
1606 
1607  int s = nc->event_subtype;
1608 
1609  bool simple = (s == MT_COLOR_INDEX_COLLAPSED) || (s == MT_COLOR_INDEX_DATE) ||
1610  (s == MT_COLOR_INDEX_LABEL) || (s == MT_COLOR_INDEX_NUMBER) ||
1611  (s == MT_COLOR_INDEX_SIZE) || (s == MT_COLOR_INDEX_TAGS);
1612  bool lists = (s == MT_COLOR_ATTACH_HEADERS) || (s == MT_COLOR_BODY) ||
1613  (s == MT_COLOR_HEADER) || (s == MT_COLOR_INDEX) ||
1614  (s == MT_COLOR_INDEX_AUTHOR) || (s == MT_COLOR_INDEX_FLAGS) ||
1615  (s == MT_COLOR_INDEX_SUBJECT) || (s == MT_COLOR_INDEX_TAG);
1616 
1617  // The changes aren't relevant to the index menu
1618  if (!simple && !lists)
1619  return 0;
1620 
1621  struct EventColor *ec = nc->event_data;
1622 
1623  // Colour deleted from a list
1624  if (!ec->set && lists && Context && Context->mailbox)
1625  {
1626  struct Mailbox *m = Context->mailbox;
1627  // Force re-caching of index colors
1628  for (int i = 0; i < m->msg_count; i++)
1629  {
1630  struct Email *e = m->emails[i];
1631  if (!e)
1632  break;
1633  e->pair = 0;
1634  }
1635  }
1636 
1638  return 0;
1639 }
1640 
1645 {
1646  if (!nc->event_data)
1647  return -1;
1648  if (nc->event_type != NT_CONFIG)
1649  return 0;
1650 
1651  struct EventConfig *ec = nc->event_data;
1652 
1653  const struct ConfigDef *cdef = ec->he->data;
1654  ConfigRedrawFlags flags = cdef->type & R_REDRAW_MASK;
1655 
1656  if (flags == R_REDRAW_NO_FLAGS)
1657  return 0;
1658 
1659  if (flags & R_INDEX)
1661  if (flags & R_PAGER)
1663  if (flags & R_PAGER_FLOW)
1664  {
1667  }
1668 
1669  if (flags & R_RESORT_SUB)
1670  OptSortSubthreads = true;
1671  if (flags & R_RESORT)
1672  OptNeedResort = true;
1673  if (flags & R_RESORT_INIT)
1674  OptResortInit = true;
1675  if (flags & R_TREE)
1676  OptRedrawTree = true;
1677 
1678  if (flags & R_REFLOW)
1679  mutt_window_reflow(NULL);
1680 #ifdef USE_SIDEBAR
1681  if (flags & R_SIDEBAR)
1683 #endif
1684  if (flags & R_MENU)
1686 
1687  return 0;
1688 }
int km_dokey(enum MenuType menu)
Determine what a keypress should do.
Definition: keymap.c:617
struct Email ** emails
Array of Emails.
Definition: mailbox.h:98
Convenience wrapper for the gui headers.
struct ColorLineList index_tag_list
List of colours applied to tags in the index.
Definition: color.h:141
MIME attachment test (takes a pattern)
Definition: color.h:63
The "current" mailbox.
Definition: context.h:36
void mutt_window_move_abs(int row, int col)
Move the cursor to an absolute screen position.
Definition: mutt_window.c:445
#define R_PAGER
Redraw the pager menu.
Definition: types.h:64
Index: index number.
Definition: color.h:110
#define REDRAW_FULL
Redraw everything.
Definition: mutt_menu.h:47
Manage keymappings.
#define NONULL(x)
Definition: string2.h:37
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
int msg_count
Total number of messages.
Definition: mailbox.h:90
Lower left corner.
Definition: mutt_menu.h:61
int mutt_str_atoi(const char *str, int *dst)
Convert ASCII string to an integer.
Definition: string.c:262
Left justify the text.
Definition: curs_lib.h:47
The envelope/body of an email.
Definition: email.h:37
#define MUTT_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:68
Index: tags field (g, J)
Definition: color.h:112
struct Email * mutt_get_virt_email(struct Mailbox *m, int vnum)
Get a virtual Email.
Definition: context.c:414
#define MIN(a, b)
Definition: memory.h:31
GUI selectable list of items.
Definition: mutt_menu.h:82
Data passed to a notification function.
Definition: observer.h:40
#define R_PAGER_FLOW
Reflow line_info and redraw the pager menu.
Definition: types.h:65
Structs that make up an email.
An Event that happened to an Colour.
Definition: color.h:159
The "currently-open" mailbox.
struct Hash * TagTransforms
Lookup table of alternative tag names.
Definition: tags.c:38
MenuType
Types of GUI selections.
Definition: keymap.h:69
#define mutt_message(...)
Definition: logging.h:83
Pager: highlight body of message (takes a pattern)
Definition: color.h:64
int oldcurrent
For driver use only.
Definition: mutt_menu.h:109
void mutt_curses_set_color(enum ColorId color)
Set the current colour for text.
Definition: mutt_curses.c:55
WHERE bool OptMenuCaller
(pseudo) tell menu to give caller a take
Definition: options.h:38
#define REDRAW_FLOW
Used by pager to reflow text.
Definition: mutt_menu.h:49
int * defs
Array of all fixed colours, see enum ColorId.
Definition: color.h:132
char * prompt
Prompt for user, similar to mutt_multi_choice.
Definition: mutt_menu.h:104
struct MuttWindow * mutt_window_find(struct MuttWindow *root, enum WindowType type)
Find a Window of a given type.
Definition: mutt_window.c:575
void mutt_window_clrtoeol(struct MuttWindow *win)
Clear to the end of the line.
Definition: mutt_window.c:135
struct PatternList * color_pattern
Compiled pattern to speed up index color calculation.
Definition: color.h:41
void mutt_resize_screen(void)
Update NeoMutt&#39;s opinion about the window size (CURSES)
Definition: resize.c:100
NeoMutt Logging.
WHERE bool C_Help
Config: Display a help line with common key bindings.
Definition: globals.h:220
WHERE bool OptNeedResort
(pseudo) used to force a re-sort
Definition: options.h:42
struct ColorLineList index_flags_list
List of colours applied to the flags in the index.
Definition: color.h:138
void mutt_check_stats(void)
Forcibly update mailbox stats.
Definition: commands.c:1392
void * mutt_hash_find(const struct Hash *table, const char *strkey)
Find the HashElem data in a Hash table element using a key.
Definition: hash.c:378
char ** dialog
Dialog lines themselves.
Definition: mutt_menu.h:102
WHERE enum MenuType CurrentMenu
Current Menu, e.g. MENU_PAGER.
Definition: globals.h:82
A config-change event.
Definition: subset.h:68
char * pattern
Pattern to match.
Definition: color.h:40
int pair
Colour pair index.
Definition: color.h:44
void mutt_enter_command(void)
enter a neomutt command
Definition: commands.c:860
struct ColorLineList index_subject_list
List of colours applied to the subject in the index.
Definition: color.h:140
void mutt_unget_event(int ch, int op)
Return a keystroke to the input buffer.
Definition: curs_lib.c:807
#define _(a)
Definition: message.h:28
WHERE bool C_WrapSearch
Config: Wrap around when the search hits the end.
Definition: globals.h:261
WHERE bool C_BrailleFriendly
Config: Move the cursor to the beginning of the line.
Definition: globals.h:205
struct MuttWindow * MuttHelpWindow
Help Window.
Definition: mutt_window.c:46
int op
function op
Definition: keymap.h:63
int ch
raw key pressed
Definition: keymap.h:62
A division of the screen.
Definition: mutt_window.h:86
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:689
Index panel (list of emails)
Definition: keymap.h:77
Config item definition.
Definition: set.h:134
Index: number of messages in collapsed thread.
Definition: color.h:107
All user-callable functions.
#define R_RESORT
Resort the mailbox.
Definition: types.h:66
void(* menu_make_entry)(char *buf, size_t buflen, struct Menu *menu, int line)
Format a item for a menu.
Definition: mutt_menu.h:120
#define mutt_get_field(field, buf, buflen, complete)
Definition: curs_lib.h:90
#define REDRAW_SIDEBAR
Redraw the sidebar.
Definition: mutt_menu.h:51
Convenience wrapper for the config headers.
void mutt_paddstr(int n, const char *s)
Display a string on screen, padded if necessary.
Definition: curs_lib.c:1239
Hundreds of global variables to back the user variables.
Right arrow.
Definition: mutt_menu.h:67
Bottom T-piece.
Definition: mutt_menu.h:72
int event_subtype
Send: Event subtype, e.g. NT_ACCOUNT_ADD.
Definition: observer.h:43
#define R_TREE
Redraw the thread tree.
Definition: types.h:69
enum NotifyType event_type
Send: Event type, e.g. NT_ACCOUNT.
Definition: observer.h:42
Some miscellaneous functions.
#define MAX(a, b)
Definition: memory.h:30
Pager pager (email viewer)
Definition: keymap.h:78
Index: author field (takes a pattern)
Definition: color.h:102
int mutt_window_addnstr(const char *str, int num)
Write a partial string to a Window.
Definition: mutt_window.c:410
Blank space.
Definition: mutt_menu.h:66
#define R_REDRAW_NO_FLAGS
No refresh/resort flags.
Definition: types.h:62
bool set
True if a colour has been set/added, false if reset/deleted.
Definition: color.h:161
Vertical line.
Definition: mutt_menu.h:65
void mutt_sleep(short s)
Sleep for a while.
Definition: muttlib.c:1544
struct HashElem * he
Config item that changed.
Definition: subset.h:72
void mutt_curses_set_cursor(enum MuttCursorState state)
Set the cursor state.
Definition: mutt_curses.c:76
enum MenuType type
Menu definition for keymap entries.
Definition: mutt_menu.h:90
struct Mailbox * mailbox
Definition: context.h:50
Many unsorted constants and some structs.
Top T-piece.
Definition: mutt_menu.h:71
Message headers (takes a pattern)
Definition: color.h:73
void mutt_flush_macro_to_endcond(void)
Drop a macro from the input buffer.
Definition: curs_lib.c:863
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:62
struct MuttWindow * win_ibar
Definition: mutt_menu.h:96
void mutt_window_clearline(struct MuttWindow *win, int row)
Clear a row of a Window.
Definition: mutt_window.c:113
WHERE bool OptMenuPopClearScreen
(pseudo) clear the screen when popping the last menu
Definition: options.h:39
void mutt_what_key(void)
Ask the user to press a key.
Definition: keymap.c:1578
Display a normal cursor.
Definition: mutt_curses.h:82
int LastKey
contains the last key the user pressed
Definition: keymap.c:145
Index: tag field (g, takes a pattern)
Definition: color.h:105
Convenience wrapper for the core headers.
#define REG_COMP(preg, regex, cflags)
Compile a regular expression.
Definition: regex3.h:52
Star character (for threads)
Definition: mutt_menu.h:68
Equals (for threads)
Definition: mutt_menu.h:70
void mutt_shell_escape(void)
invoke a command in a subshell
Definition: commands.c:832
Index: tree-drawing characters.
Definition: color.h:97
WHERE SIG_ATOMIC_VOLATILE_T SigWinch
true after SIGWINCH is received
Definition: globals.h:80
void(* menu_custom_redraw)(struct Menu *menu)
Redraw the menu.
Definition: mutt_menu.h:149
void mutt_window_clrtobot(void)
Clear to the bottom of the Window.
Definition: mutt_window.c:124
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:113
Ampersand character (for threads)
Definition: mutt_menu.h:69
#define REDRAW_MOTION
Redraw after moving the menu list.
Definition: mutt_menu.h:43
Plain text.
Definition: color.h:78
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
#define R_MENU
Redraw all menus.
Definition: types.h:72
#define REDRAW_MOTION_RESYNC
Redraw any changing the menu selection.
Definition: mutt_menu.h:44
short cols
Number of columns, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:56
int mutt_pattern_exec(struct Pattern *pat, PatternExecFlags flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
Match a pattern against an email header.
Definition: pattern.c:2124
#define R_RESORT_SUB
Resort subthreads.
Definition: types.h:67
void mutt_refresh(void)
Force a refresh of the screen.
Definition: curs_lib.c:106
Side panel containing Accounts or groups of data.
Definition: mutt_window.h:76
Index: date field.
Definition: color.h:108
Prototypes for many functions.
#define R_REFLOW
Reflow window layout and full redraw.
Definition: types.h:70
const char * line
Definition: common.c:36
struct WindowState state
Current state of the Window.
Definition: mutt_window.h:91
Question mark.
Definition: mutt_menu.h:73
#define REDRAW_STATUS
Redraw the status bar.
Definition: mutt_menu.h:46
#define SLIST_FIRST(head)
Definition: queue.h:228
Index: size field.
Definition: color.h:111
void km_error_key(enum MenuType menu)
Handle an unbound key sequence.
Definition: keymap.c:1052
Status bar (takes a pattern)
Definition: color.h:95
A mailbox.
Definition: mailbox.h:80
short rows
Number of rows, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:55
int top
Entry that is the top of the current page.
Definition: mutt_menu.h:108
bool tagprefix
Definition: mutt_menu.h:93
Manage where the email is piped to external commands.
WHERE bool C_Resolve
Config: Move to the next email whenever a command modifies an email.
Definition: globals.h:246
struct ColorLineList index_author_list
List of colours applied to the author in the index.
Definition: color.h:137
WHERE bool C_AsciiChars
Config: Use plain ASCII characters, when drawing email threads.
Definition: globals.h:194
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:773
bool is_mailbox_list
Definition: mutt_menu.h:94
WHERE bool ErrorBufMessage
true if the last message was an error
Definition: globals.h:44
Selected item in list.
Definition: color.h:74
GUI present the user with a selectable list.
int mutt_color_combine(struct Colors *c, uint32_t fg_attr, uint32_t bg_attr)
uint32_t ConfigRedrawFlags
Flags for redraw/resort, e.g. R_INDEX.
Definition: types.h:61
int search_dir
Direction of search.
Definition: mutt_menu.h:110
An event such as a keypress.
Definition: keymap.h:60
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
struct KeyEvent mutt_getch(void)
Read a character from the input buffer.
Definition: curs_lib.c:187
int pagelen
Number of entries per screen.
Definition: mutt_menu.h:92
char * keys
Keys used in the prompt.
Definition: mutt_menu.h:105
WHERE bool OptRedrawTree
(pseudo) redraw the thread tree
Definition: options.h:49
Definition: color.h:130
WHERE bool OptResortInit
(pseudo) used to force the next resort to be from scratch
Definition: options.h:50
#define MUTT_MATCH_FULL_ADDRESS
Match the full address.
Definition: pattern.h:77
void mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:453
int mutt_window_mvaddstr(struct MuttWindow *win, int row, int col, const char *str)
Move the cursor and write a fixed string to a Window.
Definition: mutt_window.c:293
int tagged
Number of tagged entries.
Definition: mutt_menu.h:111
int mutt_window_move(struct MuttWindow *win, int row, int col)
Move the cursor in a Window.
Definition: mutt_window.c:279
int(* menu_color)(int line)
Calculate the colour for a line of the menu.
Definition: mutt_menu.h:144
void * event_data
Data from notify_send()
Definition: observer.h:44
int max
Number of entries in the menu.
Definition: mutt_menu.h:88
int(* menu_tag)(struct Menu *menu, int sel, int act)
Tag some menu items.
Definition: mutt_menu.h:137
struct MuttWindow * mutt_window_dialog(struct MuttWindow *win)
Find the parent Dialog of a Window.
Definition: mutt_window.c:558
MuttRedrawFlags redraw
When to redraw the screen.
Definition: mutt_menu.h:89
int(* menu_search)(struct Menu *menu, regex_t *rx, int line)
Search a menu for a item matching a regex.
Definition: mutt_menu.h:129
Config has changed.
Definition: notify_type.h:34
void * data
Definition: hash.h:46
char * title
Title of this menu.
Definition: mutt_menu.h:84
Colour indicator.
Definition: mutt_menu.h:76
int mutt_window_addch(int ch)
Write one character to a Window.
Definition: mutt_window.c:398
Index: label field.
Definition: color.h:109
unsigned int type
Variable type, e.g. DT_STRING.
Definition: set.h:137
int offset
Row offset within the window to start the index.
Definition: mutt_menu.h:91
bool CharsetIsUtf8
Is the user&#39;s current character set utf-8?
Definition: charset.c:64
Index: subject field (takes a pattern)
Definition: color.h:104
Log at debug level 1.
Definition: logging.h:40
#define REDRAW_INDEX
Redraw the index.
Definition: mutt_menu.h:42
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
void mutt_help(enum MenuType menu, int wraplen)
Display the help menu.
Definition: help.c:444
void mutt_window_reflow(struct MuttWindow *win)
Resize a Window and its children.
Definition: mutt_window.c:346
#define mutt_error(...)
Definition: logging.h:84
int index
The absolute (unsorted) message number.
Definition: email.h:85
#define FREE(x)
Definition: memory.h:40
WHERE bool OptMsgErr
(pseudo) used by mutt_error/mutt_message
Definition: options.h:40
int dsize
Number of allocated dialog lines.
Definition: mutt_menu.h:103
Hide the cursor.
Definition: mutt_curses.h:81
WHERE bool C_AutoTag
Config: Automatically apply actions to all tagged messages.
Definition: globals.h:202
#define R_RESORT_INIT
Resort from scratch.
Definition: types.h:68
WHERE bool OptSortSubthreads
(pseudo) used when $sort_aux changes
Definition: options.h:53
void mutt_show_error(void)
Show the user an error message.
Definition: curs_lib.c:531
struct MuttWindow * MuttMessageWindow
Message Window.
Definition: mutt_window.c:47
int mutt_window_addstr(const char *str)
Write a string to a Window.
Definition: mutt_window.c:428
#define R_SIDEBAR
Redraw the sidebar.
Definition: types.h:71
Handling of global boolean variables.
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
Index: default colour (takes a pattern)
Definition: color.h:101
int current
Current entry.
Definition: mutt_menu.h:87
struct MuttWindow * win_index
Definition: mutt_menu.h:95
Convenience wrapper for the library headers.
void mutt_curses_set_attr(int attr)
Set the attributes for text.
Definition: mutt_curses.c:40
Match patterns to emails.
bool mutt_mb_is_lower(const char *s)
Does a multi-byte string contain only lowercase characters?
Definition: mbyte.c:358
Left T-piece.
Definition: mutt_menu.h:63
char * help
Quickref for the current menu.
Definition: mutt_menu.h:85
int pair
Color-pair to use when displaying in the index.
Definition: email.h:79
#define REDRAW_CURRENT
Redraw the current line of the menu.
Definition: mutt_menu.h:45
Index: flags field (takes a pattern)
Definition: color.h:103
A regular expression and a color to highlight a line.
Definition: color.h:36
#define R_REDRAW_MASK
Mask for the Redraw Flags.
Definition: types.h:74
void mutt_simple_format(char *buf, size_t buflen, int min_width, int max_width, enum FormatJustify justify, char pad_char, const char *s, size_t n, bool arboreal)
Format a string, like snprintf()
Definition: curs_lib.c:1066
#define R_INDEX
Redraw the index menu (MENU_MAIN)
Definition: types.h:63
Upper left corner.
Definition: mutt_menu.h:62
WHERE bool C_ArrowCursor
Config: Use an arrow &#39;->&#39; instead of highlighting in the index.
Definition: globals.h:193
uint16_t MuttRedrawFlags
Flags, e.g. REDRAW_INDEX.
Definition: mutt_menu.h:40
Horizontal line.
Definition: mutt_menu.h:64