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

Go to the source code of this file.

Data Structures

struct  ui_table_column_t
struct  ui_table_t
 The useful part of ui table column is in heading, width, alignment, ellipsis: together they describe what is pending, who owns it, and how much data is valid. Keep the object with its parent operation and use the parent cleanup path. More...

Typedefs

typedef void(* ui_table_cells_fn) (size_t row, const char **cells, size_t columns, void *data)

Functions

size_t ui_table_row (char *out, size_t capacity, const ui_table_column_t *columns, const char *const *cells, size_t count, int width, bool selectable, bool selected)
 When code needs to work with ui table, it keeps columns, column_count, row_count, viewport here instead of scattering it across globals. Initialization establishes the handles and sizes; teardown must release any allocation, lock, thread, or callback context recorded in those fields. terminal columns, never by bytes. The caller owns data and sorting.
void ui_table_render (frame_buffer_t *out, ui_table_t *table, int row, int column, int width, int height)

Typedef Documentation

◆ ui_table_cells_fn

typedef void(* ui_table_cells_fn) (size_t row, const char **cells, size_t columns, void *data)

Definition at line 18 of file table.h.

Function Documentation

◆ ui_table_render()

void ui_table_render ( frame_buffer_t * out,
ui_table_t * table,
int row,
int column,
int width,
int height )

Rectangular table with a fixed header and independent page/scroll state.

Definition at line 76 of file table.c.

76 {
77 if (!out || !t || !t->columns || !t->column_count || t->column_count > 32 || !t->cells || width < 2 || height < 1 ||
78 row < 1 || col < 1) {
79 SET_ERRNO(ERROR_INVALID_PARAM, "Invalid table output, data source or geometry");
80 return;
81 }
83 if (t->header) {
84 ui_table_row(line, sizeof(line), t->columns, NULL, t->column_count, width - 1, t->selectable, false);
85 frame_buffer_printf(out, "\033[%d;%dH%s%s%s", row++, col, ui_text_color_prefix(LOG_COLOR_DEBUG), line,
87 --height;
88 }
89 if (height < 1)
90 return;
91 ui_viewport_range_t range = ui_viewport_update(&t->viewport, t->row_count, (size_t)height);
92 for (int i = 0; i < height; ++i) {
93 const char *cells[UI_TABLE_CELL_CAPACITY] = {0};
94 if ((size_t)i < range.count) {
95 t->cells(range.first + (size_t)i, cells, t->column_count, t->data);
96 ui_table_row(line, sizeof(line), t->columns, cells, t->column_count, width - 1, t->selectable,
97 range.first + (size_t)i == t->viewport.selected);
98 } else
99 snprintf(line, sizeof(line), "%*s", width - 1, "");
100 bool selected = t->selectable && (size_t)i < range.count && range.first + (size_t)i == t->viewport.selected;
101 frame_buffer_printf(out, "\033[%d;%dH%s%s%s", row + i, col, selected ? "\033[7m" : "", line,
102 selected ? "\033[27m" : "");
103 }
104 ui_scrollbar_render(out, row, col + width - 1, height, range.page_count, (size_t)height, t->viewport.first_visible);
105}
#define SET_ERRNO(code,...)
char cells[(512 *256 *2)]
Definition fft.c:21
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
@ LOG_COLOR_RESET
Definition log/log.h:155
@ LOG_COLOR_DEBUG
Definition log/log.h:149
static bool size_t gotel_query_t * out
Definition queries.h:8
void ui_scrollbar_render(frame_buffer_t *out, int row, int col, int height, size_t total, size_t visible, size_t offset)
Definition scrollbar.c:40
size_t ui_table_row(char *out, size_t cap, const ui_table_column_t *cols, const char *const *cells, size_t count, int width, bool selectable, bool selected)
When code needs to work with ui table, it keeps columns, column_count, row_count, viewport here inste...
Definition table.c:18
#define UI_TABLE_LINE_BUFFER_SIZE
Definition table.c:4
#define UI_TABLE_CELL_CAPACITY
Definition table.c:7
const char * ui_text_color_prefix(log_color_t color)
Definition text.c:18
ui_viewport_range_t ui_viewport_update(ui_viewport_t *v, size_t count, size_t rows)
Definition viewport.c:4

References cells, ui_table_t::cells, ui_table_t::column_count, ui_table_t::columns, ui_viewport_range_t::count, ui_table_t::data, ERROR_INVALID_PARAM, ui_viewport_range_t::first, ui_viewport_t::first_visible, frame_buffer_printf(), ui_table_t::header, height, LOG_COLOR_DEBUG, LOG_COLOR_RESET, out, ui_viewport_range_t::page_count, ui_table_t::row_count, ui_table_t::selectable, ui_viewport_t::selected, SET_ERRNO, ui_scrollbar_render(), UI_TABLE_CELL_CAPACITY, UI_TABLE_LINE_BUFFER_SIZE, ui_table_row(), ui_text_color_prefix(), ui_viewport_update(), ui_table_t::viewport, and width.

Referenced by tui_stats_render().

◆ ui_table_row()

size_t ui_table_row ( char * out,
size_t capacity,
const ui_table_column_t * columns,
const char *const * cells,
size_t count,
int width,
bool selectable,
bool selected )

When code needs to work with ui table, it keeps columns, column_count, row_count, viewport here instead of scattering it across globals. Initialization establishes the handles and sizes; teardown must release any allocation, lock, thread, or callback context recorded in those fields. terminal columns, never by bytes. The caller owns data and sorting.

Format a complete row without allocation. Styled cells are clipped by

Definition at line 18 of file table.c.

19 {
20 if (!out || !cap) {
21 SET_ERRNO(ERROR_INVALID_PARAM, "Table row requires output storage");
22 return 0;
23 }
24 out[0] = '\0';
25 if (!cols || !count || count > 32 || width <= 0) {
26 SET_ERRNO(ERROR_INVALID_PARAM, "Invalid table columns or width");
27 return 0;
28 }
29 int64_t remaining = (int64_t)width - (selectable ? 1 : 0) - (int)(count - 1);
30 size_t flexible = 0;
31 for (size_t i = 0; i < count; ++i) {
32 if (cols[i].width < 0) {
33 SET_ERRNO(ERROR_INVALID_PARAM, "Table column width cannot be negative");
34 return 0;
35 }
36 if (cols[i].width > 0)
37 remaining -= cols[i].width;
38 else
39 ++flexible;
40 }
41 size_t used = 0;
42 int available = width;
43 if (selectable && cap > 1) {
44 out[used++] = selected ? '>' : ' ';
45 out[used] = '\0';
46 --available;
47 }
48 for (size_t i = 0; i < count && available > 0; ++i) {
49 if (i && used + 1 < cap) {
50 out[used++] = ' ';
51 out[used] = '\0';
52 --available;
53 }
54 int cell_width = cols[i].width > 0 ? cols[i].width : flexible ? remaining / (int)flexible : 0;
55 if (cell_width < 0)
56 cell_width = 0;
57 if (!cols[i].width && flexible) {
58 remaining -= cell_width;
59 --flexible;
60 }
61 if (cell_width > available)
62 cell_width = available;
63 const char *text = cells ? cells[i] : cols[i].heading;
64 char clipped[UI_TABLE_CLIPPED_BUFFER_SIZE];
65 if (text && cols[i].ellipsis && display_width(text) > cell_width) {
66 truncate_with_ellipsis_mode(text, clipped, sizeof(clipped), cell_width,
67 terminal_should_use_utf8(GET_OPTION(force_utf8)));
68 text = clipped;
69 }
70 used += ui_text_cell(out + used, cap - used, text, cell_width, cols[i].alignment);
71 available -= cell_width;
72 }
73 return used;
74}
#define GET_OPTION(field)
Safely get a specific option field (lock-free read).
Definition options.h:1336
int display_width(const char *text)
Calculate the visible display width of text with ANSI escape codes.
void truncate_with_ellipsis_mode(const char *input, char *output, size_t output_size, int max_width, bool utf8)
Truncate a string to a maximum display width with a terminal-appropriate ellipsis.
Definition string.c:334
#define UI_TABLE_CLIPPED_BUFFER_SIZE
Definition table.c:3
size_t ui_text_cell(char *out, size_t cap, const char *text, int width, ui_alignment_t align)
Definition text.c:48

References cells, display_width(), ERROR_INVALID_PARAM, GET_OPTION, ui_table_column_t::heading, out, SET_ERRNO, truncate_with_ellipsis_mode(), UI_TABLE_CLIPPED_BUFFER_SIZE, ui_text_cell(), ui_table_column_t::width, and width.

Referenced by ui_sync_render(), and ui_table_render().