NeoMutt  2024-04-25-76-g20fe7b
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
GUI: Message Windows

The Message Window is a one-line interactive window at the bottom of the screen. More...

Functions

int mw_get_field (const char *prompt, struct Buffer *buf, CompletionFlags complete, enum HistoryClass hclass, const struct CompleteOps *comp_api, void *cdata)
 Ask the user for a string -.
 
int mw_change_flag (struct Mailbox *m, struct EmailArray *ea, bool bf)
 Change the flag on a Message -.
 
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 -.
 
void mw_what_key (void)
 Display the value of a key -.
 
int mw_multi_choice (const char *prompt, const char *letters)
 Offer the user a multiple choice question -.
 
static enum QuadOption mw_yesorno (const char *prompt, enum QuadOption def, struct ConfigDef *cdef)
 Ask the user a Yes/No question offering help -.
 

Detailed Description

The Message Window is a one-line interactive window at the bottom of the screen.

It's used for asking the user questions, displaying messages and for a progress bar.

Behaviour

The Message Window has two modes of behaviour: passive, active.

Passive

Most of the time, the Message Window will be passively displaying messages to the user (or empty). This is characterised by the Window focus being somewhere else. In this mode, the Message Window is responsible for drawing itself.

See also
mutt_message(), mutt_error()

Active

The Message Window can be hijacked by other code to be used for user interaction, commonly for simple questions, "Are you sure? [Y/n]". In this active state the Window will have focus and it's the responsibility of the hijacker to perform the drawing.

See also
query_yesorno(), Progress Bar

Windows

Name Type Constructor
Message Window WT_MESSAGE msgwin_new()

Parent

Children

Data

The Message Window caches the formatted string.

Events

Once constructed, it is controlled by the following events:

Event Type Handler
NT_WINDOW msgwin_window_observer()
MuttWindow::recalc() msgwin_recalc()
MuttWindow::repaint() msgwin_repaint()

Function Documentation

◆ mw_get_field()

int mw_get_field ( const char *  prompt,
struct Buffer buf,
CompletionFlags  complete,
enum HistoryClass  hclass,
const struct CompleteOps comp_api,
void *  cdata 
)

Ask the user for a string -.

Parameters
[in]promptPrompt
[in]bufBuffer for the result
[in]hclassHistory class to use
[in]completeFlags, see CompletionFlags
[in]comp_apiAuto-completion API
[in]cdataAuto-completion private data
Return values
0Selection made
-1Aborted

This function uses the message window.

Ask the user to enter a free-form string. This function supports auto-completion and saves the result to the history.

It also supports readline style text editing. See OpEditor for a list of functions.

Definition at line 274 of file window.c.

