NeoMutt  2023-03-22
Teaching an old dog new tricks
DOXYGEN
curs_lib.c File Reference

GUI miscellaneous curses (window drawing) routines. More...

#include "config.h"
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <wchar.h>
#include "mutt/lib.h"
#include "config/lib.h"
#include "core/lib.h"
#include "mutt.h"
#include "curs_lib.h"
#include "browser/lib.h"
#include "color/lib.h"
#include "enter/lib.h"
#include "question/lib.h"
#include "globals.h"
#include "keymap.h"
#include "msgwin.h"
#include "mutt_curses.h"
#include "mutt_logging.h"
#include "mutt_thread.h"
#include "mutt_window.h"
#include "opcodes.h"
#include "protos.h"
#include "monitor.h"
+ Include dependency graph for curs_lib.c:

Go to the source code of this file.

Functions

 ARRAY_HEAD (KeyEventArray, struct KeyEvent)
 
static struct KeyEventarray_pop (struct KeyEventArray *a)
 Remove an event from the array. More...
 
static void array_add (struct KeyEventArray *a, int ch, int op)
 Add an event to the end of the array. More...
 
static void array_to_endcond (struct KeyEventArray *a)
 Clear the array until an OP_END_COND. More...
 
void mutt_beep (bool force)
 Irritate the user. More...
 
void mutt_refresh (void)
 Force a refresh of the screen. More...
 
void mutt_need_hard_redraw (void)
 Force a hard refresh. More...
 
static void set_timeout (int delay)
 Set the getch() timeout. More...
 
struct KeyEvent mutt_getch_timeout (int delay)
 Get an event with a timeout. More...
 
static int mutt_monitor_getch (void)
 Get a character and poll the filesystem monitor. More...
 
struct KeyEvent mutt_getch (void)
 Read a character from the input buffer. More...
 
void mutt_edit_file (const char *editor, const char *file)
 Let the user edit a file. More...
 
void mutt_query_exit (void)
 Ask the user if they want to leave NeoMutt. More...
 
void mutt_endwin (void)
 Shutdown curses. More...
 
void mutt_perror_debug (const char *s)
 Show the user an 'errno' message. More...
 
int mutt_any_key_to_continue (const char *s)
 Prompt the user to 'press any key' and wait. More...
 
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. More...
 
void mutt_unget_ch (int ch)
 Return a keystroke to the input buffer. More...
 
void mutt_unget_op (int op)
 Return an operation to the input buffer. More...
 
void mutt_unget_string (const char *s)
 Return a string to the input buffer. More...
 
void mutt_push_macro_event (int ch, int op)
 Add the character/operation to the macro buffer. More...
 
void mutt_flush_macro_to_endcond (void)
 Drop a macro from the input buffer. More...
 
void mutt_flush_unget_to_endcond (void)
 Clear entries from UngetKeyEvents. More...
 
void mutt_flushinp (void)
 Empty all the keyboard buffers. More...
 
int mutt_addwch (struct MuttWindow *win, wchar_t wc)
 Addwch would be provided by an up-to-date curses library. More...
 
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() More...
 
void mutt_format_s_x (char *buf, size_t buflen, const char *prec, const char *s, bool arboreal)
 Format a string like snprintf() More...
 
void mutt_format_s (char *buf, size_t buflen, const char *prec, const char *s)
 Format a simple string. More...
 
void mutt_format_s_tree (char *buf, size_t buflen, const char *prec, const char *s)
 Format a simple string with tree characters. More...
 
void mutt_paddstr (struct MuttWindow *win, int n, const char *s)
 Display a string on screen, padded if necessary. More...
 
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. More...
 
size_t mutt_strwidth (const char *s)
 Measure a string's width in screen cells. More...
 
size_t mutt_strnwidth (const char *s, size_t n)
 Measure a string's width in screen cells. More...
 

Variables

static struct KeyEventArray MacroEvents = ARRAY_HEAD_INITIALIZER
 
static struct KeyEventArray UngetKeyEvents = ARRAY_HEAD_INITIALIZER
 
int MuttGetchTimeout = -1
 Timeout in ms for mutt_getch() More...
 

Detailed Description

GUI miscellaneous curses (window drawing) routines.

Authors
  • Michael R. Elkins
  • g10 Code GmbH

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file curs_lib.c.

Function Documentation

◆ ARRAY_HEAD()

ARRAY_HEAD ( KeyEventArray  ,
struct KeyEvent   
)

◆ array_pop()

static struct KeyEvent * array_pop ( struct KeyEventArray *  a)
static

Remove an event from the array.

