NeoMutt  2025-12-11-177-g48e272
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 <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 "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_window.h"
#include "opcodes.h"
#include "thread.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.
 
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 -.
 
char * mutt_str_expand_tabs (char *str, size_t *len, int tabwidth)
 Convert tabs to spaces in a string.
 

Detailed Description

GUI miscellaneous curses (window drawing) routines.

Authors
  • Richard Russon
  • Pietro Cerutti

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

69{
70 const bool c_beep = cs_subset_bool(NeoMutt->sub, "beep");
71 if (force || c_beep)
72 beep();
73}
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition helpers.c:47
Container for Accounts, Notifications.
Definition neomutt.h:128
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:134
+ 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 78 of file curs_lib.c.

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

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

117{
118 struct Buffer *cmd = buf_pool_get();
119
120 mutt_endwin();
121 buf_file_expand_fmt_quote(cmd, editor, file);
122 if (mutt_system(buf_string(cmd)) != 0)
123 {
124 mutt_error(_("Error running \"%s\""), buf_string(cmd));
125 }
126 /* the terminal may have been resized while the editor owned it */
128
129 buf_pool_release(&cmd);
130}
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
void mutt_endwin(void)
Shutdown curses.
Definition curs_lib.c:151
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:1350
#define mutt_error(...)
Definition logging2.h:94
#define _(a)
Definition message.h:28
int mutt_system(const char *cmd)
Run an external command.
Definition system.c:51
void mutt_resize_screen(void)
Update NeoMutt's opinion about the window size.
Definition resize.c:76
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:82
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:96
String manipulation buffer.
Definition buffer.h:36
+ 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 137 of file curs_lib.c.

138{
140 if (query_yesorno(_("Exit NeoMutt without saving?"), MUTT_YES) == MUTT_YES)
141 {
142 mutt_exit(0); /* This call never returns */
143 }
145 SigInt = false;
146}
void mutt_exit(int code)
Leave NeoMutt NOW.
Definition exit.c:41
void mutt_flushinp(void)
Empty all the keyboard buffers.
Definition get.c:65
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
@ 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:326
volatile sig_atomic_t SigInt
true after SIGINT is received
Definition signal.c:68
+ 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 151 of file curs_lib.c.

152{
153 if (!OptGui)
154 return;
155
156 int e = errno;
157
158 /* at least in some situations (screen + xterm under SuSE11/12) endwin()
159 * doesn't properly flush the screen without an explicit call. */
160 mutt_refresh();
161 endwin();
162 SigWinch = true;
163
164 errno = e;
165}
void mutt_refresh(void)
Force a refresh of the screen.
Definition curs_lib.c:78
bool OptGui
(pseudo) when the gui (and curses) are started
Definition globals.c:59
volatile sig_atomic_t SigWinch
true after SIGWINCH is received
Definition signal.c:69
int endwin(void)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

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

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

320{
321 char buf[MB_LEN_MAX * 2];
322 mbstate_t mbstate = { 0 };
323 size_t n1, n2;
324
325 if (((n1 = wcrtomb(buf, wc, &mbstate)) == ICONV_ILLEGAL_SEQ) ||
326 ((n2 = wcrtomb(buf + n1, 0, &mbstate)) == ICONV_ILLEGAL_SEQ))
327 {
328 return -1; /* ERR */
329 }
330 else
331 {
332 return mutt_window_addstr(win, buf);
333 }
334}
#define ICONV_ILLEGAL_SEQ
Error value for iconv() - Illegal sequence.
Definition charset.h:114
int mutt_window_addstr(struct MuttWindow *win, const char *str)
Write a string to a Window.
+ 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 342 of file curs_lib.c.