276{
279
281 if (complete & MUTT_COMP_UNBUFFERED)
282 flags = GETCH_IGNORE_MACRO;
283
284 int rc = 0;
285
286 struct EnterState *es = enter_state_new();
287
288 win->help_data = EditorHelp;
289 win->help_menu = MENU_EDITOR;
290
292 struct MuttWindow *old_focus = window_set_focus(win);
293
294 mbstate_t mbstate = { 0 };
295 // clang-format off
296 struct EnterWindowData wdata = { buf, complete, es, hclass, comp_api, cdata, prompt, ENTER_REDRAW_NONE, (complete & MUTT_COMP_PASS), true, NULL, 0, &mbstate, 0, false, NULL, 0, 0 };
297 // clang-format on
298
299 win->wdata = &wdata;
300 win->wdata_free = NULL; // No need, we hold the data
301 win->actions |= WA_RECALC;
302 win->recalc = enter_recalc;
303 win->repaint = enter_repaint;
305
306 window_redraw(win);
307
308 if (es->wbuf[0] == L'\0')
309 {
310 /* Initialise wbuf from buf */
311 wdata.state->wbuflen = 0;
312 wdata.state->lastchar = mutt_mb_mbstowcs(&wdata.state->wbuf, &wdata.state->wbuflen,
313 0, buf_string(wdata.buffer));
315 }
316 else
317 {
319 wdata.first = false;
320 }
321
322 do
323 {
324 memset(&mbstate, 0, sizeof(mbstate));
325
326 do
327 {
328 if (wdata.redraw != ENTER_REDRAW_NONE)
329 win->actions |= WA_REPAINT;
330
331 window_redraw(NULL);
332 struct KeyEvent event = km_dokey_event(MENU_EDITOR, flags);
333 if ((event.op == OP_TIMEOUT) || (event.op == OP_REPAINT))
334 {
335 continue;
336 }
337
338 if (event.op == OP_ABORT)
339 {
340 rc = -1;
341 goto bye;
342 }
343
344 if (event.op == OP_NULL)
345 {
346 if (complete & MUTT_COMP_PASS)
347 mutt_debug(LL_DEBUG5, "Got char *\n");
348 else
349 mutt_debug(LL_DEBUG5, "Got char %c (0x%02x)\n", event.ch, event.ch);
350
351 if (self_insert(&wdata, event.ch))
352 {
353 rc = 0;
354 goto bye;
355 }
356 win->actions |= WA_REPAINT;
357 continue;
358 }
359 else
360 {
361 mutt_debug(LL_DEBUG1, "Got op %s (%d)\n", opcodes_get_name(event.op),
362 event.op);
363 }
364
365 wdata.first = false;
366 if ((event.op != OP_EDITOR_COMPLETE) && (event.op != OP_EDITOR_COMPLETE_QUERY))
367 wdata.tabs = 0;
369 int rc_disp = enter_function_dispatcher(win, event.op);
370 switch (rc_disp)
371 {
372 case FR_NO_ACTION:
373 {
374 if (self_insert(&wdata, event.ch))
375 {
376 rc = 0;
377 goto bye;
378 }
379 break;
380 }
381 case FR_CONTINUE: // repaint
382 rc = 1;
383 goto bye;
384
385 case FR_SUCCESS:
386 break;
387
388 case FR_UNKNOWN:
389 case FR_ERROR:
390 default:
391 mutt_beep(false);
392 }
393 } while (!wdata.done);
394
395 bye:
397 FREE(&wdata.tempbuf);
398 completion_data_free(&wdata.cd);
399 } while (rc == 1);
400
402 window_set_focus(old_focus);
403 mutt_window_free(&win);
404
405 if (rc == 0)
406 buf_fix_dptr(buf);
407 else
408 buf_reset(buf);
409
410 enter_state_free(&es);
411
412 return rc;
413}
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:76
void buf_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition: buffer.c:182
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:96
void mutt_beep(bool force)
Irritate the user.
Definition: curs_lib.c:68
void completion_data_free(struct CompletionData **ptr)
Free the Completion Data.
Definition: data.c:53
@ FR_SUCCESS
Valid function - successfully performed.
Definition: dispatcher.h:39
@ FR_UNKNOWN
Unknown function.
Definition: dispatcher.h:33
@ FR_ERROR
Valid function - error occurred.
Definition: dispatcher.h:38
@ FR_CONTINUE
Remain in the Dialog.
Definition: dispatcher.h:34
@ FR_NO_ACTION
Valid function - no action performed.
Definition: dispatcher.h:37
struct EnterState * enter_state_new(void)
Create a new EnterState.
Definition: state.c:75
void enter_state_free(struct EnterState **ptr)
Free an EnterState.
Definition: state.c:39
@ ENTER_REDRAW_NONE
Nothing to redraw.
Definition: wdata.h:37
@ ENTER_REDRAW_LINE
Redraw entire line.
Definition: wdata.h:39
@ ENTER_REDRAW_INIT
Go to end of line and redraw.
Definition: wdata.h:38
static const struct Mapping EditorHelp[]
Help Bar for the Command Line Editor.
Definition: window.c:49
bool self_insert(struct EnterWindowData *wdata, int ch)
Insert a normal character.
Definition: window.c:89
struct KeyEvent km_dokey_event(enum MenuType mtype, GetChFlags flags)
Determine what a keypress should do.
Definition: get.c:346
int enter_function_dispatcher(struct MuttWindow *win, int op)
Perform an Enter function - Implements function_dispatcher_t -.
Definition: functions.c:483
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
static int enter_recalc(struct MuttWindow *win)
Recalculate the Window data - Implements MuttWindow::recalc() -.
Definition: window.c:175
static bool enter_recursor(struct MuttWindow *win)
Recursor the Window - Implements MuttWindow::recursor() -.
Definition: window.c:247
static int enter_repaint(struct MuttWindow *win)
Repaint the Window - Implements MuttWindow::repaint() -.
Definition: window.c:186
void mutt_hist_reset_state(enum HistoryClass hclass)
Move the 'current' position to the end of the History.
Definition: history.c:586
uint8_t GetChFlags
Flags for mutt_getch(), e.g. GETCH_NO_FLAGS.
Definition: lib.h:50
#define GETCH_IGNORE_MACRO
Don't use MacroEvents.
Definition: lib.h:52
#define GETCH_NO_FLAGS
No flags are set.
Definition: lib.h:51
@ LL_DEBUG5
Log at debug level 5.
Definition: logging2.h:47
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43
size_t mutt_mb_mbstowcs(wchar_t **pwbuf, size_t *pwbuflen, size_t i, const char *buf)
Convert a string from multibyte to wide characters.
Definition: mbyte.c:291
#define FREE(x)
Definition: memory.h:45
void msgcont_push_window(struct MuttWindow *win)
Add a window to the Container Stack.
Definition: msgcont.c:93
struct MuttWindow * msgcont_pop_window(void)
Remove the last Window from the Container Stack.
Definition: msgcont.c:57
#define MUTT_COMP_PASS
Password mode (no echo)
Definition: mutt.h:58
#define MUTT_COMP_UNBUFFERED
Ignore macro buffer.
Definition: mutt.h:59
void window_redraw(struct MuttWindow *win)
Reflow, recalc and repaint a tree of Windows.
Definition: mutt_window.c:634
void mutt_window_free(struct MuttWindow **ptr)
Free a Window and its children.
Definition: mutt_window.c:202
struct MuttWindow * mutt_window_new(enum WindowType type, enum MuttWindowOrientation orient, enum MuttWindowSize size, int cols, int rows)
Create a new Window.
Definition: mutt_window.c:182
struct MuttWindow * window_set_focus(struct MuttWindow *win)
Set the Window focus.
Definition: mutt_window.c:684
#define WA_RECALC
Recalculate the contents of the Window.
Definition: mutt_window.h:110
@ WT_CUSTOM
Window with a custom drawing function.
Definition: mutt_window.h:95
@ MUTT_WIN_ORIENT_VERTICAL
Window uses all available vertical space.
Definition: mutt_window.h:38
#define WA_REPAINT
Redraw the contents of the Window.
Definition: mutt_window.h:111
#define MUTT_WIN_SIZE_UNLIMITED
Use as much space as possible.
Definition: mutt_window.h:52
@ MUTT_WIN_SIZE_FIXED
Window has a fixed size.
Definition: mutt_window.h:47
const char * opcodes_get_name(int op)
Get the name of an opcode.
Definition: opcodes.c:48
#define OP_TIMEOUT
1 second with no events
Definition: opcodes.h:36
#define OP_REPAINT
Repaint is needed.
Definition: opcodes.h:34
#define OP_ABORT
$abort_key pressed (Ctrl-G)
Definition: opcodes.h:37
Keep our place when entering a string.
Definition: state.h:32
size_t wbuflen
Length of buffer.
Definition: state.h:34
wchar_t * wbuf
Buffer for the string being entered.
Definition: state.h:33
size_t lastchar
Position of the last character.
Definition: state.h:35
Data to fill the Enter Window.
Definition: wdata.h:46
int tabs
Number of times the user has hit tab.
Definition: wdata.h:63
void * cdata
Auto-Completion private data.
Definition: wdata.h:53
struct CompletionData * cd
Auto-completion state data.
Definition: wdata.h:67
struct Buffer * buffer
struct Buffer for the result
Definition: wdata.h:48
bool done
Is text-entry done?
Definition: wdata.h:65
bool first
First time through, no input yet.
Definition: wdata.h:59
wchar_t * tempbuf
Buffer used by completion.
Definition: wdata.h:60
const struct CompleteOps * comp_api
Auto-Completion API.
Definition: wdata.h:52
const char * prompt
Prompt.
Definition: wdata.h:56
struct EnterState * state
Current state of text entry.
Definition: wdata.h:50
enum EnterRedrawFlags redraw
What needs redrawing? See EnterRedrawFlags.
Definition: wdata.h:57
mbstate_t * mbstate
Multi-byte state.
Definition: wdata.h:62
enum HistoryClass hclass
History to use, e.g. HC_NEO_COMMAND.
Definition: wdata.h:51
An event such as a keypress.
Definition: lib.h:81
int op
Function opcode, e.g. OP_HELP.
Definition: lib.h:83
int ch
Raw key pressed.
Definition: lib.h:82
const struct Mapping * help_data
Data for the Help Bar.
Definition: mutt_window.h:142
int(* repaint)(struct MuttWindow *win)
Definition: mutt_window.h:187
void * wdata
Private data.
Definition: mutt_window.h:145
int(* recalc)(struct MuttWindow *win)
Definition: mutt_window.h:173
void(* wdata_free)(struct MuttWindow *win, void **ptr)
Definition: mutt_window.h:159
int help_menu
Menu for key bindings, e.g. MENU_PAGER.
Definition: mutt_window.h:141
WindowActionFlags actions
Actions to be performed, e.g. WA_RECALC.
Definition: mutt_window.h:132
bool(* recursor)(struct MuttWindow *win)
Definition: mutt_window.h:205
@ MENU_EDITOR
Text entry area.
Definition: type.h:44
+ Here is the call graph for this function:

◆ mw_change_flag()

int mw_change_flag ( struct Mailbox m,
struct EmailArray *  ea,
bool  bf 
)

Change the flag on a Message -.

Parameters
mMailbox
eaArray of Emails to change
bftrue: set the flag; false: clear the flag
Return values
0Success
-1Failure

This function uses the message window.

Ask the user which flag they'd like to set/clear, e.g. Clear flag? (D/N/O/r/!):

Definition at line 454 of file flags.c.

455{
456 if (!m || !ea || ARRAY_EMPTY(ea))
457 return -1;
458
459 // blank window (0, 0)
460 struct MuttWindow *win = msgwin_new(true);
461 if (!win)
462 return -1;
463
464 char prompt[256] = { 0 };
465 snprintf(prompt, sizeof(prompt),
466 "%s? (D/N/O/r/*/!): ", bf ? _("Set flag") : _("Clear flag"));
467 msgwin_set_text(win, prompt, MT_COLOR_PROMPT);
468
470 struct MuttWindow *old_focus = window_set_focus(win);
471 window_redraw(win);
472
473 struct KeyEvent event = { 0, OP_NULL };
474 do
475 {
476 window_redraw(NULL);
477 event = mutt_getch(GETCH_NO_FLAGS);
478 } while ((event.op == OP_TIMEOUT) || (event.op == OP_REPAINT));
479
480 win = msgcont_pop_window();
481 window_set_focus(old_focus);
482 mutt_window_free(&win);
483
484 if (event.op == OP_ABORT)
485 return -1;
486
487 enum MessageType flag = MUTT_NONE;
488 switch (event.ch)
489 {
490 case 'd':
491 case 'D':
492 if (!bf)
494 flag = MUTT_DELETE;
495 break;
496
497 case 'N':
498 case 'n':
499 flag = MUTT_NEW;
500 break;
501
502 case 'o':
503 case 'O':
504 mutt_emails_set_flag(m, ea, MUTT_READ, !bf);
505 flag = MUTT_OLD;
506 break;
507
508 case 'r':
509 case 'R':
510 flag = MUTT_REPLIED;
511 break;
512
513 case '*':
514 flag = MUTT_TAG;
515 break;
516
517 case '!':
518 flag = MUTT_FLAG;
519 break;
520
521 default:
522 mutt_beep(false);
523 return -1;
524 }
525
526 mutt_emails_set_flag(m, ea, flag, bf);
527 return 0;
528}
#define ARRAY_EMPTY(head)
Check if an array is empty.
Definition: array.h:74
@ MT_COLOR_PROMPT
Question/user input.
Definition: color.h:62
struct KeyEvent mutt_getch(GetChFlags flags)
Read a character from the input buffer.
Definition: get.c:210
void mutt_emails_set_flag(struct Mailbox *m, struct EmailArray *ea, enum MessageType flag, bool bf)
Set flag on messages.
Definition: flags.c:361
struct MuttWindow * msgwin_new(bool interactive)
Create the Message Window.
Definition: msgwin.c:371
void msgwin_set_text(struct MuttWindow *win, const char *text, enum ColorId color)
Set the text for the Message Window.
Definition: msgwin.c:484
#define _(a)
Definition: message.h:28
MessageType
To set flags or match patterns.
Definition: mutt.h:67
@ MUTT_READ
Messages that have been read.
Definition: mutt.h:73
@ MUTT_OLD
Old messages.
Definition: mutt.h:71
@ MUTT_PURGE
Messages to be purged (bypass trash)
Definition: mutt.h:77
@ MUTT_NONE
No messages.
Definition: mutt.h:69
@ MUTT_TAG
Tagged messages.
Definition: mutt.h:80
@ MUTT_FLAG
Flagged messages.
Definition: mutt.h:79
@ MUTT_DELETE
Messages to be deleted.
Definition: mutt.h:75
@ MUTT_NEW
New messages.
Definition: mutt.h:70
@ MUTT_REPLIED
Messages that have been replied to.
Definition: mutt.h:72
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mw_enter_fname()

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 -.

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