Parameters
aArray
Return values
ptrEvent

Definition at line 84 of file curs_lib.c.

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}
#define ARRAY_SHRINK(head, num)
Mark a number of slots at the end of the array as unused.
Definition: array.h:171
#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
An event such as a keypress.
Definition: keymap.h:65
+ Here is the caller graph for this function:

◆ array_add()

static void array_add ( struct KeyEventArray *  a,
int  ch,
int  op 
)
static

Add an event to the end of the array.

Parameters
aArray
chCharacter
opOperation, e.g. OP_DELETE

Definition at line 102 of file curs_lib.c.

103{
104 struct KeyEvent event = { .ch = ch, .op = op };
105 ARRAY_ADD(a, event);
106}
#define ARRAY_ADD(head, elem)
Add an element at the end of the array.
Definition: array.h:155
int op
Function opcode, e.g. OP_HELP.
Definition: keymap.h:67
int ch
Raw key pressed.
Definition: keymap.h:66
+ Here is the caller graph for this function:

◆ array_to_endcond()

static void array_to_endcond ( struct KeyEventArray *  a)
static

Clear the array until an OP_END_COND.

Parameters
aArray

Definition at line 112 of file curs_lib.c.

113{
114 while (!ARRAY_EMPTY(a))
115 {
116 if (array_pop(a)->op == OP_END_COND)
117 {
118 return;
119 }
120 }
121}
static struct KeyEvent * array_pop(struct KeyEventArray *a)
Remove an event from the array.
Definition: curs_lib.c:84
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_beep()

void mutt_beep ( bool  force)

Irritate the user.

Parameters
forceIf true, ignore the "$beep" config variable

Definition at line 129 of file curs_lib.c.

130{
131 const bool c_beep = cs_subset_bool(NeoMutt->sub, "beep");
132 if (force || c_beep)
133 beep();
134}
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_refresh()

void mutt_refresh ( void  )

Force a refresh of the screen.

Definition at line 139 of file curs_lib.c.

140{
141 /* don't refresh when we are waiting for a child. */
142 if (OptKeepQuiet)
143 return;
144
145 /* don't refresh in the middle of macros unless necessary */
147 return;
148
149 /* else */
150 refresh();
151}
static struct KeyEventArray MacroEvents
Definition: curs_lib.c:73
bool OptKeepQuiet
(pseudo) shut up the message and refresh functions while we are executing an external program
Definition: globals.c:72
bool OptForceRefresh
(pseudo) refresh even during macros
Definition: globals.c:70
bool OptIgnoreMacroEvents
(pseudo) don't process macro/push/exec events while set
Definition: globals.c:71
+ Here is the caller graph for this function:

◆ mutt_need_hard_redraw()

void mutt_need_hard_redraw ( void  )

Force a hard refresh.

Make sure that the next refresh does a full refresh. This could be optimized by not doing it at all if DISPLAY is set as this might indicate that a GUI based pinentry was used. Having an option to customize this is of course the NeoMutt way.

Definition at line 161 of file curs_lib.c.

162{
163 // Forcibly switch to the alternate screen.
164 // Using encryption can leave ncurses confused about which mode it's in.
165 fputs("\033[?1049h", stdout);
166 fflush(stdout);
167 keypad(stdscr, true);
168 clearok(stdscr, true);
169 window_redraw(NULL);
170}
void window_redraw(struct MuttWindow *win)
Reflow, recalc and repaint a tree of Windows.
Definition: mutt_window.c:603
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ set_timeout()

static void set_timeout ( int  delay)
static

Set the getch() timeout.

Parameters
delayTimeout delay in ms delay is just like for timeout() or poll(): the number of milliseconds mutt_getch() should block for input.
  • delay == 0 means mutt_getch() is non-blocking.
  • delay < 0 means mutt_getch is blocking.

Definition at line 180 of file curs_lib.c.

181{
182 MuttGetchTimeout = delay;
183 timeout(delay);
184}
int MuttGetchTimeout
Timeout in ms for mutt_getch()
Definition: curs_lib.c:123
+ Here is the caller graph for this function:

◆ mutt_getch_timeout()

struct KeyEvent mutt_getch_timeout ( int  delay)

Get an event with a timeout.

Parameters
delayTimeout delay in ms
Return values
Sameas mutt_get_ch

delay is just like for timeout() or poll(): the number of milliseconds mutt_getch() should block for input.

  • delay == 0 means mutt_getch() is non-blocking.
  • delay < 0 means mutt_getch is blocking.

Definition at line 196 of file curs_lib.c.

