ascii-chat
Binary v0.15.83-53-gb711d8720
Library lib/v0.3.2-701-gb711d8720
Video chat in your terminal
Loading...
Searching...
No Matches
notice.c File Reference

Go to the source code of this file.

Data Structures

struct  notice_snapshot_t

Macros

#define FIRST_USE_LINE_COUNT   64
#define FIRST_USE_LINE_BYTES   512
#define FIRST_USE_CONTENT_COLUMNS   66

Functions

int ui_notice_render (frame_buffer_t *buffer, const char *text, ui_notice_severity_t severity, int cols, bool unicode, bool color)
const char * ui_notice_title (const void *data)
asciichat_error_t ui_notice_present (ui_notice_severity_t severity, const char *text)
asciichat_error_t ui_notice_present_first_use (const char *title, const char *text, const char *marker_path)
void ui_notice_frame_presented (const void *data)
ui_notice_key_result_t ui_notice_first_use_key (const void *data, int key)
void ui_notice_first_use_complete (const void *data)
bool ui_notice_confirm (ui_notice_severity_t severity, const char *text, unsigned timeout_seconds)
bool ui_notice_confirm_kind (ui_prompt_kind_t kind, ui_notice_severity_t severity, const char *text, unsigned timeout_seconds)
ui_prompt_kind_t ui_notice_prompt_kind (void)
ui_notice_severity_t ui_notice_prompt_severity (void)
void ui_notice_flush_snapshot (int fd, const void *data)
void ui_notice_dismiss (void)

Macro Definition Documentation

◆ FIRST_USE_CONTENT_COLUMNS

#define FIRST_USE_CONTENT_COLUMNS   66

Definition at line 203 of file notice.c.

◆ FIRST_USE_LINE_BYTES

#define FIRST_USE_LINE_BYTES   512

Definition at line 202 of file notice.c.

◆ FIRST_USE_LINE_COUNT

#define FIRST_USE_LINE_COUNT   64

Definition at line 201 of file notice.c.

Function Documentation

◆ ui_notice_confirm()

bool ui_notice_confirm ( ui_notice_severity_t severity,
const char * text,
unsigned timeout_seconds )

Explicitly styled yes/no prompt; default remains No.

Definition at line 494 of file notice.c.

494 {
495 return ui_notice_confirm_kind(UI_PROMPT_CONFIRMATION, severity, text, timeout_seconds);
496}
bool ui_notice_confirm_kind(ui_prompt_kind_t kind, ui_notice_severity_t severity, const char *text, unsigned timeout_seconds)
Definition notice.c:498

References ui_notice_confirm_kind().

◆ ui_notice_confirm_kind()

bool ui_notice_confirm_kind ( ui_prompt_kind_t kind,
ui_notice_severity_t severity,
const char * text,
unsigned timeout_seconds )

Definition at line 498 of file notice.c.

499 {
500 ui_prompt_kind_t previous_kind = g_prompt_kind;
501 g_prompt_kind = kind;
502 ui_notice_severity_t previous = g_prompt_severity;
503 g_prompt_severity = severity;
504 if (terminal_can_prompt_user(!GET_OPTION(snapshot_mode)))
505 log_msg(severity == UI_NOTICE_FATAL ? LOG_FATAL
506 : severity == UI_NOTICE_DANGER ? LOG_ERROR
507 : severity == UI_NOTICE_WARNING ? LOG_WARN
508 : LOG_INFO,
509 __FILE__, __LINE__, __func__, "%s", text);
510 else
511 ui_notice_log(severity, __FILE__, __LINE__, __func__, "CONFIRMATION REQUIRED", "%s", text);
512 bool accepted = platform_prompt_yes_no_timeout(text, false, timeout_seconds);
513 g_prompt_kind = previous_kind;
514 g_prompt_severity = previous;
515 return accepted;
516}
void log_msg(log_level_t level, const char *file, int line, const char *func, const char *fmt,...)
Log a message at a specific level.
Definition log.c:1196
#define GET_OPTION(field)
Safely get a specific option field (lock-free read).
Definition options.h:1336
void ui_notice_log(ui_notice_severity_t severity, const char *file, int line, const char *func, const char *title, const char *format,...)
Definition log.c:1181
ui_notice_severity_t
Definition notice.h:9
@ UI_NOTICE_WARNING
Definition notice.h:11
@ UI_NOTICE_DANGER
Definition notice.h:12
@ UI_NOTICE_FATAL
Definition notice.h:13
#define LOG_FATAL
Definition types.h:43
#define LOG_ERROR
Definition types.h:42
#define LOG_WARN
Definition types.h:41
#define LOG_INFO
Definition types.h:40

