NeoMutt  2023-11-03-85-g512e01
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 275 of file window.c.

277{
280
282 if (complete & MUTT_COMP_UNBUFFERED)
283 flags = GETCH_IGNORE_MACRO;
284
285 int rc = 0;
286
287 struct EnterState *es = enter_state_new();
288
289 win->help_data = EditorHelp;
290 win->help_menu = MENU_EDITOR;
291
293 struct MuttWindow *old_focus = window_set_focus(win);
294
295 mbstate_t mbstate = { 0 };
296 // clang-format off
297 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 };
298 // clang-format on
299
300 win->wdata = &wdata;
301 win->wdata_free = NULL; // No need, we hold the data
302 win->actions |= WA_RECALC;
303 win->recalc = enter_recalc;
304 win->repaint = enter_repaint;
306
307 window_redraw(win);
308
309 if (es->wbuf[0] == L'\0')
310 {
311 /* Initialise wbuf from buf */
312 wdata.state->wbuflen = 0;
313 wdata.state->lastchar = mutt_mb_mbstowcs(&wdata.state->wbuf, &wdata.state->wbuflen,
314 0, buf_string(wdata.buffer));
316 }
317 else
318 {
320 wdata.first = false;
321 }
322
323 do
324 {
325 memset(&mbstate, 0, sizeof(mbstate));
326
327 do
328 {
329 if (wdata.redraw != ENTER_REDRAW_NONE)
330 win->actions |= WA_REPAINT;
331
332 window_redraw(NULL);
333 struct KeyEvent event = km_dokey_event(MENU_EDITOR, flags);
334 if ((event.op == OP_TIMEOUT) || (event.op == OP_REPAINT))
335 {
336 continue;
337 }
338
339 if (event.op == OP_ABORT)
340 {
341 rc = -1;
342 goto bye;
343 }
344
345 if (event.op == OP_NULL)
346 {
347 if (complete & MUTT_COMP_PASS)
348 mutt_debug(LL_DEBUG5, "Got char *\n");
349 else
350 mutt_debug(LL_DEBUG5, "Got char %c (0x%02x)\n", event.ch, event.ch);
351
352 if (self_insert(&wdata, event.ch))
353 {
354 rc = 0;
355 goto bye;
356 }
357 win->actions |= WA_REPAINT;
358 continue;
359 }
360 else
361 {
362 mutt_debug(LL_DEBUG1, "Got op %s (%d)\n", opcodes_get_name(event.op),
363 event.op);
364 }
365
366 wdata.first = false;
367 if ((event.op != OP_EDITOR_COMPLETE) && (event.op != OP_EDITOR_COMPLETE_QUERY))
368 wdata.tabs = 0;
370 int rc_disp = enter_function_dispatcher(win, event.op);
371 switch (rc_disp)
372 {
373 case FR_NO_ACTION:
374 {
375 if (self_insert(&wdata, event.ch))
376 {
377 rc = 0;
378 goto bye;
379 }
380 break;
381 }
382 case FR_CONTINUE: // repaint
383 rc = 1;
384 goto bye;
385
386 case FR_SUCCESS:
387 break;
388
389 case FR_UNKNOWN:
390 case FR_ERROR:
391 default:
392 mutt_beep(false);
393 }
394 } while (!wdata.done);
395
396 bye:
398 FREE(&wdata.tempbuf);
399 completion_data_free(&wdata.cd);
400 } while (rc == 1);
401
403 window_set_focus(old_focus);
404 mutt_window_free(&win);
405
406 if (rc == 0)
407 buf_fix_dptr(buf);
408 else
409 buf_reset(buf);
410
411 enter_state_free(&es);
412
413 return rc;
414}
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:88
void buf_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition: buffer.c:194
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:93
void mutt_beep(bool force)
Irritate the user.
Definition: curs_lib.c:65
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:74
void enter_state_free(struct EnterState **ptr)
Free an EnterState.
Definition: state.c:38
@ 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:50
bool self_insert(struct EnterWindowData *wdata, int ch)
Insert a normal character.
Definition: window.c:90
struct KeyEvent km_dokey_event(enum MenuType mtype, GetChFlags flags)
Determine what a keypress should do.
Definition: get.c:357
int enter_function_dispatcher(struct MuttWindow *win, int op)
Perform an Enter function - Implements function_dispatcher_t -.
Definition: functions.c:482
#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:176
static bool enter_recursor(struct MuttWindow *win)
Recursor the Window - Implements MuttWindow::recursor() -.
Definition: window.c:248
static int enter_repaint(struct MuttWindow *win)
Repaint the Window - Implements MuttWindow::repaint() -.
Definition: window.c:187
void mutt_hist_reset_state(enum HistoryClass hclass)
Move the 'current' position to the end of the History.
Definition: history.c:581
uint8_t GetChFlags
Flags for mutt_getch(), e.g. GETCH_NO_FLAGS.
Definition: lib.h:51
#define GETCH_IGNORE_MACRO
Don't use MacroEvents.
Definition: lib.h:53
#define GETCH_NO_FLAGS
No flags are set.
Definition: lib.h:52
@ 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:290
#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:57
#define MUTT_COMP_UNBUFFERED
Ignore macro buffer.
Definition: mutt.h:58
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:34
#define OP_REPAINT
Repaint is needed.
Definition: opcodes.h:32
#define OP_ABORT
$abort_key pressed (Ctrl-G)
Definition: opcodes.h:35
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:82
int op
Function opcode, e.g. OP_HELP.
Definition: lib.h:84
int ch
Raw key pressed.
Definition: lib.h:83
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 450 of file flags.c.