197{
198 set_timeout(delay);
199 struct KeyEvent event = mutt_getch();
200 set_timeout(-1);
201 return event;
202}
struct KeyEvent mutt_getch(void)
Read a character from the input buffer.
Definition: curs_lib.c:241
static void set_timeout(int delay)
Set the getch() timeout.
Definition: curs_lib.c:180
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_monitor_getch()

static int mutt_monitor_getch ( void  )
static

Get a character and poll the filesystem monitor.

Return values
numCharacter pressed
ERRTimeout

Definition at line 210 of file curs_lib.c.

211{
212 /* ncurses has its own internal buffer, so before we perform a poll,
213 * we need to make sure there isn't a character waiting */
214 timeout(0);
215 int ch = getch();
216 timeout(MuttGetchTimeout);
217 if (ch == ERR)
218 {
219 if (mutt_monitor_poll() != 0)
220 ch = ERR;
221 else
222 ch = getch();
223 }
224 return ch;
225}
int mutt_monitor_poll(void)
Check for filesystem changes.
Definition: monitor.c:398
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_getch()

struct KeyEvent mutt_getch ( void  )

Read a character from the input buffer.

Return values
objKeyEvent to process

The priority for reading events is:

  1. UngetKeyEvents buffer
  2. MacroEvents buffer
  3. Keyboard

This function can return:

  • Error { OP_ABORT, OP_NULL }
  • Timeout { OP_TIMEOUT, OP_NULL }

Definition at line 241 of file curs_lib.c.

242{
243 int ch;
244 const struct KeyEvent err = { 0, OP_ABORT };
245 const struct KeyEvent timeout = { 0, OP_TIMEOUT };
246
247 struct KeyEvent *key = array_pop(&UngetKeyEvents);
248 if (key)
249 {
250 return *key;
251 }
252
254 {
255 return *key;
256 }
257
258 SigInt = false;
259
261#ifdef KEY_RESIZE
262 /* ncurses 4.2 sends this when the screen is resized */
263 ch = KEY_RESIZE;
264 while (ch == KEY_RESIZE)
265#endif
266#ifdef USE_INOTIFY
268#else
269 ch = getch();
270#endif
272
273 if (SigInt)
274 {
276 return err;
277 }
278
279 /* either timeout, a sigwinch (if timeout is set), the terminal
280 * has been lost, or curses was never initialized */
281 if (ch == ERR)
282 {
283 if (!isatty(0))
284 {
285 mutt_exit(1);
286 }
287
288 return OptNoCurses ? err : timeout;
289 }
290
291 const bool c_meta_key = cs_subset_bool(NeoMutt->sub, "meta_key");
292 if ((ch & 0x80) && c_meta_key)
293 {
294 /* send ALT-x as ESC-x */
295 ch &= ~0x80;
297 return (struct KeyEvent){ .ch = '\033' /* Escape */, .op = OP_NULL };
298 }
299
300 if (ch == AbortKey)
301 return err;
302
303 return (struct KeyEvent){ .ch = ch, .op = OP_NULL };
304}
static struct KeyEventArray UngetKeyEvents
Definition: curs_lib.c:77
static int mutt_monitor_getch(void)
Get a character and poll the filesystem monitor.
Definition: curs_lib.c:210
void mutt_query_exit(void)
Ask the user if they want to leave NeoMutt.
Definition: curs_lib.c:334
void mutt_unget_ch(int ch)
Return a keystroke to the input buffer.
Definition: curs_lib.c:520
bool OptNoCurses
(pseudo) when sending in batch mode
Definition: globals.c:81
SIG_ATOMIC_VOLATILE_T SigInt
true after SIGINT is received
Definition: globals.c:58
keycode_t AbortKey
code of key to abort prompts, normally Ctrl-G
Definition: keymap.c:125
void mutt_exit(int code)
Leave NeoMutt NOW.
Definition: main.c:243
#define OP_TIMEOUT
Definition: opcodes.h:32
#define OP_ABORT
Definition: opcodes.h:33
void mutt_sig_allow_interrupt(bool allow)
Allow/disallow Ctrl-C (SIGINT)
Definition: signal.c:238
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_edit_file()

void mutt_edit_file ( const char *  editor,
const char *  file 
)

Let the user edit a file.

Parameters
editorUser's editor config
fileFile to edit

Definition at line 311 of file curs_lib.c.