References GET_OPTION, LOG_ERROR, LOG_FATAL, LOG_INFO, log_msg(), LOG_WARN, UI_NOTICE_DANGER, UI_NOTICE_FATAL, ui_notice_log(), and UI_NOTICE_WARNING.

Referenced by action_completions(), config_create_default(), discovery_keys_verify_change(), prompt_unknown_host(), prompt_unknown_host_no_identity(), and ui_notice_confirm().

◆ ui_notice_dismiss()

void ui_notice_dismiss ( void )

Definition at line 541 of file notice.c.

541 {
543}
void ui_controller_remove(ui_screen_t screen)
@ UI_SCREEN_NOTICE

References ui_controller_remove(), and UI_SCREEN_NOTICE.

◆ ui_notice_first_use_complete()

void ui_notice_first_use_complete ( const void * data)

Definition at line 478 of file notice.c.

478 {
479 const notice_snapshot_t *notice = data;
480 if (!notice || !notice->marker_offset)
481 return;
483 FILE *marker = platform_fopen("first-use instructions", notice->text + notice->marker_offset, "w");
484 if (!marker) {
485 log_warn("Could not save first-use instructions state; the notice may appear again: %s",
486 notice->text + notice->marker_offset);
487 } else if (fclose(marker) != 0) {
488 log_warn("Could not finish saving first-use instructions state; the notice may appear again: %s",
489 notice->text + notice->marker_offset);
490 }
492}
void errno_scope_end(asciichat_errno_scope_t scope, asciichat_errno_outcome_t outcome)
asciichat_errno_scope_t errno_scope_begin(void)
@ ASCIICHAT_ERRNO_DISMISSED
#define log_warn(...)
Log a WARN message.
Definition log/log.h:621
When code needs to work with asciichat errno snapshot, it keeps total, copied here instead of scatter...
size_t marker_offset
Definition notice.c:178

References ASCIICHAT_ERRNO_DISMISSED, errno_scope_begin(), errno_scope_end(), log_warn, notice_snapshot_t::marker_offset, and notice_snapshot_t::text.

Referenced by ui_controller_first_use_key().

◆ ui_notice_first_use_key()

ui_notice_key_result_t ui_notice_first_use_key ( const void * data,
int key )

Definition at line 453 of file notice.c.

453 {
454 notice_snapshot_t *notice = (notice_snapshot_t *)data;
455 if (!notice || !notice->marker_offset)
457 if (key == KEY_ESCAPE || key == 'q' || key == 3)
459 if (key == KEY_QUESTION)
460 return UI_NOTICE_KEY_HELP;
461 int page = atomic_load(&notice->page);
462 int pages = atomic_load(&notice->pages);
463 if (key == KEY_LEFT && page > 0) {
464 atomic_store(&notice->presented_page, -1);
465 atomic_store(&notice->page, page - 1);
466 } else if ((key == '\r' || key == '\n' || key == KEY_RIGHT) && pages > 0 &&
467 atomic_load(&notice->presented_page) == page) {
468 if (page + 1 < pages) {
469 atomic_store(&notice->presented_page, -1);
470 atomic_store(&notice->page, page + 1);
471 } else if (key == '\r' || key == '\n') {
473 }
474 }
476}
@ KEY_ESCAPE
Escape key (ESC).
Definition keyboard.h:55
@ KEY_LEFT
Left arrow key.
Definition keyboard.h:59
@ KEY_RIGHT
Right arrow key.
Definition keyboard.h:60
@ KEY_QUESTION
'?' key - show help screen
Definition keyboard.h:83
@ UI_NOTICE_KEY_HELP
Definition notice.h:33
@ UI_NOTICE_KEY_ORDINARY
Definition notice.h:31
@ UI_NOTICE_KEY_DISMISS
Definition notice.h:34
@ UI_NOTICE_KEY_COMPLETE
Definition notice.h:35
@ UI_NOTICE_KEY_HANDLED
Definition notice.h:32
atomic_int page
Definition notice.c:180
atomic_int presented_page
Definition notice.c:182
atomic_int pages
Definition notice.c:181

References KEY_ESCAPE, KEY_LEFT, KEY_QUESTION, KEY_RIGHT, notice_snapshot_t::marker_offset, notice_snapshot_t::page, notice_snapshot_t::pages, notice_snapshot_t::presented_page, UI_NOTICE_KEY_COMPLETE, UI_NOTICE_KEY_DISMISS, UI_NOTICE_KEY_HANDLED, UI_NOTICE_KEY_HELP, and UI_NOTICE_KEY_ORDINARY.