This function uses the message window.

Allow the user to enter a filename. If they hit '?' then the browser will be started. See: dlg_browser()

Definition at line 236 of file curs_lib.c.

239{
240 struct MuttWindow *win = msgwin_new(true);
241 if (!win)
242 return -1;
243
244 int rc = -1;
245
246 struct Buffer *text = buf_pool_get();
247 const struct AttrColor *ac_normal = simple_color_get(MT_COLOR_NORMAL);
248 const struct AttrColor *ac_prompt = simple_color_get(MT_COLOR_PROMPT);
249
250 msgwin_add_text(win, prompt, ac_prompt);
251 msgwin_add_text(win, _(" ('?' for list): "), ac_prompt);
252 if (!buf_is_empty(fname))
253 msgwin_add_text(win, buf_string(fname), ac_normal);
254
256 struct MuttWindow *old_focus = window_set_focus(win);
257
258 struct KeyEvent event = { 0, OP_NULL };
259 do
260 {
261 window_redraw(NULL);
262 event = mutt_getch(GETCH_NO_FLAGS);
263 } while ((event.op == OP_TIMEOUT) || (event.op == OP_REPAINT));
264
265 mutt_refresh();
266 win = msgcont_pop_window();
267 window_set_focus(old_focus);
268 mutt_window_free(&win);
269
270 if (event.ch < 0)
271 goto done;
272
273 if (event.ch == '?')
274 {
275 buf_reset(fname);
276
277 if (flags == MUTT_SEL_NO_FLAGS)
278 flags = MUTT_SEL_FOLDER;
279 if (multiple)
280 flags |= MUTT_SEL_MULTI;
281 if (mailbox)
282 flags |= MUTT_SEL_MAILBOX;
283 dlg_browser(fname, flags, m, files, numfiles);
284 }
285 else
286 {
287 char *pc = NULL;
288 mutt_str_asprintf(&pc, "%s: ", prompt);
289 if (event.op == OP_NULL)
290 mutt_unget_ch(event.ch);
291 else
292 mutt_unget_op(event.op);
293
294 buf_alloc(fname, 1024);
295 struct FileCompletionData cdata = { multiple, m, files, numfiles };
296 enum HistoryClass hclass = mailbox ? HC_MAILBOX : HC_FILE;
297 if (mw_get_field(pc, fname, MUTT_COMP_CLEAR, hclass, &CompleteMailboxOps, &cdata) != 0)
298 {
299 buf_reset(fname);
300 }
301 FREE(&pc);
302 }
303
304 rc = 0;
305
306done:
307 buf_pool_release(&text);
308 return rc;
309}
const struct CompleteOps CompleteMailboxOps
Auto-Completion of Files / Mailboxes.
Definition: complete.c:161
#define MUTT_SEL_MAILBOX
Select a mailbox.
Definition: lib.h:58
#define MUTT_SEL_FOLDER
Select a local directory.
Definition: lib.h:60
#define MUTT_SEL_MULTI
Multi-selection is enabled.
Definition: lib.h:59
#define MUTT_SEL_NO_FLAGS
No flags are set.
Definition: lib.h:57
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:291
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:337
struct AttrColor * simple_color_get(enum ColorId cid)
Get the colour of an object by its ID.
Definition: simple.c:88
@ MT_COLOR_NORMAL
Plain text.
Definition: color.h:59
void mutt_refresh(void)
Force a refresh of the screen.
Definition: curs_lib.c:78
void mutt_unget_op(int op)
Return an operation to the input buffer.
Definition: get.c:126
void mutt_unget_ch(int ch)
Return a keystroke to the input buffer.
Definition: get.c:115
void dlg_browser(struct Buffer *file, SelectFileFlags flags, struct Mailbox *m, char ***files, int *numfiles)
Let the user select a file -.
Definition: dlg_browser.c:1295
int mw_get_field(const char *prompt, struct Buffer *buf, CompletionFlags complete, enum HistoryClass hclass, const struct CompleteOps *comp_api, void *cdata)
Ask the user for a string -.
Definition: window.c:274
HistoryClass
Type to differentiate different histories.
Definition: lib.h:50
@ HC_FILE
Files.
Definition: lib.h:54
@ HC_MAILBOX
Mailboxes.
Definition: lib.h:57
void msgwin_add_text(struct MuttWindow *win, const char *text, const struct AttrColor *ac_color)
Add text to the Message Window.
Definition: msgwin.c:419
int mutt_str_asprintf(char **strp, const char *fmt,...)
Definition: string.c:803
#define MUTT_COMP_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:57
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
A curses colour and its attributes.
Definition: attr.h:66
String manipulation buffer.
Definition: buffer.h:36
Input for the file completion function.
Definition: curs_lib.h:40
char *** files
List of files selected.
Definition: curs_lib.h:43
struct Mailbox * mailbox
Mailbox.
Definition: curs_lib.h:42
bool multiple
Allow multiple selections.
Definition: curs_lib.h:41
int * numfiles
Number of files selected.
Definition: curs_lib.h:44
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mw_what_key()

