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

Go to the source code of this file.

Macros

#define UI_POPUP_RENDERED_BUFFER_SIZE   1024

Functions

asciichat_error_t ui_popup_rule (frame_buffer_t *out, int width, ui_popup_edge_t edge, bool double_border, bool unicode, log_color_t color)
asciichat_error_t ui_popup_frame (frame_buffer_t *out, int row, int col, int width, int height, log_color_t color)
asciichat_error_t ui_popup_frame_titled (frame_buffer_t *out, int row, int col, int width, int height, log_color_t color, const char *title)
bool ui_popup_render (frame_buffer_t *output, terminal_size_t size, const ui_popup_t *box)

Macro Definition Documentation

◆ UI_POPUP_RENDERED_BUFFER_SIZE

#define UI_POPUP_RENDERED_BUFFER_SIZE   1024

Definition at line 3 of file popup.c.

Referenced by ui_popup_frame_titled(), and ui_popup_render().

Function Documentation

◆ ui_popup_frame()

asciichat_error_t ui_popup_frame ( frame_buffer_t * out,
int row,
int col,
int width,
int height,
log_color_t color )

Definition at line 28 of file popup.c.

28 {
29 if (!out || row < 1 || col < 1 || width < 2 || height < 2)
30 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid popup frame output or rectangle");
31 frame_buffer_printf(out, "\033[%d;%dH", row, col);
32 ui_popup_rule(out, width, UI_POPUP_TOP, false, terminal_should_use_utf8(GET_OPTION(force_utf8)), color);
33 const char *vertical = terminal_should_use_utf8(GET_OPTION(force_utf8)) ? "│" : "|";
34 for (int i = 1; i < height - 1; ++i)
35 frame_buffer_printf(out, "\033[%d;%dH%s%*s%s", row + i, col, colored_string(color, vertical), width - 2, "",
36 colored_string(color, vertical));
37 frame_buffer_printf(out, "\033[%d;%dH", row + height - 1, col);
38 return ui_popup_rule(out, width, UI_POPUP_BOTTOM, false, terminal_should_use_utf8(GET_OPTION(force_utf8)), color);
39}
#define SET_ERRNO(code,...)
unsigned int height
Definition fft.c:23
unsigned int width
Definition fft.c:23
void frame_buffer_printf(frame_buffer_t *buf, const char *fmt,...)
Printf-style append to the buffer.
@ ERROR_INVALID_PARAM
#define GET_OPTION(field)
Safely get a specific option field (lock-free read).
Definition options.h:1336
const char * colored_string(log_color_t color, const char *text)
Build a colored string for terminal output.
Definition string.c:284
asciichat_error_t ui_popup_rule(frame_buffer_t *out, int width, ui_popup_edge_t edge, bool double_border, bool unicode, log_color_t color)
Definition popup.c:12
@ UI_POPUP_BOTTOM
Definition popup.h:9
@ UI_POPUP_TOP
Definition popup.h:9
static bool size_t gotel_query_t * out
Definition queries.h:8

References colored_string(), ERROR_INVALID_PARAM, frame_buffer_printf(), GET_OPTION, height, out, SET_ERRNO, UI_POPUP_BOTTOM, ui_popup_rule(), UI_POPUP_TOP, and width.

Referenced by ui_error_popup_render(), ui_popup_frame_titled(), and ui_popup_render().

◆ ui_popup_frame_titled()

asciichat_error_t ui_popup_frame_titled ( frame_buffer_t * output,
int row,
int column,
int width,
int height,
log_color_t color,
const char * title )

Draw a frame with a centered, clipped title embedded in its top border.

Definition at line 41 of file popup.c.

42 {
43 if (!title || width < 5)
44 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid popup title or width");
45 asciichat_error_t result = ui_popup_frame(out, row, col, width, height, color);
46 if (result != ASCIICHAT_OK)
47 return result;
48 char rendered[UI_POPUP_RENDERED_BUFFER_SIZE];
49 truncate_with_ellipsis(title, rendered, sizeof(rendered), width - 4);
50 int title_width = display_width(rendered);
51 frame_buffer_printf(out, "\033[%d;%dH %s ", row, col + (width - title_width - 2) / 2,
53 return ASCIICHAT_OK;
54}
asciichat_error_t
Error and exit codes - unified status values (0-255).
Definition error_codes.h:44
@ ASCIICHAT_OK
Definition error_codes.h:46
@ LOG_COLOR_RESET
Definition log/log.h:155
int display_width(const char *text)
Calculate the visible display width of text with ANSI escape codes.
void truncate_with_ellipsis(const char *input, char *output, size_t output_size, int max_width)
Truncate a string to a maximum display width, with ellipsis.
Definition string.c:370
asciichat_error_t ui_popup_frame(frame_buffer_t *out, int row, int col, int width, int height, log_color_t color)
Definition popup.c:28
#define UI_POPUP_RENDERED_BUFFER_SIZE
Definition popup.c:3

References ASCIICHAT_OK, colored_string(), display_width(), ERROR_INVALID_PARAM, frame_buffer_printf(), height, LOG_COLOR_RESET, out, SET_ERRNO, truncate_with_ellipsis(), ui_popup_frame(), UI_POPUP_RENDERED_BUFFER_SIZE, and width.

◆ ui_popup_render()

bool ui_popup_render ( frame_buffer_t * output,
terminal_size_t size,
const ui_popup_t * box )

Draw a centered box without clearing the frame beneath it.

Definition at line 56 of file popup.c.

56 {
57 if (!output || !box || !box->title || (box->line_count && !box->lines) || box->top_margin < 0) {
58 SET_ERRNO(ERROR_INVALID_PARAM, "Invalid popup output, content or margins");
59 return false;
60 }
61 if (size.cols < 8 || size.rows < 5)
62 return false;
63 int content_width = display_width(box->title);
64 for (size_t i = 0; i < box->line_count; ++i) {
65 int width = display_width(box->lines[i]);
66 if (width > content_width)
67 content_width = width;
68 }
69 if (box->footer && display_width(box->footer) > content_width)
70 content_width = display_width(box->footer);
71 int width = content_width + 4;
72 if (width < box->minimum_width)
73 width = box->minimum_width;
74 if (width > size.cols - 2)
75 width = size.cols - 2;
76 int height = (int)box->line_count + (box->footer ? 5 : 4);
77 if (height > size.rows - 2 - box->top_margin)
78 return false;
79 int left = (size.cols - width) / 2 + 1;
80 int top = box->top_margin + (size.rows - box->top_margin - height) / 2 + 1;
81 if (ui_popup_frame(output, top, left, width, height, LOG_COLOR_RESET) != ASCIICHAT_OK)
82 return false;
83 char rendered[UI_POPUP_RENDERED_BUFFER_SIZE];
84 truncate_with_ellipsis(box->title, rendered, sizeof(rendered), width - 4);
85 const char *colored_title = colored_string(LOG_COLOR_RESET, rendered);
86 frame_buffer_printf(output, "\033[%d;%dH\033[1m%s\033[0m", top + 1, left + 2, colored_title);
87 for (size_t i = 0; i < box->line_count; ++i) {
88 truncate_with_ellipsis(box->lines[i], rendered, sizeof(rendered), width - 4);
89 frame_buffer_printf(output, "\033[%d;%dH%s", top + 2 + (int)i, left + 2, rendered);
90 }
91 if (box->footer) {
92 truncate_with_ellipsis(box->footer, rendered, sizeof(rendered), width - 4);
93 frame_buffer_printf(output, "\033[%d;%dH\033[2m%s\033[0m", top + height - 2, left + 2, rendered);
94 }
95 return true;
96}
int top_margin
Definition popup.h:29
const char *const * lines
Definition popup.h:25
const char * title
Definition popup.h:24
int minimum_width
Definition popup.h:28
const char * footer
Definition popup.h:27
size_t line_count
Definition popup.h:26

References ASCIICHAT_OK, colored_string(), display_width(), ERROR_INVALID_PARAM, ui_popup_t::footer, frame_buffer_printf(), height, ui_popup_t::line_count, ui_popup_t::lines, LOG_COLOR_RESET, ui_popup_t::minimum_width, SET_ERRNO, ui_popup_t::title, ui_popup_t::top_margin, truncate_with_ellipsis(), ui_popup_frame(), UI_POPUP_RENDERED_BUFFER_SIZE, and width.

Referenced by ui_help_menu_render().

◆ ui_popup_rule()

asciichat_error_t ui_popup_rule ( frame_buffer_t * output,
int width,
ui_popup_edge_t edge,
bool double_border,
bool unicode,
log_color_t color )

Shared chrome for streaming notices and nested dialog panels. No newline.

Definition at line 12 of file popup.c.

13 {
14 if (!out || width < 2 || edge < UI_POPUP_TOP || edge > UI_POPUP_RULE)
15 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid popup rule output, width or edge");
16 static const char *single[][2] = {{"┌", "┐"}, {"├", "┤"}, {"└", "┘"}, {"", ""}};
17 static const char *dual[][2] = {{"╔", "╗"}, {"╠", "╣"}, {"╚", "╝"}, {"", ""}};
18 const char *left = edge == UI_POPUP_RULE ? "" : !unicode ? "+" : double_border ? dual[edge][0] : single[edge][0];
19 const char *right = edge == UI_POPUP_RULE ? "" : !unicode ? "+" : double_border ? dual[edge][1] : single[edge][1];
20 const char *horizontal = !unicode ? "-" : double_border ? "═" : "─";
21 frame_buffer_printf(out, "%s", colored_string(color, left));
22 for (int i = 0; i < width - (edge == UI_POPUP_RULE ? 0 : 2); ++i)
23 frame_buffer_printf(out, "%s", colored_string(color, horizontal));
24 frame_buffer_printf(out, "%s", colored_string(color, right));
25 return ASCIICHAT_OK;
26}
@ UI_POPUP_RULE
Definition popup.h:9

References ASCIICHAT_OK, colored_string(), ERROR_INVALID_PARAM, frame_buffer_printf(), out, SET_ERRNO, UI_POPUP_RULE, and width.

Referenced by ui_error_popup_preserve(), and ui_popup_frame().