···
7
+
static const uint32_t col256[] = {
8
+
0x000000, 0x00005f, 0x000087, 0x0000af, 0x0000d7, 0x0000ff, 0x005f00, 0x005f5f,
9
+
0x005f87, 0x005faf, 0x005fd7, 0x005fff, 0x008700, 0x00875f, 0x008787, 0x0087af,
10
+
0x0087d7, 0x0087ff, 0x00af00, 0x00af5f, 0x00af87, 0x00afaf, 0x00afd7, 0x00afff,
11
+
0x00d700, 0x00d75f, 0x00d787, 0x00d7af, 0x00d7d7, 0x00d7ff, 0x00ff00, 0x00ff5f,
12
+
0x00ff87, 0x00ffaf, 0x00ffd7, 0x00ffff, 0x5f0000, 0x5f005f, 0x5f0087, 0x5f00af,
13
+
0x5f00d7, 0x5f00ff, 0x5f5f00, 0x5f5f5f, 0x5f5f87, 0x5f5faf, 0x5f5fd7, 0x5f5fff,
14
+
0x5f8700, 0x5f875f, 0x5f8787, 0x5f87af, 0x5f87d7, 0x5f87ff, 0x5faf00, 0x5faf5f,
15
+
0x5faf87, 0x5fafaf, 0x5fafd7, 0x5fafff, 0x5fd700, 0x5fd75f, 0x5fd787, 0x5fd7af,
16
+
0x5fd7d7, 0x5fd7ff, 0x5fff00, 0x5fff5f, 0x5fff87, 0x5fffaf, 0x5fffd7, 0x5fffff,
17
+
0x870000, 0x87005f, 0x870087, 0x8700af, 0x8700d7, 0x8700ff, 0x875f00, 0x875f5f,
18
+
0x875f87, 0x875faf, 0x875fd7, 0x875fff, 0x878700, 0x87875f, 0x878787, 0x8787af,
19
+
0x8787d7, 0x8787ff, 0x87af00, 0x87af5f, 0x87af87, 0x87afaf, 0x87afd7, 0x87afff,
20
+
0x87d700, 0x87d75f, 0x87d787, 0x87d7af, 0x87d7d7, 0x87d7ff, 0x87ff00, 0x87ff5f,
21
+
0x87ff87, 0x87ffaf, 0x87ffd7, 0x87ffff, 0xaf0000, 0xaf005f, 0xaf0087, 0xaf00af,
22
+
0xaf00d7, 0xaf00ff, 0xaf5f00, 0xaf5f5f, 0xaf5f87, 0xaf5faf, 0xaf5fd7, 0xaf5fff,
23
+
0xaf8700, 0xaf875f, 0xaf8787, 0xaf87af, 0xaf87d7, 0xaf87ff, 0xafaf00, 0xafaf5f,
24
+
0xafaf87, 0xafafaf, 0xafafd7, 0xafafff, 0xafd700, 0xafd75f, 0xafd787, 0xafd7af,
25
+
0xafd7d7, 0xafd7ff, 0xafff00, 0xafff5f, 0xafff87, 0xafffaf, 0xafffd7, 0xafffff,
26
+
0xd70000, 0xd7005f, 0xd70087, 0xd700af, 0xd700d7, 0xd700ff, 0xd75f00, 0xd75f5f,
27
+
0xd75f87, 0xd75faf, 0xd75fd7, 0xd75fff, 0xd78700, 0xd7875f, 0xd78787, 0xd787af,
28
+
0xd787d7, 0xd787ff, 0xd7af00, 0xd7af5f, 0xd7af87, 0xd7afaf, 0xd7afd7, 0xd7afff,
29
+
0xd7d700, 0xd7d75f, 0xd7d787, 0xd7d7af, 0xd7d7d7, 0xd7d7ff, 0xd7ff00, 0xd7ff5f,
30
+
0xd7ff87, 0xd7ffaf, 0xd7ffd7, 0xd7ffff, 0xff0000, 0xff005f, 0xff0087, 0xff00af,
31
+
0xff00d7, 0xff00ff, 0xff5f00, 0xff5f5f, 0xff5f87, 0xff5faf, 0xff5fd7, 0xff5fff,
32
+
0xff8700, 0xff875f, 0xff8787, 0xff87af, 0xff87d7, 0xff87ff, 0xffaf00, 0xffaf5f,
33
+
0xffaf87, 0xffafaf, 0xffafd7, 0xffafff, 0xffd700, 0xffd75f, 0xffd787, 0xffd7af,
34
+
0xffd7d7, 0xffd7ff, 0xffff00, 0xffff5f, 0xffff87, 0xffffaf, 0xffffd7, 0xffffff,
35
+
0x080808, 0x121212, 0x1c1c1c, 0x262626, 0x303030, 0x3a3a3a, 0x444444, 0x4e4e4e,
36
+
0x585858, 0x626262, 0x6c6c6c, 0x767676, 0x808080, 0x8a8a8a, 0x949494, 0x9e9e9e,
37
+
0xa8a8a8, 0xb2b2b2, 0xbcbcbc, 0xc6c6c6, 0xd0d0d0, 0xdadada, 0xe4e4e4, 0xeeeeee
40
+
// Tries to implement this standard for terminfo
41
+
// https://man7.org/linux/man-pages/man4/console_codes.4.html
43
+
#define CHARSET_DEFAULT 0
44
+
#define CHARSET_DEC_SPECIAL 1
46
+
void term_context_reinit(struct term_context *ctx) {
47
+
ctx->scroll_enabled = true;
49
+
ctx->escape_offset = 0;
50
+
ctx->control_sequence = false;
52
+
ctx->escape = false;
54
+
ctx->discard_next = false;
56
+
ctx->reverse_video = false;
57
+
ctx->dec_private = false;
58
+
ctx->esc_values_i = 0;
59
+
ctx->saved_cursor_x = 0;
60
+
ctx->saved_cursor_y = 0;
61
+
ctx->current_primary = (size_t)-1;
62
+
ctx->insert_mode = false;
63
+
ctx->scroll_top_margin = 0;
64
+
ctx->scroll_bottom_margin = ctx->rows;
65
+
ctx->current_charset = 0;
67
+
ctx->charsets[0] = CHARSET_DEFAULT;
68
+
ctx->charsets[1] = CHARSET_DEC_SPECIAL;
69
+
ctx->autoflush = true;
72
+
static void term_putchar(struct term_context *ctx, uint8_t c);
74
+
void term_write(struct term_context *ctx, const char *buf, size_t count) {
75
+
for (size_t i = 0; i < count; i++) {
76
+
term_putchar(ctx, buf[i]);
79
+
if (ctx->autoflush) {
80
+
ctx->double_buffer_flush(ctx);
84
+
static void sgr(struct term_context *ctx) {
87
+
if (!ctx->esc_values_i)
90
+
for (; i < ctx->esc_values_i; i++) {
93
+
if (ctx->esc_values[i] == 0) {
95
+
if (ctx->reverse_video) {
96
+
ctx->reverse_video = false;
97
+
ctx->swap_palette(ctx);
100
+
ctx->current_primary = (size_t)-1;
101
+
ctx->set_text_bg_default(ctx);
102
+
ctx->set_text_fg_default(ctx);
106
+
else if (ctx->esc_values[i] == 1) {
108
+
if (ctx->current_primary != (size_t)-1) {
109
+
if (!ctx->reverse_video) {
110
+
ctx->set_text_fg_bright(ctx, ctx->current_primary);
112
+
ctx->set_text_bg_bright(ctx, ctx->current_primary);
118
+
else if (ctx->esc_values[i] == 22) {
120
+
if (ctx->current_primary != (size_t)-1) {
121
+
if (!ctx->reverse_video) {
122
+
ctx->set_text_fg(ctx, ctx->current_primary);
124
+
ctx->set_text_bg(ctx, ctx->current_primary);
130
+
else if (ctx->esc_values[i] >= 30 && ctx->esc_values[i] <= 37) {
132
+
ctx->current_primary = ctx->esc_values[i] - offset;
134
+
if (ctx->reverse_video) {
139
+
if (ctx->bold && !ctx->reverse_video) {
140
+
ctx->set_text_fg_bright(ctx, ctx->esc_values[i] - offset);
142
+
ctx->set_text_fg(ctx, ctx->esc_values[i] - offset);
147
+
else if (ctx->esc_values[i] >= 40 && ctx->esc_values[i] <= 47) {
149
+
if (ctx->reverse_video) {
154
+
if (ctx->bold && ctx->reverse_video) {
155
+
ctx->set_text_bg_bright(ctx, ctx->esc_values[i] - offset);
157
+
ctx->set_text_bg(ctx, ctx->esc_values[i] - offset);
162
+
else if (ctx->esc_values[i] >= 90 && ctx->esc_values[i] <= 97) {
164
+
ctx->current_primary = ctx->esc_values[i] - offset;
166
+
if (ctx->reverse_video) {
167
+
goto set_bg_bright;
171
+
ctx->set_text_fg_bright(ctx, ctx->esc_values[i] - offset);
175
+
else if (ctx->esc_values[i] >= 100 && ctx->esc_values[i] <= 107) {
177
+
if (ctx->reverse_video) {
178
+
goto set_fg_bright;
182
+
ctx->set_text_bg_bright(ctx, ctx->esc_values[i] - offset);
186
+
else if (ctx->esc_values[i] == 39) {
187
+
ctx->current_primary = (size_t)-1;
189
+
if (ctx->reverse_video) {
190
+
ctx->swap_palette(ctx);
193
+
ctx->set_text_fg_default(ctx);
195
+
if (ctx->reverse_video) {
196
+
ctx->swap_palette(ctx);
202
+
else if (ctx->esc_values[i] == 49) {
203
+
if (ctx->reverse_video) {
204
+
ctx->swap_palette(ctx);
207
+
ctx->set_text_bg_default(ctx);
209
+
if (ctx->reverse_video) {
210
+
ctx->swap_palette(ctx);
216
+
else if (ctx->esc_values[i] == 7) {
217
+
if (!ctx->reverse_video) {
218
+
ctx->reverse_video = true;
219
+
ctx->swap_palette(ctx);
224
+
else if (ctx->esc_values[i] == 27) {
225
+
if (ctx->reverse_video) {
226
+
ctx->reverse_video = false;
227
+
ctx->swap_palette(ctx);
233
+
else if (ctx->esc_values[i] == 38 || ctx->esc_values[i] == 48) {
234
+
bool fg = ctx->esc_values[i] == 38;
237
+
if (i >= ctx->esc_values_i) {
241
+
switch (ctx->esc_values[i]) {
243
+
if (i + 3 >= ctx->esc_values_i) {
247
+
uint32_t rgb_value = 0;
249
+
rgb_value |= ctx->esc_values[i + 1] << 16;
250
+
rgb_value |= ctx->esc_values[i + 2] << 8;
251
+
rgb_value |= ctx->esc_values[i + 3];
255
+
(fg ? ctx->set_text_fg_rgb : ctx->set_text_bg_rgb)(ctx, rgb_value);
259
+
case 5: { // 256 colors
260
+
if (i + 1 >= ctx->esc_values_i) {
264
+
uint32_t col = ctx->esc_values[i + 1];
269
+
(fg ? ctx->set_text_fg : ctx->set_text_bg)(ctx, col);
270
+
} else if (col < 16) {
271
+
(fg ? ctx->set_text_fg_bright : ctx->set_text_bg_bright)(ctx, col - 8);
273
+
uint32_t rgb_value = col256[col - 16];
274
+
(fg ? ctx->set_text_fg_rgb : ctx->set_text_bg_rgb)(ctx, rgb_value);
287
+
static void dec_private_parse(struct term_context *ctx, uint8_t c) {
288
+
ctx->dec_private = false;
290
+
if (ctx->esc_values_i == 0) {
300
+
set = false; break;
305
+
switch (ctx->esc_values[0]) {
308
+
ctx->enable_cursor(ctx);
310
+
ctx->disable_cursor(ctx);
316
+
if (ctx->callback != NULL) {
317
+
ctx->callback(ctx, TERM_CB_DEC, ctx->esc_values_i, (uintptr_t)ctx->esc_values, c);
321
+
static void linux_private_parse(struct term_context *ctx) {
322
+
if (ctx->esc_values_i == 0) {
326
+
if (ctx->callback != NULL) {
327
+
ctx->callback(ctx, TERM_CB_LINUX, ctx->esc_values_i, (uintptr_t)ctx->esc_values, 0);
331
+
static void mode_toggle(struct term_context *ctx, uint8_t c) {
332
+
if (ctx->esc_values_i == 0) {
342
+
set = false; break;
347
+
switch (ctx->esc_values[0]) {
349
+
ctx->insert_mode = set; return;
352
+
if (ctx->callback != NULL) {
353
+
ctx->callback(ctx, TERM_CB_MODE, ctx->esc_values_i, (uintptr_t)ctx->esc_values, c);
357
+
static void control_sequence_parse(struct term_context *ctx, uint8_t c) {
358
+
if (ctx->escape_offset == 2) {
361
+
ctx->discard_next = true;
364
+
ctx->dec_private = true;
369
+
if (c >= '0' && c <= '9') {
370
+
if (ctx->esc_values_i == TERM_MAX_ESC_VALUES) {
374
+
ctx->esc_values[ctx->esc_values_i] *= 10;
375
+
ctx->esc_values[ctx->esc_values_i] += c - '0';
379
+
if (ctx->rrr == true) {
380
+
ctx->esc_values_i++;
384
+
} else if (c == ';') {
385
+
if (ctx->esc_values_i == TERM_MAX_ESC_VALUES) {
388
+
ctx->esc_values[ctx->esc_values_i] = 0;
389
+
ctx->esc_values_i++;
393
+
size_t esc_default;
395
+
case 'J': case 'K': case 'q':
396
+
esc_default = 0; break;
398
+
esc_default = 1; break;
401
+
for (size_t i = ctx->esc_values_i; i < TERM_MAX_ESC_VALUES; i++) {
402
+
ctx->esc_values[i] = esc_default;
405
+
if (ctx->dec_private == true) {
406
+
dec_private_parse(ctx, c);
410
+
bool r = ctx->scroll_enabled;
411
+
ctx->scroll_enabled = false;
413
+
ctx->get_cursor_pos(ctx, &x, &y);
420
+
if (ctx->esc_values[0] > y)
421
+
ctx->esc_values[0] = y;
423
+
size_t dest_y = y - ctx->esc_values[0];
424
+
bool will_be_in_scroll_region = false;
425
+
if ((ctx->scroll_top_margin >= dest_y && ctx->scroll_top_margin <= orig_y)
426
+
|| (ctx->scroll_bottom_margin >= dest_y && ctx->scroll_bottom_margin <= orig_y)) {
427
+
will_be_in_scroll_region = true;
429
+
if (will_be_in_scroll_region && dest_y < ctx->scroll_top_margin) {
430
+
dest_y = ctx->scroll_top_margin;
432
+
ctx->set_cursor_pos(ctx, x, dest_y);
440
+
if (y + ctx->esc_values[0] > ctx->rows - 1)
441
+
ctx->esc_values[0] = (ctx->rows - 1) - y;
443
+
size_t dest_y = y + ctx->esc_values[0];
444
+
bool will_be_in_scroll_region = false;
445
+
if ((ctx->scroll_top_margin >= orig_y && ctx->scroll_top_margin <= dest_y)
446
+
|| (ctx->scroll_bottom_margin >= orig_y && ctx->scroll_bottom_margin <= dest_y)) {
447
+
will_be_in_scroll_region = true;
449
+
if (will_be_in_scroll_region && dest_y >= ctx->scroll_bottom_margin) {
450
+
dest_y = ctx->scroll_bottom_margin - 1;
452
+
ctx->set_cursor_pos(ctx, x, dest_y);
457
+
if (x + ctx->esc_values[0] > ctx->cols - 1)
458
+
ctx->esc_values[0] = (ctx->cols - 1) - x;
459
+
ctx->set_cursor_pos(ctx, x + ctx->esc_values[0], y);
462
+
if (ctx->esc_values[0] > x)
463
+
ctx->esc_values[0] = x;
464
+
ctx->set_cursor_pos(ctx, x - ctx->esc_values[0], y);
467
+
if (ctx->callback != NULL) {
468
+
ctx->callback(ctx, TERM_CB_PRIVATE_ID, 0, 0, 0);
472
+
ctx->esc_values[0] -= 1;
473
+
if (ctx->esc_values[0] >= ctx->rows)
474
+
ctx->esc_values[0] = ctx->rows - 1;
475
+
ctx->set_cursor_pos(ctx, x, ctx->esc_values[0]);
479
+
ctx->esc_values[0] -= 1;
480
+
if (ctx->esc_values[0] >= ctx->cols)
481
+
ctx->esc_values[0] = ctx->cols - 1;
482
+
ctx->set_cursor_pos(ctx, ctx->esc_values[0], y);
486
+
ctx->esc_values[0] -= 1;
487
+
ctx->esc_values[1] -= 1;
488
+
if (ctx->esc_values[1] >= ctx->cols)
489
+
ctx->esc_values[1] = ctx->cols - 1;
490
+
if (ctx->esc_values[0] >= ctx->rows)
491
+
ctx->esc_values[0] = ctx->rows - 1;
492
+
ctx->set_cursor_pos(ctx, ctx->esc_values[1], ctx->esc_values[0]);
495
+
switch (ctx->esc_values[0]) {
497
+
if (ctx->callback != NULL) {
498
+
ctx->callback(ctx, TERM_CB_STATUS_REPORT, 0, 0, 0);
502
+
if (ctx->callback != NULL) {
503
+
ctx->callback(ctx, TERM_CB_POS_REPORT, x + 1, y + 1, 0);
509
+
if (ctx->callback != NULL) {
510
+
ctx->callback(ctx, TERM_CB_KBD_LEDS, ctx->esc_values[0], 0, 0);
514
+
switch (ctx->esc_values[0]) {
516
+
size_t rows_remaining = ctx->rows - (y + 1);
517
+
size_t cols_diff = ctx->cols - (x + 1);
518
+
size_t to_clear = rows_remaining * ctx->cols + cols_diff;
519
+
for (size_t i = 0; i < to_clear; i++) {
520
+
ctx->raw_putchar(ctx, ' ');
522
+
ctx->set_cursor_pos(ctx, x, y);
526
+
ctx->set_cursor_pos(ctx, 0, 0);
528
+
for (size_t yc = 0; yc < ctx->rows; yc++) {
529
+
for (size_t xc = 0; xc < ctx->cols; xc++) {
530
+
ctx->raw_putchar(ctx, ' ');
531
+
if (xc == x && yc == y) {
532
+
ctx->set_cursor_pos(ctx, x, y);
544
+
ctx->clear(ctx, false);
549
+
for (size_t i = ctx->cols - 1; ; i--) {
550
+
ctx->move_character(ctx, i + ctx->esc_values[0], y, i, y);
551
+
ctx->set_cursor_pos(ctx, i, y);
552
+
ctx->raw_putchar(ctx, ' ');
557
+
ctx->set_cursor_pos(ctx, x, y);
560
+
for (size_t i = x + ctx->esc_values[0]; i < ctx->cols; i++)
561
+
ctx->move_character(ctx, i - ctx->esc_values[0], y, i, y);
562
+
ctx->set_cursor_pos(ctx, ctx->cols - ctx->esc_values[0], y);
565
+
for (size_t i = 0; i < ctx->esc_values[0]; i++)
566
+
ctx->raw_putchar(ctx, ' ');
567
+
ctx->set_cursor_pos(ctx, x, y);
573
+
ctx->get_cursor_pos(ctx, &ctx->saved_cursor_x, &ctx->saved_cursor_y);
576
+
ctx->set_cursor_pos(ctx, ctx->saved_cursor_x, ctx->saved_cursor_y);
579
+
switch (ctx->esc_values[0]) {
581
+
for (size_t i = x; i < ctx->cols; i++)
582
+
ctx->raw_putchar(ctx, ' ');
583
+
ctx->set_cursor_pos(ctx, x, y);
587
+
ctx->set_cursor_pos(ctx, 0, y);
588
+
for (size_t i = 0; i < x; i++)
589
+
ctx->raw_putchar(ctx, ' ');
593
+
ctx->set_cursor_pos(ctx, 0, y);
594
+
for (size_t i = 0; i < ctx->cols; i++)
595
+
ctx->raw_putchar(ctx, ' ');
596
+
ctx->set_cursor_pos(ctx, x, y);
602
+
ctx->scroll_top_margin = 0;
603
+
ctx->scroll_bottom_margin = ctx->rows;
604
+
if (ctx->esc_values_i > 0) {
605
+
ctx->scroll_top_margin = ctx->esc_values[0] - 1;
607
+
if (ctx->esc_values_i > 1) {
608
+
ctx->scroll_bottom_margin = ctx->esc_values[1];
610
+
if (ctx->scroll_top_margin >= ctx->rows
611
+
|| ctx->scroll_bottom_margin > ctx->rows
612
+
|| ctx->scroll_top_margin >= (ctx->scroll_bottom_margin - 1)) {
613
+
ctx->scroll_top_margin = 0;
614
+
ctx->scroll_bottom_margin = ctx->rows;
616
+
ctx->set_cursor_pos(ctx, 0, 0);
620
+
mode_toggle(ctx, c);
623
+
linux_private_parse(ctx);
627
+
ctx->scroll_enabled = r;
630
+
ctx->control_sequence = false;
631
+
ctx->escape = false;
634
+
static void restore_state(struct term_context *ctx) {
635
+
ctx->bold = ctx->saved_state_bold;
636
+
ctx->reverse_video = ctx->saved_state_reverse_video;
637
+
ctx->current_charset = ctx->saved_state_current_charset;
638
+
ctx->current_primary = ctx->saved_state_current_primary;
640
+
ctx->restore_state(ctx);
643
+
static void save_state(struct term_context *ctx) {
644
+
ctx->save_state(ctx);
646
+
ctx->saved_state_bold = ctx->bold;
647
+
ctx->saved_state_reverse_video = ctx->reverse_video;
648
+
ctx->saved_state_current_charset = ctx->current_charset;
649
+
ctx->saved_state_current_primary = ctx->current_primary;
652
+
static void escape_parse(struct term_context *ctx, uint8_t c) {
653
+
ctx->escape_offset++;
655
+
if (ctx->control_sequence == true) {
656
+
control_sequence_parse(ctx, c);
660
+
if (ctx->csi == true) {
666
+
ctx->get_cursor_pos(ctx, &x, &y);
671
+
for (size_t i = 0; i < TERM_MAX_ESC_VALUES; i++)
672
+
ctx->esc_values[i] = 0;
673
+
ctx->esc_values_i = 0;
675
+
ctx->control_sequence = true;
681
+
restore_state(ctx);
684
+
term_context_reinit(ctx);
685
+
ctx->clear(ctx, true);
688
+
if (y == ctx->scroll_bottom_margin - 1) {
690
+
ctx->set_cursor_pos(ctx, x, y);
692
+
ctx->set_cursor_pos(ctx, x, y + 1);
696
+
if (y == ctx->scroll_bottom_margin - 1) {
698
+
ctx->set_cursor_pos(ctx, 0, y);
700
+
ctx->set_cursor_pos(ctx, 0, y + 1);
704
+
// "Reverse linefeed"
705
+
if (y == ctx->scroll_top_margin) {
706
+
ctx->revscroll(ctx);
707
+
ctx->set_cursor_pos(ctx, 0, y);
709
+
ctx->set_cursor_pos(ctx, 0, y - 1);
713
+
if (ctx->callback != NULL) {
714
+
ctx->callback(ctx, TERM_CB_PRIVATE_ID, 0, 0, 0);
719
+
ctx->g_select = c - '\'';
722
+
if (ctx->in_bootloader == true) {
723
+
ctx->raw_putchar(ctx, c);
728
+
ctx->escape = false;
731
+
static uint8_t dec_special_to_cp437(uint8_t c) {
733
+
case '`': return 0x04;
734
+
case '0': return 0xdb;
735
+
case '-': return 0x18;
736
+
case ',': return 0x1b;
737
+
case '.': return 0x19;
738
+
case 'a': return 0xb1;
739
+
case 'f': return 0xf8;
740
+
case 'g': return 0xf1;
741
+
case 'h': return 0xb0;
742
+
case 'j': return 0xd9;
743
+
case 'k': return 0xbf;
744
+
case 'l': return 0xda;
745
+
case 'm': return 0xc0;
746
+
case 'n': return 0xc5;
747
+
case 'q': return 0xc4;
748
+
case 's': return 0x5f;
749
+
case 't': return 0xc3;
750
+
case 'u': return 0xb4;
751
+
case 'v': return 0xc1;
752
+
case 'w': return 0xc2;
753
+
case 'x': return 0xb3;
754
+
case 'y': return 0xf3;
755
+
case 'z': return 0xf2;
756
+
case '~': return 0xfa;
757
+
case '_': return 0xff;
758
+
case '+': return 0x1a;
759
+
case '{': return 0xe3;
760
+
case '}': return 0x9c;
766
+
static void term_putchar(struct term_context *ctx, uint8_t c) {
767
+
if (ctx->discard_next || (ctx->in_bootloader == false && (c == 0x18 || c == 0x1a))) {
768
+
ctx->discard_next = false;
769
+
ctx->escape = false;
771
+
ctx->control_sequence = false;
776
+
if (ctx->escape == true) {
777
+
escape_parse(ctx, c);
781
+
if (ctx->g_select) {
785
+
ctx->charsets[ctx->g_select] = CHARSET_DEFAULT; break;
787
+
ctx->charsets[ctx->g_select] = CHARSET_DEC_SPECIAL; break;
794
+
ctx->get_cursor_pos(ctx, &x, &y);
804
+
ctx->escape_offset = 0;
805
+
ctx->escape = true;
808
+
if ((x / ctx->tab_size + 1) >= ctx->cols) {
809
+
ctx->set_cursor_pos(ctx, ctx->cols - 1, y);
812
+
ctx->set_cursor_pos(ctx, (x / ctx->tab_size + 1) * ctx->tab_size, y);
817
+
if (y == ctx->scroll_bottom_margin - 1) {
819
+
ctx->set_cursor_pos(ctx, 0, y);
821
+
ctx->set_cursor_pos(ctx, 0, y + 1);
825
+
ctx->set_cursor_pos(ctx, x - 1, y);
828
+
ctx->set_cursor_pos(ctx, 0, y);
831
+
// The bell is handled by the kernel
832
+
if (ctx->callback != NULL) {
833
+
ctx->callback(ctx, TERM_CB_BELL, 0, 0, 0);
838
+
ctx->current_charset = 1;
842
+
ctx->current_charset = 0;
846
+
if (ctx->insert_mode == true) {
847
+
for (size_t i = ctx->cols - 1; ; i--) {
848
+
ctx->move_character(ctx, i + 1, y, i, y);
855
+
// Translate character set
856
+
switch (ctx->charsets[ctx->current_charset]) {
857
+
case CHARSET_DEFAULT:
859
+
case CHARSET_DEC_SPECIAL:
860
+
c = dec_special_to_cp437(c);
863
+
ctx->raw_putchar(ctx, c);