NeoMutt  2021-10-29-220-g2b1eec
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 "menu/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

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...
 
void mutt_getch_timeout (int delay)
 Set the getch() 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...
 
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. More...
 
int mutt_get_field_unbuffered (const char *msg, struct Buffer *buf, CompletionFlags flags)
 Ask the user for a string (ignoring macro 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_event (int ch, int op)
 Return a keystroke 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...
 
int mutt_strwidth (const char *s)
 Measure a string's width in screen cells. More...
 
int mutt_strnwidth (const char *s, size_t n)
 Measure a string's width in screen cells. More...
 

Variables

static size_t MacroBufferCount = 0
 
static size_t MacroBufferLen = 0
 
static struct KeyEventMacroEvents
 
static size_t UngetCount = 0
 
static size_t UngetLen = 0
 
static struct KeyEventUngetKeyEvents
 
int MuttGetchTimeout = -1
 Timeout in ms for mutt_getch() More...
 
static const struct Mapping EditorHelp []
 Help Bar for the Command Line Editor. 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

◆ mutt_beep()

void mutt_beep ( bool  force)

Irritate the user.

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

Definition at line 104 of file curs_lib.c.

105 {
106  const bool c_beep = cs_subset_bool(NeoMutt->sub, "beep");
107  if (force || c_beep)
108  beep();
109 }
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 114 of file curs_lib.c.

115 {
116  /* don't refresh when we are waiting for a child. */
117  if (OptKeepQuiet)
118  return;
119 
120  /* don't refresh in the middle of macros unless necessary */
122  return;
123 
124  /* else */
125  refresh();
126 }
static size_t MacroBufferCount
Definition: curs_lib.c:73
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 136 of file curs_lib.c.

137 {
138  keypad(stdscr, true);
139  clearok(stdscr, true);
140  window_redraw(NULL);
141 }
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:

◆ mutt_getch_timeout()

void mutt_getch_timeout ( int  delay)

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

153 {
154  MuttGetchTimeout = delay;
155  timeout(delay);
156 }
int MuttGetchTimeout
Timeout in ms for mutt_getch()
Definition: curs_lib.c:83
+ 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 164 of file curs_lib.c.

165 {
166  /* ncurses has its own internal buffer, so before we perform a poll,
167  * we need to make sure there isn't a character waiting */
168  timeout(0);
169  int ch = getch();
170  timeout(MuttGetchTimeout);
171  if (ch == ERR)
172  {
173  if (mutt_monitor_poll() != 0)
174  ch = ERR;
175  else
176  ch = getch();
177  }
178  return ch;
179 }
int mutt_monitor_poll(void)
Check for filesystem changes.
Definition: monitor.c:401

◆ 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 { -1, OP_NULL }
  • Timeout { -2, OP_NULL }

Definition at line 164 of file curs_lib.c.

196 {
197  int ch;
198  struct KeyEvent err = { -1, OP_NULL }, ret;
199  struct KeyEvent timeout = { -2, OP_NULL };
200 
201  if (UngetCount)
202  return UngetKeyEvents[--UngetCount];
203 
205  return MacroEvents[--MacroBufferCount];
206 
207  SigInt = false;
208 
210 #ifdef KEY_RESIZE
211  /* ncurses 4.2 sends this when the screen is resized */
212  ch = KEY_RESIZE;
213  while (ch == KEY_RESIZE)
214 #endif
215 #ifdef USE_INOTIFY
217 #else
218  ch = getch();
219 #endif
221 
222  if (SigInt)
223  {
224  mutt_query_exit();
225  return err;
226  }
227 
228  /* either timeout, a sigwinch (if timeout is set), or the terminal
229  * has been lost */
230  if (ch == ERR)
231  {
232  if (!isatty(0))
233  mutt_exit(1);
234 
235  return timeout;
236  }
237 
238  const bool c_meta_key = cs_subset_bool(NeoMutt->sub, "meta_key");
239  if ((ch & 0x80) && c_meta_key)
240  {
241  /* send ALT-x as ESC-x */
242  ch &= ~0x80;
243  mutt_unget_event(ch, 0);
244  ret.ch = '\033'; // Escape
245  ret.op = 0;
246  return ret;
247  }
248 
249  ret.ch = ch;
250  ret.op = 0;
251  return (ch == AbortKey) ? err : ret;
252 }
static struct KeyEvent * MacroEvents
Definition: curs_lib.c:75
void mutt_unget_event(int ch, int op)
Return a keystroke to the input buffer.
Definition: curs_lib.c:560
static int mutt_monitor_getch(void)
Get a character and poll the filesystem monitor.
Definition: curs_lib.c:164
void mutt_query_exit(void)
Ask the user if they want to leave NeoMutt.
Definition: curs_lib.c:375
static size_t UngetCount
Definition: curs_lib.c:79
static struct KeyEvent * UngetKeyEvents
Definition: curs_lib.c:81
keycode_t AbortKey
code of key to abort prompts, normally Ctrl-G
Definition: keymap.c:118
void mutt_exit(int code)
Leave NeoMutt NOW.
Definition: main.c:249
SIG_ATOMIC_VOLATILE_T SigInt
true after SIGINT is received
Definition: mutt_globals.h:71
void mutt_sig_allow_interrupt(bool allow)
Allow/disallow Ctrl-C (SIGINT)
Definition: signal.c:238
An event such as a keypress.
Definition: keymap.h:65
int ch
raw key pressed
Definition: keymap.h:66
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_buffer_get_field()

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.

Parameters
[in]fieldPrompt
[in]bufBuffer for the result
[in]completeFlags, see CompletionFlags
[in]multipleAllow multiple selections
[in]mMailbox
[out]filesList of files selected
[out]numfilesNumber of files selected
Return values
1Redraw the screen and call the function again
0Selection made
-1Aborted

Definition at line 267 of file curs_lib.c.

269 {
270  struct MuttWindow *win = msgwin_get_window();
271  if (!win)
272  return -1;
273 
274  int ret;
275  int col;
276 
277  struct EnterState *es = mutt_enter_state_new();
278 
279  const struct Mapping *old_help = win->help_data;
280  int old_menu = win->help_menu;
281 
282  win->help_data = EditorHelp;
283  win->help_menu = MENU_EDITOR;
284  struct MuttWindow *old_focus = window_set_focus(win);
285 
286  window_redraw(NULL);
287  do
288  {
289  if (SigWinch)
290  {
291  SigWinch = false;
293  clearok(stdscr, true);
294  window_redraw(NULL);
295  }
296  mutt_window_clearline(win, 0);
298  mutt_window_addstr(win, field);
300  mutt_refresh();
301  mutt_window_get_coords(win, &col, NULL);
302  ret = mutt_enter_string_full(buf->data, buf->dsize, col, complete, multiple,
303  m, files, numfiles, es);
304  } while (ret == 1);
305 
306  win->help_data = old_help;
307  win->help_menu = old_menu;
308  mutt_window_move(win, 0, 0);
309  mutt_window_clearline(win, 0);
310  window_set_focus(old_focus);
311 
312  if (ret == 0)
314  else
315  mutt_buffer_reset(buf);
316 
318 
319  return ret;
320 }
void mutt_buffer_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition: buffer.c:181
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
@ MT_COLOR_NORMAL
Plain text.
Definition: color.h:53
@ MT_COLOR_PROMPT
Question/user input.
Definition: color.h:56
static const struct Mapping EditorHelp[]
Help Bar for the Command Line Editor.
Definition: curs_lib.c:86
void mutt_refresh(void)
Force a refresh of the screen.
Definition: curs_lib.c:114
void mutt_enter_state_free(struct EnterState **ptr)
Free an EnterState.
Definition: state.c:37
struct EnterState * mutt_enter_state_new(void)
Create a new EnterState.
Definition: state.c:52
int mutt_enter_string_full(char *buf, size_t buflen, int col, CompletionFlags flags, bool multiple, struct Mailbox *m, char ***files, int *numfiles, struct EnterState *state)
Ask the user for a string.
Definition: enter.c:141
struct MuttWindow * msgwin_get_window(void)
Get the Message Window pointer.
Definition: msgwin.c:251
void mutt_curses_set_color_by_id(enum ColorId cid)
Set the current colour for text.
Definition: mutt_curses.c:52
void mutt_resize_screen(void)
Update NeoMutt's opinion about the window size (CURSES)
Definition: resize.c:73
SIG_ATOMIC_VOLATILE_T SigWinch
true after SIGWINCH is received
Definition: mutt_globals.h:72
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:651
void mutt_window_get_coords(struct MuttWindow *win, int *col, int *row)
Get the cursor position in the Window.
Definition: mutt_window.c:272
void mutt_window_clearline(struct MuttWindow *win, int row)
Clear a row of a Window.
Definition: mutt_window.c:229
int mutt_window_addstr(struct MuttWindow *win, const char *str)
Write a string to a Window.
Definition: mutt_window.c:408
size_t dsize
Length of data.
Definition: buffer.h:37
char * data
Pointer to data.
Definition: buffer.h:35
Keep our place when entering a string.
Definition: state.h:33
Mapping between user-readable string and a constant.
Definition: mapping.h:32
const struct Mapping * help_data
Data for the Help Bar.
Definition: mutt_window.h:142
int help_menu
Menu for key bindings, e.g. MENU_PAGER.
Definition: mutt_window.h:141
@ MENU_EDITOR
Text entry area.
Definition: type.h:43
+ Here is the call graph for this function:

◆ mutt_get_field_unbuffered()

int mutt_get_field_unbuffered ( const char *  msg,
struct Buffer buf,
CompletionFlags  flags 
)

Ask the user for a string (ignoring macro buffer)

Parameters
msgPrompt
bufBuffer for the result
flagsFlags, see CompletionFlags
Return values
1Redraw the screen and call the function again
0Selection made
-1Aborted

Definition at line 331 of file curs_lib.c.

332 {
333  bool reset_ignoremacro = false;
334 
336  {
337  OptIgnoreMacroEvents = true;
338  reset_ignoremacro = true;
339  }
340  int rc = mutt_buffer_get_field(msg, buf, flags, false, NULL, NULL, NULL);
341  if (reset_ignoremacro)
342  OptIgnoreMacroEvents = false;
343 
344  return rc;
345 }
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: curs_lib.c:267
+ 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 352 of file curs_lib.c.

353 {
354  struct Buffer *cmd = mutt_buffer_pool_get();
355 
356  mutt_endwin();
357  mutt_buffer_file_expand_fmt_quote(cmd, editor, file);
358  if (mutt_system(mutt_buffer_string(cmd)) != 0)
359  {
360  mutt_error(_("Error running \"%s\""), mutt_buffer_string(cmd));
361  }
362  /* the terminal may have been resized while the editor owned it */
364  keypad(stdscr, true);
365  clearok(stdscr, true);
366 
368 }
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:394
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:1463
#define mutt_error(...)
Definition: logging.h:87
#define _(a)
Definition: message.h:28
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 375 of file curs_lib.c.

376 {
377  mutt_flushinp();
379  const short c_timeout = cs_subset_number(NeoMutt->sub, "timeout");
380  if (c_timeout)
381  mutt_getch_timeout(-1); /* restore blocking operation */
382  if (mutt_yesorno(_("Exit NeoMutt?"), MUTT_YES) == MUTT_YES)
383  {
384  mutt_exit(1);
385  }
388  SigInt = false;
389 }
void mutt_getch_timeout(int delay)
Set the getch() timeout.
Definition: curs_lib.c:152
void mutt_flushinp(void)
Empty all the keyboard buffers.
Definition: curs_lib.c:645
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:169
void mutt_curses_set_cursor(enum MuttCursorState state)
Set the cursor state.
Definition: mutt_curses.c:63
@ MUTT_CURSOR_RESTORE_LAST
Restore the previous cursor state.
Definition: mutt_curses.h:53
@ MUTT_CURSOR_VISIBLE
Display a normal cursor.
Definition: mutt_curses.h:55
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:113
@ 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:182
+ 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 394 of file curs_lib.c.

395 {
396  if (OptNoCurses)
397  return;
398 
399  int e = errno;
400 
401  /* at least in some situations (screen + xterm under SuSE11/12) endwin()
402  * doesn't properly flush the screen without an explicit call. */
403  mutt_refresh();
404  endwin();
405 
406  errno = e;
407 }
bool OptNoCurses
(pseudo) when sending in batch mode
Definition: options.h:53
+ 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 413 of file curs_lib.c.

414 {
415  char *p = strerror(errno);
416 
417  mutt_debug(LL_DEBUG1, "%s: %s (errno = %d)\n", s, p ? p : "unknown error", errno);
418  mutt_error("%s: %s (errno = %d)", s, p ? p : _("unknown error"), errno);
419 }
#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 427 of file curs_lib.c.

428 {
429  struct termios term;
430  struct termios old;
431 
432  int fd = open("/dev/tty", O_RDONLY);
433  if (fd < 0)
434  return EOF;
435 
436  tcgetattr(fd, &old); // Save the current tty settings
437 
438  term = old;
439  term.c_lflag &= ~(ICANON | ECHO); // Canonical (not line-buffered), don't echo the characters
440  term.c_cc[VMIN] = 1; // Wait for at least one character
441  term.c_cc[VTIME] = 255; // Wait for 25.5s
442  tcsetattr(fd, TCSANOW, &term);
443 
444  if (s)
445  fputs(s, stdout);
446  else
447  fputs(_("Press any key to continue..."), stdout);
448  fflush(stdout);
449 
450  char ch = '\0';
451  // Wait for a character. This might timeout, so loop.
452  while (read(fd, &ch, 1) == 0)
453  ; // do nothing
454 
455  // Change the tty settings to be non-blocking
456  term.c_cc[VMIN] = 0; // Returning with zero characters is acceptable
457  term.c_cc[VTIME] = 0; // Don't wait
458  tcsetattr(fd, TCSANOW, &term);
459 
460  char buf[64];
461  while (read(fd, buf, sizeof(buf)) > 0)
462  ; // Mop up any remaining chars
463 
464  tcsetattr(fd, TCSANOW, &old); // Restore the previous tty settings
465  close(fd);
466 
467  fputs("\r\n", stdout);
469  return (ch >= 0) ? ch : EOF;
470 }
+ 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 485 of file curs_lib.c.

488 {
489  struct MuttWindow *win = msgwin_get_window();
490  if (!win)
491  return -1;
492 
493  struct KeyEvent ch;
494  struct MuttWindow *old_focus = window_set_focus(win);
495 
497  mutt_window_mvaddstr(win, 0, 0, prompt);
498  mutt_window_addstr(win, _(" ('?' for list): "));
500  if (!mutt_buffer_is_empty(fname))
503  mutt_refresh();
504 
505  do
506  {
507  ch = mutt_getch();
508  } while (ch.ch == -2); // Timeout
509 
510  mutt_window_move(win, 0, 0);
512  mutt_refresh();
513  window_set_focus(old_focus);
514 
515  if (ch.ch < 0)
516  {
517  return -1;
518  }
519  else if (ch.ch == '?')
520  {
521  mutt_buffer_reset(fname);
522 
523  if (flags == MUTT_SEL_NO_FLAGS)
524  flags = MUTT_SEL_FOLDER;
525  if (multiple)
526  flags |= MUTT_SEL_MULTI;
527  if (mailbox)
528  flags |= MUTT_SEL_MAILBOX;
529  mutt_buffer_select_file(fname, flags, m, files, numfiles);
530  }
531  else
532  {
533  char *pc = mutt_mem_malloc(mutt_str_len(prompt) + 3);
534 
535  sprintf(pc, "%s: ", prompt);
536  if (ch.op == OP_NULL)
537  mutt_unget_event(ch.ch, 0);
538  else
539  mutt_unget_event(0, ch.op);
540 
541  mutt_buffer_alloc(fname, 1024);
543  multiple, m, files, numfiles) != 0)
544  {
545  mutt_buffer_reset(fname);
546  }
547  FREE(&pc);
548  }
549 
550  return 0;
551 }
#define MUTT_SEL_MAILBOX
Select a mailbox.
Definition: lib.h:48
#define MUTT_SEL_FOLDER
Select a local directory.
Definition: lib.h:50
#define MUTT_SEL_MULTI
Multi-selection is enabled.
Definition: lib.h:49
#define MUTT_SEL_NO_FLAGS
No flags are set.
Definition: lib.h:47
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:1101
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:252
struct KeyEvent mutt_getch(void)
Read a character from the input buffer.
Definition: curs_lib.c:195
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
#define FREE(x)
Definition: memory.h:40
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:475
#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
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
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_event()