451{
452 if (!m || !ea || ARRAY_EMPTY(ea))
453 return -1;
454
455 // blank window (0, 0)
456 struct MuttWindow *win = msgwin_new(true);
457 if (!win)
458 return -1;
459
460 char prompt[256] = { 0 };
461 snprintf(prompt, sizeof(prompt),
462 "%s? (D/N/O/r/*/!): ", bf ? _("Set flag") : _("Clear flag"));
463 msgwin_set_text(win, prompt, MT_COLOR_PROMPT);
464
466 struct MuttWindow *old_focus = window_set_focus(win);
467 window_redraw(win);
468
469 struct KeyEvent event = { 0, OP_NULL };
470 do
471 {
472 window_redraw(NULL);
473 event = mutt_getch(GETCH_NO_FLAGS);
474 } while ((event.op == OP_TIMEOUT) || (event.op == OP_REPAINT));
475
476 win = msgcont_pop_window();
477 window_set_focus(old_focus);
478 mutt_window_free(&win);
479
480 if (event.op == OP_ABORT)
481 return -1;
482
483 enum MessageType flag = MUTT_NONE;
484 switch (event.ch)
485 {
486 case 'd':
487 case 'D':
488 if (!bf)
490 flag = MUTT_DELETE;
491 break;
492
493 case 'N':
494 case 'n':
495 flag = MUTT_NEW;
496 break;
497
498 case 'o':
499 case 'O':
500 mutt_emails_set_flag(m, ea, MUTT_READ, !bf);
501 flag = MUTT_OLD;
502 break;
503
504 case 'r':
505 case 'R':
506 flag = MUTT_REPLIED;
507 break;
508
509 case '*':
510 flag = MUTT_TAG;
511 break;
512
513 case '!':
514 flag = MUTT_FLAG;
515 break;
516
517 default:
518 mutt_beep(false);
519 return -1;
520 }
521
522 mutt_emails_set_flag(m, ea, flag, bf);
523 return 0;
524}
#define ARRAY_EMPTY(head)
Check if an array is empty.
Definition: array.h:73
@ MT_COLOR_PROMPT
Question/user input.
Definition: color.h:61
struct KeyEvent mutt_getch(GetChFlags flags)
Read a character from the input buffer.
Definition: get.c:221
void mutt_emails_set_flag(struct Mailbox *m, struct EmailArray *ea, enum MessageType flag, bool bf)
Set flag on messages.
Definition: flags.c:357
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:66
@ MUTT_READ
Messages that have been read.
Definition: mutt.h:72
@ MUTT_OLD
Old messages.
Definition: mutt.h:70
@ MUTT_PURGE
Messages to be purged (bypass trash)
Definition: mutt.h:76
@ MUTT_NONE
No messages.
Definition: mutt.h:68
@ MUTT_TAG
Tagged messages.
Definition: mutt.h:79
@ MUTT_FLAG
Flagged messages.
Definition: mutt.h:78
@ MUTT_DELETE
Messages to be deleted.
Definition: mutt.h:74
@ MUTT_NEW
New messages.
Definition: mutt.h:69
@ MUTT_REPLIED
Messages that have been replied to.
Definition: mutt.h:71
+ 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 247 of file curs_lib.c.

