NeoMutt  2022-04-29-249-gaae397
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 "keymap.h"
#include "msgwin.h"
#include "mutt_curses.h"
#include "mutt_globals.h"
#include "mutt_logging.h"
#include "mutt_thread.h"
#include "mutt_window.h"
#include "opcodes.h"
#include "options.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 85 of file curs_lib.c.

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}
#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 103 of file curs_lib.c.

104{
105 struct KeyEvent event = { .ch = ch, .op = op };
106 ARRAY_ADD(a, event);
107}
#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 113 of file curs_lib.c.

114{
115 while (!ARRAY_EMPTY(a))
116 {
117 if (array_pop(a)->op == OP_END_COND)
118 {
119 return;
120 }
121 }
122}
static struct KeyEvent * array_pop(struct KeyEventArray *a)
Remove an event from the array.
Definition: curs_lib.c:85
+ 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 130 of file curs_lib.c.

131{
132 const bool c_beep = cs_subset_bool(NeoMutt->sub, "beep");
133 if (force || c_beep)
134 beep();
135}
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 140 of file curs_lib.c.

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}
static struct KeyEventArray MacroEvents
Definition: curs_lib.c:74
bool OptKeepQuiet
(pseudo) shut up the message and refresh functions while we are executing an external program
Definition: options.h:44
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
+ 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 162 of file curs_lib.c.

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}
void window_redraw(struct MuttWindow *win)
Reflow, recalc and repaint a tree of Windows.
Definition: mutt_window.c:604
+ 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 181 of file curs_lib.c.

182{
183 MuttGetchTimeout = delay;
184 timeout(delay);
185}
int MuttGetchTimeout
Timeout in ms for mutt_getch()
Definition: curs_lib.c:124
+ 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 197 of file curs_lib.c.

198{
199 set_timeout(delay);
200 struct KeyEvent event = mutt_getch();
201 set_timeout(-1);
202 return event;
203}
struct KeyEvent mutt_getch(void)
Read a character from the input buffer.
Definition: curs_lib.c:242
static void set_timeout(int delay)
Set the getch() timeout.
Definition: curs_lib.c:181
+ 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 211 of file curs_lib.c.

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}
int mutt_monitor_poll(void)
Check for filesystem changes.
Definition: monitor.c:399
+ 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 242 of file curs_lib.c.

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}
static struct KeyEventArray UngetKeyEvents
Definition: curs_lib.c:78
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
void mutt_unget_ch(int ch)
Return a keystroke to the input buffer.
Definition: curs_lib.c:521
keycode_t AbortKey
code of key to abort prompts, normally Ctrl-G
Definition: keymap.c:124
void mutt_exit(int code)
Leave NeoMutt NOW.
Definition: main.c:248
SIG_ATOMIC_VOLATILE_T SigInt
true after SIGINT is received
Definition: mutt_globals.h:69
#define OP_TIMEOUT
Definition: opcodes.h:32
#define OP_ABORT
Definition: opcodes.h:33
bool OptNoCurses
(pseudo) when sending in batch mode
Definition: options.h:53
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 312 of file curs_lib.c.

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}
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
void mutt_endwin(void)
Shutdown curses.
Definition: curs_lib.c:354
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 _(a)
Definition: message.h:28
void mutt_resize_screen(void)
Update NeoMutt's opinion about the window size (CURSES)
Definition: resize.c:73
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 335 of file curs_lib.c.

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}
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:592
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:74
@ 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 354 of file curs_lib.c.

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}
void mutt_refresh(void)
Force a refresh of the screen.
Definition: curs_lib.c:140
+ 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 373 of file curs_lib.c.

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}
#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 387 of file curs_lib.c.

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}
+ 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 445 of file curs_lib.c.

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}
#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: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
@ MT_COLOR_NORMAL
Plain text.
Definition: color.h:54
@ MT_COLOR_PROMPT
Question/user input.
Definition: color.h:57
void mutt_unget_op(int op)
Return an operation to the input buffer.
Definition: curs_lib.c:532
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_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: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
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: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
void mutt_window_clrtoeol(struct MuttWindow *win)
Clear to the end of the line.
Definition: mutt_window.c:242
+ 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 521 of file curs_lib.c.

522{
523 array_add(&UngetKeyEvents, ch, OP_NULL);
524}
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
+ 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 532 of file curs_lib.c.

533{
534 array_add(&UngetKeyEvents, 0, op);
535}
+ 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 543 of file curs_lib.c.

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}
+ 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 561 of file curs_lib.c.

562{
563 array_add(&MacroEvents, ch, op);
564}
+ 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 572 of file curs_lib.c.

573{
575}
static void array_to_endcond(struct KeyEventArray *a)
Clear the array until an OP_END_COND.
Definition: curs_lib.c:113
+ 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 584 of file curs_lib.c.

585{
587}
+ 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 592 of file curs_lib.c.

593{
596 flushinp();
597}
#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 606 of file curs_lib.c.

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}
+ 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 639 of file curs_lib.c.

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}
@ 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 756 of file curs_lib.c.

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}
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
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 793 of file curs_lib.c.

794{
795 mutt_format_s_x(buf, buflen, prec, s, false);
796}
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
+ 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 805 of file curs_lib.c.

806{
807 mutt_format_s_x(buf, buflen, prec, s, true);
808}
+ 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 816 of file curs_lib.c.

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}
int mutt_window_addnstr(struct MuttWindow *win, const char *str, int num)
Write a partial string to a Window.
Definition: mutt_window.c:394
int mutt_window_addch(struct MuttWindow *win, int ch)
Write one character to a Window.
Definition: mutt_window.c:381
+ 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 858 of file curs_lib.c.

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}
+ 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 907 of file curs_lib.c.

908{
909 if (!s)
910 return 0;
911 return mutt_strnwidth(s, mutt_str_len(s));
912}
size_t mutt_strnwidth(const char *s, size_t n)
Measure a string's width in screen cells.
Definition: curs_lib.c:920
+ 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 920 of file curs_lib.c.

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}
+ Here is the caller graph for this function:

Variable Documentation

◆ MacroEvents

struct KeyEventArray MacroEvents = ARRAY_HEAD_INITIALIZER
static

Definition at line 74 of file curs_lib.c.

◆ UngetKeyEvents

struct KeyEventArray UngetKeyEvents = ARRAY_HEAD_INITIALIZER
static

Definition at line 78 of file curs_lib.c.

◆ MuttGetchTimeout

int MuttGetchTimeout = -1

Timeout in ms for mutt_getch()

Definition at line 124 of file curs_lib.c.