void mutt_unget_event ( int  ch,
int  op 
)

Return a keystroke to the input buffer.

Parameters
chKey press
opOperation, e.g. OP_DELETE

This puts events into the UngetKeyEvents buffer

Definition at line 560 of file curs_lib.c.

561 {
562  struct KeyEvent tmp;
563 
564  tmp.ch = ch;
565  tmp.op = op;
566 
567  if (UngetCount >= UngetLen)
568  mutt_mem_realloc(&UngetKeyEvents, (UngetLen += 16) * sizeof(struct KeyEvent));
569 
570  UngetKeyEvents[UngetCount++] = tmp;
571 }
static size_t UngetLen
Definition: curs_lib.c:80
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
int op
function op
Definition: keymap.h:67
+ 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 579 of file curs_lib.c.

580 {
581  const char *p = s + mutt_str_len(s) - 1;
582 
583  while (p >= s)
584  {
585  mutt_unget_event((unsigned char) *p--, 0);
586  }
587 }
+ 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 597 of file curs_lib.c.

598 {
599  struct KeyEvent tmp;
600 
601  tmp.ch = ch;
602  tmp.op = op;
603 
605  mutt_mem_realloc(&MacroEvents, (MacroBufferLen += 128) * sizeof(struct KeyEvent));
606 
607  MacroEvents[MacroBufferCount++] = tmp;
608 }
static size_t MacroBufferLen
Definition: curs_lib.c:74
+ 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 616 of file curs_lib.c.

