NeoMutt  2022-04-29-145-g9b6a0e
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 181 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 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

◆ 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 211 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 
254  if (!OptIgnoreMacroEvents && (key = array_pop(&MacroEvents)))
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  {
276  mutt_query_exit();
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;
297  mutt_unget_ch(ch);
298  ch = '\033';
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 }
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:336
void mutt_unget_ch(int ch)
Return a keystroke to the input buffer.
Definition: curs_lib.c:522
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 313 of file curs_lib.c.

314 {
315  struct Buffer *cmd = mutt_buffer_pool_get();
316 
317  mutt_endwin();
318  mutt_buffer_file_expand_fmt_quote(cmd, editor, file);
319  if (mutt_system(mutt_buffer_string(cmd)) != 0)
320  {
321  mutt_error(_("Error running \"%s\""), mutt_buffer_string(cmd));
322  }
323  /* the terminal may have been resized while the editor owned it */
325  keypad(stdscr, true);
326  clearok(stdscr, true);
327 
329 }
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:355
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 336 of file curs_lib.c.

337 {
338  mutt_flushinp();
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?"), MUTT_YES) == MUTT_YES)
344  {
345  mutt_exit(1);
346  }
348  mutt_curses_set_cursor(cursor);
349  SigInt = false;
350 }
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:593
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 355 of file curs_lib.c.

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

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

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];
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 }
+ 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 446 of file curs_lib.c.

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 (!mutt_buffer_is_empty(fname))
464  mutt_refresh();
465 
467  do
468  {
469  ch = mutt_getch();
470  } while (ch.op == OP_TIMEOUT);
471  mutt_curses_set_cursor(cursor);
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  mutt_buffer_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  mutt_buffer_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  mutt_buffer_alloc(fname, 1024);
506  multiple, m, files, numfiles) != 0)
507  {
508  mutt_buffer_reset(fname);
509  }
510  FREE(&pc);
511  }
512 
513  return 0;
514 }
#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:1085
void mutt_buffer_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:265
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:250
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:81
@ MT_COLOR_NORMAL
Plain text.
Definition: color.h:53
@ MT_COLOR_PROMPT
Question/user input.
Definition: color.h:56
void mutt_unget_op(int op)
Return an operation to the input buffer.
Definition: curs_lib.c:533
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:258
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:544
#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 522 of file curs_lib.c.

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

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

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 }
+ Here is the call 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 562 of file curs_lib.c.

563 {
564  array_add(&MacroEvents, ch, op);
565 }
+ Here is the call 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 573 of file curs_lib.c.

574 {
576 }
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 585 of file curs_lib.c.

586 {
588 }
+ 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 593 of file curs_lib.c.

594 {
597  flushinp();
598 }
#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 607 of file curs_lib.c.

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)) == (size_t) (-1)) ||
614  ((n2 = wcrtomb(buf + n1, 0, &mbstate)) == (size_t) (-1)))
615  {
616  return -1; /* ERR */
617  }
618  else
619  {
620  return mutt_window_addstr(win, buf);
621  }
622 }
+ 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 640 of file curs_lib.c.

643 {
644  wchar_t wc = 0;
645  int w;
646  size_t k, k2;
647  char scratch[MB_LEN_MAX];
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 == (size_t) (-1)) || (k == (size_t) (-2)))
657  {
658  if ((k == (size_t) (-1)) && (errno == EILSEQ))
659  memset(&mbstate1, 0, sizeof(mbstate1));
660 
661  k = (k == (size_t) (-1)) ? 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) || ((k2 = wcrtomb(scratch, wc, &mbstate2)) > buflen))
692  continue;
693  min_width -= w;
694  max_width -= w;
695  strncpy(p, scratch, k2);
696  p += k2;
697  buflen -= k2;
698  }
699  }
700  w = ((int) buflen < min_width) ? buflen : min_width;
701  if (w <= 0)
702  *p = '\0';
703  else if (justify == JUSTIFY_RIGHT) /* right justify */
704  {
705  p[w] = '\0';
706  while (--p >= buf)
707  p[w] = *p;
708  while (--w >= 0)
709  buf[w] = pad_char;
710  }
711  else if (justify == JUSTIFY_CENTER) /* center */
712  {
713  char *savedp = p;
714  int half = (w + 1) / 2; /* half of cushion space */
715 
716  p[w] = '\0';
717 
718  /* move str to center of buffer */
719  while (--p >= buf)
720  p[half] = *p;
721 
722  /* fill rhs */
723  p = savedp + half;
724  while (--w >= half)
725  *p++ = pad_char;
726 
727  /* fill lhs */
728  while (half--)
729  buf[half] = pad_char;
730  }
731  else /* left justify */
732  {
733  while (--w >= 0)
734  *p++ = pad_char;
735  *p = '\0';
736  }
737 }
@ 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 753 of file curs_lib.c.

754 {
755  enum FormatJustify justify = JUSTIFY_RIGHT;
756  char *p = NULL;
757  int min_width;
758  int max_width = INT_MAX;
759 
760  if (*prec == '-')
761  {
762  prec++;
763  justify = JUSTIFY_LEFT;
764  }
765  else if (*prec == '=')
766  {
767  prec++;
768  justify = JUSTIFY_CENTER;
769  }
770  min_width = strtol(prec, &p, 10);
771  if (*p == '.')
772  {
773  prec = p + 1;
774  max_width = strtol(prec, &p, 10);
775  if (p <= prec)
776  max_width = INT_MAX;
777  }
778 
779  mutt_simple_format(buf, buflen, min_width, max_width, justify, ' ', s,
780  mutt_str_len(s), arboreal);
781 }
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
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 790 of file curs_lib.c.

791 {
792  mutt_format_s_x(buf, buflen, prec, s, false);
793 }
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:753
+ 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 802 of file curs_lib.c.

803 {
804  mutt_format_s_x(buf, buflen, prec, s, true);
805 }
+ 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 813 of file curs_lib.c.

814 {
815  wchar_t wc = 0;
816  size_t k;
817  size_t len = mutt_str_len(s);
818  mbstate_t mbstate = { 0 };
819 
820  for (; len && (k = mbrtowc(&wc, s, len, &mbstate)); s += k, len -= k)
821  {
822  if ((k == (size_t) (-1)) || (k == (size_t) (-2)))
823  {
824  if (k == (size_t) (-1))
825  memset(&mbstate, 0, sizeof(mbstate));
826  k = (k == (size_t) (-1)) ? 1 : len;
827  wc = ReplacementChar;
828  }
829  if (!IsWPrint(wc))
830  wc = '?';
831  const int w = wcwidth(wc);
832  if (w >= 0)
833  {
834  if (w > n)
835  break;
836  mutt_window_addnstr(win, (char *) s, k);
837  n -= w;
838  }
839  }
840  while (n-- > 0)
841  mutt_window_addch(win, ' ');
842 }
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 855 of file curs_lib.c.

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

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

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

Variable Documentation

◆ MacroEvents

struct KeyEventArray MacroEvents = ARRAY_HEAD_INITIALIZER
static

Definition at line 70 of file curs_lib.c.

◆ UngetKeyEvents

struct KeyEventArray UngetKeyEvents = ARRAY_HEAD_INITIALIZER
static

Definition at line 70 of file curs_lib.c.

◆ MuttGetchTimeout

int MuttGetchTimeout = -1

Timeout in ms for mutt_getch()

Definition at line 124 of file curs_lib.c.