LF OS
Hobby operating system for amd64 with high ambitions
Loading...
Searching...
No Matches
harness.c
Go to the documentation of this file.
1#include "vterm.h"
2#include "../src/vterm_internal.h" // We pull in some internal bits too
3
4#include <assert.h>
5#include <stdio.h>
6#include <string.h>
7
8#define streq(a,b) (!strcmp(a,b))
9#define strstartswith(a,b) (!strncmp(a,b,strlen(b)))
10
11static size_t inplace_hex2bytes(char *s)
12{
13 char *inpos = s, *outpos = s;
14
15 while(*inpos) {
16 unsigned int ch;
17 if(sscanf(inpos, "%2x", &ch) < 1)
18 break;
19 *outpos = ch;
20 outpos += 1; inpos += 2;
21 }
22
23 return outpos - s;
24}
25
26static VTermModifier strpe_modifiers(char **strp)
27{
29
30 while((*strp)[0]) {
31 switch(((*strp)++)[0]) {
32 case 'S': state |= VTERM_MOD_SHIFT; break;
33 case 'C': state |= VTERM_MOD_CTRL; break;
34 case 'A': state |= VTERM_MOD_ALT; break;
35 default: return state;
36 }
37 }
38
39 return state;
40}
41
42static VTermKey strp_key(char *str)
43{
44 static struct {
45 char *name;
46 VTermKey key;
47 } keys[] = {
48 { "Up", VTERM_KEY_UP },
49 { "Tab", VTERM_KEY_TAB },
50 { "Enter", VTERM_KEY_ENTER },
51 { "KP0", VTERM_KEY_KP_0 },
52 { "F1", VTERM_KEY_FUNCTION(1) },
53 { NULL, VTERM_KEY_NONE },
54 };
55
56 for(int i = 0; keys[i].name; i++) {
57 if(streq(str, keys[i].name))
58 return keys[i].key;
59 }
60
61 return VTERM_KEY_NONE;
62}
63
64static void print_color(const VTermColor *col)
65{
66 if (VTERM_COLOR_IS_RGB(col)) {
67 printf("rgb(%d,%d,%d", col->rgb.red, col->rgb.green, col->rgb.blue);
68 }
69 else if (VTERM_COLOR_IS_INDEXED(col)) {
70 printf("idx(%d", col->indexed.idx);
71 }
72 else {
73 printf("invalid(%d", col->type);
74 }
76 printf(",is_default_fg");
77 }
79 printf(",is_default_bg");
80 }
81 printf(")");
82}
83
84static VTermColor strpe_color(char **strp)
85{
86 uint8_t r, g, b, idx;
87 int len = 0;
88 VTermColor col;
89
90 if(sscanf(*strp, "rgb(%hhu,%hhu,%hhu)%n", &r, &g, &b, &len) == 3 && len > 0) {
91 *strp += len;
92 vterm_color_rgb(&col, r, g, b);
93 }
94 else if(sscanf(*strp, "idx(%hhu)%n", &idx, &len) == 1 && len > 0) {
95 *strp += len;
96 vterm_color_indexed(&col, idx);
97 }
98 else
99 vterm_color_rgb(&col, 127, 127, 127);
100
101 return col;
102}
103
104static VTerm *vt;
107
109
110static void term_output(const char *s, size_t len, void *user)
111{
112 printf("output ");
113 for(int i = 0; i < len; i++)
114 printf("%x%s", (unsigned char)s[i], i < len-1 ? "," : "\n");
115}
116
117static void printhex(const char *s, size_t len)
118{
119 while(len--)
120 printf("%02x", (uint8_t)(s++)[0]);
121}
122
123static int parser_text(const char bytes[], size_t len, void *user)
124{
125 printf("text ");
126 int i;
127 for(i = 0; i < len; i++) {
128 unsigned char b = bytes[i];
129 if(b < 0x20 || b == 0x7f || (b >= 0x80 && b < 0xa0))
130 break;
131 printf(i ? ",%x" : "%x", b);
132 }
133 printf("\n");
134
135 return i;
136}
137
138static int parser_control(unsigned char control, void *user)
139{
140 printf("control %02x\n", control);
141
142 return 1;
143}
144
145static int parser_escape(const char bytes[], size_t len, void *user)
146{
147 if(bytes[0] >= 0x20 && bytes[0] < 0x30) {
148 if(len < 2)
149 return -1;
150 len = 2;
151 }
152 else {
153 len = 1;
154 }
155
156 printf("escape ");
157 printhex(bytes, len);
158 printf("\n");
159
160 return len;
161}
162
163static int parser_csi(const char *leader, const long args[], int argcount, const char *intermed, char command, void *user)
164{
165 printf("csi %02x", command);
166
167 if(leader && leader[0]) {
168 printf(" L=");
169 for(int i = 0; leader[i]; i++)
170 printf("%02x", leader[i]);
171 }
172
173 for(int i = 0; i < argcount; i++) {
174 char sep = i ? ',' : ' ';
175
176 if(args[i] == CSI_ARG_MISSING)
177 printf("%c*", sep);
178 else
179 printf("%c%ld%s", sep, CSI_ARG(args[i]), CSI_ARG_HAS_MORE(args[i]) ? "+" : "");
180 }
181
182 if(intermed && intermed[0]) {
183 printf(" I=");
184 for(int i = 0; intermed[i]; i++)
185 printf("%02x", intermed[i]);
186 }
187
188 printf("\n");
189
190 return 1;
191}
192
193static int parser_osc(int command, VTermStringFragment frag, void *user)
194{
195 printf("osc ");
196
197 if(frag.initial) {
198 if(command == -1)
199 printf("[");
200 else
201 printf("[%d;", command);
202 }
203
204 printhex(frag.str, frag.len);
205
206 if(frag.final)
207 printf("]");
208
209 printf("\n");
210
211 return 1;
212}
213
214static int parser_dcs(const char *command, size_t commandlen, VTermStringFragment frag, void *user)
215{
216 printf("dcs ");
217
218 if(frag.initial) {
219 printf("[");
220 for(int i = 0; i < commandlen; i++)
221 printf("%02x", command[i]);
222 }
223
224 printhex(frag.str, frag.len);
225
226 if(frag.final)
227 printf("]");
228
229 printf("\n");
230
231 return 1;
232}
233
234static int parser_apc(VTermStringFragment frag, void *user)
235{
236 printf("apc ");
237
238 if(frag.initial)
239 printf("[");
240
241 printhex(frag.str, frag.len);
242
243 if(frag.final)
244 printf("]");
245
246 printf("\n");
247
248 return 1;
249}
250
251static int parser_pm(VTermStringFragment frag, void *user)
252{
253 printf("pm ");
254
255 if(frag.initial)
256 printf("[");
257
258 printhex(frag.str, frag.len);
259
260 if(frag.final)
261 printf("]");
262
263 printf("\n");
264
265 return 1;
266}
267
268static int parser_sos(VTermStringFragment frag, void *user)
269{
270 printf("sos ");
271
272 if(frag.initial)
273 printf("[");
274
275 printhex(frag.str, frag.len);
276
277 if(frag.final)
278 printf("]");
279
280 printf("\n");
281
282 return 1;
283}
284
286 .text = parser_text,
287 .control = parser_control,
288 .escape = parser_escape,
289 .csi = parser_csi,
290 .osc = parser_osc,
291 .dcs = parser_dcs,
292 .apc = parser_apc,
293 .pm = parser_pm,
294 .sos = parser_sos,
295};
296
299 .csi = parser_csi,
300 .osc = parser_osc,
301 .dcs = parser_dcs,
302 .apc = parser_apc,
303 .pm = parser_pm,
304 .sos = parser_sos,
305};
306
307/* These callbacks are shared by State and Screen */
308
309static int want_movecursor = 0;
311static int movecursor(VTermPos pos, VTermPos oldpos, int visible, void *user)
312{
313 state_pos = pos;
314
316 printf("movecursor %d,%d\n", pos.row, pos.col);
317
318 return 1;
319}
320
321static int want_scrollrect = 0;
322static int scrollrect(VTermRect rect, int downward, int rightward, void *user)
323{
324 if(!want_scrollrect)
325 return 0;
326
327 printf("scrollrect %d..%d,%d..%d => %+d,%+d\n",
328 rect.start_row, rect.end_row, rect.start_col, rect.end_col,
329 downward, rightward);
330
331 return 1;
332}
333
334static int want_moverect = 0;
335static int moverect(VTermRect dest, VTermRect src, void *user)
336{
337 if(!want_moverect)
338 return 0;
339
340 printf("moverect %d..%d,%d..%d -> %d..%d,%d..%d\n",
341 src.start_row, src.end_row, src.start_col, src.end_col,
342 dest.start_row, dest.end_row, dest.start_col, dest.end_col);
343
344 return 1;
345}
346
347static int want_settermprop = 0;
348static int settermprop(VTermProp prop, VTermValue *val, void *user)
349{
351 return 1;
352
354 switch(type) {
356 printf("settermprop %d %s\n", prop, val->boolean ? "true" : "false");
357 return 1;
359 printf("settermprop %d %d\n", prop, val->number);
360 return 1;
362 printf("settermprop %d %s\"%.*s\"%s\n", prop,
363 val->string.initial ? "[" : "", val->string.len, val->string.str, val->string.final ? "]" : "");
364 return 1;
366 printf("settermprop %d ", prop);
367 print_color(&val->color);
368 printf("\n");
369 return 1;
370
372 return 0;
373 }
374
375 return 0;
376}
377
378/* These callbacks are for State */
379
380static int want_state_putglyph = 0;
381static int state_putglyph(VTermGlyphInfo *info, VTermPos pos, void *user)
382{
384 return 1;
385
386 printf("putglyph ");
387 for(int i = 0; i < VTERM_MAX_CHARS_PER_CELL && info->chars[i]; i++)
388 printf(i ? ",%x" : "%x", info->chars[i]);
389 printf(" %d %d,%d", info->width, pos.row, pos.col);
390 if(info->protected_cell)
391 printf(" prot");
392 if(info->dwl)
393 printf(" dwl");
394 if(info->dhl)
395 printf(" dhl-%s", info->dhl == 1 ? "top" : info->dhl == 2 ? "bottom" : "?" );
396 printf("\n");
397
398 return 1;
399}
400
401static int want_state_erase = 0;
402static int state_erase(VTermRect rect, int selective, void *user)
403{
405 return 1;
406
407 printf("erase %d..%d,%d..%d%s\n",
408 rect.start_row, rect.end_row, rect.start_col, rect.end_col,
409 selective ? " selective" : "");
410
411 return 1;
412}
413
414static struct {
415 int bold;
416 int underline;
417 int italic;
418 int blink;
419 int reverse;
420 int conceal;
421 int strike;
422 int font;
423 int small;
424 int baseline;
425 VTermColor foreground;
426 VTermColor background;
428static int state_setpenattr(VTermAttr attr, VTermValue *val, void *user)
429{
430 switch(attr) {
431 case VTERM_ATTR_BOLD:
432 state_pen.bold = val->boolean;
433 break;
435 state_pen.underline = val->number;
436 break;
438 state_pen.italic = val->boolean;
439 break;
440 case VTERM_ATTR_BLINK:
441 state_pen.blink = val->boolean;
442 break;
444 state_pen.reverse = val->boolean;
445 break;
447 state_pen.conceal = val->boolean;
448 break;
450 state_pen.strike = val->boolean;
451 break;
452 case VTERM_ATTR_FONT:
453 state_pen.font = val->number;
454 break;
455 case VTERM_ATTR_SMALL:
456 state_pen.small = val->boolean;
457 break;
459 state_pen.baseline = val->number;
460 break;
462 state_pen.foreground = val->color;
463 break;
465 state_pen.background = val->color;
466 break;
467
468 case VTERM_N_ATTRS:
469 return 0;
470 }
471
472 return 1;
473}
474
475static int state_setlineinfo(int row, const VTermLineInfo *newinfo, const VTermLineInfo *oldinfo, void *user)
476{
477 return 1;
478}
479
481static int state_sb_clear(void *user) {
483 return 1;
484
485 printf("sb_clear\n");
486 return 0;
487}
488
491 .movecursor = movecursor,
492 .scrollrect = scrollrect,
493 .moverect = moverect,
494 .erase = state_erase,
495 .setpenattr = state_setpenattr,
496 .settermprop = settermprop,
497 .setlineinfo = state_setlineinfo,
498 .sb_clear = state_sb_clear,
499};
500
501static int selection_set(VTermSelectionMask mask, VTermStringFragment frag, void *user)
502{
503 printf("selection-set mask=%04X ", mask);
504 if(frag.initial)
505 printf("[");
506 printhex(frag.str, frag.len);
507 if(frag.final)
508 printf("]");
509 printf("\n");
510
511 return 1;
512}
513
514static int selection_query(VTermSelectionMask mask, void *user)
515{
516 printf("selection-query mask=%04X\n", mask);
517
518 return 1;
519}
520
525
526static int want_screen_damage = 0;
528static int screen_damage(VTermRect rect, void *user)
529{
531 return 1;
532
533 printf("damage %d..%d,%d..%d",
534 rect.start_row, rect.end_row, rect.start_col, rect.end_col);
535
537 bool equals = false;
538
539 for(int row = rect.start_row; row < rect.end_row; row++) {
540 int eol = rect.end_col;
541 while(eol > rect.start_col) {
542 VTermScreenCell cell;
543 vterm_screen_get_cell(screen, (VTermPos) { .row = row, .col = eol-1 }, &cell);
544 if(cell.chars[0])
545 break;
546
547 eol--;
548 }
549
550 if(eol == rect.start_col)
551 break;
552
553 if(!equals)
554 printf(" ="), equals = true;
555
556 printf(" %d<", row);
557 for(int col = rect.start_col; col < eol; col++) {
558 VTermScreenCell cell;
559 vterm_screen_get_cell(screen, (VTermPos) { .row = row, .col = col }, &cell);
560 printf(col == rect.start_col ? "%02X" : " %02X", cell.chars[0]);
561 }
562 printf(">");
563 }
564 }
565
566 printf("\n");
567
568 return 1;
569}
570
572static int screen_sb_pushline(int cols, const VTermScreenCell *cells, void *user)
573{
575 return 1;
576
577 int eol = cols;
578 while(eol && !cells[eol-1].chars[0])
579 eol--;
580
581 printf("sb_pushline %d =", cols);
582 for(int c = 0; c < eol; c++)
583 printf(" %02X", cells[c].chars[0]);
584 printf("\n");
585
586 return 1;
587}
588
589static int screen_sb_popline(int cols, VTermScreenCell *cells, void *user)
590{
592 return 0;
593
594 // All lines of scrollback contain "ABCDE"
595 for(int col = 0; col < cols; col++) {
596 if(col < 5)
597 cells[col].chars[0] = 'A' + col;
598 else
599 cells[col].chars[0] = 0;
600
601 cells[col].width = 1;
602 }
603
604 printf("sb_popline %d\n", cols);
605 return 1;
606}
607
608static int screen_sb_clear(void *user)
609{
611 return 1;
612
613 printf("sb_clear\n");
614 return 0;
615}
616
619 .moverect = moverect,
620 .movecursor = movecursor,
621 .settermprop = settermprop,
622 .sb_pushline = screen_sb_pushline,
623 .sb_popline = screen_sb_popline,
624 .sb_clear = screen_sb_clear,
625};
626
627int main(int argc, char **argv)
628{
629 char line[1024] = {0};
630 int flag;
631
632 int err;
633
634 setvbuf(stdout, NULL, _IONBF, 0);
635
636 while(fgets(line, sizeof line, stdin)) {
637 err = 0;
638
639 char *nl;
640 if((nl = strchr(line, '\n')))
641 *nl = '\0';
642
643 if(streq(line, "INIT")) {
644 if(!vt)
645 vt = vterm_new(25, 80);
646
648 }
649
650 else if(streq(line, "WANTPARSER")) {
651 assert(vt);
653 }
654
655 else if(strstartswith(line, "WANTSTATE") && (line[9] == '\0' || line[9] == ' ')) {
656 assert(vt);
657 if(!state) {
660 /* In some tests we want to check the behaviour of overflowing the
661 * buffer, so make it nicely small
662 */
666 }
667
668 int i = 9;
669 int sense = 1;
670 while(line[i] == ' ')
671 i++;
672 for( ; line[i]; i++)
673 switch(line[i]) {
674 case '+':
675 sense = 1;
676 break;
677 case '-':
678 sense = 0;
679 break;
680 case 'g':
681 want_state_putglyph = sense;
682 break;
683 case 's':
684 want_scrollrect = sense;
685 break;
686 case 'm':
687 want_moverect = sense;
688 break;
689 case 'e':
690 want_state_erase = sense;
691 break;
692 case 'p':
693 want_settermprop = sense;
694 break;
695 case 'f':
697 break;
698 case 'b':
699 want_state_scrollback = sense;
700 break;
701 default:
702 fprintf(stderr, "Unrecognised WANTSTATE flag '%c'\n", line[i]);
703 }
704 }
705
706 else if(strstartswith(line, "WANTSCREEN") && (line[10] == '\0' || line[10] == ' ')) {
707 assert(vt);
708 if(!screen)
711
712 int i = 10;
713 int sense = 1;
714 while(line[i] == ' ')
715 i++;
716 for( ; line[i]; i++)
717 switch(line[i]) {
718 case '-':
719 sense = 0;
720 break;
721 case 'a':
723 break;
724 case 'd':
725 want_screen_damage = sense;
726 break;
727 case 'D':
728 want_screen_damage = sense;
730 break;
731 case 'm':
732 want_moverect = sense;
733 break;
734 case 'c':
735 want_movecursor = sense;
736 break;
737 case 'p':
739 break;
740 case 'b':
742 break;
743 case 'r':
745 break;
746 default:
747 fprintf(stderr, "Unrecognised WANTSCREEN flag '%c'\n", line[i]);
748 }
749 }
750
751 else if(sscanf(line, "UTF8 %d", &flag)) {
752 vterm_set_utf8(vt, flag);
753 }
754
755 else if(streq(line, "RESET")) {
756 if(state) {
759 }
760 if(screen) {
762 }
763 }
764
765 else if(strstartswith(line, "RESIZE ")) {
766 int rows, cols;
767 char *linep = line + 7;
768 while(linep[0] == ' ')
769 linep++;
770 sscanf(linep, "%d, %d", &rows, &cols);
772 }
773
774 else if(strstartswith(line, "PUSH ")) {
775 char *bytes = line + 5;
776 size_t len = inplace_hex2bytes(bytes);
777 assert(len);
778
779 size_t written = vterm_input_write(vt, bytes, len);
780 if(written < len)
781 fprintf(stderr, "! short write\n");
782 }
783
784 else if(streq(line, "WANTENCODING")) {
785 /* This isn't really external API but it's hard to get this out any
786 * other way
787 */
789 if(encoding.enc->init)
791 }
792
793 else if(strstartswith(line, "ENCIN ")) {
794 char *bytes = line + 6;
795 size_t len = inplace_hex2bytes(bytes);
796 assert(len);
797
798 uint32_t cp[len];
799 int cpi = 0;
800 size_t pos = 0;
801
803 cp, &cpi, len, bytes, &pos, len);
804
805 if(cpi > 0) {
806 printf("encout ");
807 for(int i = 0; i < cpi; i++) {
808 printf(i ? ",%x" : "%x", cp[i]);
809 }
810 printf("\n");
811 }
812 }
813
814 else if(strstartswith(line, "INCHAR ")) {
815 char *linep = line + 7;
816 unsigned int c = 0;
817 while(linep[0] == ' ')
818 linep++;
819 VTermModifier mod = strpe_modifiers(&linep);
820 sscanf(linep, " %x", &c);
821
822 vterm_keyboard_unichar(vt, c, mod);
823 }
824
825 else if(strstartswith(line, "INKEY ")) {
826 char *linep = line + 6;
827 while(linep[0] == ' ')
828 linep++;
829 VTermModifier mod = strpe_modifiers(&linep);
830 while(linep[0] == ' ')
831 linep++;
832 VTermKey key = strp_key(linep);
833
834 vterm_keyboard_key(vt, key, mod);
835 }
836
837 else if(strstartswith(line, "PASTE ")) {
838 char *linep = line + 6;
839 if(streq(linep, "START"))
841 else if(streq(linep, "END"))
843 else
844 goto abort_line;
845 }
846
847 else if(strstartswith(line, "FOCUS ")) {
848 assert(state);
849 char *linep = line + 6;
850 if(streq(linep, "IN"))
852 else if(streq(linep, "OUT"))
854 else
855 goto abort_line;
856 }
857
858 else if(strstartswith(line, "MOUSEMOVE ")) {
859 char *linep = line + 10;
860 int row, col, len;
861 while(linep[0] == ' ')
862 linep++;
863 sscanf(linep, "%d,%d%n", &row, &col, &len);
864 linep += len;
865 while(linep[0] == ' ')
866 linep++;
867 VTermModifier mod = strpe_modifiers(&linep);
868 vterm_mouse_move(vt, row, col, mod);
869 }
870
871 else if(strstartswith(line, "MOUSEBTN ")) {
872 char *linep = line + 9;
873 char press;
874 int button, len;
875 while(linep[0] == ' ')
876 linep++;
877 sscanf(linep, "%c %d%n", &press, &button, &len);
878 linep += len;
879 while(linep[0] == ' ')
880 linep++;
881 VTermModifier mod = strpe_modifiers(&linep);
882 vterm_mouse_button(vt, button, (press == 'd' || press == 'D'), mod);
883 }
884
885 else if(strstartswith(line, "SELECTION ")) {
886 assert(state);
887 char *linep = line + 10;
888 unsigned int mask;
889 int len;
890 VTermStringFragment frag = { 0 };
891 sscanf(linep, "%x%n", &mask, &len);
892 linep += len;
893 while(linep[0] == ' ')
894 linep++;
895 if(linep[0] == '[') {
896 frag.initial = true;
897 linep++;
898 while(linep[0] == ' ')
899 linep++;
900 }
901 frag.len = inplace_hex2bytes(linep);
902 frag.str = linep;
903 assert(frag.len);
904
905 linep += frag.len * 2;
906 while(linep[0] == ' ')
907 linep++;
908 if(linep[0] == ']') {
909 frag.final = true;
910 }
912 }
913
914 else if(strstartswith(line, "DAMAGEMERGE ")) {
915 assert(screen);
916 char *linep = line + 12;
917 while(linep[0] == ' ')
918 linep++;
919 if(streq(linep, "CELL"))
921 else if(streq(linep, "ROW"))
923 else if(streq(linep, "SCREEN"))
925 else if(streq(linep, "SCROLL"))
927 }
928
929 else if(strstartswith(line, "DAMAGEFLUSH")) {
930 assert(screen);
932 }
933
934 else if(strstartswith(line, "SETDEFAULTCOL ")) {
935 assert(screen);
936 char *linep = line + 14;
937 while(linep[0] == ' ')
938 linep++;
939 VTermColor fg = strpe_color(&linep);
940 if(linep[0]) {
941 while(linep[0] == ' ')
942 linep++;
943 VTermColor bg = strpe_color(&linep);
944
946 }
947 else
949 }
950
951 else if(line[0] == '?') {
952 if(streq(line, "?cursor")) {
953 assert(state);
954 VTermPos pos;
956 if(pos.row != state_pos.row)
957 printf("! row mismatch: state=%d,%d event=%d,%d\n",
958 pos.row, pos.col, state_pos.row, state_pos.col);
959 else if(pos.col != state_pos.col)
960 printf("! col mismatch: state=%d,%d event=%d,%d\n",
961 pos.row, pos.col, state_pos.row, state_pos.col);
962 else
963 printf("%d,%d\n", state_pos.row, state_pos.col);
964 }
965 else if(strstartswith(line, "?pen ")) {
966 assert(state);
967 char *linep = line + 5;
968 while(linep[0] == ' ')
969 linep++;
970
971 VTermValue val;
972#define BOOLSTR(v) ((v) ? "on" : "off")
973
974 if(streq(linep, "bold")) {
976 if(val.boolean != state_pen.bold)
977 printf("! pen bold mismatch; state=%s, event=%s\n",
978 BOOLSTR(val.boolean), BOOLSTR(state_pen.bold));
979 else
980 printf("%s\n", BOOLSTR(state_pen.bold));
981 }
982 else if(streq(linep, "underline")) {
984 if(val.boolean != state_pen.underline)
985 printf("! pen underline mismatch; state=%d, event=%d\n",
986 val.boolean, state_pen.underline);
987 else
988 printf("%d\n", state_pen.underline);
989 }
990 else if(streq(linep, "italic")) {
992 if(val.boolean != state_pen.italic)
993 printf("! pen italic mismatch; state=%s, event=%s\n",
994 BOOLSTR(val.boolean), BOOLSTR(state_pen.italic));
995 else
996 printf("%s\n", BOOLSTR(state_pen.italic));
997 }
998 else if(streq(linep, "blink")) {
1000 if(val.boolean != state_pen.blink)
1001 printf("! pen blink mismatch; state=%s, event=%s\n",
1002 BOOLSTR(val.boolean), BOOLSTR(state_pen.blink));
1003 else
1004 printf("%s\n", BOOLSTR(state_pen.blink));
1005 }
1006 else if(streq(linep, "reverse")) {
1008 if(val.boolean != state_pen.reverse)
1009 printf("! pen reverse mismatch; state=%s, event=%s\n",
1010 BOOLSTR(val.boolean), BOOLSTR(state_pen.reverse));
1011 else
1012 printf("%s\n", BOOLSTR(state_pen.reverse));
1013 }
1014 else if(streq(linep, "font")) {
1016 if(val.boolean != state_pen.font)
1017 printf("! pen font mismatch; state=%d, event=%d\n",
1018 val.boolean, state_pen.font);
1019 else
1020 printf("%d\n", state_pen.font);
1021 }
1022 else if(streq(linep, "small")) {
1024 if(val.boolean != state_pen.small)
1025 printf("! pen small mismatch; state=%s, event=%s\n",
1026 BOOLSTR(val.boolean), BOOLSTR(state_pen.small));
1027 else
1028 printf("%s\n", BOOLSTR(state_pen.small));
1029 }
1030 else if(streq(linep, "baseline")) {
1032 if(val.number != state_pen.baseline)
1033 printf("! pen baseline mismatch: state=%d, event=%d\n",
1034 val.number, state_pen.baseline);
1035 else
1036 printf("%s\n", state_pen.baseline == VTERM_BASELINE_RAISE ? "raise"
1037 : state_pen.baseline == VTERM_BASELINE_LOWER ? "lower"
1038 : "normal");
1039 }
1040 else if(streq(linep, "foreground")) {
1041 print_color(&state_pen.foreground);
1042 printf("\n");
1043 }
1044 else if(streq(linep, "background")) {
1045 print_color(&state_pen.background);
1046 printf("\n");
1047 }
1048 else
1049 printf("?\n");
1050 }
1051 else if(strstartswith(line, "?lineinfo ")) {
1052 assert(state);
1053 char *linep = line + 10;
1054 int row;
1055 const VTermLineInfo *info;
1056 while(linep[0] == ' ')
1057 linep++;
1058 if(sscanf(linep, "%d", &row) < 1) {
1059 printf("! lineinfo unrecognised input\n");
1060 goto abort_line;
1061 }
1063 if(info->doublewidth)
1064 printf("dwl ");
1065 if(info->doubleheight)
1066 printf("dhl ");
1067 if(info->continuation)
1068 printf("cont ");
1069 printf("\n");
1070 }
1071 else if(strstartswith(line, "?screen_chars ")) {
1072 assert(screen);
1073 char *linep = line + 13;
1074 VTermRect rect;
1075 size_t len;
1076 while(linep[0] == ' ')
1077 linep++;
1078 if(sscanf(linep, "%d,%d,%d,%d", &rect.start_row, &rect.start_col, &rect.end_row, &rect.end_col) == 4)
1079 ; // fine
1080 else if(sscanf(linep, "%d", &rect.start_row) == 1) {
1081 rect.end_row = rect.start_row + 1;
1082 rect.start_col = 0;
1083 vterm_get_size(vt, NULL, &rect.end_col);
1084 }
1085 else {
1086 printf("! screen_chars unrecognised input\n");
1087 goto abort_line;
1088 }
1089 len = vterm_screen_get_chars(screen, NULL, 0, rect);
1090 if(len == (size_t)-1)
1091 printf("! screen_chars error\n");
1092 else if(len == 0)
1093 printf("\n");
1094 else {
1095 uint32_t *chars = malloc(sizeof(uint32_t) * len);
1096 vterm_screen_get_chars(screen, chars, len, rect);
1097 for(size_t i = 0; i < len; i++) {
1098 printf("0x%02x%s", chars[i], i < len-1 ? "," : "\n");
1099 }
1100 free(chars);
1101 }
1102 }
1103 else if(strstartswith(line, "?screen_text ")) {
1104 assert(screen);
1105 char *linep = line + 12;
1106 VTermRect rect;
1107 size_t len;
1108 while(linep[0] == ' ')
1109 linep++;
1110 if(sscanf(linep, "%d,%d,%d,%d", &rect.start_row, &rect.start_col, &rect.end_row, &rect.end_col) < 4) {
1111 printf("! screen_text unrecognised input\n");
1112 goto abort_line;
1113 }
1114 len = vterm_screen_get_text(screen, NULL, 0, rect);
1115 if(len == (size_t)-1)
1116 printf("! screen_text error\n");
1117 else if(len == 0)
1118 printf("\n");
1119 else {
1120 /* Put an overwrite guard at both ends of the buffer */
1121 unsigned char *buffer = malloc(len + 4);
1122 unsigned char *text = buffer + 2;
1123 text[-2] = 0x55; text[-1] = 0xAA;
1124 text[len] = 0x55; text[len+1] = 0xAA;
1125
1126 vterm_screen_get_text(screen, (char *)text, len, rect);
1127
1128 if(text[-2] != 0x55 || text[-1] != 0xAA)
1129 printf("! screen_get_text buffer overrun left [%02x,%02x]\n", text[-2], text[-1]);
1130 else if(text[len] != 0x55 || text[len+1] != 0xAA)
1131 printf("! screen_get_text buffer overrun right [%02x,%02x]\n", text[len], text[len+1]);
1132 else
1133 for(size_t i = 0; i < len; i++) {
1134 printf("0x%02x%s", text[i], i < len-1 ? "," : "\n");
1135 }
1136
1137 free(buffer);
1138 }
1139 }
1140 else if(strstartswith(line, "?screen_cell ")) {
1141 assert(screen);
1142 char *linep = line + 12;
1143 VTermPos pos;
1144 while(linep[0] == ' ')
1145 linep++;
1146 if(sscanf(linep, "%d,%d\n", &pos.row, &pos.col) < 2) {
1147 printf("! screen_cell unrecognised input\n");
1148 goto abort_line;
1149 }
1150 VTermScreenCell cell;
1151 if(!vterm_screen_get_cell(screen, pos, &cell))
1152 goto abort_line;
1153 printf("{");
1154 for(int i = 0; i < VTERM_MAX_CHARS_PER_CELL && cell.chars[i]; i++) {
1155 printf("%s0x%x", i ? "," : "", cell.chars[i]);
1156 }
1157 printf("} width=%d attrs={", cell.width);
1158 if(cell.attrs.bold) printf("B");
1159 if(cell.attrs.underline) printf("U%d", cell.attrs.underline);
1160 if(cell.attrs.italic) printf("I");
1161 if(cell.attrs.blink) printf("K");
1162 if(cell.attrs.reverse) printf("R");
1163 if(cell.attrs.font) printf("F%d", cell.attrs.font);
1164 if(cell.attrs.small) printf("S");
1165 if(cell.attrs.baseline) printf(
1166 cell.attrs.baseline == VTERM_BASELINE_RAISE ? "^" :
1167 "_");
1168 printf("} ");
1169 if(cell.attrs.dwl) printf("dwl ");
1170 if(cell.attrs.dhl) printf("dhl-%s ", cell.attrs.dhl == 2 ? "bottom" : "top");
1171 printf("fg=");
1173 print_color(&cell.fg);
1174 printf(" bg=");
1176 print_color(&cell.bg);
1177 printf("\n");
1178 }
1179 else if(strstartswith(line, "?screen_eol ")) {
1180 assert(screen);
1181 char *linep = line + 12;
1182 while(linep[0] == ' ')
1183 linep++;
1184 VTermPos pos;
1185 if(sscanf(linep, "%d,%d\n", &pos.row, &pos.col) < 2) {
1186 printf("! screen_eol unrecognised input\n");
1187 goto abort_line;
1188 }
1189 printf("%d\n", vterm_screen_is_eol(screen, pos));
1190 }
1191 else if(strstartswith(line, "?screen_attrs_extent ")) {
1192 assert(screen);
1193 char *linep = line + 21;
1194 while(linep[0] == ' ')
1195 linep++;
1196 VTermPos pos;
1197 if(sscanf(linep, "%d,%d\n", &pos.row, &pos.col) < 2) {
1198 printf("! screen_attrs_extent unrecognised input\n");
1199 goto abort_line;
1200 }
1201 VTermRect rect = {
1202 .start_col = 0,
1203 .end_col = -1,
1204 };
1205 if(!vterm_screen_get_attrs_extent(screen, &rect, pos, ~0)) {
1206 printf("! screen_attrs_extent failed\n");
1207 goto abort_line;
1208 }
1209 printf("%d,%d-%d,%d\n", rect.start_row, rect.start_col, rect.end_row, rect.end_col);
1210 }
1211 else
1212 printf("?\n");
1213
1214 memset(line, 0, sizeof line);
1215 continue;
1216 }
1217
1218 else
1219 abort_line: err = 1;
1220
1221 size_t outlen = vterm_output_get_buffer_current(vt);
1222 if(outlen > 0) {
1223 char outbuff[outlen];
1224 vterm_output_read(vt, outbuff, outlen);
1225
1226 term_output(outbuff, outlen, NULL);
1227 }
1228
1229 printf(err ? "?\n" : "DONE\n");
1230 }
1231
1232 vterm_free(vt);
1233
1234 return 0;
1235}
unsigned int uint32_t
Definition arch.h:11
unsigned char uint8_t
Definition arch.h:5
VTermEncoding * vterm_lookup_encoding(VTermEncodingType type, char designation)
Definition encoding.c:224
Definition font.h:14
static int state_erase(VTermRect rect, int selective, void *user)
Definition harness.c:402
static int screen_sb_pushline(int cols, const VTermScreenCell *cells, void *user)
Definition harness.c:572
static size_t inplace_hex2bytes(char *s)
Definition harness.c:11
static int scrollrect(VTermRect rect, int downward, int rightward, void *user)
Definition harness.c:322
static VTermModifier strpe_modifiers(char **strp)
Definition harness.c:26
#define streq(a, b)
Definition harness.c:8
static int want_screen_scrollback
Definition harness.c:571
static int state_sb_clear(void *user)
Definition harness.c:481
static int parser_control(unsigned char control, void *user)
Definition harness.c:138
static int parser_pm(VTermStringFragment frag, void *user)
Definition harness.c:251
static VTermScreen * screen
Definition harness.c:106
static struct @29 state_pen
int main(int argc, char **argv)
Definition harness.c:627
static int state_putglyph(VTermGlyphInfo *info, VTermPos pos, void *user)
Definition harness.c:381
static VTermState * state
Definition harness.c:105
static int parser_text(const char bytes[], size_t len, void *user)
Definition harness.c:123
static int parser_osc(int command, VTermStringFragment frag, void *user)
Definition harness.c:193
static int state_setpenattr(VTermAttr attr, VTermValue *val, void *user)
Definition harness.c:428
static int want_state_scrollback
Definition harness.c:480
static void printhex(const char *s, size_t len)
Definition harness.c:117
static int screen_sb_popline(int cols, VTermScreenCell *cells, void *user)
Definition harness.c:589
static VTermColor strpe_color(char **strp)
Definition harness.c:84
static VTermEncodingInstance encoding
Definition harness.c:108
static void term_output(const char *s, size_t len, void *user)
Definition harness.c:110
static int want_settermprop
Definition harness.c:347
static int parser_csi(const char *leader, const long args[], int argcount, const char *intermed, char command, void *user)
Definition harness.c:163
static int movecursor(VTermPos pos, VTermPos oldpos, int visible, void *user)
Definition harness.c:311
static int want_state_erase
Definition harness.c:401
static int screen_damage(VTermRect rect, void *user)
Definition harness.c:528
static int selection_set(VTermSelectionMask mask, VTermStringFragment frag, void *user)
Definition harness.c:501
static int screen_sb_clear(void *user)
Definition harness.c:608
static int selection_query(VTermSelectionMask mask, void *user)
Definition harness.c:514
static void print_color(const VTermColor *col)
Definition harness.c:64
static VTermParserCallbacks parser_cbs
Definition harness.c:285
static int want_moverect
Definition harness.c:334
VTermStateCallbacks state_cbs
Definition harness.c:489
static int state_setlineinfo(int row, const VTermLineInfo *newinfo, const VTermLineInfo *oldinfo, void *user)
Definition harness.c:475
static int want_movecursor
Definition harness.c:309
#define BOOLSTR(v)
static int want_state_putglyph
Definition harness.c:380
static VTermStateFallbacks fallbacks
Definition harness.c:297
static int parser_sos(VTermStringFragment frag, void *user)
Definition harness.c:268
static int settermprop(VTermProp prop, VTermValue *val, void *user)
Definition harness.c:348
static VTermKey strp_key(char *str)
Definition harness.c:42
static VTermPos state_pos
Definition harness.c:310
static int moverect(VTermRect dest, VTermRect src, void *user)
Definition harness.c:335
#define strstartswith(a, b)
Definition harness.c:9
static int parser_escape(const char bytes[], size_t len, void *user)
Definition harness.c:145
static int want_scrollrect
Definition harness.c:321
static int parser_apc(VTermStringFragment frag, void *user)
Definition harness.c:234
static VTerm * vt
Definition harness.c:104
VTermSelectionCallbacks selection_cbs
Definition harness.c:521
VTermScreenCallbacks screen_cbs
Definition harness.c:617
static int parser_dcs(const char *command, size_t commandlen, VTermStringFragment frag, void *user)
Definition harness.c:214
static int want_screen_damage_cells
Definition harness.c:527
static int want_screen_damage
Definition harness.c:526
void * memset(void *dest, int c, size_t size)
Definition string.c:72
uint32_t info
Definition elf.h:7
void * malloc(size_t size)
Definition string.c:169
void free(void *ptr)
Definition string.c:180
char name[256]
Zero terminated string with the name of the file.
Definition loader.h:1
enum MessageType type
Type of the message.
void(* init)(VTermEncoding *enc, void *data)
void(* decode)(VTermEncoding *enc, void *data, uint32_t cp[], int *cpi, int cplen, const char bytes[], size_t *pos, size_t len)
int(* text)(const char *bytes, size_t len, void *user)
Definition vterm.h:403
int(* damage)(VTermRect rect, void *user)
Definition vterm.h:535
int(* set)(VTermSelectionMask mask, VTermStringFragment frag, void *user)
Definition vterm.h:453
int(* putglyph)(VTermGlyphInfo *info, VTermPos pos, void *user)
Definition vterm.h:428
int(* control)(unsigned char control, void *user)
Definition vterm.h:443
static int rows
Definition unterm.c:31
static int cols
Definition unterm.c:30
void vterm_set_utf8(VTerm *vt, int is_utf8)
Definition vterm.c:133
#define VTERM_MAX_CHARS_PER_CELL
Definition vterm.h:24
void vterm_state_send_selection(VTermState *state, VTermSelectionMask mask, VTermStringFragment frag)
Definition state.c:2268
struct VTermColor::@11 indexed
void vterm_screen_enable_reflow(VTermScreen *screen, bool reflow)
Definition screen.c:1032
void vterm_screen_flush_damage(VTermScreen *screen)
Definition screen.c:1074
void vterm_state_set_selection_callbacks(VTermState *state, const VTermSelectionCallbacks *callbacks, void *user, char *buffer, size_t buflen)
Definition state.c:2256
const char * str
Definition vterm.h:221
unsigned int underline
Definition vterm.h:501
void vterm_screen_set_default_colors(VTermScreen *screen, const VTermColor *default_fg, const VTermColor *default_bg)
Definition screen.c:1172
void vterm_state_set_callbacks(VTermState *state, const VTermStateCallbacks *callbacks, void *user)
Definition state.c:2144
unsigned int bold
Definition vterm.h:500
unsigned int italic
Definition vterm.h:502
VTermColor fg
Definition vterm.h:531
void vterm_keyboard_end_paste(VTerm *vt)
Definition keyboard.c:222
void vterm_screen_reset(VTermScreen *screen, int hard)
Definition screen.c:902
int boolean
Definition vterm.h:228
size_t vterm_screen_get_chars(const VTermScreen *screen, uint32_t *chars, size_t len, const VTermRect rect)
Definition screen.c:960
@ VTERM_DAMAGE_SCREEN
Definition vterm.h:564
@ VTERM_DAMAGE_SCROLL
Definition vterm.h:565
@ VTERM_DAMAGE_CELL
Definition vterm.h:562
@ VTERM_DAMAGE_ROW
Definition vterm.h:563
void vterm_screen_convert_color_to_rgb(const VTermScreen *screen, VTermColor *col)
Definition screen.c:1155
void vterm_state_set_bold_highbright(VTermState *state, int bold_is_highbright)
Definition pen.c:271
unsigned int dwl
Definition vterm.h:508
#define VTERM_COLOR_IS_INDEXED(col)
Definition vterm.h:109
uint8_t type
Definition vterm.h:149
VTermColor bg
Definition vterm.h:531
static void vterm_color_rgb(VTermColor *col, uint8_t red, uint8_t green, uint8_t blue)
Definition vterm.h:186
void vterm_mouse_move(VTerm *vt, int row, int col, VTermModifier mod)
Definition mouse.c:54
#define CSI_ARG_HAS_MORE(a)
Definition vterm.h:392
int end_row
Definition vterm.h:45
unsigned int small
Definition vterm.h:510
void vterm_state_reset(VTermState *state, int hard)
Definition state.c:2072
int vterm_screen_is_eol(const VTermScreen *screen, VTermPos pos)
Definition screen.c:1009
int col
Definition vterm.h:32
uint32_t chars[VTERM_MAX_CHARS_PER_CELL]
Definition vterm.h:528
void vterm_parser_set_callbacks(VTerm *vt, const VTermParserCallbacks *callbacks, void *user)
Definition parser.c:388
void vterm_state_get_cursorpos(const VTermState *state, VTermPos *cursorpos)
Definition state.c:2139
#define VTERM_COLOR_IS_DEFAULT_FG(col)
Definition vterm.h:124
int end_col
Definition vterm.h:47
int vterm_screen_get_cell(const VTermScreen *screen, VTermPos pos, VTermScreenCell *cell)
Definition screen.c:971
#define VTERM_COLOR_IS_RGB(col)
Definition vterm.h:116
unsigned int font
Definition vterm.h:507
size_t vterm_output_read(VTerm *vt, char *buffer, size_t len)
Definition vterm.c:251
int row
Definition vterm.h:31
#define CSI_ARG_MISSING
Definition vterm.h:396
int number
Definition vterm.h:229
size_t vterm_screen_get_text(const VTermScreen *screen, char *str, size_t len, const VTermRect rect)
Definition screen.c:965
void vterm_screen_set_callbacks(VTermScreen *screen, const VTermScreenCallbacks *callbacks, void *user)
Definition screen.c:1053
void vterm_keyboard_unichar(VTerm *vt, uint32_t c, VTermModifier mod)
Definition keyboard.c:7
const VTermLineInfo * vterm_state_get_lineinfo(const VTermState *state, int row)
Definition state.c:2251
size_t vterm_output_get_buffer_current(const VTerm *vt)
Definition vterm.c:241
VTermScreenCellAttrs attrs
Definition vterm.h:530
void vterm_get_size(const VTerm *vt, int *rowsp, int *colsp)
Definition vterm.c:108
@ VTERM_BASELINE_LOWER
Definition vterm.h:524
@ VTERM_BASELINE_RAISE
Definition vterm.h:523
void vterm_state_focus_out(VTermState *state)
Definition state.c:2245
VTermStringFragment string
Definition vterm.h:230
void vterm_keyboard_start_paste(VTerm *vt)
Definition keyboard.c:216
int start_row
Definition vterm.h:44
VTermState * vterm_obtain_state(VTerm *vt)
Definition state.c:2059
VTermScreen * vterm_obtain_screen(VTerm *vt)
Definition screen.c:1021
void vterm_keyboard_key(VTerm *vt, VTermKey key, VTermModifier mod)
Definition keyboard.c:128
unsigned int dhl
Definition vterm.h:509
void vterm_state_focus_in(VTermState *state)
Definition state.c:2239
void vterm_screen_enable_altscreen(VTermScreen *screen, int altscreen)
Definition screen.c:1043
int vterm_state_get_penattr(const VTermState *state, VTermAttr attr, VTermValue *val)
Definition pen.c:551
VTermValueType vterm_get_prop_type(VTermProp prop)
Definition vterm.c:287
#define CSI_ARG(a)
Definition vterm.h:393
void vterm_output_set_callback(VTerm *vt, VTermOutputCallback *func, void *user)
Definition vterm.c:138
int vterm_screen_get_attrs_extent(const VTermScreen *screen, VTermRect *extent, VTermPos pos, VTermAttrMask attrs)
Definition screen.c:1127
int start_col
Definition vterm.h:46
void vterm_set_size(VTerm *vt, int rows, int cols)
Definition vterm.c:116
unsigned int reverse
Definition vterm.h:504
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
VTermColor color
Definition vterm.h:231
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_N_VALUETYPES
Definition vterm.h:217
@ VTERM_VALUETYPE_COLOR
Definition vterm.h:215
static void vterm_color_indexed(VTermColor *col, uint8_t idx)
Definition vterm.h:199
#define VTERM_COLOR_IS_DEFAULT_BG(col)
Definition vterm.h:132
void vterm_state_set_unrecognised_fallbacks(VTermState *state, const VTermStateFallbacks *fallbacks, void *user)
Definition state.c:2164
void vterm_free(VTerm *vt)
Definition vterm.c:84
VTermProp
Definition vterm.h:252
void vterm_screen_set_damage_merge(VTermScreen *screen, VTermDamageSize size)
Definition screen.c:1091
VTerm * vterm_new(int rows, int cols)
Definition vterm.c:30
VTermSelectionMask
Definition vterm.h:284
unsigned int blink
Definition vterm.h:503
void vterm_mouse_button(VTerm *vt, int button, bool pressed, VTermModifier mod)
Definition mouse.c:73
unsigned int baseline
Definition vterm.h:511
size_t vterm_input_write(VTerm *vt, const char *bytes, size_t len)
Definition parser.c:111
struct VTermColor::@10 rgb
VTermEncoding * enc
@ ENC_UTF8
char data[4 *sizeof(uint32_t)]
VTermModifier
@ VTERM_MOD_ALT
@ VTERM_MOD_SHIFT
@ VTERM_MOD_CTRL
VTermKey
@ VTERM_KEY_NONE
@ VTERM_KEY_KP_0
@ VTERM_KEY_TAB
@ VTERM_KEY_UP
@ VTERM_KEY_ENTER
#define VTERM_KEY_FUNCTION(n)