312{
313 struct Buffer *cmd = mutt_buffer_pool_get();
314
315 mutt_endwin();
316 mutt_buffer_file_expand_fmt_quote(cmd, editor, file);
317 if (mutt_system(mutt_buffer_string(cmd)) != 0)
318 {
319 mutt_error(_("Error running \"%s\""), mutt_buffer_string(cmd));
320 }
321 /* the terminal may have been resized while the editor owned it */
323 keypad(stdscr, true);
324 clearok(stdscr, true);
325
327}
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:78
void mutt_endwin(void)
Shutdown curses.
Definition: curs_lib.c:353
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:1504
#define mutt_error(...)
Definition: logging.h:87
#define _(a)
Definition: message.h:28
void mutt_resize_screen(void)
Update NeoMutt's opinion about the window size (CURSES)
Definition: resize.c:72
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
int mutt_system(const char *cmd)
Run an external command.
Definition: system.c:51
String manipulation buffer.
Definition: buffer.h:34
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_query_exit()

void mutt_query_exit ( void  )

Ask the user if they want to leave NeoMutt.

This function is called when the user presses the abort key.

Definition at line 334 of file curs_lib.c.

335{
338 const short c_timeout = cs_subset_number(NeoMutt->sub, "timeout");
339 if (c_timeout)
340 set_timeout(-1); /* restore blocking operation */
341 if (mutt_yesorno(_("Exit NeoMutt without saving?"), MUTT_YES) == MUTT_YES)
342 {
343 mutt_exit(0); /* This call never returns */
344 }
347 SigInt = false;
348}
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:169
void mutt_flushinp(void)
Empty all the keyboard buffers.
Definition: curs_lib.c:591
enum MuttCursorState mutt_curses_set_cursor(enum MuttCursorState state)
Set the cursor state.
Definition: mutt_curses.c:96
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
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:73
@ MUTT_YES
User answered 'Yes', or assume 'Yes'.
Definition: quad.h:39
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: question.c:194
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_endwin()

void mutt_endwin ( void  )

Shutdown curses.

Definition at line 353 of file curs_lib.c.

354{
355 if (OptNoCurses)
356 return;
357
358 int e = errno;
359
360 /* at least in some situations (screen + xterm under SuSE11/12) endwin()
361 * doesn't properly flush the screen without an explicit call. */
362 mutt_refresh();
363 endwin();
364
365 errno = e;
366}
void mutt_refresh(void)
Force a refresh of the screen.
Definition: curs_lib.c:139
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_perror_debug()

void mutt_perror_debug ( const char *  s)

Show the user an 'errno' message.

Parameters
sAdditional text to show

Definition at line 372 of file curs_lib.c.

373{
374 char *p = strerror(errno);
375
376 mutt_debug(LL_DEBUG1, "%s: %s (errno = %d)\n", s, p ? p : "unknown error", errno);
377 mutt_error("%s: %s (errno = %d)", s, p ? p : _("unknown error"), errno);
378}
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
@ LL_DEBUG1
Log at debug level 1.
Definition: logging.h:40

◆ mutt_any_key_to_continue()

int mutt_any_key_to_continue ( const char *  s)

Prompt the user to 'press any key' and wait.

Parameters
sMessage prompt
Return values
numKey pressed
EOFError, or prompt aborted

Definition at line 386 of file curs_lib.c.

387{
388 struct termios term;
389 struct termios old;
390
391 int fd = open("/dev/tty", O_RDONLY);
392 if (fd < 0)
393 return EOF;
394
395 tcgetattr(fd, &old); // Save the current tty settings
396
397 term = old;
398 term.c_lflag &= ~(ICANON | ECHO); // Canonical (not line-buffered), don't echo the characters
399 term.c_cc[VMIN] = 1; // Wait for at least one character
400 term.c_cc[VTIME] = 255; // Wait for 25.5s
401 tcsetattr(fd, TCSANOW, &term);
402
403 if (s)
404 fputs(s, stdout);
405 else
406 fputs(_("Press any key to continue..."), stdout);
407 fflush(stdout);
408
409 char ch = '\0';
410 // Wait for a character. This might timeout, so loop.
411 while (read(fd, &ch, 1) == 0)
412 ; // do nothing
413
414 // Change the tty settings to be non-blocking
415 term.c_cc[VMIN] = 0; // Returning with zero characters is acceptable
416 term.c_cc[VTIME] = 0; // Don't wait
417 tcsetattr(fd, TCSANOW, &term);
418
419 char buf[64] = { 0 };
420 while (read(fd, buf, sizeof(buf)) > 0)
421 ; // Mop up any remaining chars
422
423 tcsetattr(fd, TCSANOW, &old); // Restore the previous tty settings
424 close(fd);
425
426 fputs("\r\n", stdout);
428 return (ch >= 0) ? ch : EOF;
429}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_buffer_enter_fname()

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.