617 {
618  UngetCount = 0;
619  while (MacroBufferCount > 0)
620  {
621  if (MacroEvents[--MacroBufferCount].op == OP_END_COND)
622  return;
623  }
624 }
+ 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 633 of file curs_lib.c.

634 {
635  while (UngetCount > 0)
636  {
637  if (UngetKeyEvents[--UngetCount].op == OP_END_COND)
638  return;
639  }
640 }
+ Here is the caller graph for this function:

◆ mutt_flushinp()

void mutt_flushinp ( void  )

Empty all the keyboard buffers.

Definition at line 645 of file curs_lib.c.

646 {
647  UngetCount = 0;
648  MacroBufferCount = 0;
649  flushinp();
650 }
+ 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 659 of file curs_lib.c.

660 {
661  char buf[MB_LEN_MAX * 2];
662  mbstate_t mbstate = { 0 };
663  size_t n1, n2;
664 
665  if (((n1 = wcrtomb(buf, wc, &mbstate)) == (size_t) (-1)) ||
666  ((n2 = wcrtomb(buf + n1, 0, &mbstate)) == (size_t) (-1)))
667  {
668  return -1; /* ERR */
669  }
670  else
671  {
672  return mutt_window_addstr(win, buf);
673  }
674 }
+ 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 692 of file curs_lib.c.