Referenced by ui_controller_first_use_key().

◆ ui_notice_flush_snapshot()

void ui_notice_flush_snapshot ( int fd,
const void * snapshot )

Controller teardown writes pending notices to scrollback before releasing them.

Definition at line 526 of file notice.c.

526 {
527 const notice_snapshot_t *notice = data;
528 frame_buffer_t *buffer = frame_buffer_create(0, 0);
529 if (!buffer)
530 return;
531 if (platform_isatty(fd))
532 frame_buffer_append(buffer, "\033[0m\n", 5);
533 terminal_size_t size = {.cols = 80};
534 if (platform_isatty(fd))
535 (void)terminal_get_size_fd(fd, &size);
536 ui_notice_render(buffer, notice->text, notice->severity, size.cols, notice->unicode, notice->color);
538 frame_buffer_destroy(buffer);
539}
void frame_buffer_append(frame_buffer_t *buf, const char *str, size_t len)
Append raw bytes to the buffer.
void frame_buffer_destroy(frame_buffer_t *buf)
Destroy a frame buffer.
size_t frame_buffer_get_length(const frame_buffer_t *buf)
Get the current content length of the frame buffer.
const char * frame_buffer_get_content(const frame_buffer_t *buf)
Get a pointer to the buffer content.
frame_buffer_t * frame_buffer_create(int rows, int cols)
Create a new frame buffer.
struct frame_buffer frame_buffer_t
Opaque frame buffer handle.
size_t platform_write_all(int fd, const void *buf, size_t count)
Write all bytes to a file descriptor, handling partial writes.
int ui_notice_render(frame_buffer_t *buffer, const char *text, ui_notice_severity_t severity, int cols, bool unicode, bool color)
Definition notice.c:64
ui_notice_severity_t severity
Definition notice.c:174

References notice_snapshot_t::color, frame_buffer_append(), frame_buffer_create(), frame_buffer_destroy(), frame_buffer_get_content(), frame_buffer_get_length(), platform_write_all(), notice_snapshot_t::severity, notice_snapshot_t::text, ui_notice_render(), and notice_snapshot_t::unicode.

◆ ui_notice_frame_presented()

void ui_notice_frame_presented ( const void * snapshot)

Record which first-use page reached the terminal after a successful frame.

Definition at line 447 of file notice.c.

447 {
448 notice_snapshot_t *notice = (notice_snapshot_t *)data;
449 if (notice && notice->marker_offset)
450 atomic_store(&notice->presented_page, notice->rendered_page);
451}

References notice_snapshot_t::marker_offset, notice_snapshot_t::presented_page, and notice_snapshot_t::rendered_page.

◆ ui_notice_present()

asciichat_error_t ui_notice_present ( ui_notice_severity_t severity,
const char * text )

Present a notice without changing authentication or input policy.

Definition at line 371 of file notice.c.