250{
251 struct MuttWindow *win = msgwin_new(true);
252 if (!win)
253 return -1;
254
255 int rc = -1;
256
257 struct Buffer *text = buf_pool_get();
258 const struct AttrColor *ac_normal = simple_color_get(MT_COLOR_NORMAL);
259 const struct AttrColor *ac_prompt = simple_color_get(MT_COLOR_PROMPT);
260
261 msgwin_add_text(win, prompt, ac_prompt);
262 msgwin_add_text(win, _(" ('?' for list): "), ac_prompt);
263 if (!buf_is_empty(fname))
264 msgwin_add_text(win, buf_string(fname), ac_normal);
265
267 struct MuttWindow *old_focus = window_set_focus(win);
268
269 struct KeyEvent event = { 0, OP_NULL };
270 do
271 {
272 window_redraw(NULL);
273 event = mutt_getch(GETCH_NO_FLAGS);
274 } while ((event.op == OP_TIMEOUT) || (event.op == OP_REPAINT));
275
276 mutt_refresh();
277 win = msgcont_pop_window();
278 window_set_focus(old_focus);
279 mutt_window_free(&win);
280
281 if (event.ch < 0)
282 goto done;
283
284 if (event.ch == '?')
285 {
286 buf_reset(fname);
287
288 if (flags == MUTT_SEL_NO_FLAGS)
289 flags = MUTT_SEL_FOLDER;
290 if (multiple)
291 flags |= MUTT_SEL_MULTI;
292 if (mailbox)
293 flags |= MUTT_SEL_MAILBOX;
294 dlg_browser(fname, flags, m, files, numfiles);
295 }
296 else
297 {
298 char *pc = NULL;
299 mutt_str_asprintf(&pc, "%s: ", prompt);
300 if (event.op == OP_NULL)
301 mutt_unget_ch(event.ch);
302 else
303 mutt_unget_op(event.op);
304
305 buf_alloc(fname, 1024);
306 struct FileCompletionData cdata = { multiple, m, files, numfiles };
307 enum HistoryClass hclass = mailbox ? HC_MAILBOX : HC_FILE;
308 if (mw_get_field(pc, fname, MUTT_COMP_CLEAR, hclass, &CompleteMailboxOps, &cdata) != 0)
309 {
310 buf_reset(fname);
311 }
312 FREE(&pc);
313 }
314
315 rc = 0;
316
317done:
318 buf_pool_release(&text);
319 return rc;
320}
const struct CompleteOps CompleteMailboxOps
Auto-Completion of Files / Mailboxes.
Definition: complete.c:160
#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:303
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:349
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:58
void mutt_refresh(void)
Force a refresh of the screen.
Definition: curs_lib.c:75
void mutt_unget_op(int op)
Return an operation to the input buffer.
Definition: get.c:125
void mutt_unget_ch(int ch)
Return a keystroke to the input buffer.
Definition: get.c:114
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:1226
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:275
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:1022
#define MUTT_COMP_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:56
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:34
Input for the file completion function.
Definition: curs_lib.h:39
char *** files
List of files selected.
Definition: curs_lib.h:42
struct Mailbox * mailbox
Mailbox.
Definition: curs_lib.h:41
bool multiple
Allow multiple selections.
Definition: curs_lib.h:40
int * numfiles
Number of files selected.
Definition: curs_lib.h:43
+ 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 510 of file curs_lib.c.