695 {
696  wchar_t wc = 0;
697  int w;
698  size_t k, k2;
699  char scratch[MB_LEN_MAX];
700  mbstate_t mbstate1 = { 0 };
701  mbstate_t mbstate2 = { 0 };
702  bool escaped = false;
703 
704  buflen--;
705  char *p = buf;
706  for (; n && (k = mbrtowc(&wc, s, n, &mbstate1)); s += k, n -= k)
707  {
708  if ((k == (size_t) (-1)) || (k == (size_t) (-2)))
709  {
710  if ((k == (size_t) (-1)) && (errno == EILSEQ))
711  memset(&mbstate1, 0, sizeof(mbstate1));
712 
713  k = (k == (size_t) (-1)) ? 1 : n;
714  wc = ReplacementChar;
715  }
716  if (escaped)
717  {
718  escaped = false;
719  w = 0;
720  }
721  else if (arboreal && (wc == MUTT_SPECIAL_INDEX))
722  {
723  escaped = true;
724  w = 0;
725  }
726  else if (arboreal && (wc < MUTT_TREE_MAX))
727  {
728  w = 1; /* hack */
729  }
730  else
731  {
732 #ifdef HAVE_ISWBLANK
733  if (iswblank(wc))
734  wc = ' ';
735  else
736 #endif
737  if (!IsWPrint(wc))
738  wc = '?';
739  w = wcwidth(wc);
740  }
741  if (w >= 0)
742  {
743  if ((w > max_width) || ((k2 = wcrtomb(scratch, wc, &mbstate2)) > buflen))
744  continue;
745  min_width -= w;
746  max_width -= w;
747  strncpy(p, scratch, k2);
748  p += k2;
749  buflen -= k2;
750  }
751  }
752  w = ((int) buflen < min_width) ? buflen : min_width;
753  if (w <= 0)
754  *p = '\0';
755  else if (justify == JUSTIFY_RIGHT) /* right justify */
756  {
757  p[w] = '\0';
758  while (--p >= buf)
759  p[w] = *p;
760  while (--w >= 0)
761  buf[w] = pad_char;
762  }
763  else if (justify == JUSTIFY_CENTER) /* center */
764  {
765  char *savedp = p;
766  int half = (w + 1) / 2; /* half of cushion space */
767 
768  p[w] = '\0';
769 
770  /* move str to center of buffer */
771  while (--p >= buf)
772  p[half] = *p;
773 
774  /* fill rhs */
775  p = savedp + half;
776  while (--w >= half)
777  *p++ = pad_char;
778 
779  /* fill lhs */
780  while (half--)
781  buf[half] = pad_char;
782  }
783  else /* left justify */
784  {
785  while (--w >= 0)
786  *p++ = pad_char;
787  *p = '\0';
788  }
789 }
@ JUSTIFY_RIGHT
Right justify the text.
Definition: curs_lib.h:45
@ JUSTIFY_CENTER
Centre the text.
Definition: curs_lib.h:44
#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 805 of file curs_lib.c.

