NeoMutt  2024-04-16-36-g75b6fb
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:75
void buf_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition: buffer.c:181
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: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: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:345
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: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:584
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:209
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:162
#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:290
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:336
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: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:1296
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:797
#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:268
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:64
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 64 of file question.c.

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

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