NeoMutt  2023-05-17-56-ga67199
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 "globals.h"
51#include "keymap.h"
52#include "msgwin.h"
53#include "mutt_curses.h"
54#include "mutt_logging.h"
55#include "mutt_thread.h"
56#include "mutt_window.h"
57#include "opcodes.h"
58#include "protos.h"
59#ifdef HAVE_ISWBLANK
60#include <wctype.h>
61#endif
62#ifdef USE_INOTIFY
63#include "monitor.h"
64#endif
65
66/* not possible to unget more than one char under some curses libs, so roll our
67 * own input buffering routines. */
68
69ARRAY_HEAD(KeyEventArray, struct KeyEvent);
70
73static struct KeyEventArray MacroEvents = ARRAY_HEAD_INITIALIZER;
74
77static struct KeyEventArray UngetKeyEvents = ARRAY_HEAD_INITIALIZER;
78
84static struct KeyEvent *array_pop(struct KeyEventArray *a)
85{
86 if (ARRAY_EMPTY(a))
87 {
88 return NULL;
89 }
90
91 struct KeyEvent *event = ARRAY_LAST(a);
92 ARRAY_SHRINK(a, 1);
93 return event;
94}
95
102static void array_add(struct KeyEventArray *a, int ch, int op)
103{
104 struct KeyEvent event = { .ch = ch, .op = op };
105 ARRAY_ADD(a, event);
106}
107
112static void array_to_endcond(struct KeyEventArray *a)
113{
114 while (!ARRAY_EMPTY(a))
115 {
116 if (array_pop(a)->op == OP_END_COND)
117 {
118 return;
119 }
120 }
121}
122
126
131void mutt_beep(bool force)
132{
133 const bool c_beep = cs_subset_bool(NeoMutt->sub, "beep");
134 if (force || c_beep)
135 beep();
136}
137
141void mutt_refresh(void)
142{
143 /* don't refresh when we are waiting for a child. */
144 if (OptKeepQuiet)
145 return;
146
147 /* don't refresh in the middle of macros unless necessary */
149 return;
150
151 /* else */
152 refresh();
153}
154
164{
165 // Forcibly switch to the alternate screen.
166 // Using encryption can leave ncurses confused about which mode it's in.
167 fputs("\033[?1049h", stdout);
168 fflush(stdout);
169 keypad(stdscr, true);
170 clearok(stdscr, true);
171 window_redraw(NULL);
172}
173
182static void set_timeout(int delay)
183{
184 MuttGetchTimeout = delay;
185 timeout(delay);
186}
187
199{
200 set_timeout(delay);
201 struct KeyEvent event = mutt_getch();
202 set_timeout(-1);
203 return event;
204}
205
206#ifdef USE_INOTIFY
212static int mutt_monitor_getch(void)
213{
214 /* ncurses has its own internal buffer, so before we perform a poll,
215 * we need to make sure there isn't a character waiting */
216 timeout(0);
217 int ch = getch();
218 timeout(MuttGetchTimeout);
219 if (ch == ERR)
220 {
221 if (mutt_monitor_poll() != 0)
222 ch = ERR;
223 else
224 ch = getch();
225 }
226 return ch;
227}
228#endif /* USE_INOTIFY */
229
244{
245 int ch;
246 const struct KeyEvent err = { 0, OP_ABORT };
247 const struct KeyEvent timeout = { 0, OP_TIMEOUT };
248
249 struct KeyEvent *key = array_pop(&UngetKeyEvents);
250 if (key)
251 {
252 return *key;
253 }
254
256 {
257 return *key;
258 }
259
260 SigInt = false;
261
263#ifdef KEY_RESIZE
264 /* ncurses 4.2 sends this when the screen is resized */
265 ch = KEY_RESIZE;
266 while (ch == KEY_RESIZE)
267#endif
268#ifdef USE_INOTIFY
270#else
271 ch = getch();
272#endif
274
275 if (SigInt)
276 {
278 return err;
279 }
280
281 /* either timeout, a sigwinch (if timeout is set), the terminal
282 * has been lost, or curses was never initialized */
283 if (ch == ERR)
284 {
285 if (!isatty(0))
286 {
287 mutt_exit(1);
288 }
289
290 return OptNoCurses ? err : timeout;
291 }
292
293 const bool c_meta_key = cs_subset_bool(NeoMutt->sub, "meta_key");
294 if ((ch & 0x80) && c_meta_key)
295 {
296 /* send ALT-x as ESC-x */
297 ch &= ~0x80;
299 return (struct KeyEvent){ .ch = '\033' /* Escape */, .op = OP_NULL };
300 }
301
302 if (ch == AbortKey)
303 return err;
304
305 return (struct KeyEvent){ .ch = ch, .op = OP_NULL };
306}
307
313void mutt_edit_file(const char *editor, const char *file)
314{
315 struct Buffer *cmd = buf_pool_get();
316
317 mutt_endwin();
318 buf_file_expand_fmt_quote(cmd, editor, file);
319 if (mutt_system(buf_string(cmd)) != 0)
320 {
321 mutt_error(_("Error running \"%s\""), buf_string(cmd));
322 }
323 /* the terminal may have been resized while the editor owned it */
325 keypad(stdscr, true);
326 clearok(stdscr, true);
327
328 buf_pool_release(&cmd);
329}
330
337{
340 const short c_timeout = cs_subset_number(NeoMutt->sub, "timeout");
341 if (c_timeout)
342 set_timeout(-1); /* restore blocking operation */
343 if (mutt_yesorno(_("Exit NeoMutt without saving?"), MUTT_YES) == MUTT_YES)
344 {
345 mutt_exit(0); /* This call never returns */
346 }
349 SigInt = false;
350}
351
355void mutt_endwin(void)
356{
357 if (OptNoCurses)
358 return;
359
360 int e = errno;
361
362 /* at least in some situations (screen + xterm under SuSE11/12) endwin()
363 * doesn't properly flush the screen without an explicit call. */
364 mutt_refresh();
365 endwin();
366
367 errno = e;
368}
369
374void mutt_perror_debug(const char *s)
375{
376 char *p = strerror(errno);
377
378 mutt_debug(LL_DEBUG1, "%s: %s (errno = %d)\n", s, p ? p : "unknown error", errno);
379 mutt_error("%s: %s (errno = %d)", s, p ? p : _("unknown error"), errno);
380}
381
388int mutt_any_key_to_continue(const char *s)
389{
390 struct termios term;
391 struct termios old;
392
393 int fd = open("/dev/tty", O_RDONLY);
394 if (fd < 0)
395 return EOF;
396
397 tcgetattr(fd, &old); // Save the current tty settings
398
399 term = old;
400 term.c_lflag &= ~(ICANON | ECHO); // Canonical (not line-buffered), don't echo the characters
401 term.c_cc[VMIN] = 1; // Wait for at least one character
402 term.c_cc[VTIME] = 255; // Wait for 25.5s
403 tcsetattr(fd, TCSANOW, &term);
404
405 if (s)
406 fputs(s, stdout);
407 else
408 fputs(_("Press any key to continue..."), stdout);
409 fflush(stdout);
410
411 char ch = '\0';
412 // Wait for a character. This might timeout, so loop.
413 while (read(fd, &ch, 1) == 0)
414 ; // do nothing
415
416 // Change the tty settings to be non-blocking
417 term.c_cc[VMIN] = 0; // Returning with zero characters is acceptable
418 term.c_cc[VTIME] = 0; // Don't wait
419 tcsetattr(fd, TCSANOW, &term);
420
421 char buf[64] = { 0 };
422 while (read(fd, buf, sizeof(buf)) > 0)
423 ; // Mop up any remaining chars
424
425 tcsetattr(fd, TCSANOW, &old); // Restore the previous tty settings
426 close(fd);
427
428 fputs("\r\n", stdout);
430 return (ch >= 0) ? ch : EOF;
431}
432
446int buf_enter_fname(const char *prompt, struct Buffer *fname, bool mailbox,
447 struct Mailbox *m, bool multiple, char ***files,
448 int *numfiles, SelectFileFlags flags)
449{
450 struct MuttWindow *win = msgwin_get_window();
451 if (!win)
452 return -1;
453
454 struct KeyEvent ch = { OP_NULL, OP_NULL };
455 struct MuttWindow *old_focus = window_set_focus(win);
456
458 mutt_window_mvaddstr(win, 0, 0, prompt);
459 mutt_window_addstr(win, _(" ('?' for list): "));
461 if (!buf_is_empty(fname))
462 mutt_window_addstr(win, buf_string(fname));
464 mutt_refresh();
465
467 do
468 {
469 ch = mutt_getch();
470 } while (ch.op == OP_TIMEOUT);
472
473 mutt_window_move(win, 0, 0);
475 mutt_refresh();
476 window_set_focus(old_focus);
477
478 if (ch.ch < 0)
479 {
480 return -1;
481 }
482 else if (ch.ch == '?')
483 {
484 buf_reset(fname);
485
486 if (flags == MUTT_SEL_NO_FLAGS)
487 flags = MUTT_SEL_FOLDER;
488 if (multiple)
489 flags |= MUTT_SEL_MULTI;
490 if (mailbox)
491 flags |= MUTT_SEL_MAILBOX;
492 buf_select_file(fname, flags, m, files, numfiles);
493 }
494 else
495 {
496 char *pc = mutt_mem_malloc(mutt_str_len(prompt) + 3);
497
498 sprintf(pc, "%s: ", prompt);
499 if (ch.op == OP_NULL)
500 mutt_unget_ch(ch.ch);
501 else
502 mutt_unget_op(ch.op);
503
504 buf_alloc(fname, 1024);
506 multiple, m, files, numfiles) != 0)
507 {
508 buf_reset(fname);
509 }
510 FREE(&pc);
511 }
512
513 return 0;
514}
515
522void mutt_unget_ch(int ch)
523{
524 array_add(&UngetKeyEvents, ch, OP_NULL);
525}
526
533void mutt_unget_op(int op)
534{
535 array_add(&UngetKeyEvents, 0, op);
536}
537
544void mutt_unget_string(const char *s)
545{
546 const char *p = s + mutt_str_len(s) - 1;
547
548 while (p >= s)
549 {
550 mutt_unget_ch((unsigned char) *p--);
551 }
552}
553
562void mutt_push_macro_event(int ch, int op)
563{
564 array_add(&MacroEvents, ch, op);
565}
566
574{
576}
577
586{
588}
589
594{
597 flushinp();
598}
599
607int mutt_addwch(struct MuttWindow *win, wchar_t wc)
608{
609 char buf[MB_LEN_MAX * 2];
610 mbstate_t mbstate = { 0 };
611 size_t n1, n2;
612
613 if (((n1 = wcrtomb(buf, wc, &mbstate)) == ICONV_ILLEGAL_SEQ) ||
614 ((n2 = wcrtomb(buf + n1, 0, &mbstate)) == ICONV_ILLEGAL_SEQ))
615 {
616 return -1; /* ERR */
617 }
618 else
619 {
620 return mutt_window_addstr(win, buf);
621 }
622}
623
640void mutt_simple_format(char *buf, size_t buflen, int min_width, int max_width,
641 enum FormatJustify justify, char pad_char,
642 const char *s, size_t n, bool arboreal)
643{
644 wchar_t wc = 0;
645 int w;
646 size_t k;
647 char scratch[MB_LEN_MAX] = { 0 };
648 mbstate_t mbstate1 = { 0 };
649 mbstate_t mbstate2 = { 0 };
650 bool escaped = false;
651
652 buflen--;
653 char *p = buf;
654 for (; n && (k = mbrtowc(&wc, s, n, &mbstate1)); s += k, n -= k)
655 {
656 if ((k == ICONV_ILLEGAL_SEQ) || (k == ICONV_BUF_TOO_SMALL))
657 {
658 if ((k == ICONV_ILLEGAL_SEQ) && (errno == EILSEQ))
659 memset(&mbstate1, 0, sizeof(mbstate1));
660
661 k = (k == ICONV_ILLEGAL_SEQ) ? 1 : n;
662 wc = ReplacementChar;
663 }
664 if (escaped)
665 {
666 escaped = false;
667 w = 0;
668 }
669 else if (arboreal && (wc == MUTT_SPECIAL_INDEX))
670 {
671 escaped = true;
672 w = 0;
673 }
674 else if (arboreal && (wc < MUTT_TREE_MAX))
675 {
676 w = 1; /* hack */
677 }
678 else
679 {
680#ifdef HAVE_ISWBLANK
681 if (iswblank(wc))
682 wc = ' ';
683 else
684#endif
685 if (!IsWPrint(wc))
686 wc = '?';
687 w = wcwidth(wc);
688 }
689 if (w >= 0)
690 {
691 if (w > max_width)
692 continue;
693 size_t k2 = wcrtomb(scratch, wc, &mbstate2);
694 if ((k2 == ICONV_ILLEGAL_SEQ) || (k2 > buflen))
695 continue;
696
697 min_width -= w;
698 max_width -= w;
699 strncpy(p, scratch, k2);
700 p += k2;
701 buflen -= k2;
702 }
703 }
704 w = ((int) buflen < min_width) ? buflen : min_width;
705 if (w <= 0)
706 {
707 *p = '\0';
708 }
709 else if (justify == JUSTIFY_RIGHT) /* right justify */
710 {
711 p[w] = '\0';
712 while (--p >= buf)
713 p[w] = *p;
714 while (--w >= 0)
715 buf[w] = pad_char;
716 }
717 else if (justify == JUSTIFY_CENTER) /* center */
718 {
719 char *savedp = p;
720 int half = (w + 1) / 2; /* half of cushion space */
721
722 p[w] = '\0';
723
724 /* move str to center of buffer */
725 while (--p >= buf)
726 p[half] = *p;
727
728 /* fill rhs */
729 p = savedp + half;
730 while (--w >= half)
731 *p++ = pad_char;
732
733 /* fill lhs */
734 while (half--)
735 buf[half] = pad_char;
736 }
737 else /* left justify */
738 {
739 while (--w >= 0)
740 *p++ = pad_char;
741 *p = '\0';
742 }
743}
744
759void mutt_format_s_x(char *buf, size_t buflen, const char *prec, const char *s, bool arboreal)
760{
761 enum FormatJustify justify = JUSTIFY_RIGHT;
762 char *p = NULL;
763 int min_width;
764 int max_width = INT_MAX;
765
766 if (*prec == '-')
767 {
768 prec++;
769 justify = JUSTIFY_LEFT;
770 }
771 else if (*prec == '=')
772 {
773 prec++;
774 justify = JUSTIFY_CENTER;
775 }
776 min_width = strtol(prec, &p, 10);
777 if (*p == '.')
778 {
779 prec = p + 1;
780 max_width = strtol(prec, &p, 10);
781 if (p <= prec)
782 max_width = INT_MAX;
783 }
784
785 mutt_simple_format(buf, buflen, min_width, max_width, justify, ' ', s,
786 mutt_str_len(s), arboreal);
787}
788
796void mutt_format_s(char *buf, size_t buflen, const char *prec, const char *s)
797{
798 mutt_format_s_x(buf, buflen, prec, s, false);
799}
800
808void mutt_format_s_tree(char *buf, size_t buflen, const char *prec, const char *s)
809{
810 mutt_format_s_x(buf, buflen, prec, s, true);
811}
812
819void mutt_paddstr(struct MuttWindow *win, int n, const char *s)
820{
821 wchar_t wc = 0;
822 size_t k;
823 size_t len = mutt_str_len(s);
824 mbstate_t mbstate = { 0 };
825
826 for (; len && (k = mbrtowc(&wc, s, len, &mbstate)); s += k, len -= k)
827 {
828 if ((k == ICONV_ILLEGAL_SEQ) || (k == ICONV_BUF_TOO_SMALL))
829 {
830 if (k == ICONV_ILLEGAL_SEQ)
831 memset(&mbstate, 0, sizeof(mbstate));
832 k = (k == ICONV_ILLEGAL_SEQ) ? 1 : len;
833 wc = ReplacementChar;
834 }
835 if (!IsWPrint(wc))
836 wc = '?';
837 const int w = wcwidth(wc);
838 if (w >= 0)
839 {
840 if (w > n)
841 break;
842 mutt_window_addnstr(win, (char *) s, k);
843 n -= w;
844 }
845 }
846 while (n-- > 0)
847 mutt_window_addch(win, ' ');
848}
849
861size_t mutt_wstr_trunc(const char *src, size_t maxlen, size_t maxwid, size_t *width)
862{
863 wchar_t wc = 0;
864 size_t n, w = 0, l = 0, cl;
865 int cw;
866 mbstate_t mbstate = { 0 };
867
868 if (!src)
869 goto out;
870
871 n = mutt_str_len(src);
872
873 for (w = 0; n && (cl = mbrtowc(&wc, src, n, &mbstate)); src += cl, n -= cl)
874 {
875 if ((cl == ICONV_ILLEGAL_SEQ) || (cl == ICONV_BUF_TOO_SMALL))
876 {
877 if (cl == ICONV_ILLEGAL_SEQ)
878 memset(&mbstate, 0, sizeof(mbstate));
879 cl = (cl == ICONV_ILLEGAL_SEQ) ? 1 : n;
880 wc = ReplacementChar;
881 }
882 cw = wcwidth(wc);
883 /* hack because MUTT_TREE symbols aren't turned into characters
884 * until rendered by print_enriched_string() */
885 if ((cw < 0) && (src[0] == MUTT_SPECIAL_INDEX))
886 {
887 cl = 2; /* skip the index coloring sequence */
888 cw = 0;
889 }
890 else if ((cw < 0) && (cl == 1) && (src[0] != '\0') && (src[0] < MUTT_TREE_MAX))
891 {
892 cw = 1;
893 }
894 else if (cw < 0)
895 {
896 cw = 0; /* unprintable wchar */
897 }
898 if ((cl + l > maxlen) || (cw + w > maxwid))
899 break;
900 l += cl;
901 w += cw;
902 }
903out:
904 if (width)
905 *width = w;
906 return l;
907}
908
914size_t mutt_strwidth(const char *s)
915{
916 if (!s)
917 return 0;
918 return mutt_strnwidth(s, mutt_str_len(s));
919}
920
927size_t mutt_strnwidth(const char *s, size_t n)
928{
929 if (!s)
930 return 0;
931
932 wchar_t wc = 0;
933 int w;
934 size_t k;
935 mbstate_t mbstate = { 0 };
936
937 for (w = 0; n && (k = mbrtowc(&wc, s, n, &mbstate)); s += k, n -= k)
938 {
939 if (*s == MUTT_SPECIAL_INDEX)
940 {
941 s += 2; /* skip the index coloring sequence */
942 k = 0;
943 continue;
944 }
945
946 if ((k == ICONV_ILLEGAL_SEQ) || (k == ICONV_BUF_TOO_SMALL))
947 {
948 if (k == ICONV_ILLEGAL_SEQ)
949 memset(&mbstate, 0, sizeof(mbstate));
950 k = (k == ICONV_ILLEGAL_SEQ) ? 1 : n;
951 wc = ReplacementChar;
952 }
953 if (!IsWPrint(wc))
954 wc = '?';
955 w += wcwidth(wc);
956 }
957 return w;
958}
#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 buf_select_file(struct Buffer *file, SelectFileFlags flags, struct Mailbox *m, char ***files, int *numfiles)
Let the user select a file.
Definition: browser.c:1160
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:88
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:303
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:347
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:90
Color and attribute parsing.
@ MT_COLOR_NORMAL
Plain text.
Definition: color.h:57
@ MT_COLOR_PROMPT
Question/user input.
Definition: color.h:60
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:313
size_t mutt_strnwidth(const char *s, size_t n)
Measure a string's width in screen cells.
Definition: curs_lib.c:927
static struct KeyEventArray MacroEvents
These are used for macros and exec/push commands.
Definition: curs_lib.c:73
struct KeyEvent mutt_getch_timeout(int delay)
Get an event with a timeout.
Definition: curs_lib.c:198
void mutt_flushinp(void)
Empty all the keyboard buffers.
Definition: curs_lib.c:593
static struct KeyEventArray UngetKeyEvents
These are used in all other "normal" situations, and are not ignored when setting OptIgnoreMacroEvent...
Definition: curs_lib.c:77
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:861
static void array_add(struct KeyEventArray *a, int ch, int op)
Add an event to the end of the array.
Definition: curs_lib.c:102
static void array_to_endcond(struct KeyEventArray *a)
Clear the array until an OP_END_COND.
Definition: curs_lib.c:112
struct KeyEvent mutt_getch(void)
Read a character from the input buffer.
Definition: curs_lib.c:243
void mutt_unget_string(const char *s)
Return a string to the input buffer.
Definition: curs_lib.c:544
void mutt_push_macro_event(int ch, int op)
Add the character/operation to the macro buffer.
Definition: curs_lib.c:562
static struct KeyEvent * array_pop(struct KeyEventArray *a)
Remove an event from the array.
Definition: curs_lib.c:84
void mutt_paddstr(struct MuttWindow *win, int n, const char *s)
Display a string on screen, padded if necessary.
Definition: curs_lib.c:819
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:759
void mutt_unget_op(int op)
Return an operation to the input buffer.
Definition: curs_lib.c:533
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:808
void mutt_refresh(void)
Force a refresh of the screen.
Definition: curs_lib.c:141
static void set_timeout(int delay)
Set the getch() timeout.
Definition: curs_lib.c:182
void mutt_flush_unget_to_endcond(void)
Clear entries from UngetKeyEvents.
Definition: curs_lib.c:585
int mutt_addwch(struct MuttWindow *win, wchar_t wc)
Addwch would be provided by an up-to-date curses library.
Definition: curs_lib.c:607
void mutt_flush_macro_to_endcond(void)
Drop a macro from the input buffer.
Definition: curs_lib.c:573
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:640
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition: curs_lib.c:388
void mutt_need_hard_redraw(void)
Force a hard refresh.
Definition: curs_lib.c:163
static int mutt_monitor_getch(void)
Get a character and poll the filesystem monitor.
Definition: curs_lib.c:212
void mutt_query_exit(void)
Ask the user if they want to leave NeoMutt.
Definition: curs_lib.c:336
ARRAY_HEAD(KeyEventArray, struct KeyEvent)
void mutt_endwin(void)
Shutdown curses.
Definition: curs_lib.c:355
void mutt_beep(bool force)
Irritate the user.
Definition: curs_lib.c:131
size_t mutt_strwidth(const char *s)
Measure a string's width in screen cells.
Definition: curs_lib.c:914
void mutt_unget_ch(int ch)
Return a keystroke to the input buffer.
Definition: curs_lib.c:522
void mutt_perror_debug(const char *s)
Show the user an 'errno' message.
Definition: curs_lib.c:374
void mutt_format_s(char *buf, size_t buflen, const char *prec, const char *s)
Format a simple string.
Definition: curs_lib.c:796
int MuttGetchTimeout
Timeout for getting a character from the user.
Definition: curs_lib.c:125
int buf_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:446
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 buf_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 buf_file_expand_fmt_quote(struct Buffer *dest, const char *fmt, const char *src)
Replace s in a string with a filename.
Definition: file.c:1475
bool OptKeepQuiet
(pseudo) shut up the message and refresh functions while we are executing an external program
Definition: globals.c:73
bool OptNoCurses
(pseudo) when sending in batch mode
Definition: globals.c:82
bool OptForceRefresh
(pseudo) refresh even during macros
Definition: globals.c:71
SIG_ATOMIC_VOLATILE_T SigInt
true after SIGINT is received
Definition: globals.c:59
bool OptIgnoreMacroEvents
(pseudo) don't process macro/push/exec events while set
Definition: globals.c:72
#define mutt_error(...)
Definition: logging2.h:90
#define mutt_debug(LEVEL,...)
Definition: logging2.h:87
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: logging2.h:43
void mutt_exit(int code)
Leave NeoMutt NOW.
Definition: main.c:241
#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:407
Monitor files for changes.
struct MuttWindow * msgwin_get_window(void)
Get the Message Window pointer.
Definition: msgwin.c:261
Message Window.
wchar_t ReplacementChar
When a Unicode character can't be displayed, use this instead.
Definition: charset.c:54
#define EILSEQ
Definition: charset.c:48
#define ICONV_BUF_TOO_SMALL
Error value for iconv() - Buffer too small.
Definition: charset.h:105
#define ICONV_ILLEGAL_SEQ
Error value for iconv() - Illegal sequence.
Definition: charset.h:103
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:568
Many unsorted constants and some structs.
#define MUTT_COMP_FILE
File completion (in browser)
Definition: mutt.h:58
#define MUTT_COMP_FILE_MBOX
File completion, plus incoming folders (in browser)
Definition: mutt.h:59
#define MUTT_COMP_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:65
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:72
MuttCursorState
Cursor states for mutt_curses_set_cursor()
Definition: mutt_curses.h:58
@ MUTT_CURSOR_VISIBLE
Display a normal cursor.
Definition: mutt_curses.h:60
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:73
NeoMutt Logging.
Create/manipulate threading in emails.
@ MUTT_TREE_MAX
Definition: mutt_thread.h:69
@ MUTT_SPECIAL_INDEX
Colour indicator.
Definition: mutt_thread.h:71
void window_redraw(struct MuttWindow *win)
Reflow, recalc and repaint a tree of Windows.
Definition: mutt_window.c:605
int mutt_window_move(struct MuttWindow *win, int col, int row)
Move the cursor in a Window.
Definition: mutt_window.c:294
struct MuttWindow * window_set_focus(struct MuttWindow *win)
Set the Window focus.
Definition: mutt_window.c:660
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:308
int mutt_window_addstr(struct MuttWindow *win, const char *str)
Write a string to a Window.
Definition: mutt_window.c:410
int mutt_window_addnstr(struct MuttWindow *win, const char *str, int num)
Write a partial string to a Window.
Definition: mutt_window.c:395
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:382
Window management.
All user-callable functions.
#define OP_TIMEOUT
Definition: opcodes.h:32
#define OP_ABORT
Definition: opcodes.h:33
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
Prototypes for many functions.
int mutt_system(const char *cmd)
Run an external command.
Definition: system.c:52
@ 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:252
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