void mw_what_key ( void  )

Display the value of a key -.

This function uses the message window.

Displays the octal value back to the user. e.g. Char = h, Octal = 150, Decimal = 104

Press the $abort_key (default Ctrl-G) to exit.

Definition at line 499 of file curs_lib.c.

500{
501 struct MuttWindow *win = msgwin_new(true);
502 if (!win)
503 return;
504
505 char prompt[256] = { 0 };
506 snprintf(prompt, sizeof(prompt), _("Enter keys (%s to abort): "), km_keyname(AbortKey));
507 msgwin_set_text(win, prompt, MT_COLOR_PROMPT);
508
510 struct MuttWindow *old_focus = window_set_focus(win);
511 window_redraw(win);
512
513 char keys[256] = { 0 };
514 const struct AttrColor *ac_normal = simple_color_get(MT_COLOR_NORMAL);
515 const struct AttrColor *ac_prompt = simple_color_get(MT_COLOR_PROMPT);
516
517 // ---------------------------------------------------------------------------
518 // Event Loop
519 timeout(1000); // 1 second
520 while (true)
521 {
522 int ch = getch();
523 if (ch == AbortKey)
524 break;
525
526 if (ch == KEY_RESIZE)
527 {
528 timeout(0);
529 while ((ch = getch()) == KEY_RESIZE)
530 {
531 // do nothing
532 }
533 }
534
535 if (ch == ERR)
536 {
537 if (!isatty(0)) // terminal was lost
538 mutt_exit(1);
539
540 if (SigWinch)
541 {
542 SigWinch = false;
544 window_redraw(NULL);
545 }
546 else
547 {
549 }
550
551 continue;
552 }
553
555 snprintf(keys, sizeof(keys), _("Char = %s, Octal = %o, Decimal = %d\n"),
556 km_keyname(ch), ch, ch);
557 msgwin_add_text(win, keys, ac_normal);
558 msgwin_add_text(win, prompt, ac_prompt);
559 msgwin_add_text(win, NULL, NULL);
560 window_redraw(NULL);
561 }
562 // ---------------------------------------------------------------------------
563
564 win = msgcont_pop_window();
565 window_set_focus(old_focus);
566 mutt_window_free(&win);
567}
const char * km_keyname(int c)
Get the human name for a key.
Definition: lib.c:413
keycode_t AbortKey
code of key to abort prompts, normally Ctrl-G
Definition: lib.c:125
void mutt_exit(int code)
Leave NeoMutt NOW.
Definition: main.c:269
void msgwin_clear_text(struct MuttWindow *win)
Clear the text in the Message Window.
Definition: msgwin.c:519
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition: notify.c:173
@ NT_TIMEOUT
Timeout has occurred.
Definition: notify_type.h:56
@ NT_RESIZE
Window has been resized.
Definition: notify_type.h:52
volatile sig_atomic_t SigWinch
true after SIGWINCH is received
Definition: signal.c:67
Container for Accounts, Notifications.
Definition: neomutt.h:42
struct Notify * notify_timeout
Timeout notifications handler.
Definition: neomutt.h:45
struct Notify * notify_resize
Window resize notifications handler.
Definition: neomutt.h:44
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mw_multi_choice()

