NeoMutt  2022-04-29-249-gaae397
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 "question/lib.h"
50#include "keymap.h"
51#include "msgwin.h"
52#include "mutt_curses.h"
53#include "mutt_globals.h"
54#include "mutt_logging.h"
55#include "mutt_thread.h"
56#include "mutt_window.h"
57#include "opcodes.h"
58#include "options.h"
59#include "protos.h"
60#ifdef HAVE_ISWBLANK
61#include <wctype.h>
62#endif
63#ifdef USE_INOTIFY
64#include "monitor.h"
65#endif
66
67/* not possible to unget more than one char under some curses libs, so roll our
68 * own input buffering routines. */
69
70ARRAY_HEAD(KeyEventArray, struct KeyEvent);
71
72/* These are used for macros and exec/push commands.
73 * They can be temporarily ignored by setting OptIgnoreMacroEvents */
74static struct KeyEventArray MacroEvents = ARRAY_HEAD_INITIALIZER;
75
76/* These are used in all other "normal" situations, and are not
77 * ignored when setting OptIgnoreMacroEvents */
78static struct KeyEventArray UngetKeyEvents = ARRAY_HEAD_INITIALIZER;
79
85static struct KeyEvent *array_pop(struct KeyEventArray *a)
86{
87 if (ARRAY_EMPTY(a))
88 {
89 return NULL;
90 }
91
92 struct KeyEvent *event = ARRAY_LAST(a);
93 ARRAY_SHRINK(a, 1);
94 return event;
95}
96
103static void array_add(struct KeyEventArray *a, int ch, int op)
104{
105 struct KeyEvent event = { .ch = ch, .op = op };
106 ARRAY_ADD(a, event);
107}
108
113static void array_to_endcond(struct KeyEventArray *a)
114{
115 while (!ARRAY_EMPTY(a))
116 {
117 if (array_pop(a)->op == OP_END_COND)
118 {
119 return;
120 }
121 }
122}
123
125
130void mutt_beep(bool force)
131{
132 const bool c_beep = cs_subset_bool(NeoMutt->sub, "beep");
133 if (force || c_beep)
134 beep();
135}
136
140void mutt_refresh(void)
141{
142 /* don't refresh when we are waiting for a child. */
143 if (OptKeepQuiet)
144 return;
145
146 /* don't refresh in the middle of macros unless necessary */
148 return;
149
150 /* else */
151 refresh();
152}
153
163{
164 // Forcibly switch to the alternate screen.
165 // Using encryption can leave ncurses confused about which mode it's in.
166 fputs("\033[?1049h", stdout);
167 fflush(stdout);
168 keypad(stdscr, true);
169 clearok(stdscr, true);
170 window_redraw(NULL);
171}
172
181static void set_timeout(int delay)
182{
183 MuttGetchTimeout = delay;
184 timeout(delay);
185}
186
198{
199 set_timeout(delay);
200 struct KeyEvent event = mutt_getch();
201 set_timeout(-1);
202 return event;
203}
204
205#ifdef USE_INOTIFY
211static int mutt_monitor_getch(void)
212{
213 /* ncurses has its own internal buffer, so before we perform a poll,
214 * we need to make sure there isn't a character waiting */
215 timeout(0);
216 int ch = getch();
217 timeout(MuttGetchTimeout);
218 if (ch == ERR)
219 {
220 if (mutt_monitor_poll() != 0)
221 ch = ERR;
222 else
223 ch = getch();
224 }
225 return ch;
226}
227#endif /* USE_INOTIFY */
228
243{
244 int ch;
245 const struct KeyEvent err = { 0, OP_ABORT };
246 const struct KeyEvent timeout = { 0, OP_TIMEOUT };
247
248 struct KeyEvent *key = array_pop(&UngetKeyEvents);
249 if (key)
250 {
251 return *key;
252 }
253
255 {
256 return *key;
257 }
258
259 SigInt = false;
260
262#ifdef KEY_RESIZE
263 /* ncurses 4.2 sends this when the screen is resized */
264 ch = KEY_RESIZE;
265 while (ch == KEY_RESIZE)
266#endif
267#ifdef USE_INOTIFY
269#else
270 ch = getch();
271#endif
273
274 if (SigInt)
275 {
277 return err;
278 }
279
280 /* either timeout, a sigwinch (if timeout is set), the terminal
281 * has been lost, or curses was never initialized */
282 if (ch == ERR)
283 {
284 if (!isatty(0))
285 {
286 mutt_exit(1);
287 }
288
289 return OptNoCurses ? err : timeout;
290 }
291
292 const bool c_meta_key = cs_subset_bool(NeoMutt->sub, "meta_key");
293 if ((ch & 0x80) && c_meta_key)
294 {
295 /* send ALT-x as ESC-x */
296 ch &= ~0x80;
298 return (struct KeyEvent){ .ch = '\033' /* Escape */, .op = OP_NULL };
299 }
300
301 if (ch == AbortKey)
302 return err;
303
304 return (struct KeyEvent){ .ch = ch, .op = OP_NULL };
305}
306
312void mutt_edit_file(const char *editor, const char *file)
313{
314 struct Buffer *cmd = mutt_buffer_pool_get();
315
316 mutt_endwin();
317 mutt_buffer_file_expand_fmt_quote(cmd, editor, file);
318 if (mutt_system(mutt_buffer_string(cmd)) != 0)
319 {
320 mutt_error(_("Error running \"%s\""), mutt_buffer_string(cmd));
321 }
322 /* the terminal may have been resized while the editor owned it */
324 keypad(stdscr, true);
325 clearok(stdscr, true);
326
328}
329
336{
339 const short c_timeout = cs_subset_number(NeoMutt->sub, "timeout");
340 if (c_timeout)
341 set_timeout(-1); /* restore blocking operation */
342 if (mutt_yesorno(_("Exit NeoMutt?"), MUTT_YES) == MUTT_YES)
343 {
344 mutt_exit(1);
345 }
348 SigInt = false;
349}
350
354void mutt_endwin(void)
355{
356 if (OptNoCurses)
357 return;
358
359 int e = errno;
360
361 /* at least in some situations (screen + xterm under SuSE11/12) endwin()
362 * doesn't properly flush the screen without an explicit call. */
363 mutt_refresh();
364 endwin();
365
366 errno = e;
367}
368
373void mutt_perror_debug(const char *s)
374{
375 char *p = strerror(errno);
376
377 mutt_debug(LL_DEBUG1, "%s: %s (errno = %d)\n", s, p ? p : "unknown error", errno);
378 mutt_error("%s: %s (errno = %d)", s, p ? p : _("unknown error"), errno);
379}
380
387int mutt_any_key_to_continue(const char *s)
388{
389 struct termios term;
390 struct termios old;
391
392 int fd = open("/dev/tty", O_RDONLY);
393 if (fd < 0)
394 return EOF;
395
396 tcgetattr(fd, &old); // Save the current tty settings
397
398 term = old;
399 term.c_lflag &= ~(ICANON | ECHO); // Canonical (not line-buffered), don't echo the characters
400 term.c_cc[VMIN] = 1; // Wait for at least one character
401 term.c_cc[VTIME] = 255; // Wait for 25.5s
402 tcsetattr(fd, TCSANOW, &term);
403
404 if (s)
405 fputs(s, stdout);
406 else
407 fputs(_("Press any key to continue..."), stdout);
408 fflush(stdout);
409
410 char ch = '\0';
411 // Wait for a character. This might timeout, so loop.
412 while (read(fd, &ch, 1) == 0)
413 ; // do nothing
414
415 // Change the tty settings to be non-blocking
416 term.c_cc[VMIN] = 0; // Returning with zero characters is acceptable
417 term.c_cc[VTIME] = 0; // Don't wait
418 tcsetattr(fd, TCSANOW, &term);
419
420 char buf[64] = { 0 };
421 while (read(fd, buf, sizeof(buf)) > 0)
422 ; // Mop up any remaining chars
423
424 tcsetattr(fd, TCSANOW, &old); // Restore the previous tty settings
425 close(fd);
426
427 fputs("\r\n", stdout);
429 return (ch >= 0) ? ch : EOF;
430}
431
445int mutt_buffer_enter_fname(const char *prompt, struct Buffer *fname,
446 bool mailbox, struct Mailbox *m, bool multiple,
447 char ***files, int *numfiles, SelectFileFlags flags)
448{
449 struct MuttWindow *win = msgwin_get_window();
450 if (!win)
451 return -1;
452
453 struct KeyEvent ch = { OP_NULL, OP_NULL };
454 struct MuttWindow *old_focus = window_set_focus(win);
455
457 mutt_window_mvaddstr(win, 0, 0, prompt);
458 mutt_window_addstr(win, _(" ('?' for list): "));
460 if (!mutt_buffer_is_empty(fname))
463 mutt_refresh();
464
466 do
467 {
468 ch = mutt_getch();
469 } while (ch.op == OP_TIMEOUT);
471
472 mutt_window_move(win, 0, 0);
474 mutt_refresh();
475 window_set_focus(old_focus);
476
477 if (ch.ch < 0)
478 {
479 return -1;
480 }
481 else if (ch.ch == '?')
482 {
483 mutt_buffer_reset(fname);
484
485 if (flags == MUTT_SEL_NO_FLAGS)
486 flags = MUTT_SEL_FOLDER;
487 if (multiple)
488 flags |= MUTT_SEL_MULTI;
489 if (mailbox)
490 flags |= MUTT_SEL_MAILBOX;
491 mutt_buffer_select_file(fname, flags, m, files, numfiles);
492 }
493 else
494 {
495 char *pc = mutt_mem_malloc(mutt_str_len(prompt) + 3);
496
497 sprintf(pc, "%s: ", prompt);
498 if (ch.op == OP_NULL)
499 mutt_unget_ch(ch.ch);
500 else
501 mutt_unget_op(ch.op);
502
503 mutt_buffer_alloc(fname, 1024);
505 multiple, m, files, numfiles) != 0)
506 {
507 mutt_buffer_reset(fname);
508 }
509 FREE(&pc);
510 }
511
512 return 0;
513}
514
521void mutt_unget_ch(int ch)
522{
523 array_add(&UngetKeyEvents, ch, OP_NULL);
524}
525
532void mutt_unget_op(int op)
533{
534 array_add(&UngetKeyEvents, 0, op);
535}
536
543void mutt_unget_string(const char *s)
544{
545 const char *p = s + mutt_str_len(s) - 1;
546
547 while (p >= s)
548 {
549 mutt_unget_ch((unsigned char) *p--);
550 }
551}
552
561void mutt_push_macro_event(int ch, int op)
562{
563 array_add(&MacroEvents, ch, op);
564}
565
573{
575}
576
585{
587}
588
593{
596 flushinp();
597}
598
606int mutt_addwch(struct MuttWindow *win, wchar_t wc)
607{
608 char buf[MB_LEN_MAX * 2];
609 mbstate_t mbstate = { 0 };
610 size_t n1, n2;
611
612 if (((n1 = wcrtomb(buf, wc, &mbstate)) == (size_t) (-1)) ||
613 ((n2 = wcrtomb(buf + n1, 0, &mbstate)) == (size_t) (-1)))
614 {
615 return -1; /* ERR */
616 }
617 else
618 {
619 return mutt_window_addstr(win, buf);
620 }
621}
622
639void mutt_simple_format(char *buf, size_t buflen, int min_width, int max_width,
640 enum FormatJustify justify, char pad_char,
641 const char *s, size_t n, bool arboreal)
642{
643 wchar_t wc = 0;
644 int w;
645 size_t k;
646 char scratch[MB_LEN_MAX] = { 0 };
647 mbstate_t mbstate1 = { 0 };
648 mbstate_t mbstate2 = { 0 };
649 bool escaped = false;
650
651 buflen--;
652 char *p = buf;
653 for (; n && (k = mbrtowc(&wc, s, n, &mbstate1)); s += k, n -= k)
654 {
655 if ((k == (size_t) (-1)) || (k == (size_t) (-2)))
656 {
657 if ((k == (size_t) (-1)) && (errno == EILSEQ))
658 memset(&mbstate1, 0, sizeof(mbstate1));
659
660 k = (k == (size_t) (-1)) ? 1 : n;
661 wc = ReplacementChar;
662 }
663 if (escaped)
664 {
665 escaped = false;
666 w = 0;
667 }
668 else if (arboreal && (wc == MUTT_SPECIAL_INDEX))
669 {
670 escaped = true;
671 w = 0;
672 }
673 else if (arboreal && (wc < MUTT_TREE_MAX))
674 {
675 w = 1; /* hack */
676 }
677 else
678 {
679#ifdef HAVE_ISWBLANK
680 if (iswblank(wc))
681 wc = ' ';
682 else
683#endif
684 if (!IsWPrint(wc))
685 wc = '?';
686 w = wcwidth(wc);
687 }
688 if (w >= 0)
689 {
690 if (w > max_width)
691 continue;
692 size_t k2 = wcrtomb(scratch, wc, &mbstate2);
693 if ((k2 == (size_t) -1) || (k2 > buflen))
694 continue;
695
696 min_width -= w;
697 max_width -= w;
698 strncpy(p, scratch, k2);
699 p += k2;
700 buflen -= k2;
701 }
702 }
703 w = ((int) buflen < min_width) ? buflen : min_width;
704 if (w <= 0)
705 *p = '\0';
706 else if (justify == JUSTIFY_RIGHT) /* right justify */
707 {
708 p[w] = '\0';
709 while (--p >= buf)
710 p[w] = *p;
711 while (--w >= 0)
712 buf[w] = pad_char;
713 }
714 else if (justify == JUSTIFY_CENTER) /* center */
715 {
716 char *savedp = p;
717 int half = (w + 1) / 2; /* half of cushion space */
718
719 p[w] = '\0';
720
721 /* move str to center of buffer */
722 while (--p >= buf)
723 p[half] = *p;
724
725 /* fill rhs */
726 p = savedp + half;
727 while (--w >= half)
728 *p++ = pad_char;
729
730 /* fill lhs */
731 while (half--)
732 buf[half] = pad_char;
733 }
734 else /* left justify */
735 {
736 while (--w >= 0)
737 *p++ = pad_char;
738 *p = '\0';
739 }
740}
741
756void mutt_format_s_x(char *buf, size_t buflen, const char *prec, const char *s, bool arboreal)
757{
758 enum FormatJustify justify = JUSTIFY_RIGHT;
759 char *p = NULL;
760 int min_width;
761 int max_width = INT_MAX;
762
763 if (*prec == '-')
764 {
765 prec++;
766 justify = JUSTIFY_LEFT;
767 }
768 else if (*prec == '=')
769 {
770 prec++;
771 justify = JUSTIFY_CENTER;
772 }
773 min_width = strtol(prec, &p, 10);
774 if (*p == '.')
775 {
776 prec = p + 1;
777 max_width = strtol(prec, &p, 10);
778 if (p <= prec)
779 max_width = INT_MAX;
780 }
781
782 mutt_simple_format(buf, buflen, min_width, max_width, justify, ' ', s,
783 mutt_str_len(s), arboreal);
784}
785
793void mutt_format_s(char *buf, size_t buflen, const char *prec, const char *s)
794{
795 mutt_format_s_x(buf, buflen, prec, s, false);
796}
797
805void mutt_format_s_tree(char *buf, size_t buflen, const char *prec, const char *s)
806{
807 mutt_format_s_x(buf, buflen, prec, s, true);
808}
809
816void mutt_paddstr(struct MuttWindow *win, int n, const char *s)
817{
818 wchar_t wc = 0;
819 size_t k;
820 size_t len = mutt_str_len(s);
821 mbstate_t mbstate = { 0 };
822
823 for (; len && (k = mbrtowc(&wc, s, len, &mbstate)); s += k, len -= k)
824 {
825 if ((k == (size_t) (-1)) || (k == (size_t) (-2)))
826 {
827 if (k == (size_t) (-1))
828 memset(&mbstate, 0, sizeof(mbstate));
829 k = (k == (size_t) (-1)) ? 1 : len;
830 wc = ReplacementChar;
831 }
832 if (!IsWPrint(wc))
833 wc = '?';
834 const int w = wcwidth(wc);
835 if (w >= 0)
836 {
837 if (w > n)
838 break;
839 mutt_window_addnstr(win, (char *) s, k);
840 n -= w;
841 }
842 }
843 while (n-- > 0)
844 mutt_window_addch(win, ' ');
845}
846
858size_t mutt_wstr_trunc(const char *src, size_t maxlen, size_t maxwid, size_t *width)
859{
860 wchar_t wc = 0;
861 size_t n, w = 0, l = 0, cl;
862 int cw;
863 mbstate_t mbstate = { 0 };
864
865 if (!src)
866 goto out;
867
868 n = mutt_str_len(src);
869
870 for (w = 0; n && (cl = mbrtowc(&wc, src, n, &mbstate)); src += cl, n -= cl)
871 {
872 if ((cl == (size_t) (-1)) || (cl == (size_t) (-2)))
873 {
874 if (cl == (size_t) (-1))
875 memset(&mbstate, 0, sizeof(mbstate));
876 cl = (cl == (size_t) (-1)) ? 1 : n;
877 wc = ReplacementChar;
878 }
879 cw = wcwidth(wc);
880 /* hack because MUTT_TREE symbols aren't turned into characters
881 * until rendered by print_enriched_string() */
882 if ((cw < 0) && (src[0] == MUTT_SPECIAL_INDEX))
883 {
884 cl = 2; /* skip the index coloring sequence */
885 cw = 0;
886 }
887 else if ((cw < 0) && (cl == 1) && (src[0] != '\0') && (src[0] < MUTT_TREE_MAX))
888 cw = 1;
889 else if (cw < 0)
890 cw = 0; /* unprintable wchar */
891 if ((cl + l > maxlen) || (cw + w > maxwid))
892 break;
893 l += cl;
894 w += cw;
895 }
896out:
897 if (width)
898 *width = w;
899 return l;
900}
901
907size_t mutt_strwidth(const char *s)
908{
909 if (!s)
910 return 0;
911 return mutt_strnwidth(s, mutt_str_len(s));
912}
913
920size_t mutt_strnwidth(const char *s, size_t n)
921{
922 if (!s)
923 return 0;
924
925 wchar_t wc = 0;
926 int w;
927 size_t k;
928 mbstate_t mbstate = { 0 };
929
930 for (w = 0; n && (k = mbrtowc(&wc, s, n, &mbstate)); s += k, n -= k)
931 {
932 if (*s == MUTT_SPECIAL_INDEX)
933 {
934 s += 2; /* skip the index coloring sequence */
935 k = 0;
936 continue;
937 }
938
939 if ((k == (size_t) (-1)) || (k == (size_t) (-2)))
940 {
941 if (k == (size_t) (-1))
942 memset(&mbstate, 0, sizeof(mbstate));
943 k = (k == (size_t) (-1)) ? 1 : n;
944 wc = ReplacementChar;
945 }
946 if (!IsWPrint(wc))
947 wc = '?';
948 w += wcwidth(wc);
949 }
950 return w;
951}
#define ARRAY_SHRINK(head, num)
Mark a number of slots at the end of the array as unused.
Definition: array.h:171
#define ARRAY_ADD(head, elem)
Add an element at the end of the array.
Definition: array.h:155
#define ARRAY_LAST(head)
Convenience method to get the last element.
Definition: array.h:143
#define ARRAY_EMPTY(head)
Check if an array is empty.
Definition: array.h:73
#define ARRAY_SIZE(head)
The number of elements stored.
Definition: array.h:86
#define ARRAY_HEAD_INITIALIZER
Static initializer for arrays.
Definition: array.h:57
Select a Mailbox from a list.
#define MUTT_SEL_MAILBOX
Select a mailbox.
Definition: lib.h:56
#define MUTT_SEL_FOLDER
Select a local directory.
Definition: lib.h:58
#define MUTT_SEL_MULTI
Multi-selection is enabled.
Definition: lib.h:57
#define MUTT_SEL_NO_FLAGS
No flags are set.
Definition: lib.h:55
uint8_t SelectFileFlags
Flags for mutt_select_file(), e.g. MUTT_SEL_MAILBOX.
Definition: lib.h:54
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:1088
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:275
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:260
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:85
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:54
@ MT_COLOR_PROMPT
Question/user input.
Definition: color.h:57
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
Convenience wrapper for the config headers.
Convenience wrapper for the core headers.
void mutt_edit_file(const char *editor, const char *file)
Let the user edit a file.
Definition: curs_lib.c:312
size_t mutt_strnwidth(const char *s, size_t n)
Measure a string's width in screen cells.
Definition: curs_lib.c:920
static struct KeyEventArray MacroEvents
Definition: curs_lib.c:74
struct KeyEvent mutt_getch_timeout(int delay)
Get an event with a timeout.
Definition: curs_lib.c:197
void mutt_flushinp(void)
Empty all the keyboard buffers.
Definition: curs_lib.c:592
static struct KeyEventArray UngetKeyEvents
Definition: curs_lib.c:78
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:858
static void array_add(struct KeyEventArray *a, int ch, int op)
Add an event to the end of the array.
Definition: curs_lib.c:103
static void array_to_endcond(struct KeyEventArray *a)
Clear the array until an OP_END_COND.
Definition: curs_lib.c:113
struct KeyEvent mutt_getch(void)
Read a character from the input buffer.
Definition: curs_lib.c:242
void mutt_unget_string(const char *s)
Return a string to the input buffer.
Definition: curs_lib.c:543
void mutt_push_macro_event(int ch, int op)
Add the character/operation to the macro buffer.
Definition: curs_lib.c:561
static struct KeyEvent * array_pop(struct KeyEventArray *a)
Remove an event from the array.
Definition: curs_lib.c:85
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:445
void mutt_paddstr(struct MuttWindow *win, int n, const char *s)
Display a string on screen, padded if necessary.
Definition: curs_lib.c:816
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:756
void mutt_unget_op(int op)
Return an operation to the input buffer.
Definition: curs_lib.c:532
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:805
void mutt_refresh(void)
Force a refresh of the screen.
Definition: curs_lib.c:140
static void set_timeout(int delay)
Set the getch() timeout.
Definition: curs_lib.c:181
void mutt_flush_unget_to_endcond(void)
Clear entries from UngetKeyEvents.
Definition: curs_lib.c:584
int mutt_addwch(struct MuttWindow *win, wchar_t wc)
Addwch would be provided by an up-to-date curses library.
Definition: curs_lib.c:606
void mutt_flush_macro_to_endcond(void)
Drop a macro from the input buffer.
Definition: curs_lib.c:572
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:639
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition: curs_lib.c:387
void mutt_need_hard_redraw(void)
Force a hard refresh.
Definition: curs_lib.c:162
static int mutt_monitor_getch(void)
Get a character and poll the filesystem monitor.
Definition: curs_lib.c:211
void mutt_query_exit(void)
Ask the user if they want to leave NeoMutt.
Definition: curs_lib.c:335
ARRAY_HEAD(KeyEventArray, struct KeyEvent)
void mutt_endwin(void)
Shutdown curses.
Definition: curs_lib.c:354
void mutt_beep(bool force)
Irritate the user.
Definition: curs_lib.c:130
size_t mutt_strwidth(const char *s)
Measure a string's width in screen cells.
Definition: curs_lib.c:907
void mutt_unget_ch(int ch)
Return a keystroke to the input buffer.
Definition: curs_lib.c:521
void mutt_perror_debug(const char *s)
Show the user an 'errno' message.
Definition: curs_lib.c:373
void mutt_format_s(char *buf, size_t buflen, const char *prec, const char *s)
Format a simple string.
Definition: curs_lib.c:793
int MuttGetchTimeout
Timeout in ms for mutt_getch()
Definition: curs_lib.c:124
GUI miscellaneous curses (window drawing) routines.
FormatJustify
Alignment for mutt_simple_format()
Definition: curs_lib.h:41
@ JUSTIFY_RIGHT
Right justify the text.
Definition: curs_lib.h:44
@ JUSTIFY_LEFT
Left justify the text.
Definition: curs_lib.h:42
@ JUSTIFY_CENTER
Centre the text.
Definition: curs_lib.h:43
Enter a string.
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: window.c:180
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:1488
#define mutt_error(...)
Definition: logging.h:87
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
keycode_t AbortKey
code of key to abort prompts, normally Ctrl-G
Definition: keymap.c:124
Manage keymappings.
@ LL_DEBUG1
Log at debug level 1.
Definition: logging.h:40
void mutt_exit(int code)
Leave NeoMutt NOW.
Definition: main.c:248
#define IsWPrint(wc)
Definition: mbyte.h:39
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
#define FREE(x)
Definition: memory.h:43
int mutt_monitor_poll(void)
Check for filesystem changes.
Definition: monitor.c:399
Monitor files for changes.
struct MuttWindow * msgwin_get_window(void)
Get the Message Window pointer.
Definition: msgwin.c:260
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 _(a)
Definition: message.h:28
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:567
Many unsorted constants and some structs.
#define MUTT_COMP_FILE
File completion (in browser)
Definition: mutt.h:55
#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
enum MuttCursorState mutt_curses_set_cursor(enum MuttCursorState state)
Set the cursor state.
Definition: mutt_curses.c:96
struct AttrColor * mutt_curses_set_normal_backed_color_by_id(enum ColorId cid)
Set the colour and attributes by the colour id.
Definition: mutt_curses.c:65
struct AttrColor * mutt_curses_set_color_by_id(enum ColorId cid)
Set the colour and attributes by the colour id.
Definition: mutt_curses.c:81
Define wrapper functions around Curses.
void mutt_resize_screen(void)
Update NeoMutt's opinion about the window size (CURSES)
Definition: resize.c:73
MuttCursorState
Cursor states for mutt_curses_set_cursor()
Definition: mutt_curses.h:52
@ MUTT_CURSOR_VISIBLE
Display a normal cursor.
Definition: mutt_curses.h:54
Hundreds of global variables to back the user variables.
SIG_ATOMIC_VOLATILE_T SigInt
true after SIGINT is received
Definition: mutt_globals.h:69
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:74
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:604
int mutt_window_move(struct MuttWindow *win, int col, int row)
Move the cursor in a Window.
Definition: mutt_window.c:293
struct MuttWindow * window_set_focus(struct MuttWindow *win)
Set the Window focus.
Definition: mutt_window.c:659
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:307
int mutt_window_addstr(struct MuttWindow *win, const char *str)
Write a string to a Window.
Definition: mutt_window.c:409
int mutt_window_addnstr(struct MuttWindow *win, const char *str, int num)
Write a partial string to a Window.
Definition: mutt_window.c:394
void mutt_window_clrtoeol(struct MuttWindow *win)
Clear to the end of the line.
Definition: mutt_window.c:242
int mutt_window_addch(struct MuttWindow *win, int ch)
Write one character to a Window.
Definition: mutt_window.c:381
Window management.
All user-callable functions.
#define OP_TIMEOUT
Definition: opcodes.h:32
#define OP_ABORT
Definition: opcodes.h:33
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:194
void mutt_sig_allow_interrupt(bool allow)
Allow/disallow Ctrl-C (SIGINT)
Definition: signal.c:238
String manipulation buffer.
Definition: buffer.h:34
An event such as a keypress.
Definition: keymap.h:65
int op
Function opcode, e.g. OP_HELP.
Definition: keymap.h:67
int ch
Raw key pressed.
Definition: keymap.h:66
A mailbox.
Definition: mailbox.h:79
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39