NeoMutt  2023-11-03-85-g512e01
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
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 <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 "editor/lib.h"
#include "history/lib.h"
#include "key/lib.h"
#include "question/lib.h"
#include "globals.h"
#include "msgcont.h"
#include "msgwin.h"
#include "mutt_curses.h"
#include "mutt_logging.h"
#include "mutt_thread.h"
#include "mutt_window.h"
#include "opcodes.h"
#include "protos.h"
+ Include dependency graph for curs_lib.c:

Go to the source code of this file.

Functions

void mutt_beep (bool force)
 Irritate the user.
 
void mutt_refresh (void)
 Force a refresh of the screen.
 
void mutt_need_hard_redraw (void)
 Force a hard refresh.
 
void mutt_edit_file (const char *editor, const char *file)
 Let the user edit a file.
 
void mutt_query_exit (void)
 Ask the user if they want to leave NeoMutt.
 
void mutt_endwin (void)
 Shutdown curses.
 
void mutt_perror_debug (const char *s)
 Show the user an 'errno' message.
 
int mutt_any_key_to_continue (const char *s)
 Prompt the user to 'press any key' and wait.
 
int mw_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 -.
 
int mutt_addwch (struct MuttWindow *win, wchar_t wc)
 Addwch would be provided by an up-to-date curses library.
 
void mutt_paddstr (struct MuttWindow *win, int n, const char *s)
 Display a string on screen, padded if necessary.
 
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.
 
size_t mutt_strwidth (const char *s)
 Measure a string's width in screen cells.
 
size_t mutt_strnwidth (const char *s, size_t n)
 Measure a string's width in screen cells.
 
void mw_what_key (void)
 Display the value of a key -.
 

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

66{
67 const bool c_beep = cs_subset_bool(NeoMutt->sub, "beep");
68 if (force || c_beep)
69 beep();
70}
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:48
Container for Accounts, Notifications.
Definition: neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:45
+ 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 75 of file curs_lib.c.

76{
77 /* don't refresh when we are waiting for a child. */
78 if (OptKeepQuiet)
79 return;
80
81 /* don't refresh in the middle of macros unless necessary */
83 return;
84
85 /* else */
86 refresh();
87}
#define ARRAY_EMPTY(head)
Check if an array is empty.
Definition: array.h:73
struct KeyEventArray MacroEvents
These are used for macros and exec/push commands.
Definition: get.c:48
bool OptKeepQuiet
(pseudo) shut up the message and refresh functions while we are executing an external program
Definition: globals.c:71
bool OptForceRefresh
(pseudo) refresh even during macros
Definition: globals.c:70
+ 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 97 of file curs_lib.c.

98{
99 // Forcibly switch to the alternate screen.
100 // Using encryption can leave ncurses confused about which mode it's in.
101 fputs("\033[?1049h", stdout);
102 fflush(stdout);
103 keypad(stdscr, true);
104 clearok(stdscr, true);
105 window_redraw(NULL);
106}
void window_redraw(struct MuttWindow *win)
Reflow, recalc and repaint a tree of Windows.
Definition: mutt_window.c:634
+ 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 113 of file curs_lib.c.

114{
115 struct Buffer *cmd = buf_pool_get();
116
117 mutt_endwin();
118 buf_file_expand_fmt_quote(cmd, editor, file);
119 if (mutt_system(buf_string(cmd)) != 0)
120 {
121 mutt_error(_("Error running \"%s\""), buf_string(cmd));
122 }
123 /* the terminal may have been resized while the editor owned it */
125 keypad(stdscr, true);
126 clearok(stdscr, true);
127
128 buf_pool_release(&cmd);
129}
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:93
void mutt_endwin(void)
Shutdown curses.
Definition: curs_lib.c:150
void buf_file_expand_fmt_quote(struct Buffer *dest, const char *fmt, const char *src)
Replace s in a string with a filename.
Definition: file.c:1497
#define mutt_error(...)
Definition: logging2.h:92
#define _(a)
Definition: message.h:28
void mutt_resize_screen(void)
Update NeoMutt's opinion about the window size.
Definition: resize.c:74
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
int mutt_system(const char *cmd)
Run an external command.
Definition: system.c:50
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 136 of file curs_lib.c.