511{
512 struct MuttWindow *win = msgwin_new(true);
513 if (!win)
514 return;
515
516 char prompt[256] = { 0 };
517 snprintf(prompt, sizeof(prompt), _("Enter keys (%s to abort): "), km_keyname(AbortKey));
518 msgwin_set_text(win, prompt, MT_COLOR_PROMPT);
519
521 struct MuttWindow *old_focus = window_set_focus(win);
522 window_redraw(win);
523
524 char keys[256] = { 0 };
525 const struct AttrColor *ac_normal = simple_color_get(MT_COLOR_NORMAL);
526 const struct AttrColor *ac_prompt = simple_color_get(MT_COLOR_PROMPT);
527
528 // ---------------------------------------------------------------------------
529 // Event Loop
530 timeout(1000); // 1 second
531 while (true)
532 {
533 int ch = getch();
534 if (ch == AbortKey)
535 break;
536
537 if (ch == KEY_RESIZE)
538 {
539 timeout(0);
540 while ((ch = getch()) == KEY_RESIZE)
541 {
542 // do nothing
543 }
544 }
545
546 if (ch == ERR)
547 {
548 if (!isatty(0)) // terminal was lost
549 mutt_exit(1);
550
551 if (SigWinch)
552 {
553 SigWinch = false;
555 window_redraw(NULL);
556 }
557 else
558 {
560 }
561
562 continue;
563 }
564
566 snprintf(keys, sizeof(keys), _("Char = %s, Octal = %o, Decimal = %d\n"),
567 km_keyname(ch), ch, ch);
568 msgwin_add_text(win, keys, ac_normal);
569 msgwin_add_text(win, prompt, ac_prompt);
570 msgwin_add_text(win, NULL, NULL);
571 window_redraw(NULL);
572 }
573 // ---------------------------------------------------------------------------
574
575 win = msgcont_pop_window();
576 window_set_focus(old_focus);
577 mutt_window_free(&win);
578}
SIG_ATOMIC_VOLATILE_T SigWinch
true after SIGWINCH is received
Definition: globals.c:60
const char * km_keyname(int c)
Get the human name for a key.
Definition: lib.c:414
keycode_t AbortKey
code of key to abort prompts, normally Ctrl-G
Definition: lib.c:126
void mutt_exit(int code)
Leave NeoMutt NOW.
Definition: main.c:228
void msgwin_clear_text(struct MuttWindow *win)
Clear the text in the Message Window.
Definition: msgwin.c:516
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
Container for Accounts, Notifications.
Definition: neomutt.h:41
struct Notify * notify_timeout
Timeout notifications handler.
Definition: neomutt.h:44
struct Notify * notify_resize
Window resize notifications handler.
Definition: neomutt.h:43
+ 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 60 of file question.c.

61{
62 struct MuttWindow *win = msgwin_new(true);
63 if (!win)
64 return -1;
65
66 int choice = 0;
67
68 const struct AttrColor *ac_opts = NULL;
70 {
71 const struct AttrColor *ac_base = simple_color_get(MT_COLOR_NORMAL);
73
75 ac_opts = merged_color_overlay(ac_base, ac_opts);
76 }
77
78 const struct AttrColor *ac_normal = simple_color_get(MT_COLOR_NORMAL);
79 const struct AttrColor *ac_prompt = simple_color_get(MT_COLOR_PROMPT);
80
81 if (ac_opts)
82 {
83 char *cur = NULL;
84
85 while ((cur = strchr(prompt, '(')))
86 {
87 // write the part between prompt and cur using MT_COLOR_PROMPT
88 msgwin_add_text_n(win, prompt, cur - prompt, ac_prompt);
89
90 if (isalnum(cur[1]) && (cur[2] == ')'))
91 {
92 // we have a single letter within parentheses - MT_COLOR_OPTIONS
93 msgwin_add_text_n(win, cur + 1, 1, ac_opts);
94 prompt = cur + 3;
95 }
96 else
97 {
98 // we have a parenthesis followed by something else
99 msgwin_add_text_n(win, cur, 1, ac_prompt);
100 prompt = cur + 1;
101 }
102 }
103 }
104
105 msgwin_add_text(win, prompt, ac_prompt);
106 msgwin_add_text(win, " ", ac_normal);
107
109 struct MuttWindow *old_focus = window_set_focus(win);
110 window_redraw(win);
111
112 // ---------------------------------------------------------------------------
113 // Event Loop
114 struct KeyEvent event = { 0, OP_NULL };
115 while (true)
116 {
117 event = mutt_getch(GETCH_NO_FLAGS);
118 mutt_debug(LL_DEBUG1, "mw_multi_choice: EVENT(%d,%d)\n", event.ch, event.op);
119
120 if (event.op == OP_REPAINT)
121 window_redraw(NULL);
122
123 if ((event.op == OP_TIMEOUT) || (event.op == OP_REPAINT))
124 continue;
125
126 if ((event.op == OP_ABORT) || key_is_return(event.ch))
127 {
128 choice = -1;
129 break;
130 }
131
132 char *p = strchr(letters, event.ch);
133 if (p)
134 {
135 choice = p - letters + 1;
136 break;
137 }
138
139 if ((event.ch > '0') && (event.ch <= '9'))
140 {
141 choice = event.ch - '0';
142 if (choice <= mutt_str_len(letters))
143 break;
144 }
145 }
146 // ---------------------------------------------------------------------------
147
148 win = msgcont_pop_window();
149 window_set_focus(old_focus);
150 mutt_window_free(&win);
151
152 return choice;
153}
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:59
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:568
#define key_is_return(ch)
Definition: mutt_curses.h:51
+ 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 177 of file question.c.

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