Parameters
[in]promptPrompt
[in]fnameBuffer for the result
[in]mailboxIf true, select mailboxes
[in]multipleAllow multiple selections
[in]mMailbox
[out]filesList of files selected
[out]numfilesNumber of files selected
[in]flagsFlags, see SelectFileFlags
Return values
0Success
-1Error

Definition at line 444 of file curs_lib.c.

447{
448 struct MuttWindow *win = msgwin_get_window();
449 if (!win)
450 return -1;
451
452 struct KeyEvent ch = { OP_NULL, OP_NULL };
453 struct MuttWindow *old_focus = window_set_focus(win);
454
456 mutt_window_mvaddstr(win, 0, 0, prompt);
457 mutt_window_addstr(win, _(" ('?' for list): "));
459 if (!mutt_buffer_is_empty(fname))
462 mutt_refresh();
463
465 do
466 {
467 ch = mutt_getch();
468 } while (ch.op == OP_TIMEOUT);
470
471 mutt_window_move(win, 0, 0);
473 mutt_refresh();
474 window_set_focus(old_focus);
475
476 if (ch.ch < 0)
477 {
478 return -1;
479 }
480 else if (ch.ch == '?')
481 {
482 mutt_buffer_reset(fname);
483
484 if (flags == MUTT_SEL_NO_FLAGS)
485 flags = MUTT_SEL_FOLDER;
486 if (multiple)
487 flags |= MUTT_SEL_MULTI;
488 if (mailbox)
489 flags |= MUTT_SEL_MAILBOX;
490 mutt_buffer_select_file(fname, flags, m, files, numfiles);
491 }
492 else
493 {
494 char *pc = mutt_mem_malloc(mutt_str_len(prompt) + 3);
495
496 sprintf(pc, "%s: ", prompt);
497 if (ch.op == OP_NULL)
498 mutt_unget_ch(ch.ch);
499 else
500 mutt_unget_op(ch.op);
501
502 mutt_buffer_alloc(fname, 1024);
504 multiple, m, files, numfiles) != 0)
505 {
506 mutt_buffer_reset(fname);
507 }
508 FREE(&pc);
509 }
510
511 return 0;
512}
#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
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:1152
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:313
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:298
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:85
@ MT_COLOR_NORMAL
Plain text.
Definition: color.h:57
@ MT_COLOR_PROMPT
Question/user input.
Definition: color.h:60
void mutt_unget_op(int op)
Return an operation to the input buffer.
Definition: curs_lib.c:531
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:178
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
#define FREE(x)
Definition: memory.h:43
struct MuttWindow * msgwin_get_window(void)
Get the Message Window pointer.
Definition: msgwin.c:260
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:567
#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
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
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:658
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
int mutt_window_addstr(struct MuttWindow *win, const char *str)
Write a string to a Window.
Definition: mutt_window.c:408
void mutt_window_clrtoeol(struct MuttWindow *win)
Clear to the end of the line.
Definition: mutt_window.c:241
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_unget_ch()

void mutt_unget_ch ( int  ch)

Return a keystroke to the input buffer.

Parameters
chKey press

This puts events into the UngetKeyEvents buffer

Definition at line 520 of file curs_lib.c.

521{
522 array_add(&UngetKeyEvents, ch, OP_NULL);
523}
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
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_unget_op()

void mutt_unget_op ( int  op)

Return an operation to the input buffer.

Parameters
opOperation, e.g. OP_DELETE

This puts events into the UngetKeyEvents buffer

Definition at line 531 of file curs_lib.c.

532{
533 array_add(&UngetKeyEvents, 0, op);
534}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_unget_string()

void mutt_unget_string ( const char *  s)

Return a string to the input buffer.

Parameters
sString to return

This puts events into the UngetKeyEvents buffer

Definition at line 542 of file curs_lib.c.

543{
544 const char *p = s + mutt_str_len(s) - 1;
545
546 while (p >= s)
547 {
548 mutt_unget_ch((unsigned char) *p--);
549 }
550}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_push_macro_event()

void mutt_push_macro_event ( int  ch,
int  op 
)

Add the character/operation to the macro buffer.

Parameters
chCharacter to add
opOperation to add

Adds the ch/op to the macro buffer. This should be used for macros, push, and exec commands only.

Definition at line 560 of file curs_lib.c.

561{
562 array_add(&MacroEvents, ch, op);
563}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_flush_macro_to_endcond()

void mutt_flush_macro_to_endcond ( void  )

Drop a macro from the input buffer.

All the macro text is deleted until an OP_END_COND command, or the buffer is empty.