137{
139 if (query_yesorno(_("Exit NeoMutt without saving?"), MUTT_YES) == MUTT_YES)
140 {
141 mutt_exit(0); /* This call never returns */
142 }
144 SigInt = false;
145}
void mutt_flushinp(void)
Empty all the keyboard buffers.
Definition: get.c:57
SIG_ATOMIC_VOLATILE_T SigInt
true after SIGINT is received
Definition: globals.c:59
void mutt_exit(int code)
Leave NeoMutt NOW.
Definition: main.c:228
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:73
@ MUTT_YES
User answered 'Yes', or assume 'Yes'.
Definition: quad.h:39
enum QuadOption query_yesorno(const char *prompt, enum QuadOption def)
Ask the user a Yes/No question.
Definition: question.c:330
+ 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 150 of file curs_lib.c.

151{
152 if (OptNoCurses)
153 return;
154
155 int e = errno;
156
157 /* at least in some situations (screen + xterm under SuSE11/12) endwin()
158 * doesn't properly flush the screen without an explicit call. */
159 mutt_refresh();
160 endwin();
161 SigWinch = true;
162
163 errno = e;
164}
void mutt_refresh(void)
Force a refresh of the screen.
Definition: curs_lib.c:75
bool OptNoCurses
(pseudo) when sending in batch mode
Definition: globals.c:77
SIG_ATOMIC_VOLATILE_T SigWinch
true after SIGWINCH is received
Definition: globals.c:60
+ 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 170 of file curs_lib.c.

171{
172 char *p = strerror(errno);
173
174 mutt_debug(LL_DEBUG1, "%s: %s (errno = %d)\n", s, p ? p : "unknown error", errno);
175 mutt_error("%s: %s (errno = %d)", s, p ? p : _("unknown error"), errno);
176}
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43

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

185{
186 struct termios term = { 0 };
187 struct termios old = { 0 };
188
189 int fd = open("/dev/tty", O_RDONLY);
190 if (fd < 0)
191 return EOF;
192
193 tcgetattr(fd, &old); // Save the current tty settings
194
195 term = old;
196 term.c_lflag &= ~(ICANON | ECHO); // Canonical (not line-buffered), don't echo the characters
197 term.c_cc[VMIN] = 1; // Wait for at least one character
198 term.c_cc[VTIME] = 255; // Wait for 25.5s
199 tcsetattr(fd, TCSANOW, &term);
200
201 if (s)
202 fputs(s, stdout);
203 else
204 fputs(_("Press any key to continue..."), stdout);
205 fflush(stdout);
206
207 char ch = '\0';
208 // Wait for a character. This might timeout, so loop.
209 while (read(fd, &ch, 1) == 0)
210 ; // do nothing
211
212 // Change the tty settings to be non-blocking
213 term.c_cc[VMIN] = 0; // Returning with zero characters is acceptable
214 term.c_cc[VTIME] = 0; // Don't wait
215 tcsetattr(fd, TCSANOW, &term);
216
217 char buf[64] = { 0 };
218 while (read(fd, buf, sizeof(buf)) > 0)
219 ; // Mop up any remaining chars
220
221 tcsetattr(fd, TCSANOW, &old); // Restore the previous tty settings
222 close(fd);
223
224 fputs("\r\n", stdout);
226 return (ch >= 0) ? ch : EOF;
227}
+ Here is the call graph for this function:
+ 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 329 of file curs_lib.c.

330{
331 char buf[MB_LEN_MAX * 2];
332 mbstate_t mbstate = { 0 };
333 size_t n1, n2;
334
335 if (((n1 = wcrtomb(buf, wc, &mbstate)) == ICONV_ILLEGAL_SEQ) ||
336 ((n2 = wcrtomb(buf + n1, 0, &mbstate)) == ICONV_ILLEGAL_SEQ))
337 {
338 return -1; /* ERR */
339 }
340 else
341 {
342 return mutt_window_addstr(win, buf);
343 }
344}
#define ICONV_ILLEGAL_SEQ
Error value for iconv() - Illegal sequence.
Definition: charset.h:103
int mutt_window_addstr(struct MuttWindow *win, const char *str)
Write a string to a Window.
Definition: mutt_window.c:416
+ 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 352 of file curs_lib.c.

