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

Go to the source code of this file.

Macros

#define UI_CLIPPED_TEXT_OVERHEAD   32

Enumerations

enum  ui_alignment_t { UI_ALIGN_LEFT , UI_ALIGN_RIGHT , UI_ALIGN_CENTER }

Functions

size_t ui_text_cell (char *out, size_t capacity, const char *text, int width, ui_alignment_t alignment)
void ui_text_values (char *out, size_t capacity, const char *text)
void ui_text_values_style (char *out, size_t capacity, const char *text, log_color_t zero_color)
void ui_text_render_values (frame_buffer_t *out, const char *text)
const char * ui_text_color_prefix (log_color_t color)

Macro Definition Documentation

◆ UI_CLIPPED_TEXT_OVERHEAD

#define UI_CLIPPED_TEXT_OVERHEAD   32

Extra clipping storage for ellipsis, ANSI resets, and the terminating NUL.

Definition at line 4 of file text.h.

Enumeration Type Documentation

◆ ui_alignment_t

Enumerator
UI_ALIGN_LEFT 
UI_ALIGN_RIGHT 
UI_ALIGN_CENTER 

Definition at line 9 of file text.h.

ui_alignment_t
Definition text.h:9
@ UI_ALIGN_RIGHT
Definition text.h:9
@ UI_ALIGN_CENTER
Definition text.h:9
@ UI_ALIGN_LEFT
Definition text.h:9

Function Documentation

◆ ui_text_cell()

size_t ui_text_cell ( char * out,
size_t capacity,
const char * text,
int width,
ui_alignment_t alignment )

ANSI-aware, UTF-8-safe clipping/padding into caller-owned storage.

Definition at line 48 of file text.c.

48 {
49 if (!out || !cap) {
50 SET_ERRNO(ERROR_INVALID_PARAM, "UI text requires output storage");
51 return 0;
52 }
53 out[0] = '\0';
54 if (width <= 0)
55 return 0;
56 if (!text)
57 text = "";
58 int columns = 0;
59 const char *end = text;
60 while (*end) {
61 if (end[0] == '\033' && end[1] == '[') {
62 const char *escape = end + 2;
63 while (*escape && !(*escape >= '@' && *escape <= '~'))
64 ++escape;
65 if (!*escape)
66 break;
67 end = escape + 1;
68 continue;
69 }
70 if ((unsigned char)*end < 32)
71 break;
72 int bytes = utf8_next_char_bytes(end, strlen(end));
73 if (bytes <= 0)
74 break;
75 int n = utf8_display_width_n(end, (size_t)bytes);
76 if (n < 0 || columns + n > width)
77 break;
78 columns += n;
79 end += bytes;
80 }
81 size_t used = 0;
82 int pad = width - columns;
83 int left = align == UI_ALIGN_RIGHT ? pad : align == UI_ALIGN_CENTER ? pad / 2 : 0;
84 for (int i = 0; i < left; ++i)
85 append(out, cap, &used, " ", 1);
86 append(out, cap, &used, text, (size_t)(end - text));
87 // A clipped styled cell must not bleed into the following column.
88 if (memchr(text, '\033', (size_t)(end - text)))
89 append(out, cap, &used, "\033[0m", 4);
90 for (int i = left; i < pad; ++i)
91 append(out, cap, &used, " ", 1);
92 return used;
93}
#define SET_ERRNO(code,...)
unsigned int width
Definition fft.c:23
@ ERROR_INVALID_PARAM
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
std::string escape(const std::string &str)
Escape a string for JSON output.
static bool size_t gotel_query_t * out
Definition queries.h:8

References ERROR_INVALID_PARAM, out, SET_ERRNO, UI_ALIGN_CENTER, UI_ALIGN_RIGHT, utf8_display_width_n(), utf8_next_char_bytes(), and width.

Referenced by ui_error_popup_preserve(), ui_error_popup_render(), ui_help_menu_render(), and ui_table_row().

◆ ui_text_color_prefix()

const char * ui_text_color_prefix ( log_color_t color)

Theme-aware prefix for incremental formatting, derived from colored_string().

Definition at line 18 of file text.c.

18 {
19 static _Thread_local char buffers[LOG_COLOR_WHITE + 1][UI_TEXT_COLOR_BUFFER_SIZE];
20 if (color < LOG_COLOR_DEV || color > LOG_COLOR_WHITE) {
21 SET_ERRNO(ERROR_INVALID_PARAM, "Invalid UI text color");
22 return "";
23 }
24 char *out = buffers[color];
25 const char *styled = colored_string(color, "!");
26 const char *marker = strchr(styled, '!');
27 size_t length = marker ? (size_t)(marker - styled) : 0;
28 if (length >= sizeof(buffers[0]))
29 length = sizeof(buffers[0]) - 1;
30 memcpy(out, styled, length);
31 out[length] = '\0';
32 return out;
33}
@ LOG_COLOR_WHITE
Definition log/log.h:156
const char * colored_string(log_color_t color, const char *text)
Build a colored string for terminal output.
Definition string.c:284
#define UI_TEXT_COLOR_BUFFER_SIZE
Definition text.c:7

References colored_string(), ERROR_INVALID_PARAM, LOG_COLOR_WHITE, out, SET_ERRNO, and UI_TEXT_COLOR_BUFFER_SIZE.

Referenced by frame_buffer_render_divider(), tui_stats_render(), ui_error_popup_render(), and ui_table_render().

◆ ui_text_render_values()

void ui_text_render_values ( frame_buffer_t * out,
const char * text )

Definition at line 146 of file text.c.

146 {
147 char styled[UI_TEXT_STYLED_BUFFER_SIZE];
148 ui_text_values_style(styled, sizeof(styled), text, LOG_COLOR_FATAL);
149 frame_buffer_append(out, styled, strlen(styled));
150}
void frame_buffer_append(frame_buffer_t *buf, const char *str, size_t len)
Append raw bytes to the buffer.
@ LOG_COLOR_FATAL
Definition log/log.h:153
#define UI_TEXT_STYLED_BUFFER_SIZE
Definition text.c:4
void ui_text_values_style(char *out, size_t cap, const char *text, log_color_t zero_color)
Definition text.c:95

References frame_buffer_append(), LOG_COLOR_FATAL, out, UI_TEXT_STYLED_BUFFER_SIZE, and ui_text_values_style().

Referenced by tui_stats_render().

◆ ui_text_values()

void ui_text_values ( char * out,
size_t capacity,
const char * text )

Theme-aware numeric/boolean styling; numeric suffixes retain default color.

Definition at line 142 of file text.c.

142 {
144}
@ LOG_COLOR_ERROR
Definition log/log.h:152

References LOG_COLOR_ERROR, out, and ui_text_values_style().

◆ ui_text_values_style()

void ui_text_values_style ( char * out,
size_t capacity,
const char * text,
log_color_t zero_color )

Definition at line 95 of file text.c.

95 {
96 if (!out || !cap) {
97 SET_ERRNO(ERROR_INVALID_PARAM, "UI text requires output storage");
98 return;
99 }
100 size_t used = 0;
101 out[0] = '\0';
102 if (!text)
103 return;
104 for (const char *p = text; *p;) {
105 if (p[0] == '\033' && p[1] == '[') {
106 const char *end = p + 2;
107 while (*end && !(*end >= '@' && *end <= '~'))
108 ++end;
109 if (*end)
110 ++end;
111 append(out, cap, &used, p, (size_t)(end - p));
112 p = end;
113 } else if (isdigit((unsigned char)*p)) {
114 char *end;
115 double value = p[0] == '0' && p[1] == 'x' ? (double)strtoull(p, &end, 16) : strtod(p, &end);
116 char number[UI_TEXT_NUMBER_BUFFER_SIZE];
117 size_t length = (size_t)(end - p);
118 if (length >= sizeof(number))
119 length = sizeof(number) - 1;
120 memcpy(number, p, length);
121 number[length] = '\0';
122 const char *styled = colored_string(value == 0 ? zero_color : LOG_COLOR_FATAL, number);
123 append(out, cap, &used, styled, strlen(styled));
124 p = end;
125 } else if ((p == text || !isalnum((unsigned char)p[-1])) &&
126 ((!strncmp(p, "enabled", 7) && !isalnum((unsigned char)p[7])) ||
127 (!strncmp(p, "disabled", 8) && !isalnum((unsigned char)p[8])))) {
128 bool enabled = *p == 'e';
129 const char *styled = colored_string(enabled ? LOG_COLOR_INFO : LOG_COLOR_ERROR, enabled ? "enabled" : "disabled");
130 append(out, cap, &used, styled, strlen(styled));
131 p += enabled ? 7 : 8;
132 } else {
133 int bytes = utf8_next_char_bytes(p, strlen(p));
134 if (bytes <= 0)
135 break;
136 append(out, cap, &used, p, (size_t)bytes);
137 p += bytes;
138 }
139 }
140}
bool enabled
Is filtering active?
Definition grep.c:62
@ LOG_COLOR_INFO
Definition log/log.h:150
#define UI_TEXT_NUMBER_BUFFER_SIZE
Definition text.c:3

References colored_string(), enabled, ERROR_INVALID_PARAM, LOG_COLOR_ERROR, LOG_COLOR_FATAL, LOG_COLOR_INFO, out, SET_ERRNO, UI_TEXT_NUMBER_BUFFER_SIZE, and utf8_next_char_bytes().

Referenced by ui_help_menu_render(), ui_text_render_values(), and ui_text_values().