void shift_cursor_to(uint8_t pos){ cursor_home(); uint8_t i = 0; for(i=0; i<pos; ++i) shift_cursor(SH_RIGHT); }
void test(bool* result) { SCREEN_Screen scr; scr = screen(80, 25); update(result, tposeq("initial cursor", mkpos(0, 0), cursor(&scr))); scr = screen(80, 25); cursor_address(&scr, mkpos(5, 10)); update(result, tposeq("cursor_address", mkpos(5, 10), cursor(&scr))); scr = screen(80, 25); cursor_address(&scr, mkpos(12, 5)); carriage_return(&scr); update(result, tposeq("carriage_return", mkpos(0, 5), cursor(&scr))); scr = screen(80, 25); cursor_address(&scr, mkpos(12, 5)); newline(&scr); update(result, tposeq("newline", mkpos(0, 6), cursor(&scr))); scr = screen(80, 25); cursor_address(&scr, mkpos(10, 6)); tab(&scr); update(result, tposeq("tab", mkpos(16, 6), cursor(&scr))); scr = screen(80, 25); cursor_address(&scr, mkpos(1, 6)); column_address(&scr, 16); update(result, tposeq("column_address", mkpos(16, 6), cursor(&scr))); scr = screen(80, 25); cursor_address(&scr, mkpos(16, 6)); row_address(&scr, 12); update(result, tposeq("row_address", mkpos(16, 12), cursor(&scr))); scr = screen(80, 25); cursor_address(&scr, mkpos(15, 6)); cursor_down(&scr); update(result, tposeq("cursor_down", mkpos(15, 7), cursor(&scr))); scr = screen(80, 25); cursor_address(&scr, mkpos(15, 6)); cursor_home(&scr); update(result, tposeq("cursor_home", mkpos(0, 0), cursor(&scr))); scr = screen(80, 25); cursor_address(&scr, mkpos(6, 8)); cursor_left(&scr); update(result, tposeq("cursor_left", mkpos(5, 8), cursor(&scr))); scr = screen(80, 25); cursor_address(&scr, mkpos(6, 8)); cursor_right(&scr); update(result, tposeq("cursor_right", mkpos(7, 8), cursor(&scr))); scr = screen(80, 25); cursor_address(&scr, mkpos(6, 8)); cursor_to_ll(&scr); update(result, tposeq("cursor_to_ll", mkpos(0, 24), cursor(&scr))); scr = screen(80, 25); cursor_address(&scr, mkpos(6, 8)); cursor_up(&scr); update(result, tposeq("cursor_up", mkpos(6, 7), cursor(&scr))); scr = screen(80, 25); cursor_address(&scr, mkpos(26, 9)); parm_left_cursor(&scr, 23); update(result, tposeq("parm_left_cursor", mkpos(3, 9), cursor(&scr))); scr = screen(80, 25); cursor_address(&scr, mkpos(3, 9)); parm_right_cursor(&scr, 23); update(result, tposeq("parm_right_cursor", mkpos(26, 9), cursor(&scr))); scr = screen(80, 25); cursor_address(&scr, mkpos(26, 4)); parm_down_cursor(&scr, 11); update(result, tposeq("parm_down_cursor", mkpos(26, 15), cursor(&scr))); scr = screen(6, 4); cursor_address(&scr, mkpos(2, 3)); put_char(&scr, 'a'); SCREEN_Cell want_0 = {'a', SCREEN_COLOR_WHITE, SCREEN_COLOR_BLACK, {false, false}}; update(result, tcelleq("put_char puts", want_0, cellat(&scr, mkpos(2,3)))); scr = screen(6, 4); cursor_address(&scr, mkpos(2, 3)); put_char(&scr, 'a'); update(result, tposeq("put_char moves", mkpos(3, 3), cursor(&scr))); scr = screen(6, 4); cursor_address(&scr, mkpos(5, 1)); put_char(&scr, 'a'); update(result, tposeq("put_char am", mkpos(0, 2), cursor(&scr))); scr = screen(6, 4); put_chars(&scr, "abcdefGHIJKLmno"); SCREEN_Cell want_1 = {'J', SCREEN_COLOR_WHITE, SCREEN_COLOR_BLACK, {false, false}}; update(result, tcelleq("put_char multiple", want_1, cellat(&scr, mkpos(3,1)))); scr = screen(6, 4); put_chars(&scr, "abcdefGHIJKLmno"); clear_screen(&scr); update(result, tposeq("clear_screen homes", mkpos(0, 0), cursor(&scr))); scr = screen(6, 4); put_chars(&scr, "abcdefGHIJKLmno"); clear_screen(&scr); SCREEN_Cell want_2 = {' ', SCREEN_COLOR_WHITE, SCREEN_COLOR_BLACK, {false, false}}; update(result, tcelleq("clear_screen clears", want_2, cellat(&scr, mkpos(3,1)))); scr = screen(6, 4); cursor_address(&scr, mkpos(0, 3)); put_chars(&scr, "abcdefGHIJKLmno"); SCREEN_Cell want_3 = {'J', SCREEN_COLOR_WHITE, SCREEN_COLOR_BLACK, {false, false}}; update(result, tcelleq("put_char scrolls at end", want_3, cellat(&scr, mkpos(3,2)))); scr = screen(6, 3); put_chars(&scr, "abcdefGHIJKLmno"); cursor_home(&scr); clr_eos(&scr); SCREEN_Cell want_4 = {' ', SCREEN_COLOR_WHITE, SCREEN_COLOR_BLACK, {false, false}}; update(result, tcelleq("put_char scrolls at end", want_4, cellat(&scr, mkpos(4,1)))); scr = screen(6, 4); cursor_down(&scr); put_chars(&scr, "abcdefGHIJKLmno"); cursor_address(&scr, mkpos(0, 3)); newline(&scr); SCREEN_Cell want_5 = {'K', SCREEN_COLOR_WHITE, SCREEN_COLOR_BLACK, {false, false}}; update(result, tcelleq("newline at bottom scrolls", want_5, cellat(&scr, mkpos(4,1)))); scr = screen(6, 4); put_chars(&scr, "abcdefGHIJKLmno"); cursor_address(&scr, mkpos(0, 0)); insert_line(&scr); SCREEN_Cell want_6 = {' ', SCREEN_COLOR_WHITE, SCREEN_COLOR_BLACK, {false, false}}; update(result, tcelleq("insert_line clears full line", want_6, cellat(&scr, mkpos(5,0)))); scr = screen(24, 4); cursor_address(&scr, mkpos(20, 1)); tab(&scr); update(result, tposeq("tab at eol", mkpos(0, 2), cursor(&scr))); }
void outputter(SCREEN_Screen* scr, int terminator, GetCharFunction getf) { while (1) { unsigned char c = getf(); if (c == terminator) { return; } switch (c) { case '\a': break; // TODO: alert? case '\t': tab(scr); break; case '\n': cursor_down(scr); break; case '\b': cursor_left(scr); break; case '\r': carriage_return(scr); break; case 0x1b: { c = getf(); switch (c) { case '[': { int x; if (getnum(getf, &x, &c)) { if (x == 1 && c == 'K') { clr_bol(scr); } else { switch (c) { case 'm': mode(scr, x); break; case 'A': parm_up_cursor(scr, x); break; case 'B': parm_down_cursor(scr, x); break; case 'C': parm_right_cursor(scr, x); break; case 'D': parm_left_cursor(scr, x); break; case 'G': column_address(scr, (x-1)); break; case 'L': parm_insert_line(scr, x); break; case 'M': parm_delete_line(scr, x); break; case 'P': parm_dch(scr, x); break; case 'S': parm_index(scr, x); break; case 'T': parm_rindex(scr, x); break; case 'X': erase_chars(scr, x); break; case '@': parm_ich(scr, x); break; case 'd': row_address(scr, (x-1)); break; case ';': { int y; if (getnum(getf, &y, &c)) { switch (c) { case 'm': mode(scr, x); mode(scr, y); break; case 'H': cursor_address(scr, mkpos(y-1, x-1)); break; default: fprintf(stderr, "unhandled: ESC[%i;%i%c\n", x, y, c); break; } } else { fprintf(stderr, "unhandled: ESC[%i;%c\n", x, c); } } break; default: fprintf(stderr, "unahndled: ESC[%i%c\n", x, c); break; } } } else { switch (c) { case '@': insert_character(scr); break; case 'A': cursor_up(scr); break; case 'B': cursor_down(scr); break; case 'C': cursor_right(scr); break; case 'D': cursor_left(scr); break; case 'H': cursor_home(scr); break; case 'I': tab(scr); break; case 'J': clr_eos(scr); break; case 'K': clr_eol(scr); break; case 'L': insert_line(scr); break; case 'M': delete_line(scr); break; case 'P': delete_character(scr); break; case 'm': exit_attribute_mode(scr); break; default: fprintf(stderr, "unhandled: ESC[%c\n", c); break; } } } break; case 'M': scroll_reverse(scr); break; default: fprintf(stderr, "unhandled: ESC%c\n", c); break; } } break; default: { wchar_t wc; if ((c & 0x80) == 0x00) { wc = c; } else if ((c & 0xE0) == 0xC0) { char c1 = 0x1F & c; char c2 = 0x3F & getf(); wc = (c1 << 6) | c2; } else if ((c & 0xF0) == 0xE0) { char c1 = 0x0F & c; char c2 = 0x3F & getf(); char c3 = 0x3F & getf(); wc = (c1 << 12) | (c2 << 6) | c3; } else if ((c & 0xF8) == 0xF0) { char c1 = 0x07 & c; char c2 = 0x3F & getf(); char c3 = 0x3F & getf(); char c4 = 0x3F & getf(); wc = (c1 << 18) | (c2 << 12) | (c3 << 6) | c4; } else if ((c & 0xFC) == 0xF8) { char c1 = 0x03 & c; char c2 = 0x3F & getf(); char c3 = 0x3F & getf(); char c4 = 0x3F & getf(); char c5 = 0x3F & getf(); wc = (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | c5; } else if ((c & 0xFE) == 0xFC) { char c1 = 0x01 & c; char c2 = 0x3F & getf(); char c3 = 0x3F & getf(); char c4 = 0x3F & getf(); char c5 = 0x3F & getf(); char c6 = 0x3F & getf(); wc = (c1 << 30) | (c2 << 24) | (c3 << 18) | (c4 << 12) | (c5 < 6) | c6; } else { fprintf(stderr, "bad utf-8 sequence: c=0x%02x\n", c); wc = '\0'; } put_char(scr, wc); } break; } } }