806 {
807  enum FormatJustify justify = JUSTIFY_RIGHT;
808  char *p = NULL;
809  int min_width;
810  int max_width = INT_MAX;
811 
812  if (*prec == '-')
813  {
814  prec++;
815  justify = JUSTIFY_LEFT;
816  }
817  else if (*prec == '=')
818  {
819  prec++;
820  justify = JUSTIFY_CENTER;
821  }
822  min_width = strtol(prec, &p, 10);
823  if (*p == '.')
824  {
825  prec = p + 1;
826  max_width = strtol(prec, &p, 10);
827  if (p <= prec)
828  max_width = INT_MAX;
829  }
830 
831  mutt_simple_format(buf, buflen, min_width, max_width, justify, ' ', s,
832  mutt_str_len(s), arboreal);
833 }
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:692
FormatJustify
Alignment for mutt_simple_format()
Definition: curs_lib.h:42
@ JUSTIFY_LEFT
Left justify the text.
Definition: curs_lib.h:43
+ 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 842 of file curs_lib.c.

843 {
844  mutt_format_s_x(buf, buflen, prec, s, false);
845 }
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:805
+ 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 854 of file curs_lib.c.

855 {
856  mutt_format_s_x(buf, buflen, prec, s, true);
857 }
+ 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 865 of file curs_lib.c.