Definition at line 571 of file curs_lib.c.

572{
574}
static void array_to_endcond(struct KeyEventArray *a)
Clear the array until an OP_END_COND.
Definition: curs_lib.c:112
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_flush_unget_to_endcond()

void mutt_flush_unget_to_endcond ( void  )

Clear entries from UngetKeyEvents.

Normally, OP_END_COND should only be in the MacroEvent buffer. km_error_key() (ab)uses OP_END_COND as a barrier in the unget buffer, and calls this function to flush.

Definition at line 583 of file curs_lib.c.

584{
586}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_flushinp()

void mutt_flushinp ( void  )

Empty all the keyboard buffers.

Definition at line 591 of file curs_lib.c.

592{
595 flushinp();
596}
#define ARRAY_SIZE(head)
The number of elements stored.
Definition: array.h:86
+ Here is the caller graph for this function:

◆ mutt_addwch()

int mutt_addwch ( struct MuttWindow win,
wchar_t  wc 
)

Addwch would be provided by an up-to-date curses library.

Parameters
winWindow
wcWide char to display
Return values
0Success
-1Error

Definition at line 605 of file curs_lib.c.

606{
607 char buf[MB_LEN_MAX * 2];
608 mbstate_t mbstate = { 0 };
609 size_t n1, n2;
610
611 if (((n1 = wcrtomb(buf, wc, &mbstate)) == (size_t) (-1)) ||
612 ((n2 = wcrtomb(buf + n1, 0, &mbstate)) == (size_t) (-1)))
613 {
614 return -1; /* ERR */
615 }
616 else
617 {
618 return mutt_window_addstr(win, buf);
619 }
620}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_simple_format()

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()

Parameters
[out]bufBuffer in which to save string
[in]buflenBuffer length
[in]min_widthMinimum width
[in]max_widthMaximum width
[in]justifyJustification, e.g. JUSTIFY_RIGHT
[in]pad_charPadding character
[in]sString to format
[in]nNumber of bytes of string to format
[in]arborealIf true, string contains graphical tree characters

This formats a string, a bit like snprintf(buf, buflen, "%-*.*s", min_width, max_width, s), except that the widths refer to the number of character cells when printed.

Definition at line 638 of file curs_lib.c.

641{
642 wchar_t wc = 0;
643 int w;
644 size_t k;
645 char scratch[MB_LEN_MAX] = { 0 };
646 mbstate_t mbstate1 = { 0 };
647 mbstate_t mbstate2 = { 0 };
648 bool escaped = false;
649
650 buflen--;
651 char *p = buf;
652 for (; n && (k = mbrtowc(&wc, s, n, &mbstate1)); s += k, n -= k)
653 {
654 if ((k == (size_t) (-1)) || (k == (size_t) (-2)))
655 {
656 if ((k == (size_t) (-1)) && (errno == EILSEQ))
657 memset(&mbstate1, 0, sizeof(mbstate1));
658
659 k = (k == (size_t) (-1)) ? 1 : n;
660 wc = ReplacementChar;
661 }
662 if (escaped)
663 {
664 escaped = false;
665 w = 0;
666 }
667 else if (arboreal && (wc == MUTT_SPECIAL_INDEX))
668 {
669 escaped = true;
670 w = 0;
671 }
672 else if (arboreal && (wc < MUTT_TREE_MAX))
673 {
674 w = 1; /* hack */
675 }
676 else
677 {
678#ifdef HAVE_ISWBLANK
679 if (iswblank(wc))
680 wc = ' ';
681 else
682#endif
683 if (!IsWPrint(wc))
684 wc = '?';
685 w = wcwidth(wc);
686 }
687 if (w >= 0)
688 {
689 if (w > max_width)
690 continue;
691 size_t k2 = wcrtomb(scratch, wc, &mbstate2);
692 if ((k2 == (size_t) -1) || (k2 > buflen))
693 continue;
694
695 min_width -= w;
696 max_width -= w;
697 strncpy(p, scratch, k2);
698 p += k2;
699 buflen -= k2;
700 }
701 }
702 w = ((int) buflen < min_width) ? buflen : min_width;
703 if (w <= 0)
704 *p = '\0';
705 else if (justify == JUSTIFY_RIGHT) /* right justify */
706 {
707 p[w] = '\0';
708 while (--p >= buf)
709 p[w] = *p;
710 while (--w >= 0)
711 buf[w] = pad_char;
712 }
713 else if (justify == JUSTIFY_CENTER) /* center */
714 {
715 char *savedp = p;
716 int half = (w + 1) / 2; /* half of cushion space */
717
718 p[w] = '\0';
719
720 /* move str to center of buffer */
721 while (--p >= buf)
722 p[half] = *p;
723
724 /* fill rhs */
725 p = savedp + half;
726 while (--w >= half)
727 *p++ = pad_char;
728
729 /* fill lhs */
730 while (half--)
731 buf[half] = pad_char;
732 }
733 else /* left justify */
734 {
735 while (--w >= 0)
736 *p++ = pad_char;
737 *p = '\0';
738 }
739}
@ JUSTIFY_RIGHT
Right justify the text.
Definition: curs_lib.h:44
@ JUSTIFY_CENTER
Centre the text.
Definition: curs_lib.h:43
#define IsWPrint(wc)
Definition: mbyte.h:39
wchar_t ReplacementChar
When a Unicode character can't be displayed, use this instead.
Definition: charset.c:57
#define EILSEQ
Definition: charset.c:51
@ MUTT_TREE_MAX
Definition: mutt_thread.h:57
@ MUTT_SPECIAL_INDEX
Colour indicator.
Definition: mutt_thread.h:59
+ Here is the caller graph for this function:

◆ mutt_format_s_x()

void mutt_format_s_x ( char *  buf,
size_t  buflen,
const char *  prec,
const char *  s,
bool  arboreal 
)

Format a string like snprintf()

Parameters
[out]bufBuffer in which to save string
[in]buflenBuffer length
[in]precField precision, e.g. "-3.4"
[in]sString to format
[in]arborealIf true, string contains graphical tree characters

This formats a string rather like:

  • snprintf(fmt, sizeof(fmt), "%%%ss", prec);
  • snprintf(buf, buflen, fmt, s); except that the numbers in the conversion specification refer to the number of character cells when printed.

Definition at line 755 of file curs_lib.c.

756{
757 enum FormatJustify justify = JUSTIFY_RIGHT;
758 char *p = NULL;
759 int min_width;
760 int max_width = INT_MAX;
761
762 if (*prec == '-')
763 {
764 prec++;
765 justify = JUSTIFY_LEFT;
766 }
767 else if (*prec == '=')
768 {
769 prec++;
770 justify = JUSTIFY_CENTER;
771 }
772 min_width = strtol(prec, &p, 10);
773 if (*p == '.')
774 {
775 prec = p + 1;
776 max_width = strtol(prec, &p, 10);
777 if (p <= prec)
778 max_width = INT_MAX;
779 }
780
781 mutt_simple_format(buf, buflen, min_width, max_width, justify, ' ', s,
782 mutt_str_len(s), arboreal);
783}
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:638
FormatJustify
Alignment for mutt_simple_format()
Definition: curs_lib.h:41
@ JUSTIFY_LEFT
Left justify the text.
Definition: curs_lib.h:42
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_format_s()

void mutt_format_s ( char *  buf,
size_t  buflen,
const char *  prec,
const char *  s 
)

Format a simple string.

Parameters
[out]bufBuffer in which to save string
[in]buflenBuffer length
[in]precField precision, e.g. "-3.4"
[in]sString to format

Definition at line 792 of file curs_lib.c.

793{
794 mutt_format_s_x(buf, buflen, prec, s, false);
795}
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:755
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_format_s_tree()

void mutt_format_s_tree ( char *  buf,
size_t  buflen,
const char *  prec,
const char *  s 
)

Format a simple string with tree characters.

Parameters
[out]bufBuffer in which to save string
[in]buflenBuffer length
[in]precField precision, e.g. "-3.4"
[in]sString to format

Definition at line 804 of file curs_lib.c.

805{
806 mutt_format_s_x(buf, buflen, prec, s, true);
807}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_paddstr()

void mutt_paddstr ( struct MuttWindow win,
int  n,
const char *  s 
)

Display a string on screen, padded if necessary.

Parameters
winWindow
nFinal width of field
sString to display

Definition at line 815 of file curs_lib.c.

816{
817 wchar_t wc = 0;
818 size_t k;
819 size_t len = mutt_str_len(s);
820 mbstate_t mbstate = { 0 };
821
822 for (; len && (k = mbrtowc(&wc, s, len, &mbstate)); s += k, len -= k)
823 {
824 if ((k == (size_t) (-1)) || (k == (size_t) (-2)))
825 {
826 if (k == (size_t) (-1))
827 memset(&mbstate, 0, sizeof(mbstate));
828 k = (k == (size_t) (-1)) ? 1 : len;
829 wc = ReplacementChar;
830 }
831 if (!IsWPrint(wc))
832 wc = '?';
833 const int w = wcwidth(wc);
834 if (w >= 0)
835 {
836 if (w > n)
837 break;
838 mutt_window_addnstr(win, (char *) s, k);
839 n -= w;
840 }
841 }
842 while (n-- > 0)
843 mutt_window_addch(win, ' ');
844}
int mutt_window_addnstr(struct MuttWindow *win, const char *str, int num)
Write a partial string to a Window.
Definition: mutt_window.c:393
int mutt_window_addch(struct MuttWindow *win, int ch)
Write one character to a Window.
Definition: mutt_window.c:380
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_wstr_trunc()

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.

Parameters
[in]srcString to measure
[in]maxlenMaximum length of string in bytes
[in]maxwidMaximum width in screen columns
[out]widthSave the truncated screen column width
Return values
numBytes to use

See how many bytes to copy from string so it's at most maxlen bytes long and maxwid columns wide

Definition at line 857 of file curs_lib.c.

858{
859 wchar_t wc = 0;
860 size_t n, w = 0, l = 0, cl;
861 int cw;
862 mbstate_t mbstate = { 0 };
863
864 if (!src)
865 goto out;
866
867 n = mutt_str_len(src);
868
869 for (w = 0; n && (cl = mbrtowc(&wc, src, n, &mbstate)); src += cl, n -= cl)
870 {
871 if ((cl == (size_t) (-1)) || (cl == (size_t) (-2)))
872 {
873 if (cl == (size_t) (-1))
874 memset(&mbstate, 0, sizeof(mbstate));
875 cl = (cl == (size_t) (-1)) ? 1 : n;
876 wc = ReplacementChar;
877 }
878 cw = wcwidth(wc);
879 /* hack because MUTT_TREE symbols aren't turned into characters
880 * until rendered by print_enriched_string() */
881 if ((cw < 0) && (src[0] == MUTT_SPECIAL_INDEX))
882 {
883 cl = 2; /* skip the index coloring sequence */
884 cw = 0;
885 }
886 else if ((cw < 0) && (cl == 1) && (src[0] != '\0') && (src[0] < MUTT_TREE_MAX))
887 cw = 1;
888 else if (cw < 0)
889 cw = 0; /* unprintable wchar */
890 if ((cl + l > maxlen) || (cw + w > maxwid))
891 break;
892 l += cl;
893 w += cw;
894 }
895out:
896 if (width)
897 *width = w;
898 return l;
899}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_strwidth()

size_t mutt_strwidth ( const char *  s)

Measure a string's width in screen cells.

Parameters
sString to be measured
Return values
numScreen cells string would use

Definition at line 906 of file curs_lib.c.

907{
908 if (!s)
909 return 0;
910 return mutt_strnwidth(s, mutt_str_len(s));
911}
size_t mutt_strnwidth(const char *s, size_t n)
Measure a string's width in screen cells.
Definition: curs_lib.c:919
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_strnwidth()

size_t mutt_strnwidth ( const char *  s,
size_t  n 
)

Measure a string's width in screen cells.

Parameters
sString to be measured
nLength of string to be measured
Return values
numScreen cells string would use

Definition at line 919 of file curs_lib.c.

920{
921 if (!s)
922 return 0;
923
924 wchar_t wc = 0;
925 int w;
926 size_t k;
927 mbstate_t mbstate = { 0 };
928
929 for (w = 0; n && (k = mbrtowc(&wc, s, n, &mbstate)); s += k, n -= k)
930 {
931 if (*s == MUTT_SPECIAL_INDEX)
932 {
933 s += 2; /* skip the index coloring sequence */
934 k = 0;
935 continue;
936 }
937
938 if ((k == (size_t) (-1)) || (k == (size_t) (-2)))
939 {
940 if (k == (size_t) (-1))
941 memset(&mbstate, 0, sizeof(mbstate));
942 k = (k == (size_t) (-1)) ? 1 : n;
943 wc = ReplacementChar;
944 }
945 if (!IsWPrint(wc))
946 wc = '?';
947 w += wcwidth(wc);
948 }
949 return w;
950}
+ Here is the caller graph for this function:

Variable Documentation

◆ MacroEvents

struct KeyEventArray MacroEvents = ARRAY_HEAD_INITIALIZER
static

Definition at line 73 of file curs_lib.c.

◆ UngetKeyEvents

struct KeyEventArray UngetKeyEvents = ARRAY_HEAD_INITIALIZER
static

Definition at line 77 of file curs_lib.c.

◆ MuttGetchTimeout

int MuttGetchTimeout = -1

Timeout in ms for mutt_getch()

Definition at line 123 of file curs_lib.c.