NeoMutt  2021-02-05-666-ge300cd
Teaching an old dog new tricks
DOXYGEN
curs_lib.c
Go to the documentation of this file.
1 
30 #include "config.h"
31 #include <errno.h>
32 #include <fcntl.h>
33 #include <limits.h>
34 #include <stdbool.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <termios.h>
39 #include <unistd.h>
40 #include <wchar.h>
41 #include "mutt/lib.h"
42 #include "config/lib.h"
43 #include "core/lib.h"
44 #include "mutt.h"
45 #include "curs_lib.h"
46 #include "menu/lib.h"
47 #include "question/lib.h"
48 #include "browser.h"
49 #include "color.h"
50 #include "enter_state.h"
51 #include "keymap.h"
52 #include "msgwin.h"
53 #include "mutt_curses.h"
54 #include "mutt_globals.h"
55 #include "mutt_logging.h"
56 #include "mutt_thread.h"
57 #include "mutt_window.h"
58 #include "opcodes.h"
59 #include "options.h"
60 #include "protos.h"
61 #ifdef HAVE_ISWBLANK
62 #include <wctype.h>
63 #endif
64 #ifdef USE_INOTIFY
65 #include "monitor.h"
66 #endif
67 
68 /* not possible to unget more than one char under some curses libs, and it
69  * is impossible to unget function keys in SLang, so roll our own input
70  * buffering routines. */
71 
72 /* These are used for macros and exec/push commands.
73  * They can be temporarily ignored by setting OptIgnoreMacroEvents */
74 static size_t MacroBufferCount = 0;
75 static size_t MacroBufferLen = 0;
76 static struct KeyEvent *MacroEvents;
77 
78 /* These are used in all other "normal" situations, and are not
79  * ignored when setting OptIgnoreMacroEvents */
80 static size_t UngetCount = 0;
81 static size_t UngetLen = 0;
82 static struct KeyEvent *UngetKeyEvents;
83 
85 
87 static const struct Mapping EditorHelp[] = {
88  // clang-format off
89  { N_("Complete"), OP_EDITOR_COMPLETE },
90  { N_("Hist Up"), OP_EDITOR_HISTORY_UP },
91  { N_("Hist Down"), OP_EDITOR_HISTORY_DOWN },
92  { N_("Hist Search"), OP_EDITOR_HISTORY_SEARCH },
93  { N_("Begin Line"), OP_EDITOR_BOL },
94  { N_("End Line"), OP_EDITOR_EOL },
95  { N_("Kill Line"), OP_EDITOR_KILL_LINE },
96  { N_("Kill Word"), OP_EDITOR_KILL_WORD },
97  { NULL, 0 },
98  // clang-format off
99 };
100 
105 void mutt_beep(bool force)
106 {
107  const bool c_beep = cs_subset_bool(NeoMutt->sub, "beep");
108  if (force || c_beep)
109  beep();
110 }
111 
115 void mutt_refresh(void)
116 {
117  /* don't refresh when we are waiting for a child. */
118  if (OptKeepQuiet)
119  return;
120 
121  /* don't refresh in the middle of macros unless necessary */
123  return;
124 
125  /* else */
126  refresh();
127 }
128 
138 {
139  keypad(stdscr, true);
140  clearok(stdscr, true);
141  window_redraw(NULL);
142 }
143 
153 void mutt_getch_timeout(int delay)
154 {
155  MuttGetchTimeout = delay;
156  timeout(delay);
157 }
158 
159 #ifdef USE_INOTIFY
160 
165 static int mutt_monitor_getch(void)
166 {
167  /* ncurses has its own internal buffer, so before we perform a poll,
168  * we need to make sure there isn't a character waiting */
169  timeout(0);
170  int ch = getch();
171  timeout(MuttGetchTimeout);
172  if (ch == ERR)
173  {
174  if (mutt_monitor_poll() != 0)
175  ch = ERR;
176  else
177  ch = getch();
178  }
179  return ch;
180 }
181 #endif /* USE_INOTIFY */
182 
196 struct KeyEvent mutt_getch(void)
197 {
198  int ch;
199  struct KeyEvent err = { -1, OP_NULL }, ret;
200  struct KeyEvent timeout = { -2, OP_NULL };
201 
202  if (UngetCount)
203  return UngetKeyEvents[--UngetCount];
204 
206  return MacroEvents[--MacroBufferCount];
207 
208  SigInt = false;
209 
211 #ifdef KEY_RESIZE
212  /* ncurses 4.2 sends this when the screen is resized */
213  ch = KEY_RESIZE;
214  while (ch == KEY_RESIZE)
215 #endif
216 #ifdef USE_INOTIFY
217  ch = mutt_monitor_getch();
218 #else
219  ch = getch();
220 #endif
222 
223  if (SigInt)
224  {
225  mutt_query_exit();
226  return err;
227  }
228 
229  /* either timeout, a sigwinch (if timeout is set), or the terminal
230  * has been lost */
231  if (ch == ERR)
232  {
233  if (!isatty(0))
234  mutt_exit(1);
235 
236  return timeout;
237  }
238 
239  const bool c_meta_key = cs_subset_bool(NeoMutt->sub, "meta_key");
240  if ((ch & 0x80) && c_meta_key)
241  {
242  /* send ALT-x as ESC-x */
243  ch &= ~0x80;
244  mutt_unget_event(ch, 0);
245  ret.ch = '\033'; // Escape
246  ret.op = 0;
247  return ret;
248  }
249 
250  ret.ch = ch;
251  ret.op = 0;
252  return (ch == AbortKey) ? err : ret;
253 }
254 
268 int mutt_buffer_get_field(const char *field, struct Buffer *buf, CompletionFlags complete,
269  bool multiple, struct Mailbox *m, char ***files, int *numfiles)
270 {
271  struct MuttWindow *win = msgwin_get_window();
272  if (!win)
273  return -1;
274 
275  int ret;
276  int col;
277 
278  struct EnterState *es = mutt_enter_state_new();
279 
280  const struct Mapping *old_help = win->help_data;
281  int old_menu = win->help_menu;
282 
283  win->help_data = EditorHelp;
284  win->help_menu = MENU_EDITOR;
285  struct MuttWindow *old_focus = window_set_focus(win);
286 
287  window_redraw(NULL);
288  do
289  {
290  if (SigWinch)
291  {
292  SigWinch = false;
294  clearok(stdscr, true);
295  window_redraw(NULL);
296  }
297  mutt_window_clearline(win, 0);
299  mutt_window_addstr(win, field);
301  mutt_refresh();
302  mutt_window_get_coords(win, &col, NULL);
303  ret = mutt_enter_string_full(buf->data, buf->dsize, col, complete, multiple,
304  m, files, numfiles, es);
305  } while (ret == 1);
306 
307  win->help_data = old_help;
308  win->help_menu = old_menu;
309  window_set_focus(old_focus);
310 
311  if (ret == 0)
313  else
314  mutt_buffer_reset(buf);
315 
316  mutt_window_clearline(win, 0);
318 
319  return ret;
320 }
321 
335 int mutt_get_field(const char *field, char *buf, size_t buflen,
336  CompletionFlags complete, bool multiple, char ***files, int *numfiles)
337 {
338  if (!buf)
339  return -1;
340 
341  struct Buffer tmp = {
342  .data = buf,
343  .dptr = buf + mutt_str_len(buf),
344  .dsize = buflen,
345  };
346  return mutt_buffer_get_field(field, &tmp, complete, multiple, NULL, files, numfiles);
347 }
348 
359 int mutt_get_field_unbuffered(const char *msg, char *buf, size_t buflen, CompletionFlags flags)
360 {
361  bool reset_ignoremacro = false;
362 
364  {
365  OptIgnoreMacroEvents = true;
366  reset_ignoremacro = true;
367  }
368  int rc = mutt_get_field(msg, buf, buflen, flags, false, NULL, NULL);
369  if (reset_ignoremacro)
370  OptIgnoreMacroEvents = false;
371 
372  return rc;
373 }
374 
380 void mutt_edit_file(const char *editor, const char *file)
381 {
382  struct Buffer *cmd = mutt_buffer_pool_get();
383 
384  mutt_endwin();
385  mutt_buffer_file_expand_fmt_quote(cmd, editor, file);
386  if (mutt_system(mutt_buffer_string(cmd)) != 0)
387  {
388  mutt_error(_("Error running \"%s\""), mutt_buffer_string(cmd));
389  }
390  /* the terminal may have been resized while the editor owned it */
392  keypad(stdscr, true);
393  clearok(stdscr, true);
394 
396 }
397 
403 void mutt_query_exit(void)
404 {
405  mutt_flushinp();
407  const short c_timeout = cs_subset_number(NeoMutt->sub, "timeout");
408  if (c_timeout)
409  mutt_getch_timeout(-1); /* restore blocking operation */
410  if (mutt_yesorno(_("Exit NeoMutt?"), MUTT_YES) == MUTT_YES)
411  {
412  mutt_exit(1);
413  }
416  SigInt = false;
417 }
418 
422 void mutt_endwin(void)
423 {
424  if (OptNoCurses)
425  return;
426 
427  int e = errno;
428 
429  /* at least in some situations (screen + xterm under SuSE11/12) endwin()
430  * doesn't properly flush the screen without an explicit call. */
431  mutt_refresh();
432  endwin();
433 
434  errno = e;
435 }
436 
441 void mutt_perror_debug(const char *s)
442 {
443  char *p = strerror(errno);
444 
445  mutt_debug(LL_DEBUG1, "%s: %s (errno = %d)\n", s, p ? p : "unknown error", errno);
446  mutt_error("%s: %s (errno = %d)", s, p ? p : _("unknown error"), errno);
447 }
448 
455 int mutt_any_key_to_continue(const char *s)
456 {
457  struct termios term;
458  struct termios old;
459 
460  int fd = open("/dev/tty", O_RDONLY);
461  if (fd < 0)
462  return EOF;
463 
464  tcgetattr(fd, &old); // Save the current tty settings
465 
466  term = old;
467  term.c_lflag &= ~(ICANON | ECHO); // Canonical (not line-buffered), don't echo the characters
468  term.c_cc[VMIN] = 1; // Wait for at least one character
469  term.c_cc[VTIME] = 255; // Wait for 25.5s
470  tcsetattr(fd, TCSANOW, &term);
471 
472  if (s)
473  fputs(s, stdout);
474  else
475  fputs(_("Press any key to continue..."), stdout);
476  fflush(stdout);
477 
478  char ch = '\0';
479  // Wait for a character. This might timeout, so loop.
480  while (read(fd, &ch, 1) == 0)
481  ; // do nothing
482 
483  // Change the tty settings to be non-blocking
484  term.c_cc[VMIN] = 0; // Returning with zero characters is acceptable
485  term.c_cc[VTIME] = 0; // Don't wait
486  tcsetattr(fd, TCSANOW, &term);
487 
488  char buf[64];
489  while (read(fd, buf, sizeof(buf)) > 0)
490  ; // Mop up any remaining chars
491 
492  tcsetattr(fd, TCSANOW, &old); // Restore the previous tty settings
493  close(fd);
494 
495  fputs("\r\n", stdout);
497  return (ch >= 0) ? ch : EOF;
498 }
499 
513 int mutt_buffer_enter_fname(const char *prompt, struct Buffer *fname,
514  bool mailbox, struct Mailbox *m, bool multiple,
515  char ***files, int *numfiles, SelectFileFlags flags)
516 {
517  struct MuttWindow *win = msgwin_get_window();
518  if (!win)
519  return -1;
520 
521  struct KeyEvent ch;
522 
524  mutt_window_mvaddstr(win, 0, 0, prompt);
525  mutt_window_addstr(win, _(" ('?' for list): "));
527  if (!mutt_buffer_is_empty(fname))
530  mutt_refresh();
531 
532  do
533  {
534  ch = mutt_getch();
535  } while (ch.ch == -2); // Timeout
536  if (ch.ch < 0)
537  {
538  mutt_window_clearline(win, 0);
539  return -1;
540  }
541  else if (ch.ch == '?')
542  {
543  mutt_refresh();
544  mutt_buffer_reset(fname);
545 
546  if (flags == MUTT_SEL_NO_FLAGS)
547  flags = MUTT_SEL_FOLDER;
548  if (multiple)
549  flags |= MUTT_SEL_MULTI;
550  if (mailbox)
551  flags |= MUTT_SEL_MAILBOX;
552  mutt_buffer_select_file(fname, flags, m, files, numfiles);
553  }
554  else
555  {
556  char *pc = mutt_mem_malloc(mutt_str_len(prompt) + 3);
557 
558  sprintf(pc, "%s: ", prompt);
559  if (ch.op == OP_NULL)
560  mutt_unget_event(ch.ch, 0);
561  else
562  mutt_unget_event(0, ch.op);
563 
564  mutt_buffer_alloc(fname, 1024);
565  if (mutt_buffer_get_field(pc, fname, (mailbox ? MUTT_EFILE : MUTT_FILE) | MUTT_CLEAR,
566  multiple, m, files, numfiles) != 0)
567  {
568  mutt_buffer_reset(fname);
569  }
570  FREE(&pc);
571  }
572 
573  return 0;
574 }
575 
583 void mutt_unget_event(int ch, int op)
584 {
585  struct KeyEvent tmp;
586 
587  tmp.ch = ch;
588  tmp.op = op;
589 
590  if (UngetCount >= UngetLen)
591  mutt_mem_realloc(&UngetKeyEvents, (UngetLen += 16) * sizeof(struct KeyEvent));
592 
593  UngetKeyEvents[UngetCount++] = tmp;
594 }
595 
602 void mutt_unget_string(const char *s)
603 {
604  const char *p = s + mutt_str_len(s) - 1;
605 
606  while (p >= s)
607  {
608  mutt_unget_event((unsigned char) *p--, 0);
609  }
610 }
611 
621 {
622  struct KeyEvent tmp;
623 
624  tmp.ch = ch;
625  tmp.op = op;
626 
628  mutt_mem_realloc(&MacroEvents, (MacroBufferLen += 128) * sizeof(struct KeyEvent));
629 
630  MacroEvents[MacroBufferCount++] = tmp;
631 }
632 
640 {
641  UngetCount = 0;
642  while (MacroBufferCount > 0)
643  {
644  if (MacroEvents[--MacroBufferCount].op == OP_END_COND)
645  return;
646  }
647 }
648 
657 {
658  while (UngetCount > 0)
659  {
660  if (UngetKeyEvents[--UngetCount].op == OP_END_COND)
661  return;
662  }
663 }
664 
668 void mutt_flushinp(void)
669 {
670  UngetCount = 0;
671  MacroBufferCount = 0;
672  flushinp();
673 }
674 
682 int mutt_addwch(struct MuttWindow *win, wchar_t wc)
683 {
684  char buf[MB_LEN_MAX * 2];
685  mbstate_t mbstate;
686  size_t n1, n2;
687 
688  memset(&mbstate, 0, sizeof(mbstate));
689  if (((n1 = wcrtomb(buf, wc, &mbstate)) == (size_t) (-1)) ||
690  ((n2 = wcrtomb(buf + n1, 0, &mbstate)) == (size_t) (-1)))
691  {
692  return -1; /* ERR */
693  }
694  else
695  {
696  return mutt_window_addstr(win, buf);
697  }
698 }
699 
716 void mutt_simple_format(char *buf, size_t buflen, int min_width, int max_width,
717  enum FormatJustify justify, char pad_char,
718  const char *s, size_t n, bool arboreal)
719 {
720  wchar_t wc;
721  int w;
722  size_t k, k2;
723  char scratch[MB_LEN_MAX];
724  mbstate_t mbstate1, mbstate2;
725  bool escaped = false;
726 
727  memset(&mbstate1, 0, sizeof(mbstate1));
728  memset(&mbstate2, 0, sizeof(mbstate2));
729  buflen--;
730  char *p = buf;
731  for (; n && (k = mbrtowc(&wc, s, n, &mbstate1)); s += k, n -= k)
732  {
733  if ((k == (size_t) (-1)) || (k == (size_t) (-2)))
734  {
735  if ((k == (size_t) (-1)) && (errno == EILSEQ))
736  memset(&mbstate1, 0, sizeof(mbstate1));
737 
738  k = (k == (size_t) (-1)) ? 1 : n;
739  wc = ReplacementChar;
740  }
741  if (escaped)
742  {
743  escaped = false;
744  w = 0;
745  }
746  else if (arboreal && (wc == MUTT_SPECIAL_INDEX))
747  {
748  escaped = true;
749  w = 0;
750  }
751  else if (arboreal && (wc < MUTT_TREE_MAX))
752  {
753  w = 1; /* hack */
754  }
755  else
756  {
757 #ifdef HAVE_ISWBLANK
758  if (iswblank(wc))
759  wc = ' ';
760  else
761 #endif
762  if (!IsWPrint(wc))
763  wc = '?';
764  w = wcwidth(wc);
765  }
766  if (w >= 0)
767  {
768  if ((w > max_width) || ((k2 = wcrtomb(scratch, wc, &mbstate2)) > buflen))
769  continue;
770  min_width -= w;
771  max_width -= w;
772  strncpy(p, scratch, k2);
773  p += k2;
774  buflen -= k2;
775  }
776  }
777  w = ((int) buflen < min_width) ? buflen : min_width;
778  if (w <= 0)
779  *p = '\0';
780  else if (justify == JUSTIFY_RIGHT) /* right justify */
781  {
782  p[w] = '\0';
783  while (--p >= buf)
784  p[w] = *p;
785  while (--w >= 0)
786  buf[w] = pad_char;
787  }
788  else if (justify == JUSTIFY_CENTER) /* center */
789  {
790  char *savedp = p;
791  int half = (w + 1) / 2; /* half of cushion space */
792 
793  p[w] = '\0';
794 
795  /* move str to center of buffer */
796  while (--p >= buf)
797  p[half] = *p;
798 
799  /* fill rhs */
800  p = savedp + half;
801  while (--w >= half)
802  *p++ = pad_char;
803 
804  /* fill lhs */
805  while (half--)
806  buf[half] = pad_char;
807  }
808  else /* left justify */
809  {
810  while (--w >= 0)
811  *p++ = pad_char;
812  *p = '\0';
813  }
814 }
815 
830 void mutt_format_s_x(char *buf, size_t buflen, const char *prec, const char *s, bool arboreal)
831 {
832  enum FormatJustify justify = JUSTIFY_RIGHT;
833  char *p = NULL;
834  int min_width;
835  int max_width = INT_MAX;
836 
837  if (*prec == '-')
838  {
839  prec++;
840  justify = JUSTIFY_LEFT;
841  }
842  else if (*prec == '=')
843  {
844  prec++;
845  justify = JUSTIFY_CENTER;
846  }
847  min_width = strtol(prec, &p, 10);
848  if (*p == '.')
849  {
850  prec = p + 1;
851  max_width = strtol(prec, &p, 10);
852  if (p <= prec)
853  max_width = INT_MAX;
854  }
855 
856  mutt_simple_format(buf, buflen, min_width, max_width, justify, ' ', s,
857  mutt_str_len(s), arboreal);
858 }
859 
867 void mutt_format_s(char *buf, size_t buflen, const char *prec, const char *s)
868 {
869  mutt_format_s_x(buf, buflen, prec, s, false);
870 }
871 
879 void mutt_format_s_tree(char *buf, size_t buflen, const char *prec, const char *s)
880 {
881  mutt_format_s_x(buf, buflen, prec, s, true);
882 }
883 
890 void mutt_paddstr(struct MuttWindow *win, int n, const char *s)
891 {
892  wchar_t wc;
893  size_t k;
894  size_t len = mutt_str_len(s);
895  mbstate_t mbstate;
896 
897  memset(&mbstate, 0, sizeof(mbstate));
898  for (; len && (k = mbrtowc(&wc, s, len, &mbstate)); s += k, len -= k)
899  {
900  if ((k == (size_t) (-1)) || (k == (size_t) (-2)))
901  {
902  if (k == (size_t) (-1))
903  memset(&mbstate, 0, sizeof(mbstate));
904  k = (k == (size_t) (-1)) ? 1 : len;
905  wc = ReplacementChar;
906  }
907  if (!IsWPrint(wc))
908  wc = '?';
909  const int w = wcwidth(wc);
910  if (w >= 0)
911  {
912  if (w > n)
913  break;
914  mutt_window_addnstr(win, (char *) s, k);
915  n -= w;
916  }
917  }
918  while (n-- > 0)
919  mutt_window_addch(win, ' ');
920 }
921 
933 size_t mutt_wstr_trunc(const char *src, size_t maxlen, size_t maxwid, size_t *width)
934 {
935  wchar_t wc;
936  size_t n, w = 0, l = 0, cl;
937  int cw;
938  mbstate_t mbstate;
939 
940  if (!src)
941  goto out;
942 
943  n = mutt_str_len(src);
944 
945  memset(&mbstate, 0, sizeof(mbstate));
946  for (w = 0; n && (cl = mbrtowc(&wc, src, n, &mbstate)); src += cl, n -= cl)
947  {
948  if ((cl == (size_t) (-1)) || (cl == (size_t) (-2)))
949  {
950  if (cl == (size_t) (-1))
951  memset(&mbstate, 0, sizeof(mbstate));
952  cl = (cl == (size_t) (-1)) ? 1 : n;
953  wc = ReplacementChar;
954  }
955  cw = wcwidth(wc);
956  /* hack because MUTT_TREE symbols aren't turned into characters
957  * until rendered by print_enriched_string() */
958  if ((cw < 0) && (src[0] == MUTT_SPECIAL_INDEX))
959  {
960  cl = 2; /* skip the index coloring sequence */
961  cw = 0;
962  }
963  else if ((cw < 0) && (cl == 1) && (src[0] != '\0') && (src[0] < MUTT_TREE_MAX))
964  cw = 1;
965  else if (cw < 0)
966  cw = 0; /* unprintable wchar */
967  if ((cl + l > maxlen) || (cw + w > maxwid))
968  break;
969  l += cl;
970  w += cw;
971  }
972 out:
973  if (width)
974  *width = w;
975  return l;
976 }
977 
983 int mutt_strwidth(const char *s)
984 {
985  if (!s)
986  return 0;
987  return mutt_strnwidth(s, mutt_str_len(s));
988 }
989 
996 int mutt_strnwidth(const char *s, size_t n)
997 {
998  if (!s)
999  return 0;
1000 
1001  wchar_t wc;
1002  int w;
1003  size_t k;
1004  mbstate_t mbstate;
1005 
1006  memset(&mbstate, 0, sizeof(mbstate));
1007  for (w = 0; n && (k = mbrtowc(&wc, s, n, &mbstate)); s += k, n -= k)
1008  {
1009  if (*s == MUTT_SPECIAL_INDEX)
1010  {
1011  s += 2; /* skip the index coloring sequence */
1012  k = 0;
1013  continue;
1014  }
1015 
1016  if ((k == (size_t) (-1)) || (k == (size_t) (-2)))
1017  {
1018  if (k == (size_t) (-1))
1019  memset(&mbstate, 0, sizeof(mbstate));
1020  k = (k == (size_t) (-1)) ? 1 : n;
1021  wc = ReplacementChar;
1022  }
1023  if (!IsWPrint(wc))
1024  wc = '?';
1025  w += wcwidth(wc);
1026  }
1027  return w;
1028 }
void mutt_perror_debug(const char *s)
Show the user an &#39;errno&#39; message.
Definition: curs_lib.c:441
Manage keymappings.
Define wrapper functions around Curses/Slang.
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
Left justify the text.
Definition: curs_lib.h:43
#define MUTT_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:58
FormatJustify
Alignment for mutt_simple_format()
Definition: curs_lib.h:41
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define IsWPrint(wc)
Definition: mbyte.h:39
Window management.
GUI miscellaneous curses (window drawing) routines.
uint16_t CompletionFlags
Flags for mutt_enter_string_full(), e.g. MUTT_ALIAS.
Definition: mutt.h:51
#define mutt_error(...)
Definition: logging.h:88
static struct KeyEvent * MacroEvents
Definition: curs_lib.c:76
int mutt_buffer_get_field(const char *field, struct Buffer *buf, CompletionFlags complete, bool multiple, struct Mailbox *m, char ***files, int *numfiles)
Ask the user for a string.
Definition: curs_lib.c:268
static const struct Mapping EditorHelp[]
Help Bar for the Command Line Editor.
Definition: curs_lib.c:87
WHERE SIG_ATOMIC_VOLATILE_T SigInt
true after SIGINT is received
Definition: mutt_globals.h:67
int help_menu
Menu for key bindings, e.g. MENU_PAGER.
Definition: mutt_window.h:141
void mutt_push_macro_event(int ch, int op)
Add the character/operation to the macro buffer.
Definition: curs_lib.c:620
static size_t MacroBufferCount
Definition: curs_lib.c:74
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_curses_set_color(enum ColorId color)
Set the current colour for text.
Definition: mutt_curses.c:56
void mutt_flushinp(void)
Empty all the keyboard buffers.
Definition: curs_lib.c:668
void mutt_window_clrtoeol(struct MuttWindow *win)
Clear to the end of the line.
Definition: mutt_window.c:259
void mutt_resize_screen(void)
Update NeoMutt&#39;s opinion about the window size (CURSES)
Definition: resize.c:101
NeoMutt Logging.
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
Right justify the text.
Definition: curs_lib.h:45
String manipulation buffer.
Definition: buffer.h:33
struct MuttWindow * window_set_focus(struct MuttWindow *win)
Set the Window focus.
Definition: mutt_window.c:680
void mutt_unget_event(int ch, int op)
Return a keystroke to the input buffer.
Definition: curs_lib.c:583
#define _(a)
Definition: message.h:28
void window_redraw(struct MuttWindow *win)
Reflow, recalc and repaint a tree of Windows.
Definition: mutt_window.c:632
WHERE bool OptNoCurses
(pseudo) when sending in batch mode
Definition: options.h:47
int op
function op
Definition: keymap.h:67
int ch
raw key pressed
Definition: keymap.h:66
#define MUTT_SEL_NO_FLAGS
No flags are set.
Definition: browser.h:36
WHERE bool OptIgnoreMacroEvents
(pseudo) don&#39;t process macro/push/exec events while set
Definition: options.h:37
void mutt_query_exit(void)
Ask the user if they want to leave NeoMutt.
Definition: curs_lib.c:403
int mutt_window_mvaddstr(struct MuttWindow *win, int col, int row, const char *str)
Move the cursor and write a fixed string to a Window.
Definition: mutt_window.c:324
All user-callable functions.
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:169
Container for Accounts, Notifications.
Definition: neomutt.h:36
void mutt_sig_allow_interrupt(bool allow)
Allow/disallow Ctrl-C (SIGINT)
Definition: signal.c:238
Convenience wrapper for the config headers.
GUI component for displaying/selecting items from a list.
#define MUTT_SEL_FOLDER
Select a local directory.
Definition: browser.h:39
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
static size_t UngetCount
Definition: curs_lib.c:80
void mutt_beep(bool force)
Irritate the user.
Definition: curs_lib.c:105
size_t dsize
Length of data.
Definition: buffer.h:37
void mutt_curses_set_cursor(enum MuttCursorState state)
Set the cursor state.
Definition: mutt_curses.c:71
Many unsorted constants and some structs.
void mutt_flush_macro_to_endcond(void)
Drop a macro from the input buffer.
Definition: curs_lib.c:639
Centre the text.
Definition: curs_lib.h:44
Text entry area.
Definition: type.h:43
void mutt_window_clearline(struct MuttWindow *win, int row)
Clear a row of a Window.
Definition: mutt_window.c:247
struct MuttWindow * msgwin_get_window(void)
Get the Message Window pointer.
Definition: msgwin.c:253
int mutt_window_addstr(struct MuttWindow *win, const char *str)
Write a string to a Window.
Definition: mutt_window.c:434
Display a normal cursor.
Definition: mutt_curses.h:81
Convenience wrapper for the core headers.
Struct to store the cursor position when entering text.
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:112
#define EILSEQ
Definition: charset.c:51
int mutt_monitor_poll(void)
Check for filesystem changes.
Definition: monitor.c:399
void mutt_buffer_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition: buffer.c:181
Plain text.
Definition: color.h:58
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
Keep our place when entering a string.
Definition: enter_state.h:32
void mutt_refresh(void)
Force a refresh of the screen.
Definition: curs_lib.c:115
WHERE bool OptForceRefresh
(pseudo) refresh even during macros
Definition: options.h:36
Prototypes for many functions.
void mutt_window_get_coords(struct MuttWindow *win, int *col, int *row)
Get the cursor position in the Window.
Definition: mutt_window.c:290
int mutt_enter_string_full(char *buf, size_t buflen, int col, CompletionFlags flags, bool multiple, struct Mailbox *m, char ***files, int *numfiles, struct EnterState *state)
Ask the user for a string.
Definition: enter.c:150
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:422
static struct KeyEvent * UngetKeyEvents
Definition: curs_lib.c:82
Create/manipulate threading in emails.
A mailbox.
Definition: mailbox.h:81
int mutt_strwidth(const char *s)
Measure a string&#39;s width in screen cells.
Definition: curs_lib.c:983
void mutt_format_s_x(char *buf, size_t buflen, const char *prec, const char *s, bool arboreal)
Format a string like snprintf()
Definition: curs_lib.c:830
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
void mutt_enter_state_free(struct EnterState **ptr)
Free an EnterState.
Definition: enter.c:818
Message Window.
const struct Mapping * help_data
Data for the Help Bar.
Definition: mutt_window.h:142
char * data
Pointer to data.
Definition: buffer.h:35
static int mutt_monitor_getch(void)
Get a character and poll the filesystem monitor.
Definition: curs_lib.c:165
wchar_t ReplacementChar
When a Unicode character can&#39;t be displayed, use this instead.
Definition: charset.c:57
size_t mutt_wstr_trunc(const char *src, size_t maxlen, size_t maxwid, size_t *width)
Work out how to truncate a widechar string.
Definition: curs_lib.c:933
Ask the user a question.
An event such as a keypress.
Definition: keymap.h:64
int mutt_addwch(struct MuttWindow *win, wchar_t wc)
addwch would be provided by an up-to-date curses library
Definition: curs_lib.c:682
struct KeyEvent mutt_getch(void)
Read a character from the input buffer.
Definition: curs_lib.c:196
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
Color and attribute parsing.
int mutt_strnwidth(const char *s, size_t n)
Measure a string&#39;s width in screen cells.
Definition: curs_lib.c:996
#define MUTT_SEL_MULTI
Multi-selection is enabled.
Definition: browser.h:38
keycode_t AbortKey
code of key to abort prompts, normally Ctrl-G
Definition: keymap.c:124
#define MUTT_FILE
Do file completion.
Definition: mutt.h:54
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: question.c:180
int mutt_get_field_unbuffered(const char *msg, char *buf, size_t buflen, CompletionFlags flags)
Ask the user for a string (ignoring macro buffer)
Definition: curs_lib.c:359
Restore the previous cursor state.
Definition: mutt_curses.h:79
#define MUTT_SEL_MAILBOX
Select a mailbox.
Definition: browser.h:37
void mutt_exit(int code)
Leave NeoMutt NOW.
Definition: main.c:279
int mutt_any_key_to_continue(const char *s)
Prompt the user to &#39;press any key&#39; and wait.
Definition: curs_lib.c:455
static size_t MacroBufferLen
Definition: curs_lib.c:75
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:664
#define MUTT_EFILE
Do file completion, plus incoming folders.
Definition: mutt.h:55
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
void mutt_format_s(char *buf, size_t buflen, const char *prec, const char *s)
Format a simple string.
Definition: curs_lib.c:867
Log at debug level 1.
Definition: logging.h:40
void mutt_flush_unget_to_endcond(void)
Clear entries from UngetKeyEvents.
Definition: curs_lib.c:656
void mutt_getch_timeout(int delay)
Set the getch() timeout.
Definition: curs_lib.c:153
void mutt_buffer_file_expand_fmt_quote(struct Buffer *dest, const char *fmt, const char *src)
Replace s in a string with a filename.
Definition: file.c:1435
void mutt_buffer_select_file(struct Buffer *file, SelectFileFlags flags, struct Mailbox *m, char ***files, int *numfiles)
Let the user select a file.
Definition: browser.c:1254
Colour indicator.
Definition: mutt_thread.h:57
#define FREE(x)
Definition: memory.h:40
Mapping between user-readable string and a constant.
Definition: mapping.h:31
Monitor files for changes.
void mutt_unget_string(const char *s)
Return a string to the input buffer.
Definition: curs_lib.c:602
int mutt_window_addnstr(struct MuttWindow *win, const char *str, int num)
Write a partial string to a Window.
Definition: mutt_window.c:415
struct EnterState * mutt_enter_state_new(void)
Create a new EnterState.
Definition: enter.c:130
Hundreds of global variables to back the user variables.
Handling of global boolean variables.
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
Convenience wrapper for the library headers.
WHERE bool OptKeepQuiet
(pseudo) shut up the message and refresh functions while we are executing an external program ...
Definition: options.h:38
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
void mutt_need_hard_redraw(void)
Force a hard refresh.
Definition: curs_lib.c:137
#define N_(a)
Definition: message.h:32
WHERE SIG_ATOMIC_VOLATILE_T SigWinch
true after SIGWINCH is received
Definition: mutt_globals.h:68
void mutt_edit_file(const char *editor, const char *file)
Let the user edit a file.
Definition: curs_lib.c:380
int mutt_system(const char *cmd)
Run an external command.
Definition: system.c:51
Question/user input.
Definition: color.h:61
int MuttGetchTimeout
Timeout in ms for mutt_getch()
Definition: curs_lib.c:84
int mutt_window_addch(struct MuttWindow *win, int ch)
Write one character to a Window.
Definition: mutt_window.c:402
void mutt_paddstr(struct MuttWindow *win, int n, const char *s)
Display a string on screen, padded if necessary.
Definition: curs_lib.c:890
void mutt_format_s_tree(char *buf, size_t buflen, const char *prec, const char *s)
Format a simple string with tree characters.
Definition: curs_lib.c:879
static size_t UngetLen
Definition: curs_lib.c:81
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:716
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
uint8_t SelectFileFlags
Flags for mutt_select_file(), e.g. MUTT_SEL_MAILBOX.
Definition: browser.h:33