866 {
867  wchar_t wc = 0;
868  size_t k;
869  size_t len = mutt_str_len(s);
870  mbstate_t mbstate = { 0 };
871 
872  for (; len && (k = mbrtowc(&wc, s, len, &mbstate)); s += k, len -= k)
873  {
874  if ((k == (size_t) (-1)) || (k == (size_t) (-2)))
875  {
876  if (k == (size_t) (-1))
877  memset(&mbstate, 0, sizeof(mbstate));
878  k = (k == (size_t) (-1)) ? 1 : len;
879  wc = ReplacementChar;
880  }
881  if (!IsWPrint(wc))
882  wc = '?';
883  const int w = wcwidth(wc);
884  if (w >= 0)
885  {
886  if (w > n)
887  break;
888  mutt_window_addnstr(win, (char *) s, k);
889  n -= w;
890  }
891  }
892  while (n-- > 0)
893  mutt_window_addch(win, ' ');
894 }
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 907 of file curs_lib.c.

908 {
909  wchar_t wc = 0;
910  size_t n, w = 0, l = 0, cl;
911  int cw;
912  mbstate_t mbstate = { 0 };
913 
914  if (!src)
915  goto out;
916 
917  n = mutt_str_len(src);
918 
919  for (w = 0; n && (cl = mbrtowc(&wc, src, n, &mbstate)); src += cl, n -= cl)
920  {
921  if ((cl == (size_t) (-1)) || (cl == (size_t) (-2)))
922  {
923  if (cl == (size_t) (-1))
924  memset(&mbstate, 0, sizeof(mbstate));
925  cl = (cl == (size_t) (-1)) ? 1 : n;
926  wc = ReplacementChar;
927  }
928  cw = wcwidth(wc);
929  /* hack because MUTT_TREE symbols aren't turned into characters
930  * until rendered by print_enriched_string() */
931  if ((cw < 0) && (src[0] == MUTT_SPECIAL_INDEX))
932  {
933  cl = 2; /* skip the index coloring sequence */
934  cw = 0;
935  }
936  else if ((cw < 0) && (cl == 1) && (src[0] != '\0') && (src[0] < MUTT_TREE_MAX))
937  cw = 1;
938  else if (cw < 0)
939  cw = 0; /* unprintable wchar */
940  if ((cl + l > maxlen) || (cw + w > maxwid))
941  break;
942  l += cl;
943  w += cw;
944  }
945 out:
946  if (width)
947  *width = w;
948  return l;
949 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_strwidth()

int 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 956 of file curs_lib.c.

957 {
958  if (!s)
959  return 0;
960  return mutt_strnwidth(s, mutt_str_len(s));
961 }
int mutt_strnwidth(const char *s, size_t n)
Measure a string's width in screen cells.
Definition: curs_lib.c:969
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_strnwidth()

int 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 969 of file curs_lib.c.

970 {
971  if (!s)
972  return 0;
973 
974  wchar_t wc = 0;
975  int w;
976  size_t k;
977  mbstate_t mbstate = { 0 };
978 
979  for (w = 0; n && (k = mbrtowc(&wc, s, n, &mbstate)); s += k, n -= k)
980  {
981  if (*s == MUTT_SPECIAL_INDEX)
982  {
983  s += 2; /* skip the index coloring sequence */
984  k = 0;
985  continue;
986  }
987 
988  if ((k == (size_t) (-1)) || (k == (size_t) (-2)))
989  {
990  if (k == (size_t) (-1))
991  memset(&mbstate, 0, sizeof(mbstate));
992  k = (k == (size_t) (-1)) ? 1 : n;
993  wc = ReplacementChar;
994  }
995  if (!IsWPrint(wc))
996  wc = '?';
997  w += wcwidth(wc);
998  }
999  return w;
1000 }
+ Here is the caller graph for this function:

Variable Documentation

◆ MacroBufferCount

size_t MacroBufferCount = 0
static

Definition at line 73 of file curs_lib.c.

◆ MacroBufferLen

size_t MacroBufferLen = 0
static

Definition at line 74 of file curs_lib.c.

◆ MacroEvents

struct KeyEvent* MacroEvents
static

Definition at line 75 of file curs_lib.c.

◆ UngetCount

size_t UngetCount = 0
static

Definition at line 79 of file curs_lib.c.

◆ UngetLen

size_t UngetLen = 0
static

Definition at line 80 of file curs_lib.c.

◆ UngetKeyEvents

struct KeyEvent* UngetKeyEvents
static

Definition at line 81 of file curs_lib.c.

◆ MuttGetchTimeout

int MuttGetchTimeout = -1

Timeout in ms for mutt_getch()

Definition at line 83 of file curs_lib.c.

◆ EditorHelp

const struct Mapping EditorHelp[]
static
Initial value:
= {
{ N_("Complete"), OP_EDITOR_COMPLETE },
{ N_("Hist Up"), OP_EDITOR_HISTORY_UP },
{ N_("Hist Down"), OP_EDITOR_HISTORY_DOWN },
{ N_("Hist Search"), OP_EDITOR_HISTORY_SEARCH },
{ N_("Begin Line"), OP_EDITOR_BOL },
{ N_("End Line"), OP_EDITOR_EOL },
{ N_("Kill Line"), OP_EDITOR_KILL_LINE },
{ N_("Kill Word"), OP_EDITOR_KILL_WORD },
{ NULL, 0 },
}
#define N_(a)
Definition: message.h:32

Help Bar for the Command Line Editor.

Definition at line 83 of file curs_lib.c.