int mw_multi_choice ( const char *  prompt,
const char *  letters 
)

Offer the user a multiple choice question -.

Parameters
promptMessage prompt
lettersAllowable selection keys
Return values
>=11-based user selection
-1Selection aborted

This function uses a message window.

Ask the user a multiple-choice question, using shortcut letters, e.g. PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, s/(m)ime or (c)lear?

Colours:

  • Question: color prompt
  • Shortcuts: color options

Definition at line 63 of file question.c.

64{
65 struct MuttWindow *win = msgwin_new(true);
66 if (!win)
67 return -1;
68
69 int choice = 0;
70
71 const struct AttrColor *ac_normal = simple_color_get(MT_COLOR_NORMAL);
72 const struct AttrColor *ac_prompt = merged_color_overlay(ac_normal,
74
76 {
77 const struct AttrColor *ac_opts = merged_color_overlay(ac_prompt,
79 char *cur = NULL;
80
81 while ((cur = strchr(prompt, '(')))
82 {
83 // write the part between prompt and cur using MT_COLOR_PROMPT
84 msgwin_add_text_n(win, prompt, cur - prompt, ac_prompt);
85
86 if (isalnum(cur[1]) && (cur[2] == ')'))
87 {
88 // we have a single letter within parentheses - MT_COLOR_OPTIONS
89 msgwin_add_text_n(win, cur + 1, 1, ac_opts);
90 prompt = cur + 3;
91 }
92 else
93 {
94 // we have a parenthesis followed by something else
95 msgwin_add_text_n(win, cur, 1, ac_prompt);
96 prompt = cur + 1;
97 }
98 }
99 }
100
101 msgwin_add_text(win, prompt, ac_prompt);
102 msgwin_add_text(win, " ", ac_normal);
103
105 struct MuttWindow *old_focus = window_set_focus(win);
106 window_redraw(win);
107
108 // ---------------------------------------------------------------------------
109 // Event Loop
110 struct KeyEvent event = { 0, OP_NULL };
111 while (true)
112 {
113 event = mutt_getch(GETCH_NO_FLAGS);
114 mutt_debug(LL_DEBUG1, "mw_multi_choice: EVENT(%d,%d)\n", event.ch, event.op);
115
116 if (event.op == OP_REPAINT)
117 window_redraw(NULL);
118
119 if ((event.op == OP_TIMEOUT) || (event.op == OP_REPAINT))
120 continue;
121
122 if ((event.op == OP_ABORT) || key_is_return(event.ch))
123 {
124 choice = -1;
125 break;
126 }
127
128 char *p = strchr(letters, event.ch);
129 if (p)
130 {
131 choice = p - letters + 1;
132 break;
133 }
134
135 if ((event.ch > '0') && (event.ch <= '9'))
136 {
137 choice = event.ch - '0';
138 if (choice <= mutt_str_len(letters))
139 break;
140 }
141 }
142 // ---------------------------------------------------------------------------
143
144 win = msgcont_pop_window();
145 window_set_focus(old_focus);
146 mutt_window_free(&win);
147
148 return choice;
149}
bool simple_color_is_set(enum ColorId cid)
Is the object coloured?
Definition: simple.c:109
@ MT_COLOR_OPTIONS
Options in prompt.
Definition: color.h:60
const struct AttrColor * merged_color_overlay(const struct AttrColor *base, const struct AttrColor *over)
Combine two colours.
Definition: merged.c:107
void msgwin_add_text_n(struct MuttWindow *win, const char *text, int bytes, const struct AttrColor *ac_color)
Add some text to the Message Window.
Definition: msgwin.c:450
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:496
#define key_is_return(ch)
Definition: mutt_curses.h:57
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mw_yesorno()

static enum QuadOption mw_yesorno ( const char *  prompt,
enum QuadOption  def,
struct ConfigDef cdef 
)
static

Ask the user a Yes/No question offering help -.

Parameters
promptPrompt
defDefault answer, e.g. MUTT_YES
cdefConfig definition for help
Return values
enumQuadOption, Selection made

This function uses a message window.

Ask the user a yes/no question, using shortcut letters, e.g. Quit NeoMutt? ([yes]/no):

This question can be answered using locale-dependent letters, e.g.

  • English, [+1yY] or [-0nN]
  • Serbian, [+1yYdDДд] or [-0nNНн]

If a config variable (cdef) is given, then help is offered. The options change to: ([yes]/no/?)

Pressing '?' will show the name and one-line description of the config variable. Additionally, if $help is set, a link to the config's documentation is shown.

Definition at line 173 of file question.c.

175{
176 struct MuttWindow *win = msgwin_new(true);
177 if (!win)
178 return MUTT_ABORT;
179
180 char *yes = N_("yes");
181 char *no = N_("no");
182 char *trans_yes = _(yes);
183 char *trans_no = _(no);
184
185 regex_t reyes = { 0 };
186 regex_t reno = { 0 };
187
188 bool reyes_ok = false;
189 bool reno_ok = false;
190
191#ifdef OpenBSD
192 /* OpenBSD only supports locale C and UTF-8
193 * so there is no suitable base system's locale identification
194 * Remove this code immediately if this situation changes! */
195 char rexyes[16] = "^[+1YyYy]";
196 rexyes[6] = toupper(trans_yes[0]);
197 rexyes[7] = tolower(trans_yes[0]);
198
199 char rexno[16] = "^[-0NnNn]";
200 rexno[6] = toupper(trans_no[0]);
201 rexno[7] = tolower(trans_no[0]);
202
203 if (REG_COMP(&reyes, rexyes, REG_NOSUB) == 0)
204 reyes_ok = true;
205
206 if (REG_COMP(&reno, rexno, REG_NOSUB) == 0)
207 reno_ok = true;
208
209#else
210 char *expr = NULL;
211 reyes_ok = (expr = nl_langinfo(YESEXPR)) && (expr[0] == '^') &&
212 (REG_COMP(&reyes, expr, REG_NOSUB) == 0);
213 reno_ok = (expr = nl_langinfo(NOEXPR)) && (expr[0] == '^') &&
214 (REG_COMP(&reno, expr, REG_NOSUB) == 0);
215#endif
216
217 if ((yes != trans_yes) && (no != trans_no) && reyes_ok && reno_ok)
218 {
219 // If all parts of the translation succeeded...
220 yes = trans_yes;
221 no = trans_no;
222 }
223 else
224 {
225 // otherwise, fallback to English
226 if (reyes_ok)
227 {
228 regfree(&reyes);
229 reyes_ok = false;
230 }
231 if (reno_ok)
232 {
233 regfree(&reno);
234 reno_ok = false;
235 }
236 }
237
238 bool show_help_prompt = cdef;
239
240 struct Buffer *text = buf_pool_get();
241 buf_printf(text, "%s ([%s]/%s%s): ", prompt, (def == MUTT_YES) ? yes : no,
242 (def == MUTT_YES) ? no : yes, show_help_prompt ? "/?" : "");
243
246 struct MuttWindow *old_focus = window_set_focus(win);
247
248 struct KeyEvent event = { 0, OP_NULL };
249 window_redraw(NULL);
250 while (true)
251 {
252 event = mutt_getch(GETCH_NO_FLAGS);
253 if ((event.op == OP_TIMEOUT) || (event.op == OP_REPAINT))
254 {
255 window_redraw(NULL);
256 mutt_refresh();
257 continue;
258 }
259
260 if (key_is_return(event.ch))
261 break; // Do nothing, use default
262
263 if (event.op == OP_ABORT)
264 {
265 def = MUTT_ABORT;
266 break;
267 }
268
269 char answer[4] = { 0 };
270 answer[0] = event.ch;
271 if (reyes_ok ? (regexec(&reyes, answer, 0, 0, 0) == 0) : (tolower(event.ch) == 'y'))
272 {
273 def = MUTT_YES;
274 break;
275 }
276 if (reno_ok ? (regexec(&reno, answer, 0, 0, 0) == 0) : (tolower(event.ch) == 'n'))
277 {
278 def = MUTT_NO;
279 break;
280 }
281 if (show_help_prompt && (event.ch == '?'))
282 {
283 show_help_prompt = false;
285 buf_printf(text, "$%s - %s\n", cdef->name, cdef->docs);
286
287 char hyphen[128] = { 0 };
288 mutt_str_hyphenate(hyphen, sizeof(hyphen), cdef->name);
289 buf_add_printf(text, "https://neomutt.org/guide/reference#%s\n", hyphen);
290
292
293 buf_printf(text, "%s ([%s]/%s): ", prompt, (def == MUTT_YES) ? yes : no,
294 (def == MUTT_YES) ? no : yes);
296 msgwin_add_text(win, NULL, NULL);
297
298 window_redraw(NULL);
299 mutt_refresh();
300 }
301
302 mutt_beep(false);
303 }
304
305 win = msgcont_pop_window();
306 window_set_focus(old_focus);
307 mutt_window_free(&win);
308
309 if (reyes_ok)
310 regfree(&reyes);
311 if (reno_ok)
312 regfree(&reno);
313
314 buf_pool_release(&text);
315 return def;
316}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:161
int buf_add_printf(struct Buffer *buf, const char *fmt,...)
Format a string appending a Buffer.
Definition: buffer.c:204
#define N_(a)
Definition: message.h:32
void mutt_str_hyphenate(char *buf, size_t buflen, const char *str)
Hyphenate a snake-case string.
Definition: string.c:849
@ MUTT_ABORT
User aborted the question (with Ctrl-G)
Definition: quad.h:37
@ MUTT_NO
User answered 'No', or assume 'No'.
Definition: quad.h:38
@ MUTT_YES
User answered 'Yes', or assume 'Yes'.
Definition: quad.h:39
#define REG_COMP(preg, regex, cflags)
Compile a regular expression.
Definition: regex3.h:49
const char * name
User-visible name.
Definition: set.h:65
const char * docs
One-liner description.
Definition: set.h:84
+ Here is the call graph for this function:
+ Here is the caller graph for this function: