LF OS
Hobby operating system for amd64 with high ambitions
Loading...
Searching...
No Matches
vterm.c
Go to the documentation of this file.
1#include "vterm_internal.h"
2
3#include <stdio.h>
4#include <stdlib.h>
5#include <stdarg.h>
6#include <string.h>
7
8/*****************
9 * API functions *
10 *****************/
11
12static void *default_malloc(size_t size, void *allocdata)
13{
14 void *ptr = malloc(size);
15 if(ptr)
16 memset(ptr, 0, size);
17 return ptr;
18}
19
20static void default_free(void *ptr, void *allocdata)
21{
22 free(ptr);
23}
24
29
31{
32 return vterm_build(&(const struct VTermBuilder){
33 .rows = rows,
34 .cols = cols,
35 });
36}
37
39{
40 return vterm_build(&(const struct VTermBuilder){
41 .rows = rows,
42 .cols = cols,
43 .allocator = funcs,
44 .allocdata = allocdata,
45 });
46}
47
48/* A handy macro for defaulting values out of builder fields */
49#define DEFAULT(v, def) ((v) ? (v) : (def))
50
51VTerm *vterm_build(const struct VTermBuilder *builder)
52{
54
55 /* Need to bootstrap using the allocator function directly */
56 VTerm *vt = (*allocator->malloc)(sizeof(VTerm), builder->allocdata);
57
59 vt->allocdata = builder->allocdata;
60
61 vt->rows = builder->rows;
62 vt->cols = builder->cols;
63
64 vt->parser.state = NORMAL;
65
66 vt->parser.callbacks = NULL;
67 vt->parser.cbdata = NULL;
68
69 vt->parser.emit_nul = false;
70
71 vt->outfunc = NULL;
72 vt->outdata = NULL;
73
74 vt->outbuffer_len = DEFAULT(builder->outbuffer_len, 4096);
75 vt->outbuffer_cur = 0;
77
78 vt->tmpbuffer_len = DEFAULT(builder->tmpbuffer_len, 4096);
80
81 return vt;
82}
83
97
99{
100 return (*vt->allocator->malloc)(size, vt->allocdata);
101}
102
104{
105 (*vt->allocator->free)(ptr, vt->allocdata);
106}
107
108void vterm_get_size(const VTerm *vt, int *rowsp, int *colsp)
109{
110 if(rowsp)
111 *rowsp = vt->rows;
112 if(colsp)
113 *colsp = vt->cols;
114}
115
117{
118 if(rows < 1 || cols < 1)
119 return;
120
121 vt->rows = rows;
122 vt->cols = cols;
123
124 if(vt->parser.callbacks && vt->parser.callbacks->resize)
125 (*vt->parser.callbacks->resize)(rows, cols, vt->parser.cbdata);
126}
127
129{
130 return vt->mode.utf8;
131}
132
133void vterm_set_utf8(VTerm *vt, int is_utf8)
134{
135 vt->mode.utf8 = is_utf8;
136}
137
139{
140 vt->outfunc = func;
141 vt->outdata = user;
142}
143
144INTERNAL void vterm_push_output_bytes(VTerm *vt, const char *bytes, size_t len)
145{
146 if(vt->outfunc) {
147 (vt->outfunc)(bytes, len, vt->outdata);
148 return;
149 }
150
151 if(len > vt->outbuffer_len - vt->outbuffer_cur)
152 return;
153
154 memcpy(vt->outbuffer + vt->outbuffer_cur, bytes, len);
155 vt->outbuffer_cur += len;
156}
157
159{
160 size_t len = vsnprintf(vt->tmpbuffer, vt->tmpbuffer_len,
161 format, args);
162
164}
165
167{
168 va_list args;
169 va_start(args, format);
171 va_end(args);
172}
173
174INTERNAL void vterm_push_output_sprintf_ctrl(VTerm *vt, unsigned char ctrl, const char *fmt, ...)
175{
176 size_t cur;
177
178 if(ctrl >= 0x80 && !vt->mode.ctrl8bit)
179 cur = snprintf(vt->tmpbuffer, vt->tmpbuffer_len,
180 ESC_S "%c", ctrl - 0x40);
181 else
182 cur = snprintf(vt->tmpbuffer, vt->tmpbuffer_len,
183 "%c", ctrl);
184
185 if(cur >= vt->tmpbuffer_len)
186 return;
187
188 va_list args;
189 va_start(args, fmt);
190 cur += vsnprintf(vt->tmpbuffer + cur, vt->tmpbuffer_len - cur,
191 fmt, args);
192 va_end(args);
193
194 if(cur >= vt->tmpbuffer_len)
195 return;
196
198}
199
200INTERNAL void vterm_push_output_sprintf_str(VTerm *vt, unsigned char ctrl, bool term, const char *fmt, ...)
201{
202 size_t cur = 0;
203
204 if(ctrl) {
205 if(ctrl >= 0x80 && !vt->mode.ctrl8bit)
206 cur = snprintf(vt->tmpbuffer, vt->tmpbuffer_len,
207 ESC_S "%c", ctrl - 0x40);
208 else
209 cur = snprintf(vt->tmpbuffer, vt->tmpbuffer_len,
210 "%c", ctrl);
211
212 if(cur >= vt->tmpbuffer_len)
213 return;
214 }
215
216 va_list args;
217 va_start(args, fmt);
218 cur += vsnprintf(vt->tmpbuffer + cur, vt->tmpbuffer_len - cur,
219 fmt, args);
220 va_end(args);
221
222 if(cur >= vt->tmpbuffer_len)
223 return;
224
225 if(term) {
226 cur += snprintf(vt->tmpbuffer + cur, vt->tmpbuffer_len - cur,
227 vt->mode.ctrl8bit ? "\x9C" : ESC_S "\\"); // ST
228
229 if(cur >= vt->tmpbuffer_len)
230 return;
231 }
232
234}
235
237{
238 return vt->outbuffer_len;
239}
240
242{
243 return vt->outbuffer_cur;
244}
245
250
251size_t vterm_output_read(VTerm *vt, char *buffer, size_t len)
252{
253 if(len > vt->outbuffer_cur)
254 len = vt->outbuffer_cur;
255
256 memcpy(buffer, vt->outbuffer, len);
257
258 if(len < vt->outbuffer_cur)
259 memmove(vt->outbuffer, vt->outbuffer + len, vt->outbuffer_cur - len);
260
261 vt->outbuffer_cur -= len;
262
263 return len;
264}
265
267{
268 switch(attr) {
281
282 case VTERM_N_ATTRS: return 0;
283 }
284 return 0; /* UNREACHABLE */
285}
286
288{
289 switch(prop) {
299
300 case VTERM_N_PROPS: return 0;
301 }
302 return 0; /* UNREACHABLE */
303}
304
306 int downward,
307 int rightward,
308 int (*moverect)(VTermRect src, VTermRect dest, void *user),
309 int (*eraserect)(VTermRect rect, int selective, void *user),
310 void *user)
311{
312 VTermRect src;
313 VTermRect dest;
314
315 if(abs(downward) >= rect.end_row - rect.start_row ||
316 abs(rightward) >= rect.end_col - rect.start_col) {
317 /* Scroll more than area; just erase the lot */
318 (*eraserect)(rect, 0, user);
319 return;
320 }
321
322 if(rightward >= 0) {
323 /* rect: [XXX................]
324 * src: [----------------]
325 * dest: [----------------]
326 */
327 dest.start_col = rect.start_col;
328 dest.end_col = rect.end_col - rightward;
329 src.start_col = rect.start_col + rightward;
330 src.end_col = rect.end_col;
331 }
332 else {
333 /* rect: [................XXX]
334 * src: [----------------]
335 * dest: [----------------]
336 */
337 int leftward = -rightward;
338 dest.start_col = rect.start_col + leftward;
339 dest.end_col = rect.end_col;
340 src.start_col = rect.start_col;
341 src.end_col = rect.end_col - leftward;
342 }
343
344 if(downward >= 0) {
345 dest.start_row = rect.start_row;
346 dest.end_row = rect.end_row - downward;
347 src.start_row = rect.start_row + downward;
348 src.end_row = rect.end_row;
349 }
350 else {
351 int upward = -downward;
352 dest.start_row = rect.start_row + upward;
353 dest.end_row = rect.end_row;
354 src.start_row = rect.start_row;
355 src.end_row = rect.end_row - upward;
356 }
357
358 if(moverect)
359 (*moverect)(dest, src, user);
360
361 if(downward > 0)
362 rect.start_row = rect.end_row - downward;
363 else if(downward < 0)
364 rect.end_row = rect.start_row - downward;
365
366 if(rightward > 0)
367 rect.start_col = rect.end_col - rightward;
368 else if(rightward < 0)
369 rect.end_col = rect.start_col - rightward;
370
371 (*eraserect)(rect, 0, user);
372}
373
375 VTermRect src,
376 void (*copycell)(VTermPos dest, VTermPos src, void *user),
377 void *user)
378{
379 int downward = src.start_row - dest.start_row;
380 int rightward = src.start_col - dest.start_col;
381
382 int init_row, test_row, init_col, test_col;
383 int inc_row, inc_col;
384
385 if(downward < 0) {
386 init_row = dest.end_row - 1;
387 test_row = dest.start_row - 1;
388 inc_row = -1;
389 }
390 else /* downward >= 0 */ {
391 init_row = dest.start_row;
392 test_row = dest.end_row;
393 inc_row = +1;
394 }
395
396 if(rightward < 0) {
397 init_col = dest.end_col - 1;
398 test_col = dest.start_col - 1;
399 inc_col = -1;
400 }
401 else /* rightward >= 0 */ {
402 init_col = dest.start_col;
403 test_col = dest.end_col;
404 inc_col = +1;
405 }
406
407 VTermPos pos;
408 for(pos.row = init_row; pos.row != test_row; pos.row += inc_row)
409 for(pos.col = init_col; pos.col != test_col; pos.col += inc_col) {
410 VTermPos srcpos = { pos.row + downward, pos.col + rightward };
411 (*copycell)(pos, srcpos, user);
412 }
413}
414
415void vterm_check_version(int major, int minor)
416{
417 if(major != VTERM_VERSION_MAJOR) {
418 fprintf(stderr, "libvterm major version mismatch; %d (wants) != %d (library)\n",
419 major, VTERM_VERSION_MAJOR);
420 exit(1);
421 }
422
423 if(minor > VTERM_VERSION_MINOR) {
424 fprintf(stderr, "libvterm minor version mismatch; %d (wants) > %d (library)\n",
425 minor, VTERM_VERSION_MINOR);
426 exit(1);
427 }
428
429 // Happy
430}
static int moverect(VTermRect dest, VTermRect src, void *user)
Definition harness.c:335
void * memcpy(void *dest, void const *source, size_t size)
Definition string.c:80
void * memset(void *dest, int c, size_t size)
Definition string.c:72
void * memmove(void *dest, const void *source, size_t size)
Definition string.c:106
void * malloc(size_t size)
Definition string.c:169
void free(void *ptr)
Definition string.c:180
uint16_t size
Size of the loaded file.
Definition loader.h:5
INTERNAL void vterm_screen_free(VTermScreen *screen)
Definition screen.c:891
INTERNAL void vterm_state_free(VTermState *state)
Definition state.c:102
#define va_start(ap, X)
Definition stdarg.h:6
#define va_end(ap)
Definition stdarg.h:8
__builtin_va_list va_list
Definition stdarg.h:4
void *(* malloc)(size_t size, void *allocdata)
Definition vterm.h:319
void(* free)(void *ptr, void *allocdata)
Definition vterm.h:320
static int rows
Definition unterm.c:31
static int cols
Definition unterm.c:30
static VTerm * vt
Definition unterm.c:27
static enum @5 format
void vterm_set_utf8(VTerm *vt, int is_utf8)
Definition vterm.c:133
static void default_free(void *ptr, void *allocdata)
Definition vterm.c:20
#define DEFAULT(v, def)
Definition vterm.c:49
INTERNAL void vterm_push_output_sprintf_ctrl(VTerm *vt, unsigned char ctrl, const char *fmt,...)
Definition vterm.c:174
void vterm_copy_cells(VTermRect dest, VTermRect src, void(*copycell)(VTermPos dest, VTermPos src, void *user), void *user)
Definition vterm.c:374
INTERNAL void vterm_push_output_sprintf_str(VTerm *vt, unsigned char ctrl, bool term, const char *fmt,...)
Definition vterm.c:200
INTERNAL void * vterm_allocator_malloc(VTerm *vt, size_t size)
Definition vterm.c:98
VTerm * vterm_new_with_allocator(int rows, int cols, VTermAllocatorFunctions *funcs, void *allocdata)
Definition vterm.c:38
static void * default_malloc(size_t size, void *allocdata)
Definition vterm.c:12
INTERNAL void vterm_push_output_sprintf(VTerm *vt, const char *format,...)
Definition vterm.c:166
VTerm * vterm_build(const struct VTermBuilder *builder)
Definition vterm.c:51
size_t vterm_output_read(VTerm *vt, char *buffer, size_t len)
Definition vterm.c:251
void vterm_scroll_rect(VTermRect rect, int downward, int rightward, int(*moverect)(VTermRect src, VTermRect dest, void *user), int(*eraserect)(VTermRect rect, int selective, void *user), void *user)
Definition vterm.c:305
size_t vterm_output_get_buffer_size(const VTerm *vt)
Definition vterm.c:236
size_t vterm_output_get_buffer_remaining(const VTerm *vt)
Definition vterm.c:246
INTERNAL void vterm_push_output_bytes(VTerm *vt, const char *bytes, size_t len)
Definition vterm.c:144
size_t vterm_output_get_buffer_current(const VTerm *vt)
Definition vterm.c:241
static VTermAllocatorFunctions default_allocator
Definition vterm.c:25
void vterm_get_size(const VTerm *vt, int *rowsp, int *colsp)
Definition vterm.c:108
void vterm_check_version(int major, int minor)
Definition vterm.c:415
VTermValueType vterm_get_prop_type(VTermProp prop)
Definition vterm.c:287
void vterm_output_set_callback(VTerm *vt, VTermOutputCallback *func, void *user)
Definition vterm.c:138
VTermValueType vterm_get_attr_type(VTermAttr attr)
Definition vterm.c:266
INTERNAL void vterm_push_output_vsprintf(VTerm *vt, const char *format, va_list args)
Definition vterm.c:158
void vterm_set_size(VTerm *vt, int rows, int cols)
Definition vterm.c:116
INTERNAL void vterm_allocator_free(VTerm *vt, void *ptr)
Definition vterm.c:103
int vterm_get_utf8(const VTerm *vt)
Definition vterm.c:128
void vterm_free(VTerm *vt)
Definition vterm.c:84
VTerm * vterm_new(int rows, int cols)
Definition vterm.c:30
#define VTERM_VERSION_MAJOR
Definition vterm.h:14
const VTermAllocatorFunctions * allocator
Definition vterm.h:330
size_t tmpbuffer_len
Definition vterm.h:335
int end_row
Definition vterm.h:45
int col
Definition vterm.h:32
int end_col
Definition vterm.h:47
int row
Definition vterm.h:31
#define VTERM_VERSION_MINOR
Definition vterm.h:15
int start_row
Definition vterm.h:44
size_t outbuffer_len
Definition vterm.h:334
void * allocdata
Definition vterm.h:331
void VTermOutputCallback(const char *s, size_t len, void *user)
Definition vterm.h:356
int start_col
Definition vterm.h:46
VTermAttr
Definition vterm.h:234
@ VTERM_ATTR_BOLD
Definition vterm.h:236
@ VTERM_N_ATTRS
Definition vterm.h:249
@ VTERM_ATTR_FOREGROUND
Definition vterm.h:244
@ VTERM_ATTR_UNDERLINE
Definition vterm.h:237
@ VTERM_ATTR_ITALIC
Definition vterm.h:238
@ VTERM_ATTR_BACKGROUND
Definition vterm.h:245
@ VTERM_ATTR_FONT
Definition vterm.h:243
@ VTERM_ATTR_BLINK
Definition vterm.h:239
@ VTERM_ATTR_STRIKE
Definition vterm.h:242
@ VTERM_ATTR_SMALL
Definition vterm.h:246
@ VTERM_ATTR_REVERSE
Definition vterm.h:240
@ VTERM_ATTR_BASELINE
Definition vterm.h:247
@ VTERM_ATTR_CONCEAL
Definition vterm.h:241
VTermValueType
Definition vterm.h:210
@ VTERM_VALUETYPE_STRING
Definition vterm.h:214
@ VTERM_VALUETYPE_INT
Definition vterm.h:213
@ VTERM_VALUETYPE_BOOL
Definition vterm.h:212
@ VTERM_VALUETYPE_COLOR
Definition vterm.h:215
VTermProp
Definition vterm.h:252
@ VTERM_PROP_REVERSE
Definition vterm.h:259
@ VTERM_PROP_CURSORBLINK
Definition vterm.h:255
@ VTERM_PROP_ALTSCREEN
Definition vterm.h:256
@ VTERM_PROP_FOCUSREPORT
Definition vterm.h:262
@ VTERM_N_PROPS
Definition vterm.h:264
@ VTERM_PROP_CURSORVISIBLE
Definition vterm.h:254
@ VTERM_PROP_ICONNAME
Definition vterm.h:258
@ VTERM_PROP_TITLE
Definition vterm.h:257
@ VTERM_PROP_CURSORSHAPE
Definition vterm.h:260
@ VTERM_PROP_MOUSE
Definition vterm.h:261
#define INTERNAL
size_t tmpbuffer_len
VTermState * state
const VTermAllocatorFunctions * allocator
void * allocdata
#define ESC_S
char * tmpbuffer
struct VTerm::@24 parser
char * outbuffer
struct VTerm::@23 mode
VTermOutputCallback * outfunc
size_t outbuffer_cur
void * outdata
VTermScreen * screen
size_t outbuffer_len