353{
354 wchar_t wc = 0;
355 size_t k;
356 size_t len = mutt_str_len(s);
357 mbstate_t mbstate = { 0 };
358
359 for (; len && (k = mbrtowc(&wc, s, len, &mbstate)); s += k, len -= k)
360 {
361 if ((k == ICONV_ILLEGAL_SEQ) || (k == ICONV_BUF_TOO_SMALL))
362 {
363 if (k == ICONV_ILLEGAL_SEQ)
364 memset(&mbstate, 0, sizeof(mbstate));
365 k = (k == ICONV_ILLEGAL_SEQ) ? 1 : len;
366 wc = ReplacementChar;
367 }
368 if (!IsWPrint(wc))
369 wc = '?';
370 const int w = wcwidth(wc);
371 if (w >= 0)
372 {
373 if (w > n)
374 break;
375 mutt_window_addnstr(win, (char *) s, k);
376 n -= w;
377 }
378 }
379 while (n-- > 0)
380 mutt_window_addch(win, ' ');
381}
#define IsWPrint(wc)
Definition: mbyte.h:41
wchar_t ReplacementChar
When a Unicode character can't be displayed, use this instead.
Definition: charset.c:58
#define ICONV_BUF_TOO_SMALL
Error value for iconv() - Buffer too small.
Definition: charset.h:105
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:568
int mutt_window_addnstr(struct MuttWindow *win, const char *str, int num)
Write a partial string to a Window.
Definition: mutt_window.c:401
int mutt_window_addch(struct MuttWindow *win, int ch)
Write one character to a Window.
Definition: mutt_window.c:388
+ 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 394 of file curs_lib.c.

395{
396 wchar_t wc = 0;
397 size_t n, w = 0, l = 0, cl;
398 int cw;
399 mbstate_t mbstate = { 0 };
400
401 if (!src)
402 goto out;
403
404 n = mutt_str_len(src);
405
406 for (w = 0; n && (cl = mbrtowc(&wc, src, n, &mbstate)); src += cl, n -= cl)
407 {
408 if (cl == ICONV_ILLEGAL_SEQ)
409 {
410 memset(&mbstate, 0, sizeof(mbstate));
411 cl = 1;
412 wc = ReplacementChar;
413 }
414 else if (cl == ICONV_BUF_TOO_SMALL)
415 {
416 cl = n;
417 wc = ReplacementChar;
418 }
419
420 cw = wcwidth(wc);
421 /* hack because MUTT_TREE symbols aren't turned into characters
422 * until rendered by print_enriched_string() */
423 if ((cw < 0) && (src[0] == MUTT_SPECIAL_INDEX))
424 {
425 cl = 2; /* skip the index coloring sequence */
426 cw = 0;
427 }
428 else if ((cw < 0) && (cl == 1) && (src[0] != '\0') && (src[0] < MUTT_TREE_MAX))
429 {
430 cw = 1;
431 }
432 else if (cw < 0)
433 {
434 cw = 0; /* unprintable wchar */
435 }
436 if (wc == '\n')
437 break;
438 if (((cl + l) > maxlen) || ((cw + w) > maxwid))
439 break;
440 l += cl;
441 w += cw;
442 }
443out:
444 if (width)
445 *width = w;
446 return l;
447}
@ MUTT_TREE_MAX
Definition: mutt_thread.h:69
@ MUTT_SPECIAL_INDEX
Colour indicator.
Definition: mutt_thread.h:71
+ 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 454 of file curs_lib.c.

455{
456 if (!s)
457 return 0;
458 return mutt_strnwidth(s, mutt_str_len(s));
459}
size_t mutt_strnwidth(const char *s, size_t n)
Measure a string's width in screen cells.
Definition: curs_lib.c:467
+ 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 467 of file curs_lib.c.

468{
469 if (!s)
470 return 0;
471
472 wchar_t wc = 0;
473 int w;
474 size_t k;
475 mbstate_t mbstate = { 0 };
476
477 for (w = 0; n && (k = mbrtowc(&wc, s, n, &mbstate)); s += k, n -= k)
478 {
479 if (*s == MUTT_SPECIAL_INDEX)
480 {
481 s += 2; /* skip the index coloring sequence */
482 k = 0;
483 continue;
484 }
485
486 if ((k == ICONV_ILLEGAL_SEQ) || (k == ICONV_BUF_TOO_SMALL))
487 {
488 if (k == ICONV_ILLEGAL_SEQ)
489 memset(&mbstate, 0, sizeof(mbstate));
490 k = (k == ICONV_ILLEGAL_SEQ) ? 1 : n;
491 wc = ReplacementChar;
492 }
493 if (!IsWPrint(wc))
494 wc = '?';
495 w += wcwidth(wc);
496 }
497 return w;
498}
+ Here is the caller graph for this function: