NeoMutt  2021-10-29-220-g2b1eec
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 "browser/lib.h"
47 #include "color/lib.h"
48 #include "enter/lib.h"
49 #include "menu/lib.h"
50 #include "question/lib.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, so roll our
69  * own input buffering routines. */
70 
71 /* These are used for macros and exec/push commands.
72  * They can be temporarily ignored by setting OptIgnoreMacroEvents */
73 static size_t MacroBufferCount = 0;
74 static size_t MacroBufferLen = 0;
75 static struct KeyEvent *MacroEvents;
76 
77 /* These are used in all other "normal" situations, and are not
78  * ignored when setting OptIgnoreMacroEvents */
79 static size_t UngetCount = 0;
80 static size_t UngetLen = 0;
81 static struct KeyEvent *UngetKeyEvents;
82 
84 
86 static const struct Mapping EditorHelp[] = {
87  // clang-format off
88  { N_("Complete"), OP_EDITOR_COMPLETE },
89  { N_("Hist Up"), OP_EDITOR_HISTORY_UP },
90  { N_("Hist Down"), OP_EDITOR_HISTORY_DOWN },
91  { N_("Hist Search"), OP_EDITOR_HISTORY_SEARCH },
92  { N_("Begin Line"), OP_EDITOR_BOL },
93  { N_("End Line"), OP_EDITOR_EOL },
94  { N_("Kill Line"), OP_EDITOR_KILL_LINE },
95  { N_("Kill Word"), OP_EDITOR_KILL_WORD },
96  { NULL, 0 },
97  // clang-format on
98 };
99 
104 void mutt_beep(bool force)
105 {
106  const bool c_beep = cs_subset_bool(NeoMutt->sub, "beep");
107  if (force || c_beep)
108  beep();
109 }
110 
114 void mutt_refresh(void)
115 {
116  /* don't refresh when we are waiting for a child. */
117  if (OptKeepQuiet)
118  return;
119 
120  /* don't refresh in the middle of macros unless necessary */
122  return;
123 
124  /* else */
125  refresh();
126 }
127 
137 {
138  keypad(stdscr, true);
139  clearok(stdscr, true);
140  window_redraw(NULL);
141 }
142 
152 void mutt_getch_timeout(int delay)
153 {
154  MuttGetchTimeout = delay;
155  timeout(delay);
156 }
157 
158 #ifdef USE_INOTIFY
164 static int mutt_monitor_getch(void)
165 {
166  /* ncurses has its own internal buffer, so before we perform a poll,
167  * we need to make sure there isn't a character waiting */
168  timeout(0);
169  int ch = getch();
170  timeout(MuttGetchTimeout);
171  if (ch == ERR)
172  {
173  if (mutt_monitor_poll() != 0)
174  ch = ERR;
175  else
176  ch = getch();
177  }
178  return ch;
179 }
180 #endif /* USE_INOTIFY */
181 
195 struct KeyEvent mutt_getch(void)
196 {
197  int ch;
198  struct KeyEvent err = { -1, OP_NULL }, ret;
199  struct KeyEvent timeout = { -2, OP_NULL };
200 
201  if (UngetCount)
202  return UngetKeyEvents[--UngetCount];
203 
205  return MacroEvents[--MacroBufferCount];
206 
207  SigInt = false;
208 
210 #ifdef KEY_RESIZE
211  /* ncurses 4.2 sends this when the screen is resized */
212  ch = KEY_RESIZE;
213  while (ch == KEY_RESIZE)
214 #endif
215 #ifdef USE_INOTIFY
217 #else
218  ch = getch();
219 #endif
221 
222  if (SigInt)
223  {
224  mutt_query_exit();
225  return err;
226  }
227 
228  /* either timeout, a sigwinch (if timeout is set), or the terminal
229  * has been lost */
230  if (ch == ERR)
231  {
232  if (!isatty(0))
233  mutt_exit(1);
234 
235  return timeout;
236  }
237 
238  const bool c_meta_key = cs_subset_bool(NeoMutt->sub, "meta_key");
239  if ((ch & 0x80) && c_meta_key)
240  {
241  /* send ALT-x as ESC-x */
242  ch &= ~0x80;
243  mutt_unget_event(ch, 0);
244  ret.ch = '\033'; // Escape
245  ret.op = 0;
246  return ret;
247  }
248 
249  ret.ch = ch;
250  ret.op = 0;
251  return (ch == AbortKey) ? err : ret;
252 }
253 
267 int mutt_buffer_get_field(const char *field, struct Buffer *buf, CompletionFlags complete,
268  bool multiple, struct Mailbox *m, char ***files, int *numfiles)
269 {
270  struct MuttWindow *win = msgwin_get_window();
271  if (!win)
272  return -1;
273 
274  int ret;
275  int col;
276 
277  struct EnterState *es = mutt_enter_state_new();
278 
279  const struct Mapping *old_help = win->help_data;
280  int old_menu = win->help_menu;
281 
282  win->help_data = EditorHelp;
283  win->help_menu = MENU_EDITOR;
284  struct MuttWindow *old_focus = window_set_focus(win);
285 
286  window_redraw(NULL);
287  do
288  {
289  if (SigWinch)
290  {
291  SigWinch = false;
293  clearok(stdscr, true);
294  window_redraw(NULL);
295  }
296  mutt_window_clearline(win, 0);
298  mutt_window_addstr(win, field);
300  mutt_refresh();
301  mutt_window_get_coords(win, &col, NULL);
302  ret = mutt_enter_string_full(buf->data, buf->dsize, col, complete, multiple,
303  m, files, numfiles, es);
304  } while (ret == 1);
305 
306  win->help_data = old_help;
307  win->help_menu = old_menu;
308  mutt_window_move(win, 0, 0);
309  mutt_window_clearline(win, 0);
310  window_set_focus(old_focus);
311 
312  if (ret == 0)
314  else
315  mutt_buffer_reset(buf);
316 
318 
319  return ret;
320 }
321 
331 int mutt_get_field_unbuffered(const char *msg, struct Buffer *buf, CompletionFlags flags)
332 {
333  bool reset_ignoremacro = false;
334 
336  {
337  OptIgnoreMacroEvents = true;
338  reset_ignoremacro = true;
339  }
340  int rc = mutt_buffer_get_field(msg, buf, flags, false, NULL, NULL, NULL);
341  if (reset_ignoremacro)
342  OptIgnoreMacroEvents = false;
343 
344  return rc;
345 }
346 
352 void mutt_edit_file(const char *editor, const char *file)
353 {
354  struct Buffer *cmd = mutt_buffer_pool_get();
355 
356  mutt_endwin();
357  mutt_buffer_file_expand_fmt_quote(cmd, editor, file);
358  if (mutt_system(mutt_buffer_string(cmd)) != 0)
359  {
360  mutt_error(_("Error running \"%s\""), mutt_buffer_string(cmd));
361  }
362  /* the terminal may have been resized while the editor owned it */
364  keypad(stdscr, true);
365  clearok(stdscr, true);
366 
368 }
369 
375 void mutt_query_exit(void)
376 {
377  mutt_flushinp();
379  const short c_timeout = cs_subset_number(NeoMutt->sub, "timeout");
380  if (c_timeout)
381  mutt_getch_timeout(-1); /* restore blocking operation */
382  if (mutt_yesorno(_("Exit NeoMutt?"), MUTT_YES) == MUTT_YES)
383  {
384  mutt_exit(1);
385  }
388  SigInt = false;
389 }
390 
394 void mutt_endwin(void)
395 {
396  if (OptNoCurses)
397  return;
398 
399  int e = errno;
400 
401  /* at least in some situations (screen + xterm under SuSE11/12) endwin()
402  * doesn't properly flush the screen without an explicit call. */
403  mutt_refresh();
404  endwin();
405 
406  errno = e;
407 }
408 
413 void mutt_perror_debug(const char *s)
414 {
415  char *p = strerror(errno);
416 
417  mutt_debug(LL_DEBUG1, "%s: %s (errno = %d)\n", s, p ? p : "unknown error", errno);
418  mutt_error("%s: %s (errno = %d)", s, p ? p : _("unknown error"), errno);
419 }
420 
427 int mutt_any_key_to_continue(const char *s)
428 {
429  struct termios term;
430  struct termios old;
431 
432  int fd = open("/dev/tty", O_RDONLY);
433  if (fd < 0)
434  return EOF;
435 
436  tcgetattr(fd, &old); // Save the current tty settings
437 
438  term = old;
439  term.c_lflag &= ~(ICANON | ECHO); // Canonical (not line-buffered), don't echo the characters
440  term.c_cc[VMIN] = 1; // Wait for at least one character
441  term.c_cc[VTIME] = 255; // Wait for 25.5s
442  tcsetattr(fd, TCSANOW, &term);
443 
444  if (s)
445  fputs(s, stdout);
446  else
447  fputs(_("Press any key to continue..."), stdout);
448  fflush(stdout);
449 
450  char ch = '\0';
451  // Wait for a character. This might timeout, so loop.
452  while (read(fd, &ch, 1) == 0)
453  ; // do nothing
454 
455  // Change the tty settings to be non-blocking
456  term.c_cc[VMIN] = 0; // Returning with zero characters is acceptable
457  term.c_cc[VTIME] = 0; // Don't wait
458  tcsetattr(fd, TCSANOW, &term);
459 
460  char buf[64];
461  while (read(fd, buf, sizeof(buf)) > 0)
462  ; // Mop up any remaining chars
463 
464  tcsetattr(fd, TCSANOW, &old); // Restore the previous tty settings
465  close(fd);
466 
467  fputs("\r\n", stdout);
469  return (ch >= 0) ? ch : EOF;
470 }
471 
485 int mutt_buffer_enter_fname(const char *prompt, struct Buffer *fname,
486  bool mailbox, struct Mailbox *m, bool multiple,
487  char ***files, int *numfiles, SelectFileFlags flags)
488 {
489  struct MuttWindow *win = msgwin_get_window();
490  if (!win)
491  return -1;
492 
493  struct KeyEvent ch;
494  struct MuttWindow *old_focus = window_set_focus(win);
495 
497  mutt_window_mvaddstr(win, 0, 0, prompt);
498  mutt_window_addstr(win, _(" ('?' for list): "));
500  if (!mutt_buffer_is_empty(fname))
503  mutt_refresh();
504 
505  do
506  {
507  ch = mutt_getch();
508  } while (ch.ch == -2); // Timeout
509 
510  mutt_window_move(win, 0, 0);
512  mutt_refresh();
513  window_set_focus(old_focus);
514 
515  if (ch.ch < 0)
516  {
517  return -1;
518  }
519  else if (ch.ch == '?')
520  {
521  mutt_buffer_reset(fname);
522 
523  if (flags == MUTT_SEL_NO_FLAGS)
524  flags = MUTT_SEL_FOLDER;
525  if (multiple)
526  flags |= MUTT_SEL_MULTI;
527  if (mailbox)
528  flags |= MUTT_SEL_MAILBOX;
529  mutt_buffer_select_file(fname, flags, m, files, numfiles);
530  }
531  else
532  {
533  char *pc = mutt_mem_malloc(mutt_str_len(prompt) + 3);
534 
535  sprintf(pc, "%s: ", prompt);
536  if (ch.op == OP_NULL)
537  mutt_unget_event(ch.ch, 0);
538  else
539  mutt_unget_event(0, ch.op);
540 
541  mutt_buffer_alloc(fname, 1024);
543  multiple, m, files, numfiles) != 0)
544  {
545  mutt_buffer_reset(fname);
546  }
547  FREE(&pc);
548  }
549 
550  return 0;
551 }
552 
560 void mutt_unget_event(int ch, int op)
561 {
562  struct KeyEvent tmp;
563 
564  tmp.ch = ch;
565  tmp.op = op;
566 
567  if (UngetCount >= UngetLen)
568  mutt_mem_realloc(&UngetKeyEvents, (UngetLen += 16) * sizeof(struct KeyEvent));
569 
570  UngetKeyEvents[UngetCount++] = tmp;
571 }
572 
579 void mutt_unget_string(const char *s)
580 {
581  const char *p = s + mutt_str_len(s) - 1;
582 
583  while (p >= s)
584  {
585  mutt_unget_event((unsigned char) *p--, 0);
586  }
587 }
588 
598 {
599  struct KeyEvent tmp;
600 
601  tmp.ch = ch;
602  tmp.op = op;
603 
605  mutt_mem_realloc(&MacroEvents, (MacroBufferLen += 128) * sizeof(struct KeyEvent));
606 
607  MacroEvents[MacroBufferCount++] = tmp;
608 }
609 
617 {
618  UngetCount = 0;
619  while (MacroBufferCount > 0)
620  {
621  if (MacroEvents[--MacroBufferCount].op == OP_END_COND)
622  return;
623  }
624 }
625 
634 {
635  while (UngetCount > 0)
636  {
637  if (UngetKeyEvents[--UngetCount].op == OP_END_COND)
638  return;
639  }
640 }
641 
645 void mutt_flushinp(void)
646 {
647  UngetCount = 0;
648  MacroBufferCount = 0;
649  flushinp();
650 }
651 
659 int mutt_addwch(struct MuttWindow *win, wchar_t wc)
660 {
661  char buf[MB_LEN_MAX * 2];
662  mbstate_t mbstate = { 0 };
663  size_t n1, n2;
664 
665  if (((n1 = wcrtomb(buf, wc, &mbstate)) == (size_t) (-1)) ||
666  ((n2 = wcrtomb(buf + n1, 0, &mbstate)) == (size_t) (-1)))
667  {
668  return -1; /* ERR */
669  }
670  else
671  {
672  return mutt_window_addstr(win, buf);
673  }
674 }
675 
692 void mutt_simple_format(char *buf, size_t buflen, int min_width, int max_width,
693  enum FormatJustify justify, char pad_char,
694  const char *s, size_t n, bool arboreal)
695 {
696  wchar_t wc = 0;
697  int w;
698  size_t k, k2;
699  char scratch[MB_LEN_MAX];
700  mbstate_t mbstate1 = { 0 };
701  mbstate_t mbstate2 = { 0 };
702  bool escaped = false;
703 
704  buflen--;
705  char *p = buf;
706  for (; n && (k = mbrtowc(&wc, s, n, &mbstate1)); s += k, n -= k)
707  {
708  if ((k == (size_t) (-1)) || (k == (size_t) (-2)))
709  {
710  if ((k == (size_t) (-1)) && (errno == EILSEQ))
711  memset(&mbstate1, 0, sizeof(mbstate1));
712 
713  k = (k == (size_t) (-1)) ? 1 : n;
714  wc = ReplacementChar;
715  }
716  if (escaped)
717  {
718  escaped = false;
719  w = 0;
720  }
721  else if (arboreal && (wc == MUTT_SPECIAL_INDEX))
722  {
723  escaped = true;
724  w = 0;
725  }
726  else if (arboreal && (wc < MUTT_TREE_MAX))
727  {
728  w = 1; /* hack */
729  }
730  else
731  {
732 #ifdef HAVE_ISWBLANK
733  if (iswblank(wc))
734  wc = ' ';
735  else
736 #endif
737  if (!IsWPrint(wc))
738  wc = '?';
739  w = wcwidth(wc);
740  }
741  if (w >= 0)
742  {
743  if ((w > max_width) || ((k2 = wcrtomb(scratch, wc, &mbstate2)) > buflen))
744  continue;
745  min_width -= w;
746  max_width -= w;
747  strncpy(p, scratch, k2);
748  p += k2;
749  buflen -= k2;
750  }
751  }
752  w = ((int) buflen < min_width) ? buflen : min_width;
753  if (w <= 0)
754  *p = '\0';
755  else if (justify == JUSTIFY_RIGHT) /* right justify */
756  {
757  p[w] = '\0';
758  while (--p >= buf)
759  p[w] = *p;
760  while (--w >= 0)
761  buf[w] = pad_char;
762  }
763  else if (justify == JUSTIFY_CENTER) /* center */
764  {
765  char *savedp = p;
766  int half = (w + 1) / 2; /* half of cushion space */
767 
768  p[w] = '\0';
769 
770  /* move str to center of buffer */
771  while (--p >= buf)
772  p[half] = *p;
773 
774  /* fill rhs */
775  p = savedp + half;
776  while (--w >= half)
777  *p++ = pad_char;
778 
779  /* fill lhs */
780  while (half--)
781  buf[half] = pad_char;
782  }
783  else /* left justify */
784  {
785  while (--w >= 0)
786  *p++ = pad_char;
787  *p = '\0';
788  }
789 }
790 
805 void mutt_format_s_x(char *buf, size_t buflen, const char *prec, const char *s, bool arboreal)
806 {
807  enum FormatJustify justify = JUSTIFY_RIGHT;
808  char *p = NULL;
809  int min_width;
810  int max_width = INT_MAX;
811 
812  if (*prec == '-')
813  {
814  prec++;
815  justify = JUSTIFY_LEFT;
816  }
817  else if (*prec == '=')
818  {
819  prec++;
820  justify = JUSTIFY_CENTER;
821  }
822  min_width = strtol(prec, &p, 10);
823  if (*p == '.')
824  {
825  prec = p + 1;
826  max_width = strtol(prec, &p, 10);
827  if (p <= prec)
828  max_width = INT_MAX;
829  }
830 
831  mutt_simple_format(buf, buflen, min_width, max_width, justify, ' ', s,
832  mutt_str_len(s), arboreal);
833 }
834 
842 void mutt_format_s(char *buf, size_t buflen, const char *prec, const char *s)
843 {
844  mutt_format_s_x(buf, buflen, prec, s, false);
845 }
846 
854 void mutt_format_s_tree(char *buf, size_t buflen, const char *prec, const char *s)
855 {
856  mutt_format_s_x(buf, buflen, prec, s, true);
857 }
858 
865 void mutt_paddstr(struct MuttWindow *win, int n, const char *s)
866 {
867  wchar_t wc = 0;
868  size_t k;
869  size_t len = mutt_str_len(s);
870  mbstate_t mbstate = { 0 };
871 
872  for (; len && (k = mbrtowc(&wc, s, len, &mbstate)); s += k, len -= k)
873  {
874  if ((k == (size_t) (-1)) || (k == (size_t) (-2)))
875  {
876  if (k == (size_t) (-1))
877  memset(&mbstate, 0, sizeof(mbstate));
878  k = (k == (size_t) (-1)) ? 1 : len;
879  wc = ReplacementChar;
880  }
881  if (!IsWPrint(wc))
882  wc = '?';
883  const int w = wcwidth(wc);
884  if (w >= 0)
885  {
886  if (w > n)
887  break;
888  mutt_window_addnstr(win, (char *) s, k);
889  n -= w;
890  }
891  }
892  while (n-- > 0)
893  mutt_window_addch(win, ' ');
894 }
895 
907 size_t mutt_wstr_trunc(const char *src, size_t maxlen, size_t maxwid, size_t *width)
908 {
909  wchar_t wc = 0;
910  size_t n, w = 0, l = 0, cl;
911  int cw;
912  mbstate_t mbstate = { 0 };
913 
914  if (!src)
915  goto out;
916 
917  n = mutt_str_len(src);
918 
919  for (w = 0; n && (cl = mbrtowc(&wc, src, n, &mbstate)); src += cl, n -= cl)
920  {
921  if ((cl == (size_t) (-1)) || (cl == (size_t) (-2)))
922  {
923  if (cl == (size_t) (-1))
924  memset(&mbstate, 0, sizeof(mbstate));
925  cl = (cl == (size_t) (-1)) ? 1 : n;
926  wc = ReplacementChar;
927  }
928  cw = wcwidth(wc);
929  /* hack because MUTT_TREE symbols aren't turned into characters
930  * until rendered by print_enriched_string() */
931  if ((cw < 0) && (src[0] == MUTT_SPECIAL_INDEX))
932  {
933  cl = 2; /* skip the index coloring sequence */
934  cw = 0;
935  }
936  else if ((cw < 0) && (cl == 1) && (src[0] != '\0') && (src[0] < MUTT_TREE_MAX))
937  cw = 1;
938  else if (cw < 0)
939  cw = 0; /* unprintable wchar */
940  if ((cl + l > maxlen) || (cw + w > maxwid))
941  break;
942  l += cl;
943  w += cw;
944  }
945 out:
946  if (width)
947  *width = w;
948  return l;
949 }
950 
956 int mutt_strwidth(const char *s)
957 {
958  if (!s)
959  return 0;
960  return mutt_strnwidth(s, mutt_str_len(s));
961 }
962 
969 int mutt_strnwidth(const char *s, size_t n)
970 {
971  if (!s)
972  return 0;
973 
974  wchar_t wc = 0;
975  int w;
976  size_t k;
977  mbstate_t mbstate = { 0 };
978 
979  for (w = 0; n && (k = mbrtowc(&wc, s, n, &mbstate)); s += k, n -= k)
980  {
981  if (*s == MUTT_SPECIAL_INDEX)
982  {
983  s += 2; /* skip the index coloring sequence */
984  k = 0;
985  continue;
986  }
987 
988  if ((k == (size_t) (-1)) || (k == (size_t) (-2)))
989  {
990  if (k == (size_t) (-1))
991  memset(&mbstate, 0, sizeof(mbstate));
992  k = (k == (size_t) (-1)) ? 1 : n;
993  wc = ReplacementChar;
994  }
995  if (!IsWPrint(wc))
996  wc = '?';
997  w += wcwidth(wc);
998  }
999  return w;
1000 }
Select a Mailbox from a list.
#define MUTT_SEL_MAILBOX
Select a mailbox.
Definition: lib.h:48
#define MUTT_SEL_FOLDER
Select a local directory.
Definition: lib.h:50
#define MUTT_SEL_MULTI
Multi-selection is enabled.
Definition: lib.h:49
#define MUTT_SEL_NO_FLAGS
No flags are set.
Definition: lib.h:47
uint8_t SelectFileFlags
Flags for mutt_select_file(), e.g. MUTT_SEL_MAILBOX.
Definition: lib.h:44
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:1101
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
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
void mutt_buffer_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition: buffer.c:181
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
Color and attribute parsing.
@ MT_COLOR_NORMAL
Plain text.
Definition: color.h:53
@ MT_COLOR_PROMPT
Question/user input.
Definition: color.h:56
Convenience wrapper for the config headers.
Convenience wrapper for the core headers.
static size_t MacroBufferCount
Definition: curs_lib.c:73
void mutt_edit_file(const char *editor, const char *file)
Let the user edit a file.
Definition: curs_lib.c:352
void mutt_getch_timeout(int delay)
Set the getch() timeout.
Definition: curs_lib.c:152
static size_t UngetLen
Definition: curs_lib.c:80
void mutt_flushinp(void)
Empty all the keyboard buffers.
Definition: curs_lib.c:645
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:907
static struct KeyEvent * MacroEvents
Definition: curs_lib.c:75
int mutt_get_field_unbuffered(const char *msg, struct Buffer *buf, CompletionFlags flags)
Ask the user for a string (ignoring macro buffer)
Definition: curs_lib.c:331
static size_t MacroBufferLen
Definition: curs_lib.c:74
struct KeyEvent mutt_getch(void)
Read a character from the input buffer.
Definition: curs_lib.c:195
void mutt_unget_string(const char *s)
Return a string to the input buffer.
Definition: curs_lib.c:579
void mutt_push_macro_event(int ch, int op)
Add the character/operation to the macro buffer.
Definition: curs_lib.c:597
static const struct Mapping EditorHelp[]
Help Bar for the Command Line Editor.
Definition: curs_lib.c:86
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:485
void mutt_paddstr(struct MuttWindow *win, int n, const char *s)
Display a string on screen, padded if necessary.
Definition: curs_lib.c:865
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:805
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:267
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:854
void mutt_refresh(void)
Force a refresh of the screen.
Definition: curs_lib.c:114
void mutt_unget_event(int ch, int op)
Return a keystroke to the input buffer.
Definition: curs_lib.c:560
void mutt_flush_unget_to_endcond(void)
Clear entries from UngetKeyEvents.
Definition: curs_lib.c:633
int mutt_addwch(struct MuttWindow *win, wchar_t wc)
Addwch would be provided by an up-to-date curses library.
Definition: curs_lib.c:659
void mutt_flush_macro_to_endcond(void)
Drop a macro from the input buffer.
Definition: curs_lib.c:616
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:692
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition: curs_lib.c:427
void mutt_need_hard_redraw(void)
Force a hard refresh.
Definition: curs_lib.c:136
static int mutt_monitor_getch(void)
Get a character and poll the filesystem monitor.
Definition: curs_lib.c:164
void mutt_query_exit(void)
Ask the user if they want to leave NeoMutt.
Definition: curs_lib.c:375
static size_t UngetCount
Definition: curs_lib.c:79
void mutt_endwin(void)
Shutdown curses.
Definition: curs_lib.c:394
void mutt_beep(bool force)
Irritate the user.
Definition: curs_lib.c:104
int mutt_strnwidth(const char *s, size_t n)
Measure a string's width in screen cells.
Definition: curs_lib.c:969
static struct KeyEvent * UngetKeyEvents
Definition: curs_lib.c:81
int mutt_strwidth(const char *s)
Measure a string's width in screen cells.
Definition: curs_lib.c:956
void mutt_perror_debug(const char *s)
Show the user an 'errno' message.
Definition: curs_lib.c:413
void mutt_format_s(char *buf, size_t buflen, const char *prec, const char *s)
Format a simple string.
Definition: curs_lib.c:842
int MuttGetchTimeout
Timeout in ms for mutt_getch()
Definition: curs_lib.c:83
GUI miscellaneous curses (window drawing) routines.
FormatJustify
Alignment for mutt_simple_format()
Definition: curs_lib.h:42
@ JUSTIFY_RIGHT
Right justify the text.
Definition: curs_lib.h:45
@ JUSTIFY_LEFT
Left justify the text.
Definition: curs_lib.h:43
@ JUSTIFY_CENTER
Centre the text.
Definition: curs_lib.h:44
Enter a string.
void mutt_enter_state_free(struct EnterState **ptr)
Free an EnterState.
Definition: state.c:37
struct EnterState * mutt_enter_state_new(void)
Create a new EnterState.
Definition: state.c:52
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:141
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:1463
#define mutt_error(...)
Definition: logging.h:87
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:169
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
keycode_t AbortKey
code of key to abort prompts, normally Ctrl-G
Definition: keymap.c:118
Manage keymappings.
@ LL_DEBUG1
Log at debug level 1.
Definition: logging.h:40
void mutt_exit(int code)
Leave NeoMutt NOW.
Definition: main.c:249
#define IsWPrint(wc)
Definition: mbyte.h:39
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
#define FREE(x)
Definition: memory.h:40
GUI present the user with a selectable list.
int mutt_monitor_poll(void)
Check for filesystem changes.
Definition: monitor.c:401
Monitor files for changes.
struct MuttWindow * msgwin_get_window(void)
Get the Message Window pointer.
Definition: msgwin.c:251
Message Window.
wchar_t ReplacementChar
When a Unicode character can't be displayed, use this instead.
Definition: charset.c:57
#define EILSEQ
Definition: charset.c:51
Convenience wrapper for the library headers.
#define N_(a)
Definition: message.h:32
#define _(a)
Definition: message.h:28
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:475
Many unsorted constants and some structs.
#define MUTT_COMP_FILE
File completion (in browser)
Definition: mutt.h:55
uint16_t CompletionFlags
Flags for mutt_enter_string_full(), e.g. MUTT_COMP_ALIAS.
Definition: mutt.h:51
#define MUTT_COMP_FILE_MBOX
File completion, plus incoming folders (in browser)
Definition: mutt.h:56
#define MUTT_COMP_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:62
void mutt_curses_set_color_by_id(enum ColorId cid)
Set the current colour for text.
Definition: mutt_curses.c:52
void mutt_curses_set_cursor(enum MuttCursorState state)
Set the cursor state.
Definition: mutt_curses.c:63
Define wrapper functions around Curses.
void mutt_resize_screen(void)
Update NeoMutt's opinion about the window size (CURSES)
Definition: resize.c:73
@ MUTT_CURSOR_RESTORE_LAST
Restore the previous cursor state.
Definition: mutt_curses.h:53
@ MUTT_CURSOR_VISIBLE
Display a normal cursor.
Definition: mutt_curses.h:55
Hundreds of global variables to back the user variables.
SIG_ATOMIC_VOLATILE_T SigWinch
true after SIGWINCH is received
Definition: mutt_globals.h:72
SIG_ATOMIC_VOLATILE_T SigInt
true after SIGINT is received
Definition: mutt_globals.h:71
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:113
NeoMutt Logging.
Create/manipulate threading in emails.
@ MUTT_TREE_MAX
Definition: mutt_thread.h:57
@ MUTT_SPECIAL_INDEX
Colour indicator.
Definition: mutt_thread.h:59
void window_redraw(struct MuttWindow *win)
Reflow, recalc and repaint a tree of Windows.
Definition: mutt_window.c:603
int mutt_window_move(struct MuttWindow *win, int col, int row)
Move the cursor in a Window.
Definition: mutt_window.c:292
struct MuttWindow * window_set_focus(struct MuttWindow *win)
Set the Window focus.
Definition: mutt_window.c:651
void mutt_window_get_coords(struct MuttWindow *win, int *col, int *row)
Get the cursor position in the Window.
Definition: mutt_window.c:272
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:306
void mutt_window_clearline(struct MuttWindow *win, int row)
Clear a row of a Window.
Definition: mutt_window.c:229
int mutt_window_addstr(struct MuttWindow *win, const char *str)
Write a string to a Window.
Definition: mutt_window.c:408
int mutt_window_addnstr(struct MuttWindow *win, const char *str, int num)
Write a partial string to a Window.
Definition: mutt_window.c:393
void mutt_window_clrtoeol(struct MuttWindow *win)
Clear to the end of the line.
Definition: mutt_window.c:241
int mutt_window_addch(struct MuttWindow *win, int ch)
Write one character to a Window.
Definition: mutt_window.c:380
Window management.
All user-callable functions.
Handling of global boolean variables.
bool OptKeepQuiet
(pseudo) shut up the message and refresh functions while we are executing an external program
Definition: options.h:44
bool OptNoCurses
(pseudo) when sending in batch mode
Definition: options.h:53
bool OptForceRefresh
(pseudo) refresh even during macros
Definition: options.h:42
bool OptIgnoreMacroEvents
(pseudo) don't process macro/push/exec events while set
Definition: options.h:43
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
Prototypes for many functions.
int mutt_system(const char *cmd)
Run an external command.
Definition: system.c:51
@ MUTT_YES
User answered 'Yes', or assume 'Yes'.
Definition: quad.h:39
Ask the user a question.
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: question.c:182
void mutt_sig_allow_interrupt(bool allow)
Allow/disallow Ctrl-C (SIGINT)
Definition: signal.c:238
String manipulation buffer.
Definition: buffer.h:34
size_t dsize
Length of data.
Definition: buffer.h:37
char * data
Pointer to data.
Definition: buffer.h:35
Keep our place when entering a string.
Definition: state.h:33
An event such as a keypress.
Definition: keymap.h:65
int op
function op
Definition: keymap.h:67
int ch
raw key pressed
Definition: keymap.h:66
A mailbox.
Definition: mailbox.h:82
Mapping between user-readable string and a constant.
Definition: mapping.h:32
const struct Mapping * help_data
Data for the Help Bar.
Definition: mutt_window.h:142
int help_menu
Menu for key bindings, e.g. MENU_PAGER.
Definition: mutt_window.h:141
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
@ MENU_EDITOR
Text entry area.
Definition: type.h:43