371 {
372 if (!text)
373 return SET_ERRNO(ERROR_INVALID_PARAM, "Missing notice text");
374 bool tty = platform_isatty(STDERR_FILENO);
375 bool color = !GET_OPTION(strip_ansi) && terminal_should_color_output(STDERR_FILENO, options_terminal_settings());
376 bool unicode = tty && terminal_should_use_utf8(GET_OPTION(force_utf8));
377 if (severity != UI_NOTICE_FATAL && tty && ui_controller_is_presenting() && !ui_controller_is_owner() &&
378 !GET_OPTION(snapshot_mode)) {
379 size_t text_bytes = strlen(text) + 1;
380 size_t bytes = sizeof(notice_snapshot_t) + text_bytes;
381 notice_snapshot_t *snapshot = SAFE_MALLOC(bytes, notice_snapshot_t *);
382 if (!snapshot)
383 return SET_ERRNO(ERROR_MEMORY, "Cannot allocate notice");
384 snapshot->severity = severity;
385 snapshot->unicode = unicode;
386 snapshot->color = color;
387 snapshot->started = time_get_ns();
388 snapshot->marker_offset = snapshot->title_offset = 0;
389 atomic_init(&snapshot->page, 0);
390 atomic_init(&snapshot->pages, 0);
391 atomic_init(&snapshot->presented_page, -1);
392 snapshot->rendered_page = -1;
393 snapshot->rendered_cols = snapshot->rendered_rows = 0;
394 memcpy(snapshot->text, text, text_bytes);
396 UI_SCREEN_NOTICE, STDERR_FILENO, (terminal_size_t){.cols = 1, .rows = 1}, render_notice, snapshot, bytes);
397 SAFE_FREE(snapshot);
398 return result;
399 }
400 frame_buffer_t *buffer = frame_buffer_create(0, 0);
401 if (!buffer)
402 return SET_ERRNO(ERROR_MEMORY, "Cannot allocate notice buffer");
403 if (severity == UI_NOTICE_FATAL && tty)
404 frame_buffer_append(buffer, "\033[0m\033[?25h\r\n", 12);
405 int cols = tty ? ui_controller_size().cols : 80;
406 ui_notice_render(buffer, text, severity, cols, unicode, color);
408 if (severity == UI_NOTICE_FATAL && !ui_controller_is_owner())
410 else
411 result = ui_controller_write(STDERR_FILENO, frame_buffer_get_content(buffer), frame_buffer_get_length(buffer));
412 frame_buffer_destroy(buffer);
413 return result;
414}
#define SET_ERRNO(code,...)
#define SAFE_FREE(ptr)
Definition common.h:377
#define SAFE_MALLOC(size, cast)
Definition common.h:265
asciichat_error_t
Error and exit codes - unified status values (0-255).
Definition error_codes.h:44
@ ERROR_MEMORY
Definition error_codes.h:51
@ ASCIICHAT_OK
Definition error_codes.h:46
@ ERROR_INVALID_PARAM
#define options_terminal_settings()
Definition options.h:1296
uint64_t started
Definition notice.c:177
size_t title_offset
Definition notice.c:179
asciichat_error_t ui_controller_submit(ui_screen_t screen, int fd, terminal_size_t minimum, ui_render_fn render, const void *snapshot, size_t bytes)
bool ui_controller_is_presenting(void)
bool ui_controller_is_owner(void)
void ui_controller_finish(int fd, const char *data, size_t len)
terminal_size_t ui_controller_size(void)
asciichat_error_t ui_controller_write(int fd, const char *data, size_t len)

References ASCIICHAT_OK, notice_snapshot_t::color, ERROR_INVALID_PARAM, ERROR_MEMORY, frame_buffer_append(), frame_buffer_create(), frame_buffer_destroy(), frame_buffer_get_content(), frame_buffer_get_length(), GET_OPTION, notice_snapshot_t::marker_offset, options_terminal_settings, notice_snapshot_t::page, notice_snapshot_t::pages, notice_snapshot_t::presented_page, notice_snapshot_t::rendered_cols, notice_snapshot_t::rendered_page, notice_snapshot_t::rendered_rows, SAFE_FREE, SAFE_MALLOC, SET_ERRNO, notice_snapshot_t::severity, notice_snapshot_t::started, notice_snapshot_t::text, notice_snapshot_t::title_offset, ui_controller_finish(), ui_controller_is_owner(), ui_controller_is_presenting(), ui_controller_size(), ui_controller_submit(), ui_controller_write(), UI_NOTICE_FATAL, ui_notice_render(), UI_SCREEN_NOTICE, and notice_snapshot_t::unicode.

◆ ui_notice_present_first_use()

asciichat_error_t ui_notice_present_first_use ( const char * title,
const char * text,
const char * marker_path )

Show a first-use notice until the user dismisses it.

Definition at line 416 of file notice.c.

416 {
417 if (!title || !text || !marker_path || !platform_isatty(STDERR_FILENO) || GET_OPTION(snapshot_mode))
418 return SET_ERRNO(ERROR_INVALID_PARAM, "First-use notice requires an interactive terminal and marker path");
419 size_t text_bytes = strlen(text) + 1, title_bytes = strlen(title) + 1, marker_bytes = strlen(marker_path) + 1;
420 if (title_bytes > SIZE_MAX - marker_bytes - sizeof(notice_snapshot_t) ||
421 text_bytes > SIZE_MAX - title_bytes - marker_bytes - sizeof(notice_snapshot_t))
422 return SET_ERRNO(ERROR_BUFFER_OVERFLOW, "First-use notice is too large");
423 size_t bytes = sizeof(notice_snapshot_t) + text_bytes + title_bytes + marker_bytes;
424 notice_snapshot_t *snapshot = SAFE_MALLOC(bytes, notice_snapshot_t *);
425 if (!snapshot)
426 return SET_ERRNO(ERROR_MEMORY, "Cannot allocate first-use notice");
427 snapshot->severity = UI_NOTICE_INFO;
428 snapshot->unicode = terminal_should_use_utf8(GET_OPTION(force_utf8));
429 snapshot->color = !GET_OPTION(strip_ansi) && terminal_should_color_output(STDERR_FILENO, options_terminal_settings());
430 snapshot->started = time_get_ns();
431 snapshot->title_offset = text_bytes;
432 snapshot->marker_offset = text_bytes + title_bytes;
433 atomic_init(&snapshot->page, 0);
434 atomic_init(&snapshot->pages, 0);
435 atomic_init(&snapshot->presented_page, -1);
436 snapshot->rendered_page = -1;
437 snapshot->rendered_cols = snapshot->rendered_rows = 0;
438 memcpy(snapshot->text, text, text_bytes);
439 memcpy(snapshot->text + text_bytes, title, title_bytes);
440 memcpy(snapshot->text + snapshot->marker_offset, marker_path, marker_bytes);
442 UI_SCREEN_NOTICE, STDERR_FILENO, (terminal_size_t){.cols = 20, .rows = 8}, render_notice, snapshot, bytes);
443 SAFE_FREE(snapshot);
444 return result;
445}
@ ERROR_BUFFER_OVERFLOW
@ UI_NOTICE_INFO
Definition notice.h:10

References notice_snapshot_t::color, ERROR_BUFFER_OVERFLOW, ERROR_INVALID_PARAM, ERROR_MEMORY, GET_OPTION, notice_snapshot_t::marker_offset, options_terminal_settings, notice_snapshot_t::page, notice_snapshot_t::pages, notice_snapshot_t::presented_page, notice_snapshot_t::rendered_cols, notice_snapshot_t::rendered_page, notice_snapshot_t::rendered_rows, SAFE_FREE, SAFE_MALLOC, SET_ERRNO, notice_snapshot_t::severity, notice_snapshot_t::started, notice_snapshot_t::text, notice_snapshot_t::title_offset, ui_controller_submit(), UI_NOTICE_INFO, UI_SCREEN_NOTICE, and notice_snapshot_t::unicode.

◆ ui_notice_prompt_kind()

ui_prompt_kind_t ui_notice_prompt_kind ( void )

Definition at line 518 of file notice.c.

518 {
519 return g_prompt_kind;
520}

Referenced by main().

◆ ui_notice_prompt_severity()

ui_notice_severity_t ui_notice_prompt_severity ( void )

Definition at line 522 of file notice.c.

522 {
523 return g_prompt_severity;
524}

Referenced by ui_prompt_present_kind().

◆ ui_notice_render()

int ui_notice_render ( frame_buffer_t * buffer,
const char * text,
ui_notice_severity_t severity,
int cols,
bool unicode,
bool color )

Append a complete box, or measure it when buffer is NULL. Returns its row count. Text is plain UTF-8. Terminal control characters are made visible, never executed.

Definition at line 64 of file notice.c.

65 {
66 if (!text)
67 text = "";
68 const char *body = text;
69 text = notice_label(severity);
70 bool rendering_label = true;
71 const char *text_end = text + strlen(text);
72 // Reserve the final column to avoid terminal autowrap at the right border.
73 int width = cols > 81 ? 80 : cols - 1;
74 bool boxed = width >= 8;
75 int content = boxed ? width - 4 : (cols > 2 ? cols - 1 : 2);
76 const char *side = unicode ? "║" : "|";
77 if (buffer && color)
78 frame_buffer_printf(buffer, "\033[1m%s", notice_color(severity));
79 if (boxed)
80 border(buffer, width, UI_POPUP_TOP, unicode, severity, color);
81 int rows = boxed ? 2 : 0;
82 const char *art_end = NULL;
83 const char *word_end = NULL;
84 bool title_word = false;
85 bool first_letter = false;
86 do {
87 // The Keymask formatter identifies complete plain-text blocks; input ANSI
88 // escapes still pass through the normal control-character sanitization.
89 const char *block_end = key_identity_art_end(text);
90 if (block_end)
91 art_end = block_end;
92 bool neutral = art_end && text < art_end;
93 int used = 0;
94 if (buffer && boxed)
95 frame_buffer_printf(buffer, "%s ", side);
96 if (buffer && color && neutral)
97 frame_buffer_append(buffer, "\033[0;39m", 7);
98 while (*text && *text != '\n') {
99 int bytes = utf8_next_char_bytes(text, (size_t)(text_end - text));
100 if (bytes <= 0)
101 bytes = 1;
102 bool control = (unsigned char)*text < 32 || (unsigned char)*text == 127 ||
103 (bytes == 2 && (unsigned char)text[0] == 0xc2 && (unsigned char)text[1] >= 0x80 &&
104 (unsigned char)text[1] <= 0x9f);
105 int cells = control ? 1 : utf8_display_width_n(text, (size_t)bytes);
106 if (cells < 0)
107 cells = 1;
108 if (used + cells > content && used)
109 break;
110 if (buffer) {
111 if (control)
112 frame_buffer_append(buffer, "?", 1);
113 else if (!rendering_label && !neutral) {
114 if (!word_end || text >= word_end) {
115 word_end = text;
116 title_word = (*text >= 'A' && *text <= 'Z') || (*text >= 'a' && *text <= 'z');
117 first_letter = true;
118 while (*word_end && *word_end != ' ' && *word_end != '\n' && *word_end != '\t') {
119 unsigned char c = (unsigned char)*word_end;
120 bool letter = (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
121 bool punctuation = strchr(",.;:!?", c) && (!word_end[1] || word_end[1] == ' ' || word_end[1] == '\n');
122 if (!letter && !punctuation)
123 title_word = false;
124 ++word_end;
125 }
126 }
127 if (title_word && bytes == 1) {
128 char c = *text;
129 if (first_letter && c >= 'a' && c <= 'z')
130 c -= 'a' - 'A';
131 else if (!first_letter && c >= 'A' && c <= 'Z')
132 c += 'a' - 'A';
133 first_letter = false;
134 frame_buffer_append(buffer, &c, 1);
135 } else {
136 frame_buffer_append(buffer, text, (size_t)bytes);
137 }
138 } else
139 frame_buffer_append(buffer, text, (size_t)bytes);
140 }
141 used += cells;
142 text += bytes;
143 }
144 if (buffer) {
145 if (color && neutral)
146 frame_buffer_printf(buffer, "\033[1m%s", notice_color(severity));
147 if (boxed)
148 frame_buffer_printf(buffer, "%*s %s", content - used, "", side);
149 frame_buffer_append(buffer, "\n", 1);
150 }
151 ++rows;
152 if (*text == '\n')
153 ++text;
154 if (!*text) {
155 if (!rendering_label)
156 break;
157 if (boxed) {
158 border(buffer, width, UI_POPUP_SEPARATOR, unicode, severity, color);
159 ++rows;
160 }
161 rendering_label = false;
162 text = body;
163 text_end = text + strlen(text);
164 }
165 } while (true);
166 if (boxed)
167 border(buffer, width, UI_POPUP_BOTTOM, unicode, severity, color);
168 if (buffer && color)
169 frame_buffer_append(buffer, "\033[0m", 4);
170 return rows;
171}
char cells[(512 *256 *2)]
Definition fft.c:21
unsigned int width
Definition fft.c:23
void frame_buffer_printf(frame_buffer_t *buf, const char *fmt,...)
Printf-style append to the buffer.
int utf8_display_width_n(const char *str, size_t max_bytes)
Calculate terminal display width of a UTF-8 string up to byte limit.
Definition utf8.c:102
int utf8_next_char_bytes(const char *str, size_t max_bytes)
Get byte length of next UTF-8 character.
Definition utf8.c:177
const char * key_identity_art_end(const char *text)
@ UI_POPUP_BOTTOM
Definition popup.h:9
@ UI_POPUP_SEPARATOR
Definition popup.h:9
@ UI_POPUP_TOP
Definition popup.h:9

References cells, frame_buffer_append(), frame_buffer_printf(), key_identity_art_end(), UI_POPUP_BOTTOM, UI_POPUP_SEPARATOR, UI_POPUP_TOP, utf8_display_width_n(), utf8_next_char_bytes(), and width.

Referenced by ui_notice_flush_snapshot(), ui_notice_present(), ui_prompt_present_kind(), and ui_prompt_required_rows().

◆ ui_notice_title()

const char * ui_notice_title ( const void * data)

Definition at line 194 of file notice.c.

194 {
195 const notice_snapshot_t *notice = data;
196 return notice->severity == UI_NOTICE_WARNING ? "warning"
197 : notice->severity == UI_NOTICE_DANGER || notice->severity == UI_NOTICE_FATAL ? "error"
198 : "notice";
199}

References notice_snapshot_t::severity, UI_NOTICE_DANGER, UI_NOTICE_FATAL, and UI_NOTICE_WARNING.