343{
344 wchar_t wc = 0;
345 size_t k;
346 size_t len = mutt_str_len(s);
347 mbstate_t mbstate = { 0 };
348
349 for (; len && (k = mbrtowc(&wc, s, len, &mbstate)); s += k, len -= k)
350 {
351 if ((k == ICONV_ILLEGAL_SEQ) || (k == ICONV_BUF_TOO_SMALL))
352 {
353 if (k == ICONV_ILLEGAL_SEQ)
354 memset(&mbstate, 0, sizeof(mbstate));
355 k = (k == ICONV_ILLEGAL_SEQ) ? 1 : len;
356 wc = ReplacementChar;
357 }
358 if (!IsWPrint(wc))
359 wc = '?';
360 const int w = wcwidth(wc);
361 if (w >= 0)
362 {
363 if (w > n)
364 break;
365 mutt_addwch(win, wc);
366 n -= w;
367 }
368 }
369 while (n-- > 0)
370 mutt_window_addch(win, ' ');
371}
int mutt_addwch(struct MuttWindow *win, wchar_t wc)
Addwch would be provided by an up-to-date curses library.
Definition curs_lib.c:319
#define IsWPrint(wc)
Definition mbyte.h:41
wchar_t ReplacementChar
When a Unicode character can't be displayed, use this instead.
Definition charset.c:61
#define ICONV_BUF_TOO_SMALL
Error value for iconv() - Buffer too small.
Definition charset.h:116
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition string.c:500
int mutt_window_addch(struct MuttWindow *win, int ch)
Write one character to a Window.
+ 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 384 of file curs_lib.c.

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

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

458{
459 if (!s)
460 return 0;
461
462 wchar_t wc = 0;
463 int w;
464 size_t k;
465 mbstate_t mbstate = { 0 };
466
467 for (w = 0; n && (k = mbrtowc(&wc, s, n, &mbstate)); s += k, n -= k)
468 {
469 if (*s == MUTT_SPECIAL_INDEX)
470 {
471 s += 2; /* skip the index coloring sequence */
472 k = 0;
473 continue;
474 }
475
476 if ((k == ICONV_ILLEGAL_SEQ) || (k == ICONV_BUF_TOO_SMALL))
477 {
478 if (k == ICONV_ILLEGAL_SEQ)
479 memset(&mbstate, 0, sizeof(mbstate));
480 k = (k == ICONV_ILLEGAL_SEQ) ? 1 : n;
481 wc = ReplacementChar;
482 }
483 if (!IsWPrint(wc))
484 wc = '?';
485 w += wcwidth(wc);
486 }
487 return w;
488}
+ Here is the caller graph for this function:

◆ mutt_str_expand_tabs()

char * mutt_str_expand_tabs ( char * str,
size_t * len,
int tabwidth )

Convert tabs to spaces in a string.

Parameters
strInput string
lenLength of the string
tabwidthThe number of spaces per indentation-level

Replace tab characters (\t) with spaces in the string. The string will be resized to fit the expanded version if necessary.

Definition at line 591 of file curs_lib.c.

592{
593 if (!str || !len || (tabwidth < 1))
594 return NULL;
595
596 // calculate how much space we need
597 size_t required_len = 0;
598 for (int i = 0; (i < *len) && (str[i] != '\0'); i++)
599 {
600 if (str[i] == '\t')
601 required_len += tabwidth; // cheat, just assume full tab width
602 else
603 required_len++;
604 }
605
606 // resize the string if there isn't enough space
607 while (required_len > *len)
608 {
609 *len += 256;
610 MUTT_MEM_REALLOC(&str, *len, char);
611 }
612
613 // expand tabs
614 for (int i = 0; i < *len; i++)
615 {
616 if (str[i] == '\t')
617 {
618 int num_cells = mutt_strnwidth(str, i);
619 int indent = abs((num_cells % tabwidth) - tabwidth);
620 memmove(str + i + indent, str + i + 1, *len - (i + indent) - indent);
621 memset(str + i, ' ', indent);
622 }
623 }
624
625 return str;
626}
#define MUTT_MEM_REALLOC(pptr, n, type)
Definition memory.h:51
+ Here is the call graph for this function:
+ Here is the caller graph for this function: