ascii-chat 0.11.33
Video chat in your terminal
Loading...
Searching...
No Matches
frame_buffer.c File Reference

Buffered terminal frame rendering implementation. More...

Go to the source code of this file.

Data Structures

struct  frame_buffer
 Frame buffer structure. More...
 

Functions

frame_buffer_t * frame_buffer_create (int rows, int cols)
 Create a new frame buffer.
 
void frame_buffer_destroy (frame_buffer_t *buf)
 Destroy a frame buffer.
 
void frame_buffer_reset (frame_buffer_t *buf)
 Clear buffer contents while keeping allocation.
 
void frame_buffer_append (frame_buffer_t *buf, const char *str, size_t len)
 Append raw bytes to the buffer.
 
void frame_buffer_printf (frame_buffer_t *buf, const char *fmt,...)
 Printf-style append to the buffer.
 
void frame_buffer_cursor_home (frame_buffer_t *buf)
 Append cursor home escape code (\033[H)
 
void frame_buffer_clear_screen (frame_buffer_t *buf)
 Append clear screen and home escape codes (\033[2J\033[H)
 
void frame_buffer_flush (frame_buffer_t *buf)
 Flush the entire buffer to stdout in one atomic write.
 
void frame_buffer_set_screen_output_fd (int fd)
 Set output file descriptor for terminal screen (splash/status) rendering.
 
int frame_buffer_get_screen_output_fd (void)
 Get current output file descriptor for terminal screens.
 
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.
 
void frame_buffer_render_border (frame_buffer_t *buf, int cols, const char *color)
 Render a horizontal border line (used by both splash and status screens)
 
int frame_buffer_render_centered (frame_buffer_t *buf, const char *text, int cols)
 Render centered text (used by both splash and status screens)
 

Detailed Description

Buffered terminal frame rendering implementation.

Accumulates terminal output into a growable buffer and flushes atomically.

Definition in file frame_buffer.c.

Function Documentation

◆ frame_buffer_append()

void frame_buffer_append ( frame_buffer_t *  buf,
const char *  str,
size_t  len 
)

Append raw bytes to the buffer.

Parameters
bufFrame buffer
strPointer to data (may contain ANSI codes, not NULL-terminated)
lenNumber of bytes to append

Grows the buffer as needed. Does not add newlines or NULL terminators.

Definition at line 67 of file frame_buffer.c.

67 {
68 if (!buf || !str || len == 0) {
69 return;
70 }
71
72 // Grow buffer if needed
73 if (buf->len + len > buf->capacity) {
74 size_t new_capacity = buf->capacity * 2;
75 while (new_capacity < buf->len + len) {
76 new_capacity *= 2;
77 }
78
79 char *new_data = SAFE_MALLOC(new_capacity, char *);
80 if (!new_data) {
81 return; // Failed to grow, silently ignore
82 }
83
84 if (buf->len > 0 && buf->data) {
85 memcpy(new_data, buf->data, buf->len);
86 }
87
88 SAFE_FREE(buf->data);
89 buf->data = new_data;
90 buf->capacity = new_capacity;
91 }
92
93 // Append the data
94 memcpy(buf->data + buf->len, str, len);
95 buf->len += len;
96}
#define SAFE_FREE(ptr)
Definition common.h:376
#define SAFE_MALLOC(size, cast)
Definition common.h:264
char * data
Allocated buffer.
size_t len
Current content length.
size_t capacity
Allocated capacity.

References frame_buffer::capacity, frame_buffer::data, frame_buffer::len, SAFE_FREE, and SAFE_MALLOC.

Referenced by frame_buffer_clear_screen(), and frame_buffer_cursor_home().

◆ frame_buffer_clear_screen()

void frame_buffer_clear_screen ( frame_buffer_t *  buf)

Append clear screen and home escape codes (\033[2J\033[H)

Parameters
bufFrame buffer

Combines clear screen and cursor home into a single operation for atomicity.

Definition at line 144 of file frame_buffer.c.

144 {
145 if (!buf) {
146 return;
147 }
148
149 // Combine clear screen and home in one operation
150 frame_buffer_append(buf, "\033[2J\033[H", 8);
151}
void frame_buffer_append(frame_buffer_t *buf, const char *str, size_t len)
Append raw bytes to the buffer.

References frame_buffer_append().

◆ frame_buffer_create()

frame_buffer_t * frame_buffer_create ( int  rows,
int  cols 
)

Create a new frame buffer.

Parameters
rowsTerminal row count (used for initial capacity estimate)
colsTerminal column count (used for initial capacity estimate)
Returns
Newly allocated frame buffer, or NULL on allocation failure

Initial capacity is set to rows * cols * 16 to account for ANSI escape overhead.

Definition at line 29 of file frame_buffer.c.

29 {
31 if (!buf) {
32 return NULL;
33 }
34
35 // Initial capacity: rows * cols * 16 to account for ANSI codes
36 size_t initial_capacity = (rows > 0 && cols > 0) ? (size_t)rows * cols * 16 : 4096;
37
38 buf->data = SAFE_MALLOC(initial_capacity, char *);
39 if (!buf->data) {
40 SAFE_FREE(buf);
41 return NULL;
42 }
43
44 buf->len = 0;
45 buf->capacity = initial_capacity;
46
47 return buf;
48}
Frame buffer structure.

References frame_buffer::capacity, frame_buffer::data, frame_buffer::len, SAFE_FREE, and SAFE_MALLOC.

Referenced by terminal_screen_render().

◆ frame_buffer_cursor_home()

void frame_buffer_cursor_home ( frame_buffer_t *  buf)

Append cursor home escape code (\033[H)

Parameters
bufFrame buffer

Definition at line 136 of file frame_buffer.c.

136 {
137 if (!buf) {
138 return;
139 }
140
141 frame_buffer_append(buf, "\033[H", 3);
142}

References frame_buffer_append().

Referenced by terminal_screen_render().

◆ frame_buffer_destroy()

void frame_buffer_destroy ( frame_buffer_t *  buf)

Destroy a frame buffer.

Parameters
bufFrame buffer to destroy (may be NULL)

Definition at line 50 of file frame_buffer.c.

50 {
51 if (!buf) {
52 return;
53 }
54
55 SAFE_FREE(buf->data);
56 SAFE_FREE(buf);
57}

References frame_buffer::data, and SAFE_FREE.

Referenced by terminal_screen_cleanup(), and terminal_screen_render().

◆ frame_buffer_flush()

void frame_buffer_flush ( frame_buffer_t *  buf)

Flush the entire buffer to stdout in one atomic write.

Parameters
bufFrame buffer

Writes all accumulated content to stdout via platform_write_all(), bypassing libc buffering. Safe for high-frequency rendering.

Definition at line 156 of file frame_buffer.c.

156 {
157 if (!buf || buf->len == 0 || !buf->data) {
158 return;
159 }
160
161 // Repaint from the top while erasing each line before writing it. A full
162 // screen erase on every animation frame exposes a black frame on Windows
163 // terminals and makes the splash appear to flicker.
164 size_t line_count = 1;
165 for (size_t i = 0; i < buf->len; i++) {
166 if (buf->data[i] == '\n') {
167 line_count++;
168 }
169 }
170
171 size_t output_size = 3 + buf->len + (line_count * 4);
172 char *output = SAFE_MALLOC(output_size, char *);
173 if (!output) {
174 return;
175 }
176
177 size_t output_len = 0;
178 memcpy(output + output_len, "\033[H", 3);
179 output_len += 3;
180 bool at_line_start = true;
181 for (size_t i = 0; i < buf->len; i++) {
182 if (at_line_start) {
183 memcpy(output + output_len, "\033[2K", 4);
184 output_len += 4;
185 at_line_start = false;
186 }
187 output[output_len++] = buf->data[i];
188 if (buf->data[i] == '\n') {
189 at_line_start = true;
190 }
191 }
192
193 platform_write_all(g_terminal_screen_output_fd, output, output_len);
194 SAFE_FREE(output);
195}
size_t platform_write_all(int fd, const void *buf, size_t count)
Write all bytes to a file descriptor, handling partial writes.
Definition system.c:224

References frame_buffer::data, frame_buffer::len, platform_write_all(), SAFE_FREE, and SAFE_MALLOC.

Referenced by terminal_screen_render().

◆ frame_buffer_get_content()

const char * frame_buffer_get_content ( const frame_buffer_t *  buf)

Get a pointer to the buffer content.

Parameters
bufFrame buffer
Returns
Pointer to the buffer data (NULL if buffer is empty or NULL)

Returns the raw buffer content for reading. The content is NOT null-terminated. Use frame_buffer_get_length() to get the actual size.

Definition at line 212 of file frame_buffer.c.

212 {
213 if (!buf || !buf->data) {
214 return NULL;
215 }
216 return buf->data;
217}

References frame_buffer::data.

Referenced by terminal_screen_render().

◆ frame_buffer_get_length()

size_t frame_buffer_get_length ( const frame_buffer_t *  buf)

Get the current content length of the frame buffer.

Parameters
bufFrame buffer
Returns
Number of bytes currently in the buffer

Useful for debugging and verifying frame consistency.

Definition at line 205 of file frame_buffer.c.

205 {
206 if (!buf) {
207 return 0;
208 }
209 return buf->len;
210}

References frame_buffer::len.

Referenced by terminal_screen_render().

◆ frame_buffer_get_screen_output_fd()

int frame_buffer_get_screen_output_fd ( void  )

Get current output file descriptor for terminal screens.

Returns
File descriptor (STDOUT_FILENO or STDERR_FILENO)

Definition at line 201 of file frame_buffer.c.

201 {
202 return g_terminal_screen_output_fd;
203}

◆ frame_buffer_printf()

void frame_buffer_printf ( frame_buffer_t *  buf,
const char *  fmt,
  ... 
)

Printf-style append to the buffer.

Parameters
bufFrame buffer
fmtFormat string (standard printf syntax)
...Arguments

Formats the string into the buffer using snprintf. Grows buffer as needed.

Definition at line 98 of file frame_buffer.c.

98 {
99 if (!buf || !fmt) {
100 return;
101 }
102
103 // Ensure we have space for a formatted string
104 // Start with a reasonable buffer size
105 size_t remaining = buf->capacity - buf->len;
106 if (remaining < 256) {
107 // Grow buffer to have at least 512 bytes of space
108 size_t new_capacity = buf->capacity + 512;
109 char *new_data = SAFE_MALLOC(new_capacity, char *);
110 if (!new_data) {
111 return;
112 }
113
114 if (buf->len > 0 && buf->data) {
115 memcpy(new_data, buf->data, buf->len);
116 }
117
118 SAFE_FREE(buf->data);
119 buf->data = new_data;
120 buf->capacity = new_capacity;
121 remaining = buf->capacity - buf->len;
122 }
123
124 // Format the string into the buffer
125 va_list args;
126 va_start(args, fmt);
127 int written = vsnprintf(buf->data + buf->len, remaining, fmt, args);
128 va_end(args);
129
130 if (written > 0 && written < (int)remaining) {
131 buf->len += (size_t)written;
132 }
133 // If vsnprintf failed or truncated, we silently ignore (buffer may be full)
134}
action_args_t args

References args, frame_buffer::capacity, frame_buffer::data, frame_buffer::len, SAFE_FREE, and SAFE_MALLOC.

Referenced by frame_buffer_render_border(), frame_buffer_render_centered(), and terminal_screen_render().

◆ frame_buffer_render_border()

void frame_buffer_render_border ( frame_buffer_t *  buf,
int  cols,
const char *  color 
)

Render a horizontal border line (used by both splash and status screens)

Parameters
bufFrame buffer to write into
colsTerminal width (number of columns)
colorANSI color code (e.g., "\033[1;36m" for cyan) or NULL for no color

Definition at line 219 of file frame_buffer.c.

219 {
220 if (!buf || cols <= 0) {
221 return;
222 }
223
224 if (color) {
225 frame_buffer_printf(buf, "%s━", color);
226 } else {
227 frame_buffer_printf(buf, "━");
228 }
229 for (int i = 1; i < cols - 1; i++) {
230 frame_buffer_printf(buf, "━");
231 }
232 if (color) {
233 frame_buffer_printf(buf, "\033[0m");
234 }
235 frame_buffer_printf(buf, "\n");
236}
void frame_buffer_printf(frame_buffer_t *buf, const char *fmt,...)
Printf-style append to the buffer.

References frame_buffer_printf().

◆ frame_buffer_render_centered()

int frame_buffer_render_centered ( frame_buffer_t *  buf,
const char *  text,
int  cols 
)

Render centered text (used by both splash and status screens)

Parameters
bufFrame buffer to write into
textText to center (may contain ANSI codes)
colsTerminal width
Returns
Padding added on left side (for manual padding if needed)

Automatically centers the text accounting for ANSI escape codes.

Definition at line 238 of file frame_buffer.c.

238 {
239 if (!buf || !text || cols <= 0) {
240 return 0;
241 }
242
243 // Calculate visible width accounting for ANSI codes
244 int visible_width = display_width(text);
245 if (visible_width < 0) {
246 visible_width = (int)strlen(text);
247 }
248
249 int padding = (cols - visible_width) / 2;
250 if (padding < 0) {
251 padding = 0;
252 }
253
254 for (int i = 0; i < padding; i++) {
255 frame_buffer_printf(buf, " ");
256 }
257 frame_buffer_printf(buf, "%s\n", text);
258
259 return padding;
260}
int display_width(const char *text)
Calculate the visible display width of text with ANSI escape codes.

References display_width(), and frame_buffer_printf().

◆ frame_buffer_reset()

void frame_buffer_reset ( frame_buffer_t *  buf)

Clear buffer contents while keeping allocation.

Resets the buffer for a new frame without deallocating the underlying memory. More efficient than destroy/create for repeated frame rendering.

Parameters
bufFrame buffer to reset

Definition at line 59 of file frame_buffer.c.

59 {
60 if (!buf) {
61 return;
62 }
63
64 buf->len = 0;
65}

References frame_buffer::len.

Referenced by terminal_screen_render().

◆ frame_buffer_set_screen_output_fd()

void frame_buffer_set_screen_output_fd ( int  fd)

Set output file descriptor for terminal screen (splash/status) rendering.

Parameters
fdFile descriptor (STDOUT_FILENO for TTY, STDERR_FILENO for piped output)

Controls where splash and status screens write their output. Used internally by terminal_screen_render() for consistent output routing.

Definition at line 197 of file frame_buffer.c.

197 {
198 g_terminal_screen_output_fd = fd;
199}

Referenced by terminal_screen_set_output_fd().