| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| /* | ||
| * Some utility functions on VTermRect structures | ||
| */ | ||
|
|
||
| #define STRFrect "(%d,%d-%d,%d)" | ||
| #define ARGSrect(r) (r).start_row, (r).start_col, (r).end_row, (r).end_col | ||
|
|
||
| /* Expand dst to contain src as well */ | ||
| static void rect_expand(VTermRect *dst, VTermRect *src) | ||
| { | ||
| if(dst->start_row > src->start_row) dst->start_row = src->start_row; | ||
| if(dst->start_col > src->start_col) dst->start_col = src->start_col; | ||
| if(dst->end_row < src->end_row) dst->end_row = src->end_row; | ||
| if(dst->end_col < src->end_col) dst->end_col = src->end_col; | ||
| } | ||
|
|
||
| /* Clip the dst to ensure it does not step outside of bounds */ | ||
| static void rect_clip(VTermRect *dst, VTermRect *bounds) | ||
| { | ||
| if(dst->start_row < bounds->start_row) dst->start_row = bounds->start_row; | ||
| if(dst->start_col < bounds->start_col) dst->start_col = bounds->start_col; | ||
| if(dst->end_row > bounds->end_row) dst->end_row = bounds->end_row; | ||
| if(dst->end_col > bounds->end_col) dst->end_col = bounds->end_col; | ||
| /* Ensure it doesn't end up negatively-sized */ | ||
| if(dst->end_row < dst->start_row) dst->end_row = dst->start_row; | ||
| if(dst->end_col < dst->start_col) dst->end_col = dst->start_col; | ||
| } | ||
|
|
||
| /* True if the two rectangles are equal */ | ||
| static int rect_equal(VTermRect *a, VTermRect *b) | ||
| { | ||
| return (a->start_row == b->start_row) && | ||
| (a->start_col == b->start_col) && | ||
| (a->end_row == b->end_row) && | ||
| (a->end_col == b->end_col); | ||
| } | ||
|
|
||
| /* True if small is contained entirely within big */ | ||
| static int rect_contains(VTermRect *big, VTermRect *small) | ||
| { | ||
| if(small->start_row < big->start_row) return 0; | ||
| if(small->start_col < big->start_col) return 0; | ||
| if(small->end_row > big->end_row) return 0; | ||
| if(small->end_col > big->end_col) return 0; | ||
| return 1; | ||
| } | ||
|
|
||
| /* True if the rectangles overlap at all */ | ||
| static int rect_intersects(VTermRect *a, VTermRect *b) | ||
| { | ||
| if(a->start_row > b->end_row || b->start_row > a->end_row) | ||
| return 0; | ||
| if(a->start_col > b->end_col || b->start_col > a->end_col) | ||
| return 0; | ||
| return 1; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,331 @@ | ||
| #include "vterm_internal.h" | ||
|
|
||
| /* ### The following from http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c | ||
| * With modifications: | ||
| * made functions static | ||
| * moved 'combining' table to file scope, so other functions can see it | ||
| * ################################################################### | ||
| */ | ||
|
|
||
| /* | ||
| * This is an implementation of wcwidth() and wcswidth() (defined in | ||
| * IEEE Std 1002.1-2001) for Unicode. | ||
| * | ||
| * http://www.opengroup.org/onlinepubs/007904975/functions/wcwidth.html | ||
| * http://www.opengroup.org/onlinepubs/007904975/functions/wcswidth.html | ||
| * | ||
| * In fixed-width output devices, Latin characters all occupy a single | ||
| * "cell" position of equal width, whereas ideographic CJK characters | ||
| * occupy two such cells. Interoperability between terminal-line | ||
| * applications and (teletype-style) character terminals using the | ||
| * UTF-8 encoding requires agreement on which character should advance | ||
| * the cursor by how many cell positions. No established formal | ||
| * standards exist at present on which Unicode character shall occupy | ||
| * how many cell positions on character terminals. These routines are | ||
| * a first attempt of defining such behavior based on simple rules | ||
| * applied to data provided by the Unicode Consortium. | ||
| * | ||
| * For some graphical characters, the Unicode standard explicitly | ||
| * defines a character-cell width via the definition of the East Asian | ||
| * FullWidth (F), Wide (W), Half-width (H), and Narrow (Na) classes. | ||
| * In all these cases, there is no ambiguity about which width a | ||
| * terminal shall use. For characters in the East Asian Ambiguous (A) | ||
| * class, the width choice depends purely on a preference of backward | ||
| * compatibility with either historic CJK or Western practice. | ||
| * Choosing single-width for these characters is easy to justify as | ||
| * the appropriate long-term solution, as the CJK practice of | ||
| * displaying these characters as double-width comes from historic | ||
| * implementation simplicity (8-bit encoded characters were displayed | ||
| * single-width and 16-bit ones double-width, even for Greek, | ||
| * Cyrillic, etc.) and not any typographic considerations. | ||
| * | ||
| * Much less clear is the choice of width for the Not East Asian | ||
| * (Neutral) class. Existing practice does not dictate a width for any | ||
| * of these characters. It would nevertheless make sense | ||
| * typographically to allocate two character cells to characters such | ||
| * as for instance EM SPACE or VOLUME INTEGRAL, which cannot be | ||
| * represented adequately with a single-width glyph. The following | ||
| * routines at present merely assign a single-cell width to all | ||
| * neutral characters, in the interest of simplicity. This is not | ||
| * entirely satisfactory and should be reconsidered before | ||
| * establishing a formal standard in this area. At the moment, the | ||
| * decision which Not East Asian (Neutral) characters should be | ||
| * represented by double-width glyphs cannot yet be answered by | ||
| * applying a simple rule from the Unicode database content. Setting | ||
| * up a proper standard for the behavior of UTF-8 character terminals | ||
| * will require a careful analysis not only of each Unicode character, | ||
| * but also of each presentation form, something the author of these | ||
| * routines has avoided to do so far. | ||
| * | ||
| * http://www.unicode.org/unicode/reports/tr11/ | ||
| * | ||
| * Markus Kuhn -- 2007-05-26 (Unicode 5.0) | ||
| * | ||
| * Permission to use, copy, modify, and distribute this software | ||
| * for any purpose and without fee is hereby granted. The author | ||
| * disclaims all warranties with regard to this software. | ||
| * | ||
| * Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c | ||
| */ | ||
|
|
||
| struct interval { | ||
| int first; | ||
| int last; | ||
| }; | ||
|
|
||
| /* sorted list of non-overlapping intervals of non-spacing characters */ | ||
| /* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */ | ||
| static const struct interval combining[] = { | ||
| { 0x0300, 0x036F }, { 0x0483, 0x0486 }, { 0x0488, 0x0489 }, | ||
| { 0x0591, 0x05BD }, { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 }, | ||
| { 0x05C4, 0x05C5 }, { 0x05C7, 0x05C7 }, { 0x0600, 0x0603 }, | ||
| { 0x0610, 0x0615 }, { 0x064B, 0x065E }, { 0x0670, 0x0670 }, | ||
| { 0x06D6, 0x06E4 }, { 0x06E7, 0x06E8 }, { 0x06EA, 0x06ED }, | ||
| { 0x070F, 0x070F }, { 0x0711, 0x0711 }, { 0x0730, 0x074A }, | ||
| { 0x07A6, 0x07B0 }, { 0x07EB, 0x07F3 }, { 0x0901, 0x0902 }, | ||
| { 0x093C, 0x093C }, { 0x0941, 0x0948 }, { 0x094D, 0x094D }, | ||
| { 0x0951, 0x0954 }, { 0x0962, 0x0963 }, { 0x0981, 0x0981 }, | ||
| { 0x09BC, 0x09BC }, { 0x09C1, 0x09C4 }, { 0x09CD, 0x09CD }, | ||
| { 0x09E2, 0x09E3 }, { 0x0A01, 0x0A02 }, { 0x0A3C, 0x0A3C }, | ||
| { 0x0A41, 0x0A42 }, { 0x0A47, 0x0A48 }, { 0x0A4B, 0x0A4D }, | ||
| { 0x0A70, 0x0A71 }, { 0x0A81, 0x0A82 }, { 0x0ABC, 0x0ABC }, | ||
| { 0x0AC1, 0x0AC5 }, { 0x0AC7, 0x0AC8 }, { 0x0ACD, 0x0ACD }, | ||
| { 0x0AE2, 0x0AE3 }, { 0x0B01, 0x0B01 }, { 0x0B3C, 0x0B3C }, | ||
| { 0x0B3F, 0x0B3F }, { 0x0B41, 0x0B43 }, { 0x0B4D, 0x0B4D }, | ||
| { 0x0B56, 0x0B56 }, { 0x0B82, 0x0B82 }, { 0x0BC0, 0x0BC0 }, | ||
| { 0x0BCD, 0x0BCD }, { 0x0C3E, 0x0C40 }, { 0x0C46, 0x0C48 }, | ||
| { 0x0C4A, 0x0C4D }, { 0x0C55, 0x0C56 }, { 0x0CBC, 0x0CBC }, | ||
| { 0x0CBF, 0x0CBF }, { 0x0CC6, 0x0CC6 }, { 0x0CCC, 0x0CCD }, | ||
| { 0x0CE2, 0x0CE3 }, { 0x0D41, 0x0D43 }, { 0x0D4D, 0x0D4D }, | ||
| { 0x0DCA, 0x0DCA }, { 0x0DD2, 0x0DD4 }, { 0x0DD6, 0x0DD6 }, | ||
| { 0x0E31, 0x0E31 }, { 0x0E34, 0x0E3A }, { 0x0E47, 0x0E4E }, | ||
| { 0x0EB1, 0x0EB1 }, { 0x0EB4, 0x0EB9 }, { 0x0EBB, 0x0EBC }, | ||
| { 0x0EC8, 0x0ECD }, { 0x0F18, 0x0F19 }, { 0x0F35, 0x0F35 }, | ||
| { 0x0F37, 0x0F37 }, { 0x0F39, 0x0F39 }, { 0x0F71, 0x0F7E }, | ||
| { 0x0F80, 0x0F84 }, { 0x0F86, 0x0F87 }, { 0x0F90, 0x0F97 }, | ||
| { 0x0F99, 0x0FBC }, { 0x0FC6, 0x0FC6 }, { 0x102D, 0x1030 }, | ||
| { 0x1032, 0x1032 }, { 0x1036, 0x1037 }, { 0x1039, 0x1039 }, | ||
| { 0x1058, 0x1059 }, { 0x1160, 0x11FF }, { 0x135F, 0x135F }, | ||
| { 0x1712, 0x1714 }, { 0x1732, 0x1734 }, { 0x1752, 0x1753 }, | ||
| { 0x1772, 0x1773 }, { 0x17B4, 0x17B5 }, { 0x17B7, 0x17BD }, | ||
| { 0x17C6, 0x17C6 }, { 0x17C9, 0x17D3 }, { 0x17DD, 0x17DD }, | ||
| { 0x180B, 0x180D }, { 0x18A9, 0x18A9 }, { 0x1920, 0x1922 }, | ||
| { 0x1927, 0x1928 }, { 0x1932, 0x1932 }, { 0x1939, 0x193B }, | ||
| { 0x1A17, 0x1A18 }, { 0x1B00, 0x1B03 }, { 0x1B34, 0x1B34 }, | ||
| { 0x1B36, 0x1B3A }, { 0x1B3C, 0x1B3C }, { 0x1B42, 0x1B42 }, | ||
| { 0x1B6B, 0x1B73 }, { 0x1DC0, 0x1DCA }, { 0x1DFE, 0x1DFF }, | ||
| { 0x200B, 0x200F }, { 0x202A, 0x202E }, { 0x2060, 0x2063 }, | ||
| { 0x206A, 0x206F }, { 0x20D0, 0x20EF }, { 0x302A, 0x302F }, | ||
| { 0x3099, 0x309A }, { 0xA806, 0xA806 }, { 0xA80B, 0xA80B }, | ||
| { 0xA825, 0xA826 }, { 0xFB1E, 0xFB1E }, { 0xFE00, 0xFE0F }, | ||
| { 0xFE20, 0xFE23 }, { 0xFEFF, 0xFEFF }, { 0xFFF9, 0xFFFB }, | ||
| { 0x10A01, 0x10A03 }, { 0x10A05, 0x10A06 }, { 0x10A0C, 0x10A0F }, | ||
| { 0x10A38, 0x10A3A }, { 0x10A3F, 0x10A3F }, { 0x1D167, 0x1D169 }, | ||
| { 0x1D173, 0x1D182 }, { 0x1D185, 0x1D18B }, { 0x1D1AA, 0x1D1AD }, | ||
| { 0x1D242, 0x1D244 }, { 0xE0001, 0xE0001 }, { 0xE0020, 0xE007F }, | ||
| { 0xE0100, 0xE01EF } | ||
| }; | ||
|
|
||
|
|
||
| /* auxiliary function for binary search in interval table */ | ||
| static int bisearch(uint32_t ucs, const struct interval *table, int max) { | ||
| int min = 0; | ||
| int mid; | ||
|
|
||
| if ((int)ucs < table[0].first || (int)ucs > table[max].last) | ||
| return 0; | ||
| while (max >= min) { | ||
| mid = (min + max) / 2; | ||
| if ((int)ucs > table[mid].last) | ||
| min = mid + 1; | ||
| else if ((int)ucs < table[mid].first) | ||
| max = mid - 1; | ||
| else | ||
| return 1; | ||
| } | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
|
|
||
| /* The following two functions define the column width of an ISO 10646 | ||
| * character as follows: | ||
| * | ||
| * - The null character (U+0000) has a column width of 0. | ||
| * | ||
| * - Other C0/C1 control characters and DEL will lead to a return | ||
| * value of -1. | ||
| * | ||
| * - Non-spacing and enclosing combining characters (general | ||
| * category code Mn or Me in the Unicode database) have a | ||
| * column width of 0. | ||
| * | ||
| * - SOFT HYPHEN (U+00AD) has a column width of 1. | ||
| * | ||
| * - Other format characters (general category code Cf in the Unicode | ||
| * database) and ZERO WIDTH SPACE (U+200B) have a column width of 0. | ||
| * | ||
| * - Hangul Jamo medial vowels and final consonants (U+1160-U+11FF) | ||
| * have a column width of 0. | ||
| * | ||
| * - Spacing characters in the East Asian Wide (W) or East Asian | ||
| * Full-width (F) category as defined in Unicode Technical | ||
| * Report #11 have a column width of 2. | ||
| * | ||
| * - All remaining characters (including all printable | ||
| * ISO 8859-1 and WGL4 characters, Unicode control characters, | ||
| * etc.) have a column width of 1. | ||
| * | ||
| * This implementation assumes that uint32_t characters are encoded | ||
| * in ISO 10646. | ||
| */ | ||
|
|
||
|
|
||
| static int mk_wcwidth(uint32_t ucs) | ||
| { | ||
| /* test for 8-bit control characters */ | ||
| if (ucs == 0) | ||
| return 0; | ||
| if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0)) | ||
| return -1; | ||
|
|
||
| /* binary search in table of non-spacing characters */ | ||
| if (bisearch(ucs, combining, | ||
| sizeof(combining) / sizeof(struct interval) - 1)) | ||
| return 0; | ||
|
|
||
| /* if we arrive here, ucs is not a combining or C0/C1 control character */ | ||
|
|
||
| return 1 + | ||
| (ucs >= 0x1100 && | ||
| (ucs <= 0x115f || /* Hangul Jamo init. consonants */ | ||
| ucs == 0x2329 || ucs == 0x232a || | ||
| (ucs >= 0x2e80 && ucs <= 0xa4cf && | ||
| ucs != 0x303f) || /* CJK ... Yi */ | ||
| (ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */ | ||
| (ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility Ideographs */ | ||
| (ucs >= 0xfe10 && ucs <= 0xfe19) || /* Vertical forms */ | ||
| (ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */ | ||
| (ucs >= 0xff00 && ucs <= 0xff60) || /* Fullwidth Forms */ | ||
| (ucs >= 0xffe0 && ucs <= 0xffe6) || | ||
| (ucs >= 0x20000 && ucs <= 0x2fffd) || | ||
| (ucs >= 0x30000 && ucs <= 0x3fffd))); | ||
| } | ||
|
|
||
| #if 0 /* unused */ | ||
| static int mk_wcswidth(const uint32_t *pwcs, size_t n) | ||
| { | ||
| int w, width = 0; | ||
|
|
||
| for (;*pwcs && n-- > 0; pwcs++) | ||
| if ((w = mk_wcwidth(*pwcs)) < 0) | ||
| return -1; | ||
| else | ||
| width += w; | ||
|
|
||
| return width; | ||
| } | ||
|
|
||
|
|
||
| /* | ||
| * The following functions are the same as mk_wcwidth() and | ||
| * mk_wcswidth(), except that spacing characters in the East Asian | ||
| * Ambiguous (A) category as defined in Unicode Technical Report #11 | ||
| * have a column width of 2. This variant might be useful for users of | ||
| * CJK legacy encodings who want to migrate to UCS without changing | ||
| * the traditional terminal character-width behaviour. It is not | ||
| * otherwise recommended for general use. | ||
| */ | ||
| static int mk_wcwidth_cjk(uint32_t ucs) | ||
| { | ||
| /* sorted list of non-overlapping intervals of East Asian Ambiguous | ||
| * characters, generated by "uniset +WIDTH-A -cat=Me -cat=Mn -cat=Cf c" */ | ||
| static const struct interval ambiguous[] = { | ||
| { 0x00A1, 0x00A1 }, { 0x00A4, 0x00A4 }, { 0x00A7, 0x00A8 }, | ||
| { 0x00AA, 0x00AA }, { 0x00AE, 0x00AE }, { 0x00B0, 0x00B4 }, | ||
| { 0x00B6, 0x00BA }, { 0x00BC, 0x00BF }, { 0x00C6, 0x00C6 }, | ||
| { 0x00D0, 0x00D0 }, { 0x00D7, 0x00D8 }, { 0x00DE, 0x00E1 }, | ||
| { 0x00E6, 0x00E6 }, { 0x00E8, 0x00EA }, { 0x00EC, 0x00ED }, | ||
| { 0x00F0, 0x00F0 }, { 0x00F2, 0x00F3 }, { 0x00F7, 0x00FA }, | ||
| { 0x00FC, 0x00FC }, { 0x00FE, 0x00FE }, { 0x0101, 0x0101 }, | ||
| { 0x0111, 0x0111 }, { 0x0113, 0x0113 }, { 0x011B, 0x011B }, | ||
| { 0x0126, 0x0127 }, { 0x012B, 0x012B }, { 0x0131, 0x0133 }, | ||
| { 0x0138, 0x0138 }, { 0x013F, 0x0142 }, { 0x0144, 0x0144 }, | ||
| { 0x0148, 0x014B }, { 0x014D, 0x014D }, { 0x0152, 0x0153 }, | ||
| { 0x0166, 0x0167 }, { 0x016B, 0x016B }, { 0x01CE, 0x01CE }, | ||
| { 0x01D0, 0x01D0 }, { 0x01D2, 0x01D2 }, { 0x01D4, 0x01D4 }, | ||
| { 0x01D6, 0x01D6 }, { 0x01D8, 0x01D8 }, { 0x01DA, 0x01DA }, | ||
| { 0x01DC, 0x01DC }, { 0x0251, 0x0251 }, { 0x0261, 0x0261 }, | ||
| { 0x02C4, 0x02C4 }, { 0x02C7, 0x02C7 }, { 0x02C9, 0x02CB }, | ||
| { 0x02CD, 0x02CD }, { 0x02D0, 0x02D0 }, { 0x02D8, 0x02DB }, | ||
| { 0x02DD, 0x02DD }, { 0x02DF, 0x02DF }, { 0x0391, 0x03A1 }, | ||
| { 0x03A3, 0x03A9 }, { 0x03B1, 0x03C1 }, { 0x03C3, 0x03C9 }, | ||
| { 0x0401, 0x0401 }, { 0x0410, 0x044F }, { 0x0451, 0x0451 }, | ||
| { 0x2010, 0x2010 }, { 0x2013, 0x2016 }, { 0x2018, 0x2019 }, | ||
| { 0x201C, 0x201D }, { 0x2020, 0x2022 }, { 0x2024, 0x2027 }, | ||
| { 0x2030, 0x2030 }, { 0x2032, 0x2033 }, { 0x2035, 0x2035 }, | ||
| { 0x203B, 0x203B }, { 0x203E, 0x203E }, { 0x2074, 0x2074 }, | ||
| { 0x207F, 0x207F }, { 0x2081, 0x2084 }, { 0x20AC, 0x20AC }, | ||
| { 0x2103, 0x2103 }, { 0x2105, 0x2105 }, { 0x2109, 0x2109 }, | ||
| { 0x2113, 0x2113 }, { 0x2116, 0x2116 }, { 0x2121, 0x2122 }, | ||
| { 0x2126, 0x2126 }, { 0x212B, 0x212B }, { 0x2153, 0x2154 }, | ||
| { 0x215B, 0x215E }, { 0x2160, 0x216B }, { 0x2170, 0x2179 }, | ||
| { 0x2190, 0x2199 }, { 0x21B8, 0x21B9 }, { 0x21D2, 0x21D2 }, | ||
| { 0x21D4, 0x21D4 }, { 0x21E7, 0x21E7 }, { 0x2200, 0x2200 }, | ||
| { 0x2202, 0x2203 }, { 0x2207, 0x2208 }, { 0x220B, 0x220B }, | ||
| { 0x220F, 0x220F }, { 0x2211, 0x2211 }, { 0x2215, 0x2215 }, | ||
| { 0x221A, 0x221A }, { 0x221D, 0x2220 }, { 0x2223, 0x2223 }, | ||
| { 0x2225, 0x2225 }, { 0x2227, 0x222C }, { 0x222E, 0x222E }, | ||
| { 0x2234, 0x2237 }, { 0x223C, 0x223D }, { 0x2248, 0x2248 }, | ||
| { 0x224C, 0x224C }, { 0x2252, 0x2252 }, { 0x2260, 0x2261 }, | ||
| { 0x2264, 0x2267 }, { 0x226A, 0x226B }, { 0x226E, 0x226F }, | ||
| { 0x2282, 0x2283 }, { 0x2286, 0x2287 }, { 0x2295, 0x2295 }, | ||
| { 0x2299, 0x2299 }, { 0x22A5, 0x22A5 }, { 0x22BF, 0x22BF }, | ||
| { 0x2312, 0x2312 }, { 0x2460, 0x24E9 }, { 0x24EB, 0x254B }, | ||
| { 0x2550, 0x2573 }, { 0x2580, 0x258F }, { 0x2592, 0x2595 }, | ||
| { 0x25A0, 0x25A1 }, { 0x25A3, 0x25A9 }, { 0x25B2, 0x25B3 }, | ||
| { 0x25B6, 0x25B7 }, { 0x25BC, 0x25BD }, { 0x25C0, 0x25C1 }, | ||
| { 0x25C6, 0x25C8 }, { 0x25CB, 0x25CB }, { 0x25CE, 0x25D1 }, | ||
| { 0x25E2, 0x25E5 }, { 0x25EF, 0x25EF }, { 0x2605, 0x2606 }, | ||
| { 0x2609, 0x2609 }, { 0x260E, 0x260F }, { 0x2614, 0x2615 }, | ||
| { 0x261C, 0x261C }, { 0x261E, 0x261E }, { 0x2640, 0x2640 }, | ||
| { 0x2642, 0x2642 }, { 0x2660, 0x2661 }, { 0x2663, 0x2665 }, | ||
| { 0x2667, 0x266A }, { 0x266C, 0x266D }, { 0x266F, 0x266F }, | ||
| { 0x273D, 0x273D }, { 0x2776, 0x277F }, { 0xE000, 0xF8FF }, | ||
| { 0xFFFD, 0xFFFD }, { 0xF0000, 0xFFFFD }, { 0x100000, 0x10FFFD } | ||
| }; | ||
|
|
||
| /* binary search in table of non-spacing characters */ | ||
| if (bisearch(ucs, ambiguous, | ||
| sizeof(ambiguous) / sizeof(struct interval) - 1)) | ||
| return 2; | ||
|
|
||
| return mk_wcwidth(ucs); | ||
| } | ||
|
|
||
| static int mk_wcswidth_cjk(const uint32_t *pwcs, size_t n) | ||
| { | ||
| int w, width = 0; | ||
|
|
||
| for (;*pwcs && n-- > 0; pwcs++) | ||
| if ((w = mk_wcwidth_cjk(*pwcs)) < 0) | ||
| return -1; | ||
| else | ||
| width += w; | ||
|
|
||
| return width; | ||
| } | ||
| #endif | ||
|
|
||
| /* ################################ | ||
| * ### The rest added by Paul Evans */ | ||
|
|
||
| INTERNAL int vterm_unicode_width(uint32_t codepoint) | ||
| { | ||
| return mk_wcwidth(codepoint); | ||
| } | ||
|
|
||
| INTERNAL int vterm_unicode_is_combining(uint32_t codepoint) | ||
| { | ||
| return bisearch(codepoint, combining, sizeof(combining) / sizeof(struct interval) - 1); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| /* The following functions copied and adapted from libtermkey | ||
| * | ||
| * http://www.leonerd.org.uk/code/libtermkey/ | ||
| */ | ||
| unsigned int utf8_seqlen(long codepoint); | ||
|
|
||
| #if defined(DEFINE_INLINES) || USE_INLINE | ||
| INLINE unsigned int utf8_seqlen(long codepoint) | ||
| { | ||
| if(codepoint < 0x0000080) return 1; | ||
| if(codepoint < 0x0000800) return 2; | ||
| if(codepoint < 0x0010000) return 3; | ||
| if(codepoint < 0x0200000) return 4; | ||
| if(codepoint < 0x4000000) return 5; | ||
| return 6; | ||
| } | ||
| #endif | ||
|
|
||
| /* Does NOT NUL-terminate the buffer */ | ||
| int fill_utf8(long codepoint, char *str); | ||
|
|
||
| #if defined(DEFINE_INLINES) || USE_INLINE | ||
| INLINE int fill_utf8(long codepoint, char *str) | ||
| { | ||
| int nbytes = utf8_seqlen(codepoint); | ||
|
|
||
| /* This is easier done backwards */ | ||
| int b = nbytes; | ||
| while(b > 1) { | ||
| b--; | ||
| str[b] = 0x80 | (codepoint & 0x3f); | ||
| codepoint >>= 6; | ||
| } | ||
|
|
||
| switch(nbytes) { | ||
| case 1: str[0] = (codepoint & 0x7f); break; | ||
| case 2: str[0] = 0xc0 | (codepoint & 0x1f); break; | ||
| case 3: str[0] = 0xe0 | (codepoint & 0x0f); break; | ||
| case 4: str[0] = 0xf0 | (codepoint & 0x07); break; | ||
| case 5: str[0] = 0xf8 | (codepoint & 0x03); break; | ||
| case 6: str[0] = 0xfc | (codepoint & 0x01); break; | ||
| } | ||
|
|
||
| return nbytes; | ||
| } | ||
| #endif | ||
| /* end copy */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,385 @@ | ||
| #define DEFINE_INLINES | ||
|
|
||
| #include "vterm_internal.h" | ||
|
|
||
| #include <stdio.h> | ||
| #include <stdlib.h> | ||
| #include <stdarg.h> | ||
| #include <string.h> | ||
|
|
||
| #include "utf8.h" | ||
|
|
||
| /***************** | ||
| * API functions * | ||
| *****************/ | ||
|
|
||
| static void *default_malloc(size_t size, void *allocdata UNUSED) | ||
| { | ||
| void *ptr = malloc(size); | ||
| if(ptr) | ||
| memset(ptr, 0, size); | ||
| return ptr; | ||
| } | ||
|
|
||
| static void default_free(void *ptr, void *allocdata UNUSED) | ||
| { | ||
| free(ptr); | ||
| } | ||
|
|
||
| static VTermAllocatorFunctions default_allocator = { | ||
| &default_malloc, /* malloc */ | ||
| &default_free /* free */ | ||
| }; | ||
|
|
||
| VTerm *vterm_new(int rows, int cols) | ||
| { | ||
| return vterm_new_with_allocator(rows, cols, &default_allocator, NULL); | ||
| } | ||
|
|
||
| VTerm *vterm_new_with_allocator(int rows, int cols, VTermAllocatorFunctions *funcs, void *allocdata) | ||
| { | ||
| /* Need to bootstrap using the allocator function directly */ | ||
| VTerm *vt = (*funcs->malloc)(sizeof(VTerm), allocdata); | ||
|
|
||
| vt->allocator = funcs; | ||
| vt->allocdata = allocdata; | ||
|
|
||
| vt->rows = rows; | ||
| vt->cols = cols; | ||
|
|
||
| vt->parser_state = NORMAL; | ||
|
|
||
| vt->parser_callbacks = NULL; | ||
| vt->cbdata = NULL; | ||
|
|
||
| vt->strbuffer_len = 64; | ||
| vt->strbuffer_cur = 0; | ||
| vt->strbuffer = vterm_allocator_malloc(vt, vt->strbuffer_len); | ||
|
|
||
| vt->outbuffer_len = 64; | ||
| vt->outbuffer_cur = 0; | ||
| vt->outbuffer = vterm_allocator_malloc(vt, vt->outbuffer_len); | ||
|
|
||
| return vt; | ||
| } | ||
|
|
||
| void vterm_free(VTerm *vt) | ||
| { | ||
| if(vt->screen) | ||
| vterm_screen_free(vt->screen); | ||
|
|
||
| if(vt->state) | ||
| vterm_state_free(vt->state); | ||
|
|
||
| vterm_allocator_free(vt, vt->strbuffer); | ||
| vterm_allocator_free(vt, vt->outbuffer); | ||
|
|
||
| vterm_allocator_free(vt, vt); | ||
| } | ||
|
|
||
| INTERNAL void *vterm_allocator_malloc(VTerm *vt, size_t size) | ||
| { | ||
| return (*vt->allocator->malloc)(size, vt->allocdata); | ||
| } | ||
|
|
||
| INTERNAL void vterm_allocator_free(VTerm *vt, void *ptr) | ||
| { | ||
| (*vt->allocator->free)(ptr, vt->allocdata); | ||
| } | ||
|
|
||
| void vterm_get_size(const VTerm *vt, int *rowsp, int *colsp) | ||
| { | ||
| if(rowsp) | ||
| *rowsp = vt->rows; | ||
| if(colsp) | ||
| *colsp = vt->cols; | ||
| } | ||
|
|
||
| void vterm_set_size(VTerm *vt, int rows, int cols) | ||
| { | ||
| vt->rows = rows; | ||
| vt->cols = cols; | ||
|
|
||
| if(vt->parser_callbacks && vt->parser_callbacks->resize) | ||
| (*vt->parser_callbacks->resize)(rows, cols, vt->cbdata); | ||
| } | ||
|
|
||
| int vterm_get_utf8(const VTerm *vt) | ||
| { | ||
| return vt->mode.utf8; | ||
| } | ||
|
|
||
| void vterm_set_utf8(VTerm *vt, int is_utf8) | ||
| { | ||
| vt->mode.utf8 = is_utf8; | ||
| } | ||
|
|
||
| INTERNAL void vterm_push_output_bytes(VTerm *vt, const char *bytes, size_t len) | ||
| { | ||
| if(len > vt->outbuffer_len - vt->outbuffer_cur) { | ||
| DEBUG_LOG("vterm_push_output(): buffer overflow; truncating output\n"); | ||
| len = vt->outbuffer_len - vt->outbuffer_cur; | ||
| } | ||
|
|
||
| memcpy(vt->outbuffer + vt->outbuffer_cur, bytes, len); | ||
| vt->outbuffer_cur += len; | ||
| } | ||
|
|
||
| static int outbuffer_is_full(VTerm *vt) | ||
| { | ||
| return vt->outbuffer_cur >= vt->outbuffer_len - 1; | ||
| } | ||
|
|
||
| INTERNAL void vterm_push_output_vsprintf(VTerm *vt, const char *format, va_list args) | ||
| { | ||
| int written; | ||
| char buffer[1024]; /* 1Kbyte is enough for everybody, right? */ | ||
|
|
||
| if(outbuffer_is_full(vt)) { | ||
| DEBUG_LOG("vterm_push_output(): buffer overflow; truncating output\n"); | ||
| return; | ||
| } | ||
|
|
||
| written = vsprintf(buffer, format, args); | ||
|
|
||
| if(written >= (int)(vt->outbuffer_len - vt->outbuffer_cur)) { | ||
| /* output was truncated */ | ||
| written = vt->outbuffer_len - vt->outbuffer_cur; | ||
| } | ||
| if (written > 0) | ||
| { | ||
| strncpy(vt->outbuffer + vt->outbuffer_cur, buffer, written + 1); | ||
| vt->outbuffer_cur += written; | ||
| } | ||
| } | ||
|
|
||
| INTERNAL void vterm_push_output_sprintf(VTerm *vt, const char *format, ...) | ||
| { | ||
| va_list args; | ||
| va_start(args, format); | ||
| vterm_push_output_vsprintf(vt, format, args); | ||
| va_end(args); | ||
| } | ||
|
|
||
| INTERNAL void vterm_push_output_sprintf_ctrl(VTerm *vt, unsigned char ctrl, const char *fmt, ...) | ||
| { | ||
| size_t orig_cur = vt->outbuffer_cur; | ||
| va_list args; | ||
|
|
||
| if(ctrl >= 0x80 && !vt->mode.ctrl8bit) | ||
| vterm_push_output_sprintf(vt, ESC_S "%c", ctrl - 0x40); | ||
| else | ||
| vterm_push_output_sprintf(vt, "%c", ctrl); | ||
|
|
||
| va_start(args, fmt); | ||
| vterm_push_output_vsprintf(vt, fmt, args); | ||
| va_end(args); | ||
|
|
||
| if(outbuffer_is_full(vt)) | ||
| vt->outbuffer_cur = orig_cur; | ||
| } | ||
|
|
||
| INTERNAL void vterm_push_output_sprintf_dcs(VTerm *vt, const char *fmt, ...) | ||
| { | ||
| size_t orig_cur = vt->outbuffer_cur; | ||
| va_list args; | ||
|
|
||
| if(!vt->mode.ctrl8bit) | ||
| vterm_push_output_sprintf(vt, ESC_S "%c", C1_DCS - 0x40); | ||
| else | ||
| vterm_push_output_sprintf(vt, "%c", C1_DCS); | ||
|
|
||
| va_start(args, fmt); | ||
| vterm_push_output_vsprintf(vt, fmt, args); | ||
| va_end(args); | ||
|
|
||
| vterm_push_output_sprintf_ctrl(vt, C1_ST, ""); | ||
|
|
||
| if(outbuffer_is_full(vt)) | ||
| vt->outbuffer_cur = orig_cur; | ||
| } | ||
|
|
||
| size_t vterm_output_get_buffer_size(const VTerm *vt) | ||
| { | ||
| return vt->outbuffer_len; | ||
| } | ||
|
|
||
| size_t vterm_output_get_buffer_current(const VTerm *vt) | ||
| { | ||
| return vt->outbuffer_cur; | ||
| } | ||
|
|
||
| size_t vterm_output_get_buffer_remaining(const VTerm *vt) | ||
| { | ||
| return vt->outbuffer_len - vt->outbuffer_cur; | ||
| } | ||
|
|
||
| size_t vterm_output_read(VTerm *vt, char *buffer, size_t len) | ||
| { | ||
| if(len > vt->outbuffer_cur) | ||
| len = vt->outbuffer_cur; | ||
|
|
||
| memcpy(buffer, vt->outbuffer, len); | ||
|
|
||
| if(len < vt->outbuffer_cur) | ||
| memmove(vt->outbuffer, vt->outbuffer + len, vt->outbuffer_cur - len); | ||
|
|
||
| vt->outbuffer_cur -= len; | ||
|
|
||
| return len; | ||
| } | ||
|
|
||
| void vterm_parser_set_callbacks(VTerm *vt, const VTermParserCallbacks *callbacks, void *user) | ||
| { | ||
| vt->parser_callbacks = callbacks; | ||
| vt->cbdata = user; | ||
| } | ||
|
|
||
| void *vterm_parser_get_cbdata(VTerm *vt) | ||
| { | ||
| return vt->cbdata; | ||
| } | ||
|
|
||
| VTermValueType vterm_get_attr_type(VTermAttr attr) | ||
| { | ||
| switch(attr) { | ||
| case VTERM_ATTR_BOLD: return VTERM_VALUETYPE_BOOL; | ||
| case VTERM_ATTR_UNDERLINE: return VTERM_VALUETYPE_INT; | ||
| case VTERM_ATTR_ITALIC: return VTERM_VALUETYPE_BOOL; | ||
| case VTERM_ATTR_BLINK: return VTERM_VALUETYPE_BOOL; | ||
| case VTERM_ATTR_REVERSE: return VTERM_VALUETYPE_BOOL; | ||
| case VTERM_ATTR_STRIKE: return VTERM_VALUETYPE_BOOL; | ||
| case VTERM_ATTR_FONT: return VTERM_VALUETYPE_INT; | ||
| case VTERM_ATTR_FOREGROUND: return VTERM_VALUETYPE_COLOR; | ||
| case VTERM_ATTR_BACKGROUND: return VTERM_VALUETYPE_COLOR; | ||
| } | ||
| return 0; /* UNREACHABLE */ | ||
| } | ||
|
|
||
| VTermValueType vterm_get_prop_type(VTermProp prop) | ||
| { | ||
| switch(prop) { | ||
| case VTERM_PROP_CURSORVISIBLE: return VTERM_VALUETYPE_BOOL; | ||
| case VTERM_PROP_CURSORBLINK: return VTERM_VALUETYPE_BOOL; | ||
| case VTERM_PROP_ALTSCREEN: return VTERM_VALUETYPE_BOOL; | ||
| case VTERM_PROP_TITLE: return VTERM_VALUETYPE_STRING; | ||
| case VTERM_PROP_ICONNAME: return VTERM_VALUETYPE_STRING; | ||
| case VTERM_PROP_REVERSE: return VTERM_VALUETYPE_BOOL; | ||
| case VTERM_PROP_CURSORSHAPE: return VTERM_VALUETYPE_INT; | ||
| case VTERM_PROP_MOUSE: return VTERM_VALUETYPE_INT; | ||
| } | ||
| return 0; /* UNREACHABLE */ | ||
| } | ||
|
|
||
| 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) | ||
| { | ||
| VTermRect src; | ||
| VTermRect dest; | ||
|
|
||
| if(abs(downward) >= rect.end_row - rect.start_row || | ||
| abs(rightward) >= rect.end_col - rect.start_col) { | ||
| /* Scroll more than area; just erase the lot */ | ||
| (*eraserect)(rect, 0, user); | ||
| return; | ||
| } | ||
|
|
||
| if(rightward >= 0) { | ||
| /* rect: [XXX................] | ||
| * src: [----------------] | ||
| * dest: [----------------] | ||
| */ | ||
| dest.start_col = rect.start_col; | ||
| dest.end_col = rect.end_col - rightward; | ||
| src.start_col = rect.start_col + rightward; | ||
| src.end_col = rect.end_col; | ||
| } | ||
| else { | ||
| /* rect: [................XXX] | ||
| * src: [----------------] | ||
| * dest: [----------------] | ||
| */ | ||
| int leftward = -rightward; | ||
| dest.start_col = rect.start_col + leftward; | ||
| dest.end_col = rect.end_col; | ||
| src.start_col = rect.start_col; | ||
| src.end_col = rect.end_col - leftward; | ||
| } | ||
|
|
||
| if(downward >= 0) { | ||
| dest.start_row = rect.start_row; | ||
| dest.end_row = rect.end_row - downward; | ||
| src.start_row = rect.start_row + downward; | ||
| src.end_row = rect.end_row; | ||
| } | ||
| else { | ||
| int upward = -downward; | ||
| dest.start_row = rect.start_row + upward; | ||
| dest.end_row = rect.end_row; | ||
| src.start_row = rect.start_row; | ||
| src.end_row = rect.end_row - upward; | ||
| } | ||
|
|
||
| if(moverect) | ||
| (*moverect)(dest, src, user); | ||
|
|
||
| if(downward > 0) | ||
| rect.start_row = rect.end_row - downward; | ||
| else if(downward < 0) | ||
| rect.end_row = rect.start_row - downward; | ||
|
|
||
| if(rightward > 0) | ||
| rect.start_col = rect.end_col - rightward; | ||
| else if(rightward < 0) | ||
| rect.end_col = rect.start_col - rightward; | ||
|
|
||
| (*eraserect)(rect, 0, user); | ||
| } | ||
|
|
||
| void vterm_copy_cells(VTermRect dest, | ||
| VTermRect src, | ||
| void (*copycell)(VTermPos dest, VTermPos src, void *user), | ||
| void *user) | ||
| { | ||
| int downward = src.start_row - dest.start_row; | ||
| int rightward = src.start_col - dest.start_col; | ||
|
|
||
| int init_row, test_row, init_col, test_col; | ||
| int inc_row, inc_col; | ||
|
|
||
| VTermPos pos; | ||
|
|
||
| if(downward < 0) { | ||
| init_row = dest.end_row - 1; | ||
| test_row = dest.start_row - 1; | ||
| inc_row = -1; | ||
| } | ||
| else /* downward >= 0 */ { | ||
| init_row = dest.start_row; | ||
| test_row = dest.end_row; | ||
| inc_row = +1; | ||
| } | ||
|
|
||
| if(rightward < 0) { | ||
| init_col = dest.end_col - 1; | ||
| test_col = dest.start_col - 1; | ||
| inc_col = -1; | ||
| } | ||
| else /* rightward >= 0 */ { | ||
| init_col = dest.start_col; | ||
| test_col = dest.end_col; | ||
| inc_col = +1; | ||
| } | ||
|
|
||
| for(pos.row = init_row; pos.row != test_row; pos.row += inc_row) | ||
| for(pos.col = init_col; pos.col != test_col; pos.col += inc_col) { | ||
| VTermPos srcpos; | ||
| srcpos.row = pos.row + downward; | ||
| srcpos.col = pos.col + rightward; | ||
| (*copycell)(pos, srcpos, user); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,237 @@ | ||
| #ifndef __VTERM_INTERNAL_H__ | ||
| #define __VTERM_INTERNAL_H__ | ||
|
|
||
| #include "vterm.h" | ||
|
|
||
| #include <stdarg.h> | ||
|
|
||
| #if defined(__GNUC__) | ||
| # define INTERNAL __attribute__((visibility("internal"))) | ||
| # define UNUSED __attribute__((unused)) | ||
| #else | ||
| # define INTERNAL | ||
| # define UNUSED | ||
| #endif | ||
|
|
||
| #ifdef DEBUG | ||
| # define DEBUG_LOG(s) fprintf(stderr, s) | ||
| # define DEBUG_LOG1(s, a) fprintf(stderr, s, a) | ||
| # define DEBUG_LOG2(s, a, b) fprintf(stderr, s, a, b) | ||
| # define DEBUG_LOG3(s, a, b, c) fprintf(stderr, s, a, b, c) | ||
| #else | ||
| # define DEBUG_LOG(s) | ||
| # define DEBUG_LOG1(s, a) | ||
| # define DEBUG_LOG2(s, a, b) | ||
| # define DEBUG_LOG3(s, a, b, c) | ||
| #endif | ||
|
|
||
| #define ESC_S "\x1b" | ||
|
|
||
| typedef struct VTermEncoding VTermEncoding; | ||
|
|
||
| typedef struct { | ||
| VTermEncoding *enc; | ||
|
|
||
| /* This size should be increased if required by other stateful encodings */ | ||
| char data[4*sizeof(uint32_t)]; | ||
| } VTermEncodingInstance; | ||
|
|
||
| struct VTermPen | ||
| { | ||
| VTermColor fg; | ||
| VTermColor bg; | ||
| unsigned int bold:1; | ||
| unsigned int underline:2; | ||
| unsigned int italic:1; | ||
| unsigned int blink:1; | ||
| unsigned int reverse:1; | ||
| unsigned int strike:1; | ||
| unsigned int font:4; /* To store 0-9 */ | ||
| }; | ||
|
|
||
| int vterm_color_equal(VTermColor a, VTermColor b); | ||
|
|
||
| #if defined(DEFINE_INLINES) || USE_INLINE | ||
| INLINE int vterm_color_equal(VTermColor a, VTermColor b) | ||
| { | ||
| return a.red == b.red && a.green == b.green && a.blue == b.blue; | ||
| } | ||
| #endif | ||
|
|
||
| struct VTermState | ||
| { | ||
| VTerm *vt; | ||
|
|
||
| const VTermStateCallbacks *callbacks; | ||
| void *cbdata; | ||
|
|
||
| const VTermParserCallbacks *fallbacks; | ||
| void *fbdata; | ||
|
|
||
| int rows; | ||
| int cols; | ||
|
|
||
| /* Current cursor position */ | ||
| VTermPos pos; | ||
|
|
||
| int at_phantom; /* True if we're on the "81st" phantom column to defer a wraparound */ | ||
|
|
||
| int scrollregion_top; | ||
| int scrollregion_bottom; /* -1 means unbounded */ | ||
| #define SCROLLREGION_BOTTOM(state) ((state)->scrollregion_bottom > -1 ? (state)->scrollregion_bottom : (state)->rows) | ||
| int scrollregion_left; | ||
| #define SCROLLREGION_LEFT(state) ((state)->mode.leftrightmargin ? (state)->scrollregion_left : 0) | ||
| int scrollregion_right; /* -1 means unbounded */ | ||
| #define SCROLLREGION_RIGHT(state) ((state)->mode.leftrightmargin && (state)->scrollregion_right > -1 ? (state)->scrollregion_right : (state)->cols) | ||
|
|
||
| /* Bitvector of tab stops */ | ||
| unsigned char *tabstops; | ||
|
|
||
| VTermLineInfo *lineinfo; | ||
| #define ROWWIDTH(state,row) ((state)->lineinfo[(row)].doublewidth ? ((state)->cols / 2) : (state)->cols) | ||
| #define THISROWWIDTH(state) ROWWIDTH(state, (state)->pos.row) | ||
|
|
||
| /* Mouse state */ | ||
| int mouse_col, mouse_row; | ||
| int mouse_buttons; | ||
| int mouse_flags; | ||
| #define MOUSE_WANT_CLICK 0x01 | ||
| #define MOUSE_WANT_DRAG 0x02 | ||
| #define MOUSE_WANT_MOVE 0x04 | ||
|
|
||
| enum { MOUSE_X10, MOUSE_UTF8, MOUSE_SGR, MOUSE_RXVT } mouse_protocol; | ||
|
|
||
| /* Last glyph output, for Unicode recombining purposes */ | ||
| uint32_t *combine_chars; | ||
| size_t combine_chars_size; /* Number of ELEMENTS in the above */ | ||
| int combine_width; /* The width of the glyph above */ | ||
| VTermPos combine_pos; /* Position before movement */ | ||
|
|
||
| struct { | ||
| unsigned int keypad:1; | ||
| unsigned int cursor:1; | ||
| unsigned int autowrap:1; | ||
| unsigned int insert:1; | ||
| unsigned int newline:1; | ||
| unsigned int cursor_visible:1; | ||
| unsigned int cursor_blink:1; | ||
| unsigned int cursor_shape:2; | ||
| unsigned int alt_screen:1; | ||
| unsigned int origin:1; | ||
| unsigned int screen:1; | ||
| unsigned int leftrightmargin:1; | ||
| unsigned int bracketpaste:1; | ||
| } mode; | ||
|
|
||
| VTermEncodingInstance encoding[4], encoding_utf8; | ||
| int gl_set, gr_set, gsingle_set; | ||
|
|
||
| struct VTermPen pen; | ||
|
|
||
| VTermColor default_fg; | ||
| VTermColor default_bg; | ||
| VTermColor colors[16]; /* Store the 8 ANSI and the 8 ANSI high-brights only */ | ||
|
|
||
| int fg_index; | ||
| int bg_index; | ||
| int bold_is_highbright; | ||
|
|
||
| unsigned int protected_cell : 1; | ||
|
|
||
| /* Saved state under DEC mode 1048/1049 */ | ||
| struct { | ||
| VTermPos pos; | ||
| struct VTermPen pen; | ||
|
|
||
| struct { | ||
| int cursor_visible:1; | ||
| int cursor_blink:1; | ||
| unsigned int cursor_shape:2; | ||
| } mode; | ||
| } saved; | ||
| }; | ||
|
|
||
| struct VTerm | ||
| { | ||
| VTermAllocatorFunctions *allocator; | ||
| void *allocdata; | ||
|
|
||
| int rows; | ||
| int cols; | ||
|
|
||
| struct { | ||
| unsigned int utf8:1; | ||
| unsigned int ctrl8bit:1; | ||
| } mode; | ||
|
|
||
| enum VTermParserState { | ||
| NORMAL, | ||
| CSI, | ||
| OSC, | ||
| DCS, | ||
| ESC, | ||
| ESC_IN_OSC, | ||
| ESC_IN_DCS | ||
| } parser_state; | ||
| const VTermParserCallbacks *parser_callbacks; | ||
| void *cbdata; | ||
|
|
||
| /* len == malloc()ed size; cur == number of valid bytes */ | ||
| char *strbuffer; | ||
| size_t strbuffer_len; | ||
| size_t strbuffer_cur; | ||
|
|
||
| char *outbuffer; | ||
| size_t outbuffer_len; | ||
| size_t outbuffer_cur; | ||
|
|
||
| VTermState *state; | ||
| VTermScreen *screen; | ||
| }; | ||
|
|
||
| struct VTermEncoding { | ||
| 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); | ||
| }; | ||
|
|
||
| typedef enum { | ||
| ENC_UTF8, | ||
| ENC_SINGLE_94 | ||
| } VTermEncodingType; | ||
|
|
||
| void *vterm_allocator_malloc(VTerm *vt, size_t size); | ||
| void vterm_allocator_free(VTerm *vt, void *ptr); | ||
|
|
||
| void vterm_push_output_bytes(VTerm *vt, const char *bytes, size_t len); | ||
| void vterm_push_output_vsprintf(VTerm *vt, const char *format, va_list args); | ||
| void vterm_push_output_sprintf(VTerm *vt, const char *format, ...); | ||
| void vterm_push_output_sprintf_ctrl(VTerm *vt, unsigned char ctrl, const char *fmt, ...); | ||
| void vterm_push_output_sprintf_dcs(VTerm *vt, const char *fmt, ...); | ||
|
|
||
| void vterm_state_free(VTermState *state); | ||
|
|
||
| void vterm_state_newpen(VTermState *state); | ||
| void vterm_state_resetpen(VTermState *state); | ||
| void vterm_state_setpen(VTermState *state, const long args[], int argcount); | ||
| int vterm_state_getpen(VTermState *state, long args[], int argcount); | ||
| void vterm_state_savepen(VTermState *state, int save); | ||
|
|
||
| enum { | ||
| C1_SS3 = 0x8f, | ||
| C1_DCS = 0x90, | ||
| C1_CSI = 0x9b, | ||
| C1_ST = 0x9c | ||
| }; | ||
|
|
||
| void vterm_state_push_output_sprintf_CSI(VTermState *vts, const char *format, ...); | ||
|
|
||
| void vterm_screen_free(VTermScreen *screen); | ||
|
|
||
| VTermEncoding *vterm_lookup_encoding(VTermEncodingType type, char designation); | ||
|
|
||
| int vterm_unicode_width(uint32_t codepoint); | ||
| int vterm_unicode_is_combining(uint32_t codepoint); | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,200 @@ | ||
| INIT | ||
| UTF8 0 | ||
| WANTPARSER | ||
|
|
||
| !Basic text | ||
| PUSH "hello" | ||
| text 0x68, 0x65, 0x6c, 0x6c, 0x6f | ||
|
|
||
| !C0 | ||
| PUSH "\x03" | ||
| control 3 | ||
|
|
||
| PUSH "\x1f" | ||
| control 0x1f | ||
|
|
||
| !C1 8bit | ||
| PUSH "\x83" | ||
| control 0x83 | ||
|
|
||
| PUSH "\x9f" | ||
| control 0x9f | ||
|
|
||
| !C1 7bit | ||
| PUSH "\e\x43" | ||
| control 0x83 | ||
|
|
||
| PUSH "\e\x5f" | ||
| control 0x9f | ||
|
|
||
| !High bytes | ||
| PUSH "\xa0\xcc\xfe" | ||
| text 0xa0, 0xcc, 0xfe | ||
|
|
||
| !Mixed | ||
| PUSH "1\n2" | ||
| text 0x31 | ||
| control 10 | ||
| text 0x32 | ||
|
|
||
| !Escape | ||
| PUSH "\e=" | ||
| escape "=" | ||
|
|
||
| !Escape 2-byte | ||
| PUSH "\e(X" | ||
| escape "(X" | ||
|
|
||
| !Split write Escape | ||
| PUSH "\e(" | ||
| PUSH "Y" | ||
| escape "(Y" | ||
|
|
||
| !Escape cancels Escape, starts another | ||
| PUSH "\e(\e)Z" | ||
| escape ")Z" | ||
|
|
||
| !CAN cancels Escape, returns to normal mode | ||
| PUSH "\e(\x{18}AB" | ||
| text 0x41, 0x42 | ||
|
|
||
| !C0 in Escape interrupts and continues | ||
| PUSH "\e(\nX" | ||
| control 10 | ||
| escape "(X" | ||
|
|
||
| !CSI 0 args | ||
| PUSH "\e[a" | ||
| csi 0x61 * | ||
|
|
||
| !CSI 1 arg | ||
| PUSH "\e[9b" | ||
| csi 0x62 9 | ||
|
|
||
| !CSI 2 args | ||
| PUSH "\e[3;4c" | ||
| csi 0x63 3,4 | ||
|
|
||
| !CSI 1 arg 1 sub | ||
| PUSH "\e[1:2c" | ||
| csi 0x63 1+,2 | ||
|
|
||
| !CSI many digits | ||
| PUSH "\e[678d" | ||
| csi 0x64 678 | ||
|
|
||
| !CSI leading zero | ||
| PUSH "\e[007e" | ||
| csi 0x65 7 | ||
|
|
||
| !CSI qmark | ||
| PUSH "\e[?2;7f" | ||
| csi 0x66 L=3f 2,7 | ||
|
|
||
| !CSI greater | ||
| PUSH "\e[>c" | ||
| csi 0x63 L=3e * | ||
|
|
||
| !CSI SP | ||
| PUSH "\e[12 q" | ||
| csi 0x71 12 I=20 | ||
|
|
||
| !Mixed CSI | ||
| PUSH "A\e[8mB" | ||
| text 0x41 | ||
| csi 0x6d 8 | ||
| text 0x42 | ||
|
|
||
| !Split write | ||
| PUSH "\e" | ||
| PUSH "[a" | ||
| csi 0x61 * | ||
| PUSH "foo\e[" | ||
| text 0x66, 0x6f, 0x6f | ||
| PUSH "4b" | ||
| csi 0x62 4 | ||
| PUSH "\e[12;" | ||
| PUSH "3c" | ||
| csi 0x63 12,3 | ||
|
|
||
| !Escape cancels CSI, starts Escape | ||
| PUSH "\e[123\e9" | ||
| escape "9" | ||
|
|
||
| !CAN cancels CSI, returns to normal mode | ||
| PUSH "\e[12\x{18}AB" | ||
| text 0x41, 0x42 | ||
|
|
||
| !C0 in Escape interrupts and continues | ||
| PUSH "\e[12\n;3X" | ||
| control 10 | ||
| csi 0x58 12,3 | ||
|
|
||
| !OSC BEL | ||
| PUSH "\e]1;Hello\x07" | ||
| osc "1;Hello" | ||
|
|
||
| !OSC ST (7bit) | ||
| PUSH "\e]1;Hello\e\\" | ||
| osc "1;Hello" | ||
|
|
||
| !OSC ST (8bit) | ||
| PUSH "\x{9d}1;Hello\x9c" | ||
| osc "1;Hello" | ||
|
|
||
| !Escape cancels OSC, starts Escape | ||
| PUSH "\e]Something\e9" | ||
| escape "9" | ||
|
|
||
| !CAN cancels OSC, returns to normal mode | ||
| PUSH "\e]12\x{18}AB" | ||
| text 0x41, 0x42 | ||
|
|
||
| !C0 in OSC interrupts and continues | ||
| PUSH "\e]2;\nBye\x07" | ||
| control 10 | ||
| osc "2;Bye" | ||
|
|
||
| !DCS BEL | ||
| PUSH "\ePHello\x07" | ||
| dcs "Hello" | ||
|
|
||
| !DCS ST (7bit) | ||
| PUSH "\ePHello\e\\" | ||
| dcs "Hello" | ||
|
|
||
| !DCS ST (8bit) | ||
| PUSH "\x{90}Hello\x9c" | ||
| dcs "Hello" | ||
|
|
||
| !Escape cancels DCS, starts Escape | ||
| PUSH "\ePSomething\e9" | ||
| escape "9" | ||
|
|
||
| !CAN cancels DCS, returns to normal mode | ||
| PUSH "\eP12\x{18}AB" | ||
| text 0x41, 0x42 | ||
|
|
||
| !C0 in OSC interrupts and continues | ||
| PUSH "\ePBy\ne\x07" | ||
| control 10 | ||
| dcs "Bye" | ||
|
|
||
| !NUL ignored | ||
| PUSH "\x{00}" | ||
|
|
||
| !NUL ignored within CSI | ||
| PUSH "\e[12\x{00}3m" | ||
| csi 0x6d 123 | ||
|
|
||
| !DEL ignored | ||
| PUSH "\x{7f}" | ||
|
|
||
| !DEL ignored within CSI | ||
| PUSH "\e[12\x{7f}3m" | ||
| csi 0x6d 123 | ||
|
|
||
| !DEL inside text" | ||
| PUSH "AB\x{7f}C" | ||
| text 0x41,0x42 | ||
| text 0x43 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,122 @@ | ||
| INIT | ||
| WANTENCODING | ||
|
|
||
| !Low | ||
| ENCIN "123" | ||
| encout 0x31,0x32,0x33 | ||
|
|
||
| # We want to prove the UTF-8 parser correctly handles all the sequences. | ||
| # Easy way to do this is to check it does low/high boundary cases, as that | ||
| # leaves only two for each sequence length | ||
| # | ||
| # These ranges are therefore: | ||
| # | ||
| # Two bytes: | ||
| # U+0080 = 000 10000000 => 00010 000000 | ||
| # => 11000010 10000000 = C2 80 | ||
| # U+07FF = 111 11111111 => 11111 111111 | ||
| # => 11011111 10111111 = DF BF | ||
| # | ||
| # Three bytes: | ||
| # U+0800 = 00001000 00000000 => 0000 100000 000000 | ||
| # => 11100000 10100000 10000000 = E0 A0 80 | ||
| # U+FFFD = 11111111 11111101 => 1111 111111 111101 | ||
| # => 11101111 10111111 10111101 = EF BF BD | ||
| # (We avoid U+FFFE and U+FFFF as they're invalid codepoints) | ||
| # | ||
| # Four bytes: | ||
| # U+10000 = 00001 00000000 00000000 => 000 010000 000000 000000 | ||
| # => 11110000 10010000 10000000 10000000 = F0 90 80 80 | ||
| # U+1FFFFF = 11111 11111111 11111111 => 111 111111 111111 111111 | ||
| # => 11110111 10111111 10111111 10111111 = F7 BF BF BF | ||
|
|
||
| !2 byte | ||
| ENCIN "\xC2\x80\xDF\xBF" | ||
| encout 0x0080, 0x07FF | ||
|
|
||
| !3 byte | ||
| ENCIN "\xE0\xA0\x80\xEF\xBF\xBD" | ||
| encout 0x0800,0xFFFD | ||
|
|
||
| !4 byte | ||
| ENCIN "\xF0\x90\x80\x80\xF7\xBF\xBF\xBF" | ||
| encout 0x10000,0x1fffff | ||
|
|
||
| # Next up, we check some invalid sequences | ||
| # + Early termination (back to low bytes too soon) | ||
| # + Early restart (another sequence introduction before the previous one was finished) | ||
|
|
||
| !Early termination | ||
| ENCIN "\xC2!" | ||
| encout 0xfffd,0x21 | ||
|
|
||
| ENCIN "\xE0!\xE0\xA0!" | ||
| encout 0xfffd,0x21,0xfffd,0x21 | ||
|
|
||
| ENCIN "\xF0!\xF0\x90!\xF0\x90\x80!" | ||
| encout 0xfffd,0x21,0xfffd,0x21,0xfffd,0x21 | ||
|
|
||
| !Early restart | ||
| ENCIN "\xC2\xC2\x90" | ||
| encout 0xfffd,0x0090 | ||
|
|
||
| ENCIN "\xE0\xC2\x90\xE0\xA0\xC2\x90" | ||
| encout 0xfffd,0x0090,0xfffd,0x0090 | ||
|
|
||
| ENCIN "\xF0\xC2\x90\xF0\x90\xC2\x90\xF0\x90\x80\xC2\x90" | ||
| encout 0xfffd,0x0090,0xfffd,0x0090,0xfffd,0x0090 | ||
|
|
||
| # Test the overlong sequences by giving an overlong encoding of U+0000 and | ||
| # an encoding of the highest codepoint still too short | ||
| # | ||
| # Two bytes: | ||
| # U+0000 = C0 80 | ||
| # U+007F = 000 01111111 => 00001 111111 => | ||
| # => 11000001 10111111 => C1 BF | ||
| # | ||
| # Three bytes: | ||
| # U+0000 = E0 80 80 | ||
| # U+07FF = 00000111 11111111 => 0000 011111 111111 | ||
| # => 11100000 10011111 10111111 = E0 9F BF | ||
| # | ||
| # Four bytes: | ||
| # U+0000 = F0 80 80 80 | ||
| # U+FFFF = 11111111 11111111 => 000 001111 111111 111111 | ||
| # => 11110000 10001111 10111111 10111111 = F0 8F BF BF | ||
|
|
||
| !Overlong | ||
| ENCIN "\xC0\x80\xC1\xBF" | ||
| encout 0xfffd,0xfffd | ||
|
|
||
| ENCIN "\xE0\x80\x80\xE0\x9F\xBF" | ||
| encout 0xfffd,0xfffd | ||
|
|
||
| ENCIN "\xF0\x80\x80\x80\xF0\x8F\xBF\xBF" | ||
| encout 0xfffd,0xfffd | ||
|
|
||
| # UTF-16 surrogates U+D800 and U+DFFF | ||
| !UTF-16 Surrogates | ||
| ENCIN "\xED\xA0\x80\xED\xBF\xBF" | ||
| encout 0xfffd,0xfffd | ||
|
|
||
| !Split write | ||
| ENCIN "\xC2" | ||
| ENCIN "\xA0" | ||
| encout 0x000A0 | ||
|
|
||
| ENCIN "\xE0" | ||
| ENCIN "\xA0\x80" | ||
| encout 0x00800 | ||
| ENCIN "\xE0\xA0" | ||
| ENCIN "\x80" | ||
| encout 0x00800 | ||
|
|
||
| ENCIN "\xF0" | ||
| ENCIN "\x90\x80\x80" | ||
| encout 0x10000 | ||
| ENCIN "\xF0\x90" | ||
| ENCIN "\x80\x80" | ||
| encout 0x10000 | ||
| ENCIN "\xF0\x90\x80" | ||
| ENCIN "\x80" | ||
| encout 0x10000 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| INIT | ||
| UTF8 1 | ||
| WANTSTATE g | ||
|
|
||
| !Low | ||
| RESET | ||
| PUSH "ABC" | ||
| putglyph 0x41 1 0,0 | ||
| putglyph 0x42 1 0,1 | ||
| putglyph 0x43 1 0,2 | ||
|
|
||
| !UTF-8 1 char | ||
| # U+00C1 = 0xC3 0x81 name: LATIN CAPITAL LETTER A WITH ACUTE | ||
| # U+00E9 = 0xC3 0xA9 name: LATIN SMALL LETTER E WITH ACUTE | ||
| RESET | ||
| PUSH "\xC3\x81\xC3\xA9" | ||
| putglyph 0xc1 1 0,0 | ||
| putglyph 0xe9 1 0,1 | ||
|
|
||
| !UTF-8 wide char | ||
| # U+FF10 = 0xEF 0xBC 0x90 name: FULLWIDTH DIGIT ZERO | ||
| RESET | ||
| PUSH "\xEF\xBC\x90 " | ||
| putglyph 0xff10 2 0,0 | ||
| putglyph 0x20 1 0,2 | ||
|
|
||
| !UTF-8 combining chars | ||
| # U+0301 = 0xCC 0x81 name: COMBINING ACUTE | ||
| RESET | ||
| PUSH "e\xCC\x81Z" | ||
| putglyph 0x65,0x301 1 0,0 | ||
| putglyph 0x5a 1 0,1 | ||
|
|
||
| !Combining across buffers | ||
| RESET | ||
| PUSH "e" | ||
| putglyph 0x65 1 0,0 | ||
| PUSH "\xCC\x81Z" | ||
| putglyph 0x65,0x301 1 0,0 | ||
| putglyph 0x5a 1 0,1 | ||
|
|
||
| RESET | ||
| PUSH "e" | ||
| putglyph 0x65 1 0,0 | ||
| PUSH "\xCC\x81" | ||
| putglyph 0x65,0x301 1 0,0 | ||
| PUSH "\xCC\x82" | ||
| putglyph 0x65,0x301,0x302 1 0,0 | ||
|
|
||
| !DECSCA protected | ||
| RESET | ||
| PUSH "A\e[1\"qB\e[2\"qC" | ||
| putglyph 0x41 1 0,0 | ||
| putglyph 0x42 1 0,1 prot | ||
| putglyph 0x43 1 0,2 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,224 @@ | ||
| INIT | ||
| UTF8 1 | ||
| WANTSTATE | ||
|
|
||
| !Implicit | ||
| PUSH "ABC" | ||
| ?cursor = 0,3 | ||
| !Backspace | ||
| PUSH "\b" | ||
| ?cursor = 0,2 | ||
| !Horizontal Tab | ||
| PUSH "\t" | ||
| ?cursor = 0,8 | ||
| !Carriage Return | ||
| PUSH "\r" | ||
| ?cursor = 0,0 | ||
| !Linefeed | ||
| PUSH "\n" | ||
| ?cursor = 1,0 | ||
|
|
||
| !Backspace bounded by lefthand edge | ||
| PUSH "\e[4;2H" | ||
| ?cursor = 3,1 | ||
| PUSH "\b" | ||
| ?cursor = 3,0 | ||
| PUSH "\b" | ||
| ?cursor = 3,0 | ||
|
|
||
| !Backspace cancels phantom | ||
| PUSH "\e[4;80H" | ||
| ?cursor = 3,79 | ||
| PUSH "X" | ||
| ?cursor = 3,79 | ||
| PUSH "\b" | ||
| ?cursor = 3,78 | ||
|
|
||
| !HT bounded by righthand edge | ||
| PUSH "\e[1;78H" | ||
| ?cursor = 0,77 | ||
| PUSH "\t" | ||
| ?cursor = 0,79 | ||
| PUSH "\t" | ||
| ?cursor = 0,79 | ||
|
|
||
| RESET | ||
|
|
||
| !Index | ||
| PUSH "ABC\eD" | ||
| ?cursor = 1,3 | ||
| !Reverse Index | ||
| PUSH "\eM" | ||
| ?cursor = 0,3 | ||
| !Newline | ||
| PUSH "\eE" | ||
| ?cursor = 1,0 | ||
|
|
||
| RESET | ||
|
|
||
| !Cursor Forward | ||
| PUSH "\e[B" | ||
| ?cursor = 1,0 | ||
| PUSH "\e[3B" | ||
| ?cursor = 4,0 | ||
| PUSH "\e[0B" | ||
| ?cursor = 5,0 | ||
|
|
||
| !Cursor Down | ||
| PUSH "\e[C" | ||
| ?cursor = 5,1 | ||
| PUSH "\e[3C" | ||
| ?cursor = 5,4 | ||
| PUSH "\e[0C" | ||
| ?cursor = 5,5 | ||
|
|
||
| !Cursor Up | ||
| PUSH "\e[A" | ||
| ?cursor = 4,5 | ||
| PUSH "\e[3A" | ||
| ?cursor = 1,5 | ||
| PUSH "\e[0A" | ||
| ?cursor = 0,5 | ||
|
|
||
| !Cursor Backward | ||
| PUSH "\e[D" | ||
| ?cursor = 0,4 | ||
| PUSH "\e[3D" | ||
| ?cursor = 0,1 | ||
| PUSH "\e[0D" | ||
| ?cursor = 0,0 | ||
|
|
||
| !Cursor Next Line | ||
| PUSH " " | ||
| ?cursor = 0,3 | ||
| PUSH "\e[E" | ||
| ?cursor = 1,0 | ||
| PUSH " " | ||
| ?cursor = 1,3 | ||
| PUSH "\e[2E" | ||
| ?cursor = 3,0 | ||
| PUSH "\e[0E" | ||
| ?cursor = 4,0 | ||
|
|
||
| !Cursor Previous Line | ||
| PUSH " " | ||
| ?cursor = 4,3 | ||
| PUSH "\e[F" | ||
| ?cursor = 3,0 | ||
| PUSH " " | ||
| ?cursor = 3,3 | ||
| PUSH "\e[2F" | ||
| ?cursor = 1,0 | ||
| PUSH "\e[0F" | ||
| ?cursor = 0,0 | ||
|
|
||
| !Cursor Horizonal Absolute | ||
| PUSH "\n" | ||
| ?cursor = 1,0 | ||
| PUSH "\e[20G" | ||
| ?cursor = 1,19 | ||
| PUSH "\e[G" | ||
| ?cursor = 1,0 | ||
|
|
||
| !Cursor Position | ||
| PUSH "\e[10;5H" | ||
| ?cursor = 9,4 | ||
| PUSH "\e[8H" | ||
| ?cursor = 7,0 | ||
| PUSH "\e[H" | ||
| ?cursor = 0,0 | ||
|
|
||
| !Cursor Position cancels phantom | ||
| PUSH "\e[10;78H" | ||
| ?cursor = 9,77 | ||
| PUSH "ABC" | ||
| ?cursor = 9,79 | ||
| PUSH "\e[10;80H" | ||
| PUSH "C" | ||
| ?cursor = 9,79 | ||
| PUSH "X" | ||
| ?cursor = 10,1 | ||
|
|
||
| RESET | ||
|
|
||
| !Bounds Checking | ||
| PUSH "\e[A" | ||
| ?cursor = 0,0 | ||
| PUSH "\e[D" | ||
| ?cursor = 0,0 | ||
| PUSH "\e[25;80H" | ||
| ?cursor = 24,79 | ||
| PUSH "\e[B" | ||
| ?cursor = 24,79 | ||
| PUSH "\e[C" | ||
| ?cursor = 24,79 | ||
| PUSH "\e[E" | ||
| ?cursor = 24,0 | ||
| PUSH "\e[H" | ||
| ?cursor = 0,0 | ||
| PUSH "\e[F" | ||
| ?cursor = 0,0 | ||
| PUSH "\e[999G" | ||
| ?cursor = 0,79 | ||
| PUSH "\e[99;99H" | ||
| ?cursor = 24,79 | ||
|
|
||
| RESET | ||
|
|
||
| !Horizontal Position Absolute | ||
| PUSH "\e[5`" | ||
| ?cursor = 0,4 | ||
|
|
||
| !Horizontal Position Relative | ||
| PUSH "\e[3a" | ||
| ?cursor = 0,7 | ||
|
|
||
| !Horizontal Position Backward | ||
| PUSH "\e[3j" | ||
| ?cursor = 0,4 | ||
|
|
||
| !Horizontal and Vertical Position | ||
| PUSH "\e[3;3f" | ||
| ?cursor = 2,2 | ||
|
|
||
| !Vertical Position Absolute | ||
| PUSH "\e[5d" | ||
| ?cursor = 4,2 | ||
|
|
||
| !Vertical Position Relative | ||
| PUSH "\e[2e" | ||
| ?cursor = 6,2 | ||
|
|
||
| !Vertical Position Backward | ||
| PUSH "\e[2k" | ||
| ?cursor = 4,2 | ||
|
|
||
| RESET | ||
|
|
||
| !Horizontal Tab | ||
| PUSH "\t" | ||
| ?cursor = 0,8 | ||
| PUSH " " | ||
| ?cursor = 0,11 | ||
| PUSH "\t" | ||
| ?cursor = 0,16 | ||
| PUSH " " | ||
| ?cursor = 0,23 | ||
| PUSH "\t" | ||
| ?cursor = 0,24 | ||
| PUSH " " | ||
| ?cursor = 0,32 | ||
| PUSH "\t" | ||
| ?cursor = 0,40 | ||
|
|
||
| !Cursor Horizontal Tab | ||
| PUSH "\e[I" | ||
| ?cursor = 0,48 | ||
| PUSH "\e[2I" | ||
| ?cursor = 0,64 | ||
|
|
||
| !Cursor Backward Tab | ||
| PUSH "\e[Z" | ||
| ?cursor = 0,56 | ||
| PUSH "\e[2Z" | ||
| ?cursor = 0,40 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,150 @@ | ||
| INIT | ||
| UTF8 1 | ||
| WANTSTATE s | ||
|
|
||
| !Linefeed | ||
| PUSH "\n"x24 | ||
| ?cursor = 24,0 | ||
| PUSH "\n" | ||
| scrollrect 0..25,0..80 => +1,+0 | ||
| ?cursor = 24,0 | ||
|
|
||
| RESET | ||
|
|
||
| !Index | ||
| PUSH "\e[25H" | ||
| PUSH "\eD" | ||
| scrollrect 0..25,0..80 => +1,+0 | ||
|
|
||
| RESET | ||
|
|
||
| !Reverse Index | ||
| PUSH "\eM" | ||
| scrollrect 0..25,0..80 => -1,+0 | ||
|
|
||
| RESET | ||
|
|
||
| !Linefeed in DECSTBM | ||
| PUSH "\e[1;10r" | ||
| ?cursor = 0,0 | ||
| PUSH "\n"x9 | ||
| ?cursor = 9,0 | ||
| PUSH "\n" | ||
| scrollrect 0..10,0..80 => +1,+0 | ||
| ?cursor = 9,0 | ||
|
|
||
| !Linefeed outside DECSTBM | ||
| PUSH "\e[20H" | ||
| ?cursor = 19,0 | ||
| PUSH "\n" | ||
| ?cursor = 20,0 | ||
|
|
||
| !Index in DECSTBM | ||
| PUSH "\e[10H" | ||
| PUSH "\e[9;10r" | ||
| PUSH "\eM" | ||
| ?cursor = 8,0 | ||
| PUSH "\eM" | ||
| scrollrect 8..10,0..80 => -1,+0 | ||
|
|
||
| !Reverse Index in DECSTBM | ||
| PUSH "\e[25H" | ||
| ?cursor = 24,0 | ||
| PUSH "\n" | ||
| # no scrollrect | ||
| ?cursor = 24,0 | ||
|
|
||
| !Linefeed in DECSTBM+DECSLRM | ||
| PUSH "\e[?69h" | ||
| PUSH "\e[3;10r\e[10;40s" | ||
| PUSH "\e[10;10H\n" | ||
| scrollrect 2..10,9..40 => +1,+0 | ||
|
|
||
| !IND/RI in DECSTBM+DECSLRM | ||
| PUSH "\eD" | ||
| scrollrect 2..10,9..40 => +1,+0 | ||
| PUSH "\e[3;10H\eM" | ||
| scrollrect 2..10,9..40 => -1,+0 | ||
|
|
||
| !DECRQSS on DECSTBM | ||
| PUSH "\eP\$qr\e\\" | ||
| output "\eP1\$r3;10r\e\\" | ||
|
|
||
| !DECRQSS on DECSLRM | ||
| PUSH "\eP\$qs\e\\" | ||
| output "\eP1\$r10;40s\e\\" | ||
|
|
||
| !Setting invalid DECSLRM with !DECVSSM is still rejected | ||
| PUSH "\e[?69l\e[;0s\e[?69h" | ||
|
|
||
| RESET | ||
|
|
||
| !Scroll Down | ||
| PUSH "\e[S" | ||
| scrollrect 0..25,0..80 => +1,+0 | ||
| ?cursor = 0,0 | ||
| PUSH "\e[2S" | ||
| scrollrect 0..25,0..80 => +2,+0 | ||
| ?cursor = 0,0 | ||
| PUSH "\e[100S" | ||
| scrollrect 0..25,0..80 => +25,+0 | ||
|
|
||
| !Scroll Up | ||
| PUSH "\e[T" | ||
| scrollrect 0..25,0..80 => -1,+0 | ||
| ?cursor = 0,0 | ||
| PUSH "\e[2T" | ||
| scrollrect 0..25,0..80 => -2,+0 | ||
| ?cursor = 0,0 | ||
| PUSH "\e[100T" | ||
| scrollrect 0..25,0..80 => -25,+0 | ||
|
|
||
| !SD/SU in DECSTBM | ||
| PUSH "\e[5;20r" | ||
| PUSH "\e[S" | ||
| scrollrect 4..20,0..80 => +1,+0 | ||
| PUSH "\e[T" | ||
| scrollrect 4..20,0..80 => -1,+0 | ||
|
|
||
| RESET | ||
|
|
||
| !SD/SU in DECSTBM+DECSLRM | ||
| PUSH "\e[?69h" | ||
| PUSH "\e[3;10r\e[10;40s" | ||
| ?cursor = 0,0 | ||
| PUSH "\e[3;10H" | ||
| ?cursor = 2,9 | ||
| PUSH "\e[S" | ||
| scrollrect 2..10,9..40 => +1,+0 | ||
| PUSH "\e[?69l" | ||
| PUSH "\e[S" | ||
| scrollrect 2..10,0..80 => +1,+0 | ||
|
|
||
| !Invalid boundaries | ||
| RESET | ||
|
|
||
| PUSH "\e[100;105r\eD" | ||
| PUSH "\e[5;2r\eD" | ||
|
|
||
| RESET | ||
| WANTSTATE -s+me | ||
|
|
||
| !Scroll Down move+erase emulation | ||
| PUSH "\e[S" | ||
| moverect 1..25,0..80 -> 0..24,0..80 | ||
| erase 24..25,0..80 | ||
| ?cursor = 0,0 | ||
| PUSH "\e[2S" | ||
| moverect 2..25,0..80 -> 0..23,0..80 | ||
| erase 23..25,0..80 | ||
| ?cursor = 0,0 | ||
|
|
||
| !Scroll Up move+erase emulation | ||
| PUSH "\e[T" | ||
| moverect 0..24,0..80 -> 1..25,0..80 | ||
| erase 0..1,0..80 | ||
| ?cursor = 0,0 | ||
| PUSH "\e[2T" | ||
| moverect 0..23,0..80 -> 2..25,0..80 | ||
| erase 0..2,0..80 | ||
| ?cursor = 0,0 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,300 @@ | ||
| INIT | ||
| UTF8 1 | ||
| WANTSTATE se | ||
|
|
||
| !ICH | ||
| RESET | ||
| erase 0..25,0..80 | ||
| ?cursor = 0,0 | ||
| PUSH "ACD" | ||
| PUSH "\e[2D" | ||
| ?cursor = 0,1 | ||
| PUSH "\e[@" | ||
| scrollrect 0..1,1..80 => +0,-1 | ||
| ?cursor = 0,1 | ||
| PUSH "B" | ||
| ?cursor = 0,2 | ||
| PUSH "\e[3@" | ||
| scrollrect 0..1,2..80 => +0,-3 | ||
|
|
||
| !ICH with DECSLRM | ||
| PUSH "\e[?69h" | ||
| PUSH "\e[;50s" | ||
| PUSH "\e[20G\e[@" | ||
| scrollrect 0..1,19..50 => +0,-1 | ||
|
|
||
| !ICH outside DECSLRM | ||
| PUSH "\e[70G\e[@" | ||
| # nothing happens | ||
|
|
||
| !DCH | ||
| RESET | ||
| erase 0..25,0..80 | ||
| ?cursor = 0,0 | ||
| PUSH "ABBC" | ||
| PUSH "\e[3D" | ||
| ?cursor = 0,1 | ||
| PUSH "\e[P" | ||
| scrollrect 0..1,1..80 => +0,+1 | ||
| ?cursor = 0,1 | ||
| PUSH "\e[3P" | ||
| scrollrect 0..1,1..80 => +0,+3 | ||
| ?cursor = 0,1 | ||
|
|
||
| !DCH with DECSLRM | ||
| PUSH "\e[?69h" | ||
| PUSH "\e[;50s" | ||
| PUSH "\e[20G\e[P" | ||
| scrollrect 0..1,19..50 => +0,+1 | ||
|
|
||
| !DCH outside DECSLRM | ||
| PUSH "\e[70G\e[P" | ||
| # nothing happens | ||
|
|
||
| !ECH | ||
| RESET | ||
| erase 0..25,0..80 | ||
| ?cursor = 0,0 | ||
| PUSH "ABC" | ||
| PUSH "\e[2D" | ||
| ?cursor = 0,1 | ||
| PUSH "\e[X" | ||
| erase 0..1,1..2 | ||
| ?cursor = 0,1 | ||
| PUSH "\e[3X" | ||
| erase 0..1,1..4 | ||
| ?cursor = 0,1 | ||
| # ECH more columns than there are should be bounded | ||
| PUSH "\e[100X" | ||
| erase 0..1,1..80 | ||
|
|
||
| !IL | ||
| RESET | ||
| erase 0..25,0..80 | ||
| ?cursor = 0,0 | ||
| PUSH "A\r\nC" | ||
| ?cursor = 1,1 | ||
| PUSH "\e[L" | ||
| scrollrect 1..25,0..80 => -1,+0 | ||
| # TODO: ECMA-48 says we should move to line home, but neither xterm nor | ||
| # xfce4-terminal do this | ||
| ?cursor = 1,1 | ||
| PUSH "\rB" | ||
| ?cursor = 1,1 | ||
| PUSH "\e[3L" | ||
| scrollrect 1..25,0..80 => -3,+0 | ||
|
|
||
| !IL with DECSTBM | ||
| PUSH "\e[5;15r" | ||
| PUSH "\e[5H\e[L" | ||
| scrollrect 4..15,0..80 => -1,+0 | ||
|
|
||
| !IL outside DECSTBM | ||
| PUSH "\e[20H\e[L" | ||
| # nothing happens | ||
|
|
||
| !IL with DECSTBM+DECSLRM | ||
| PUSH "\e[?69h" | ||
| PUSH "\e[10;50s" | ||
| PUSH "\e[5;10H\e[L" | ||
| scrollrect 4..15,9..50 => -1,+0 | ||
|
|
||
| !DL | ||
| RESET | ||
| erase 0..25,0..80 | ||
| ?cursor = 0,0 | ||
| PUSH "A\r\nB\r\nB\r\nC" | ||
| ?cursor = 3,1 | ||
| PUSH "\e[2H" | ||
| ?cursor = 1,0 | ||
| PUSH "\e[M" | ||
| scrollrect 1..25,0..80 => +1,+0 | ||
| ?cursor = 1,0 | ||
| PUSH "\e[3M" | ||
| scrollrect 1..25,0..80 => +3,+0 | ||
| ?cursor = 1,0 | ||
|
|
||
| !DL with DECSTBM | ||
| PUSH "\e[5;15r" | ||
| PUSH "\e[5H\e[M" | ||
| scrollrect 4..15,0..80 => +1,+0 | ||
|
|
||
| !DL outside DECSTBM | ||
| PUSH "\e[20H\e[M" | ||
| # nothing happens | ||
|
|
||
| !DL with DECSTBM+DECSLRM | ||
| PUSH "\e[?69h" | ||
| PUSH "\e[10;50s" | ||
| PUSH "\e[5;10H\e[M" | ||
| scrollrect 4..15,9..50 => +1,+0 | ||
|
|
||
| !DECIC | ||
| RESET | ||
| erase 0..25,0..80 | ||
| PUSH "\e[20G\e[5'}" | ||
| scrollrect 0..25,19..80 => +0,-5 | ||
|
|
||
| !DECIC with DECSTBM+DECSLRM | ||
| PUSH "\e[?69h" | ||
| PUSH "\e[4;20r\e[20;60s" | ||
| PUSH "\e[4;20H\e[3'}" | ||
| scrollrect 3..20,19..60 => +0,-3 | ||
|
|
||
| !DECIC outside DECSLRM | ||
| PUSH "\e[70G\e['}" | ||
| # nothing happens | ||
|
|
||
| !DECDC | ||
| RESET | ||
| erase 0..25,0..80 | ||
| PUSH "\e[20G\e[5'~" | ||
| scrollrect 0..25,19..80 => +0,+5 | ||
|
|
||
| !DECDC with DECSTBM+DECSLRM | ||
| PUSH "\e[?69h" | ||
| PUSH "\e[4;20r\e[20;60s" | ||
| PUSH "\e[4;20H\e[3'~" | ||
| scrollrect 3..20,19..60 => +0,+3 | ||
|
|
||
| !DECDC outside DECSLRM | ||
| PUSH "\e[70G\e['~" | ||
| # nothing happens | ||
|
|
||
| !EL 0 | ||
| RESET | ||
| erase 0..25,0..80 | ||
| ?cursor = 0,0 | ||
| PUSH "ABCDE" | ||
| PUSH "\e[3D" | ||
| ?cursor = 0,2 | ||
| PUSH "\e[0K" | ||
| erase 0..1,2..80 | ||
| ?cursor = 0,2 | ||
|
|
||
| !EL 1 | ||
| RESET | ||
| erase 0..25,0..80 | ||
| ?cursor = 0,0 | ||
| PUSH "ABCDE" | ||
| PUSH "\e[3D" | ||
| ?cursor = 0,2 | ||
| PUSH "\e[1K" | ||
| erase 0..1,0..3 | ||
| ?cursor = 0,2 | ||
|
|
||
| !EL 2 | ||
| RESET | ||
| erase 0..25,0..80 | ||
| ?cursor = 0,0 | ||
| PUSH "ABCDE" | ||
| PUSH "\e[3D" | ||
| ?cursor = 0,2 | ||
| PUSH "\e[2K" | ||
| erase 0..1,0..80 | ||
| ?cursor = 0,2 | ||
|
|
||
| !SEL | ||
| RESET | ||
| erase 0..25,0..80 | ||
| ?cursor = 0,0 | ||
| PUSH "\e[11G" | ||
| ?cursor = 0,10 | ||
| PUSH "\e[?0K" | ||
| erase 0..1,10..80 selective | ||
| ?cursor = 0,10 | ||
| PUSH "\e[?1K" | ||
| erase 0..1,0..11 selective | ||
| ?cursor = 0,10 | ||
| PUSH "\e[?2K" | ||
| erase 0..1,0..80 selective | ||
| ?cursor = 0,10 | ||
|
|
||
| !ED 0 | ||
| RESET | ||
| erase 0..25,0..80 | ||
| ?cursor = 0,0 | ||
| PUSH "\e[2;2H" | ||
| ?cursor = 1,1 | ||
| PUSH "\e[0J" | ||
| erase 1..2,1..80 | ||
| erase 2..25,0..80 | ||
| ?cursor = 1,1 | ||
|
|
||
| !ED 1 | ||
| RESET | ||
| erase 0..25,0..80 | ||
| ?cursor = 0,0 | ||
| PUSH "\e[2;2H" | ||
| ?cursor = 1,1 | ||
| PUSH "\e[1J" | ||
| erase 0..1,0..80 | ||
| erase 1..2,0..2 | ||
| ?cursor = 1,1 | ||
|
|
||
| !ED 2 | ||
| RESET | ||
| erase 0..25,0..80 | ||
| ?cursor = 0,0 | ||
| PUSH "\e[2;2H" | ||
| ?cursor = 1,1 | ||
| PUSH "\e[2J" | ||
| erase 0..25,0..80 | ||
| ?cursor = 1,1 | ||
|
|
||
| !SED | ||
| RESET | ||
| erase 0..25,0..80 | ||
| PUSH "\e[5;5H" | ||
| ?cursor = 4,4 | ||
| PUSH "\e[?0J" | ||
| erase 4..5,4..80 selective | ||
| erase 5..25,0..80 selective | ||
| ?cursor = 4,4 | ||
| PUSH "\e[?1J" | ||
| erase 0..4,0..80 selective | ||
| erase 4..5,0..5 selective | ||
| ?cursor = 4,4 | ||
| PUSH "\e[?2J" | ||
| erase 0..25,0..80 selective | ||
| ?cursor = 4,4 | ||
|
|
||
| !DECRQSS on DECSCA | ||
| PUSH "\e[2\"q" | ||
| PUSH "\eP\$q\"q\e\\" | ||
| output "\eP1\$r2\"q\e\\" | ||
|
|
||
| WANTSTATE -s+m | ||
|
|
||
| !ICH move+erase emuation | ||
| RESET | ||
| erase 0..25,0..80 | ||
| ?cursor = 0,0 | ||
| PUSH "ACD" | ||
| PUSH "\e[2D" | ||
| ?cursor = 0,1 | ||
| PUSH "\e[@" | ||
| moverect 0..1,1..79 -> 0..1,2..80 | ||
| erase 0..1,1..2 | ||
| ?cursor = 0,1 | ||
| PUSH "B" | ||
| ?cursor = 0,2 | ||
| PUSH "\e[3@" | ||
| moverect 0..1,2..77 -> 0..1,5..80 | ||
| erase 0..1,2..5 | ||
|
|
||
| !DCH move+erase emulation | ||
| RESET | ||
| erase 0..25,0..80 | ||
| ?cursor = 0,0 | ||
| PUSH "ABBC" | ||
| PUSH "\e[3D" | ||
| ?cursor = 0,1 | ||
| PUSH "\e[P" | ||
| moverect 0..1,2..80 -> 0..1,1..79 | ||
| erase 0..1,79..80 | ||
| ?cursor = 0,1 | ||
| PUSH "\e[3P" | ||
| moverect 0..1,4..80 -> 0..1,1..77 | ||
| erase 0..1,77..80 | ||
| ?cursor = 0,1 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,105 @@ | ||
| INIT | ||
| WANTSTATE g | ||
|
|
||
| !Default | ||
| RESET | ||
| PUSH "#" | ||
| putglyph 0x23 1 0,0 | ||
|
|
||
| !Designate G0=UK | ||
| RESET | ||
| PUSH "\e(A" | ||
| PUSH "#" | ||
| putglyph 0x00a3 1 0,0 | ||
|
|
||
| !Designate G0=DEC drawing | ||
| RESET | ||
| PUSH "\e(0" | ||
| PUSH "a" | ||
| putglyph 0x2592 1 0,0 | ||
|
|
||
| !Designate G1 + LS1 | ||
| RESET | ||
| PUSH "\e)0" | ||
| PUSH "a" | ||
| putglyph 0x61 1 0,0 | ||
| PUSH "\x0e" | ||
| PUSH "a" | ||
| putglyph 0x2592 1 0,1 | ||
| !LS0 | ||
| PUSH "\x0f" | ||
| PUSH "a" | ||
| putglyph 0x61 1 0,2 | ||
|
|
||
| !Designate G2 + LS2 | ||
| PUSH "\e*0" | ||
| PUSH "a" | ||
| putglyph 0x61 1 0,3 | ||
| PUSH "\en" | ||
| PUSH "a" | ||
| putglyph 0x2592 1 0,4 | ||
| PUSH "\x0f" | ||
| PUSH "a" | ||
| putglyph 0x61 1 0,5 | ||
|
|
||
| !Designate G3 + LS3 | ||
| PUSH "\e+0" | ||
| PUSH "a" | ||
| putglyph 0x61 1 0,6 | ||
| PUSH "\eo" | ||
| PUSH "a" | ||
| putglyph 0x2592 1 0,7 | ||
| PUSH "\x0f" | ||
| PUSH "a" | ||
| putglyph 0x61 1 0,8 | ||
|
|
||
| !SS2 | ||
| PUSH "a\x{8e}aa" | ||
| putglyph 0x61 1 0,9 | ||
| putglyph 0x2592 1 0,10 | ||
| putglyph 0x61 1 0,11 | ||
|
|
||
| !SS3 | ||
| PUSH "a\x{8f}aa" | ||
| putglyph 0x61 1 0,12 | ||
| putglyph 0x2592 1 0,13 | ||
| putglyph 0x61 1 0,14 | ||
|
|
||
| !LS1R | ||
| RESET | ||
| PUSH "\e~" | ||
| PUSH "\xe1" | ||
| putglyph 0x61 1 0,0 | ||
| PUSH "\e)0" | ||
| PUSH "\xe1" | ||
| putglyph 0x2592 1 0,1 | ||
|
|
||
| !LS2R | ||
| RESET | ||
| PUSH "\e}" | ||
| PUSH "\xe1" | ||
| putglyph 0x61 1 0,0 | ||
| PUSH "\e*0" | ||
| PUSH "\xe1" | ||
| putglyph 0x2592 1 0,1 | ||
|
|
||
| !LS3R | ||
| RESET | ||
| PUSH "\e|" | ||
| PUSH "\xe1" | ||
| putglyph 0x61 1 0,0 | ||
| PUSH "\e+0" | ||
| PUSH "\xe1" | ||
| putglyph 0x2592 1 0,1 | ||
|
|
||
| UTF8 1 | ||
|
|
||
| !Mixed US-ASCII and UTF-8 | ||
| # U+0108 == 0xc4 0x88 | ||
| RESET | ||
| PUSH "\e(B" | ||
| PUSH "AB\xc4\x88D" | ||
| putglyph 0x0041 1 0,0 | ||
| putglyph 0x0042 1 0,1 | ||
| putglyph 0x0108 1 0,2 | ||
| putglyph 0x0044 1 0,3 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,86 @@ | ||
| INIT | ||
| UTF8 1 | ||
| WANTSTATE gme | ||
|
|
||
| !Insert/Replace Mode | ||
| RESET | ||
| erase 0..25,0..80 | ||
| ?cursor = 0,0 | ||
| PUSH "AC\e[DB" | ||
| putglyph 0x41 1 0,0 | ||
| putglyph 0x43 1 0,1 | ||
| putglyph 0x42 1 0,1 | ||
| PUSH "\e[4h" | ||
| PUSH "\e[G" | ||
| PUSH "AC\e[DB" | ||
| moverect 0..1,0..79 -> 0..1,1..80 | ||
| erase 0..1,0..1 | ||
| putglyph 0x41 1 0,0 | ||
| moverect 0..1,1..79 -> 0..1,2..80 | ||
| erase 0..1,1..2 | ||
| putglyph 0x43 1 0,1 | ||
| moverect 0..1,1..79 -> 0..1,2..80 | ||
| erase 0..1,1..2 | ||
| putglyph 0x42 1 0,1 | ||
|
|
||
| !Insert mode only happens once for UTF-8 combining | ||
| PUSH "e" | ||
| moverect 0..1,2..79 -> 0..1,3..80 | ||
| erase 0..1,2..3 | ||
| putglyph 0x65 1 0,2 | ||
| PUSH "\xCC\x81" | ||
| putglyph 0x65,0x301 1 0,2 | ||
|
|
||
| !Newline/Linefeed mode | ||
| RESET | ||
| erase 0..25,0..80 | ||
| ?cursor = 0,0 | ||
| PUSH "\e[5G\n" | ||
| ?cursor = 1,4 | ||
| PUSH "\e[20h" | ||
| PUSH "\e[5G\n" | ||
| ?cursor = 2,0 | ||
|
|
||
| !DEC origin mode | ||
| RESET | ||
| erase 0..25,0..80 | ||
| ?cursor = 0,0 | ||
| PUSH "\e[5;15r" | ||
| PUSH "\e[H" | ||
| ?cursor = 0,0 | ||
| PUSH "\e[3;3H" | ||
| ?cursor = 2,2 | ||
| PUSH "\e[?6h" | ||
| PUSH "\e[H" | ||
| ?cursor = 4,0 | ||
| PUSH "\e[3;3H" | ||
| ?cursor = 6,2 | ||
|
|
||
| !DECRQM on DECOM | ||
| PUSH "\e[?6h" | ||
| PUSH "\e[?6\$p" | ||
| output "\e[?6;1\$y" | ||
| PUSH "\e[?6l" | ||
| PUSH "\e[?6\$p" | ||
| output "\e[?6;2\$y" | ||
|
|
||
| !Origin mode with DECSLRM | ||
| PUSH "\e[?6h" | ||
| PUSH "\e[?69h" | ||
| PUSH "\e[20;60s" | ||
| PUSH "\e[H" | ||
| ?cursor = 4,19 | ||
|
|
||
| PUSH "\e[?69l" | ||
|
|
||
| !Origin mode bounds cursor to scrolling region | ||
| PUSH "\e[H" | ||
| PUSH "\e[10A" | ||
| ?cursor = 4,0 | ||
| PUSH "\e[20B" | ||
| ?cursor = 14,0 | ||
|
|
||
| !Origin mode without scroll region | ||
| PUSH "\e[?6l" | ||
| PUSH "\e[r\e[?6h" | ||
| ?cursor = 0,0 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| INIT | ||
| WANTSTATE g | ||
|
|
||
| !Placement | ||
| RESET | ||
| PUSH "AB\e[79GCDE" | ||
| putglyph 0x41 1 0,0 | ||
| putglyph 0x42 1 0,1 | ||
| putglyph 0x43 1 0,78 | ||
| putglyph 0x44 1 0,79 | ||
| putglyph 0x45 1 1,0 | ||
|
|
||
| !Resize | ||
| RESET | ||
| RESIZE 27,85 | ||
| PUSH "AB\e[79GCDE" | ||
| putglyph 0x41 1 0,0 | ||
| putglyph 0x42 1 0,1 | ||
| putglyph 0x43 1 0,78 | ||
| putglyph 0x44 1 0,79 | ||
| putglyph 0x45 1 0,80 | ||
| ?cursor = 0,81 | ||
|
|
||
| !Resize without reset | ||
| RESIZE 28,90 | ||
| ?cursor = 0,81 | ||
| PUSH "FGHI" | ||
| putglyph 0x46 1 0,81 | ||
| putglyph 0x47 1 0,82 | ||
| putglyph 0x48 1 0,83 | ||
| putglyph 0x49 1 0,84 | ||
| ?cursor = 0,85 | ||
|
|
||
| !Resize shrink moves cursor | ||
| RESIZE 25,80 | ||
| ?cursor = 0,79 | ||
|
|
||
| !Resize grow doesn't cancel phantom | ||
| RESET | ||
| PUSH "\e[79GAB" | ||
| putglyph 0x41 1 0,78 | ||
| putglyph 0x42 1 0,79 | ||
| ?cursor = 0,79 | ||
| RESIZE 30,100 | ||
| ?cursor = 0,80 | ||
| PUSH "C" | ||
| putglyph 0x43 1 0,80 | ||
| ?cursor = 0,81 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,172 @@ | ||
| INIT | ||
| WANTSTATE p | ||
|
|
||
| !DECRQM on with mouse off | ||
| PUSH "\e[?1000\$p" | ||
| output "\e[?1000;2\$y" | ||
| PUSH "\e[?1002\$p" | ||
| output "\e[?1002;2\$y" | ||
| PUSH "\e[?1003\$p" | ||
| output "\e[?1003;2\$y" | ||
|
|
||
| !Mouse in simple button report mode | ||
| RESET | ||
| settermprop 1 true | ||
| settermprop 2 true | ||
| settermprop 7 1 | ||
| PUSH "\e[?1000h" | ||
| settermprop 8 1 | ||
|
|
||
| !Press 1 | ||
| MOUSEMOVE 0,0 0 | ||
| MOUSEBTN d 1 0 | ||
| output "\e[M\x20\x21\x21" | ||
|
|
||
| !Release 1 | ||
| MOUSEBTN u 1 0 | ||
| output "\e[M\x23\x21\x21" | ||
|
|
||
| !Ctrl-Press 1 | ||
| MOUSEBTN d 1 C | ||
| output "\e[M\x30\x21\x21" | ||
| MOUSEBTN u 1 C | ||
| output "\e[M\x33\x21\x21" | ||
|
|
||
| !Button 2 | ||
| MOUSEBTN d 2 0 | ||
| output "\e[M\x21\x21\x21" | ||
| MOUSEBTN u 2 0 | ||
| output "\e[M\x23\x21\x21" | ||
|
|
||
| !Position | ||
| MOUSEMOVE 10,20 0 | ||
| MOUSEBTN d 1 0 | ||
| output "\e[M\x20\x35\x2b" | ||
|
|
||
| MOUSEBTN u 1 0 | ||
| output "\e[M\x23\x35\x2b" | ||
| MOUSEMOVE 10,21 0 | ||
| # no output | ||
|
|
||
| !Wheel events | ||
| MOUSEBTN d 4 0 | ||
| output "\e[M\x60\x36\x2b" | ||
| MOUSEBTN d 4 0 | ||
| output "\e[M\x60\x36\x2b" | ||
| MOUSEBTN d 5 0 | ||
| output "\e[M\x61\x36\x2b" | ||
|
|
||
| !DECRQM on mouse button mode | ||
| PUSH "\e[?1000\$p" | ||
| output "\e[?1000;1\$y" | ||
| PUSH "\e[?1002\$p" | ||
| output "\e[?1002;2\$y" | ||
| PUSH "\e[?1003\$p" | ||
| output "\e[?1003;2\$y" | ||
|
|
||
| !Drag events | ||
| RESET | ||
| settermprop 1 true | ||
| settermprop 2 true | ||
| settermprop 7 1 | ||
| PUSH "\e[?1002h" | ||
| settermprop 8 2 | ||
|
|
||
| MOUSEMOVE 5,5 0 | ||
| MOUSEBTN d 1 0 | ||
| output "\e[M\x20\x26\x26" | ||
| MOUSEMOVE 5,6 0 | ||
| output "\e[M\x40\x27\x26" | ||
| MOUSEMOVE 6,6 0 | ||
| output "\e[M\x40\x27\x27" | ||
| MOUSEMOVE 6,6 0 | ||
| # no output | ||
| MOUSEBTN u 1 0 | ||
| output "\e[M\x23\x27\x27" | ||
| MOUSEMOVE 6,7 | ||
| # no output | ||
|
|
||
| !DECRQM on mouse drag mode | ||
| PUSH "\e[?1000\$p" | ||
| output "\e[?1000;2\$y" | ||
| PUSH "\e[?1002\$p" | ||
| output "\e[?1002;1\$y" | ||
| PUSH "\e[?1003\$p" | ||
| output "\e[?1003;2\$y" | ||
|
|
||
| !Non-drag motion events | ||
| PUSH "\e[?1003h" | ||
| settermprop 8 3 | ||
|
|
||
| MOUSEMOVE 6,8 0 | ||
| output "\e[M\x43\x29\x27" | ||
|
|
||
| !DECRQM on mouse motion mode | ||
| PUSH "\e[?1000\$p" | ||
| output "\e[?1000;2\$y" | ||
| PUSH "\e[?1002\$p" | ||
| output "\e[?1002;2\$y" | ||
| PUSH "\e[?1003\$p" | ||
| output "\e[?1003;1\$y" | ||
|
|
||
| !Bounds checking | ||
| MOUSEMOVE 300,300 0 | ||
| output "\e[M\x43\xff\xff" | ||
| MOUSEBTN d 1 0 | ||
| output "\e[M\x20\xff\xff" | ||
| MOUSEBTN u 1 0 | ||
| output "\e[M\x23\xff\xff" | ||
|
|
||
| !DECRQM on standard encoding mode | ||
| PUSH "\e[?1005\$p" | ||
| output "\e[?1005;2\$y" | ||
| PUSH "\e[?1006\$p" | ||
| output "\e[?1006;2\$y" | ||
| PUSH "\e[?1015\$p" | ||
| output "\e[?1015;2\$y" | ||
|
|
||
| !UTF-8 extended encoding mode | ||
| # 300 + 32 + 1 = 333 = U+014d = \xc5\x8d | ||
| PUSH "\e[?1005h" | ||
| MOUSEBTN d 1 0 | ||
| output "\e[M\x20\xc5\x8d\xc5\x8d" | ||
| MOUSEBTN u 1 0 | ||
| output "\e[M\x23\xc5\x8d\xc5\x8d" | ||
|
|
||
| !DECRQM on UTF-8 extended encoding mode | ||
| PUSH "\e[?1005\$p" | ||
| output "\e[?1005;1\$y" | ||
| PUSH "\e[?1006\$p" | ||
| output "\e[?1006;2\$y" | ||
| PUSH "\e[?1015\$p" | ||
| output "\e[?1015;2\$y" | ||
|
|
||
| !SGR extended encoding mode | ||
| PUSH "\e[?1006h" | ||
| MOUSEBTN d 1 0 | ||
| output "\e[<0;301;301M" | ||
| MOUSEBTN u 1 0 | ||
| output "\e[<0;301;301m" | ||
|
|
||
| !DECRQM on SGR extended encoding mode | ||
| PUSH "\e[?1005\$p" | ||
| output "\e[?1005;2\$y" | ||
| PUSH "\e[?1006\$p" | ||
| output "\e[?1006;1\$y" | ||
| PUSH "\e[?1015\$p" | ||
| output "\e[?1015;2\$y" | ||
|
|
||
| !rxvt extended encoding mode | ||
| PUSH "\e[?1015h" | ||
| MOUSEBTN d 1 0 | ||
| output "\e[0;301;301M" | ||
| MOUSEBTN u 1 0 | ||
| output "\e[3;301;301M" | ||
|
|
||
| !DECRQM on rxvt extended encoding mode | ||
| PUSH "\e[?1005\$p" | ||
| output "\e[?1005;2\$y" | ||
| PUSH "\e[?1006\$p" | ||
| output "\e[?1006;2\$y" | ||
| PUSH "\e[?1015\$p" | ||
| output "\e[?1015;1\$y" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| INIT | ||
| WANTSTATE p | ||
|
|
||
| RESET | ||
| settermprop 1 true | ||
| settermprop 2 true | ||
| settermprop 7 1 | ||
|
|
||
| !Cursor visibility | ||
| PUSH "\e[?25h" | ||
| settermprop 1 true | ||
| PUSH "\e[?25\$p" | ||
| output "\e[?25;1\$y" | ||
| PUSH "\e[?25l" | ||
| settermprop 1 false | ||
| PUSH "\e[?25\$p" | ||
| output "\e[?25;2\$y" | ||
|
|
||
| !Cursor blink | ||
| PUSH "\e[?12h" | ||
| settermprop 2 true | ||
| PUSH "\e[?12\$p" | ||
| output "\e[?12;1\$y" | ||
| PUSH "\e[?12l" | ||
| settermprop 2 false | ||
| PUSH "\e[?12\$p" | ||
| output "\e[?12;2\$y" | ||
|
|
||
| !Cursor shape | ||
| PUSH "\e[3 q" | ||
| settermprop 2 true | ||
| settermprop 7 2 | ||
|
|
||
| !Title | ||
| PUSH "\e]2;Here is my title\a" | ||
| settermprop 4 "Here is my title" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| INIT | ||
| UTF8 1 | ||
| WANTSTATE gm | ||
|
|
||
| !79th Column | ||
| PUSH "\e[75G" | ||
| PUSH "A"x5 | ||
| putglyph 0x41 1 0,74 | ||
| putglyph 0x41 1 0,75 | ||
| putglyph 0x41 1 0,76 | ||
| putglyph 0x41 1 0,77 | ||
| putglyph 0x41 1 0,78 | ||
| ?cursor = 0,79 | ||
|
|
||
| !80th Column Phantom | ||
| PUSH "A" | ||
| putglyph 0x41 1 0,79 | ||
| ?cursor = 0,79 | ||
|
|
||
| !Line Wraparound | ||
| PUSH "B" | ||
| putglyph 0x42 1 1,0 | ||
| ?cursor = 1,1 | ||
|
|
||
| !Line Wraparound during combined write | ||
| PUSH "\e[78G" | ||
| PUSH "BBBCC" | ||
| putglyph 0x42 1 1,77 | ||
| putglyph 0x42 1 1,78 | ||
| putglyph 0x42 1 1,79 | ||
| putglyph 0x43 1 2,0 | ||
| putglyph 0x43 1 2,1 | ||
| ?cursor = 2,2 | ||
|
|
||
| !DEC Auto Wrap Mode | ||
| RESET | ||
| PUSH "\e[?7l" | ||
| PUSH "\e[75G" | ||
| PUSH "D"x6 | ||
| putglyph 0x44 1 0,74 | ||
| putglyph 0x44 1 0,75 | ||
| putglyph 0x44 1 0,76 | ||
| putglyph 0x44 1 0,77 | ||
| putglyph 0x44 1 0,78 | ||
| putglyph 0x44 1 0,79 | ||
| ?cursor = 0,79 | ||
| PUSH "D" | ||
| putglyph 0x44 1 0,79 | ||
| ?cursor = 0,79 | ||
| PUSH "\e[?7h" | ||
|
|
||
| !80th column causes linefeed on wraparound | ||
| PUSH "\e[25;78HABC" | ||
| putglyph 0x41 1 24,77 | ||
| putglyph 0x42 1 24,78 | ||
| putglyph 0x43 1 24,79 | ||
| ?cursor = 24,79 | ||
| PUSH "D" | ||
| moverect 1..25,0..80 -> 0..24,0..80 | ||
| putglyph 0x44 1 24,0 | ||
|
|
||
| !80th column phantom linefeed phantom cancelled by explicit cursor move | ||
| PUSH "\e[25;78HABC" | ||
| putglyph 0x41 1 24,77 | ||
| putglyph 0x42 1 24,78 | ||
| putglyph 0x43 1 24,79 | ||
| ?cursor = 24,79 | ||
| PUSH "\e[25;1HD" | ||
| putglyph 0x44 1 24,0 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| INIT | ||
| WANTSTATE g | ||
|
|
||
| !Initial | ||
| RESET | ||
| PUSH "\tX" | ||
| putglyph 0x58 1 0,8 | ||
| PUSH "\tX" | ||
| putglyph 0x58 1 0,16 | ||
| ?cursor = 0,17 | ||
|
|
||
| !HTS | ||
| PUSH "\e[5G\eH" | ||
| PUSH "\e[G\tX" | ||
| putglyph 0x58 1 0,4 | ||
| ?cursor = 0,5 | ||
|
|
||
| !TBC 0 | ||
| PUSH "\e[9G\e[g" | ||
| PUSH "\e[G\tX\tX" | ||
| putglyph 0x58 1 0,4 | ||
| putglyph 0x58 1 0,16 | ||
| ?cursor = 0,17 | ||
|
|
||
| !TBC 3 | ||
| PUSH "\e[3g\e[50G\eH\e[G" | ||
| ?cursor = 0,0 | ||
| PUSH "\tX" | ||
| putglyph 0x58 1 0,49 | ||
| ?cursor = 0,50 | ||
|
|
||
| !Tabstops after resize | ||
| RESET | ||
| RESIZE 30,100 | ||
| # Should be 100/8 = 12 tabstops | ||
| PUSH "\tX" | ||
| putglyph 0x58 1 0,8 | ||
| PUSH "\tX" | ||
| putglyph 0x58 1 0,16 | ||
| PUSH "\tX" | ||
| putglyph 0x58 1 0,24 | ||
| PUSH "\tX" | ||
| putglyph 0x58 1 0,32 | ||
| PUSH "\tX" | ||
| putglyph 0x58 1 0,40 | ||
| PUSH "\tX" | ||
| putglyph 0x58 1 0,48 | ||
| PUSH "\tX" | ||
| putglyph 0x58 1 0,56 | ||
| PUSH "\tX" | ||
| putglyph 0x58 1 0,64 | ||
| PUSH "\tX" | ||
| putglyph 0x58 1 0,72 | ||
| PUSH "\tX" | ||
| putglyph 0x58 1 0,80 | ||
| PUSH "\tX" | ||
| putglyph 0x58 1 0,88 | ||
| PUSH "\tX" | ||
| putglyph 0x58 1 0,96 | ||
| ?cursor = 0,97 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| INIT | ||
| WANTSTATE p | ||
|
|
||
| RESET | ||
| settermprop 1 true | ||
| settermprop 2 true | ||
| settermprop 7 1 | ||
|
|
||
| !Set up state | ||
| PUSH "\e[2;2H" | ||
| ?cursor = 1,1 | ||
| PUSH "\e[1m" | ||
| ?pen bold = on | ||
|
|
||
| !Save | ||
| PUSH "\e[?1048h" | ||
|
|
||
| !Change state | ||
| PUSH "\e[5;5H" | ||
| ?cursor = 4,4 | ||
| PUSH "\e[4 q" | ||
| settermprop 2 false | ||
| settermprop 7 2 | ||
| PUSH "\e[22;4m" | ||
| ?pen bold = off | ||
| ?pen underline = 1 | ||
|
|
||
| !Restore | ||
| PUSH "\e[?1048l" | ||
| settermprop 1 true | ||
| settermprop 2 true | ||
| settermprop 7 1 | ||
| ?cursor = 1,1 | ||
| ?pen bold = on | ||
| ?pen underline = 0 | ||
|
|
||
| !Save/restore using DECSC/DECRC | ||
| PUSH "\e[2;2H\e7" | ||
| ?cursor = 1,1 | ||
|
|
||
| PUSH "\e[5;5H" | ||
| ?cursor = 4,4 | ||
| PUSH "\e8" | ||
| settermprop 1 true | ||
| settermprop 2 true | ||
| settermprop 7 1 | ||
| ?cursor = 1,1 | ||
|
|
||
| !Save twice, restore twice happens on both edge transitions | ||
| PUSH "\e[2;10H\e[?1048h\e[6;10H\e[?1048h" | ||
| PUSH "\e[H" | ||
| ?cursor = 0,0 | ||
| PUSH "\e[?1048l" | ||
| settermprop 1 true | ||
| settermprop 2 true | ||
| settermprop 7 1 | ||
| ?cursor = 5,9 | ||
| PUSH "\e[H" | ||
| ?cursor = 0,0 | ||
| PUSH "\e[?1048l" | ||
| settermprop 1 true | ||
| settermprop 2 true | ||
| settermprop 7 1 | ||
| ?cursor = 5,9 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,132 @@ | ||
| INIT | ||
| WANTSTATE | ||
|
|
||
| !Unmodified ASCII | ||
| INCHAR 0 41 | ||
| output "A" | ||
| INCHAR 0 61 | ||
| output "a" | ||
|
|
||
| !Ctrl modifier on ASCII letters | ||
| INCHAR C 41 | ||
| output "\e[65;5u" | ||
| INCHAR C 61 | ||
| output "\x01" | ||
|
|
||
| !Alt modifier on ASCII letters | ||
| INCHAR A 41 | ||
| output "\eA" | ||
| INCHAR A 61 | ||
| output "\ea" | ||
|
|
||
| !Ctrl-Alt modifier on ASCII letters | ||
| INCHAR CA 41 | ||
| output "\e[65;7u" | ||
| INCHAR CA 61 | ||
| output "\e\x01" | ||
|
|
||
| !Special handling of Ctrl-I | ||
| INCHAR 0 49 | ||
| output "I" | ||
| INCHAR 0 69 | ||
| output "i" | ||
| INCHAR C 49 | ||
| output "\e[73;5u" | ||
| INCHAR C 69 | ||
| output "\e[105;5u" | ||
| INCHAR A 49 | ||
| output "\eI" | ||
| INCHAR A 69 | ||
| output "\ei" | ||
| INCHAR CA 49 | ||
| output "\e[73;7u" | ||
| INCHAR CA 69 | ||
| output "\e[105;7u" | ||
|
|
||
| !Special handling of Space | ||
| INCHAR 0 20 | ||
| output " " | ||
| INCHAR S 20 | ||
| output "\e[32;2u" | ||
| INCHAR C 20 | ||
| output "\0" | ||
| INCHAR SC 20 | ||
| output "\e[32;6u" | ||
| INCHAR A 20 | ||
| output "\e " | ||
| INCHAR SA 20 | ||
| output "\e[32;4u" | ||
| INCHAR CA 20 | ||
| output "\e\0" | ||
| INCHAR SCA 20 | ||
| output "\e[32;8u" | ||
|
|
||
| !Cursor keys in reset (cursor) mode | ||
| INKEY 0 Up | ||
| output "\e[A" | ||
| INKEY S Up | ||
| output "\e[1;2A" | ||
| INKEY C Up | ||
| output "\e[1;5A" | ||
| INKEY SC Up | ||
| output "\e[1;6A" | ||
| INKEY A Up | ||
| output "\e[1;3A" | ||
| INKEY SA Up | ||
| output "\e[1;4A" | ||
| INKEY CA Up | ||
| output "\e[1;7A" | ||
| INKEY SCA Up | ||
| output "\e[1;8A" | ||
|
|
||
| !Cursor keys in application mode | ||
| PUSH "\e[?1h" | ||
| # Plain "Up" should be SS3 A now | ||
| INKEY 0 Up | ||
| output "\eOA" | ||
| # Modified keys should still use CSI | ||
| INKEY S Up | ||
| output "\e[1;2A" | ||
| INKEY C Up | ||
| output "\e[1;5A" | ||
|
|
||
| !Shift-Tab should be different | ||
| INKEY 0 Tab | ||
| output "\x09" | ||
| INKEY S Tab | ||
| output "\e[Z" | ||
| INKEY C Tab | ||
| output "\e[9;5u" | ||
| INKEY A Tab | ||
| output "\e\x09" | ||
| INKEY CA Tab | ||
| output "\e[9;7u" | ||
|
|
||
| !Enter in linefeed mode | ||
| INKEY 0 Enter | ||
| output "\x0d" | ||
|
|
||
| !Enter in newline mode | ||
| PUSH "\e[20h" | ||
| INKEY 0 Enter | ||
| output "\x0d\x0a" | ||
|
|
||
| !Keypad in DECKPNM | ||
| INKEY 0 KP0 | ||
| output "0" | ||
|
|
||
| !Keypad in DECKPAM | ||
| PUSH "\e=" | ||
| INKEY 0 KP0 | ||
| output "\eOp" | ||
|
|
||
| !Bracketed paste mode off | ||
| PASTE START | ||
| PASTE END | ||
|
|
||
| !Bracketed paste mode on | ||
| PUSH "\e[?2004h" | ||
| PASTE START | ||
| output "\e[200~" | ||
| PASTE END | ||
| output "\e[201~" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| INIT | ||
| WANTSTATE | ||
|
|
||
| !DA | ||
| RESET | ||
| PUSH "\e[c" | ||
| output "\e[?1;2c" | ||
|
|
||
| !DSR | ||
| RESET | ||
| PUSH "\e[5n" | ||
| output "\e[0n" | ||
|
|
||
| !CPR | ||
| PUSH "\e[6n" | ||
| output "\e[1;1R" | ||
| PUSH "\e[10;10H\e[6n" | ||
| output "\e[10;10R" | ||
|
|
||
| !DECCPR | ||
| PUSH "\e[?6n" | ||
| output "\e[?10;10R" | ||
|
|
||
| !DECRQSS on DECSCUSR | ||
| PUSH "\e[3 q" | ||
| PUSH "\eP\$q q\e\\" | ||
| output "\eP1\$r3 q\e\\" | ||
|
|
||
| !DECRQSS on SGR | ||
| PUSH "\e[1;5;7m" | ||
| PUSH "\eP\$qm\e\\" | ||
| output "\eP1\$r1;5;7m\e\\" | ||
|
|
||
| !DECRQSS on SGR ANSI colours | ||
| PUSH "\e[0;31;42m" | ||
| PUSH "\eP\$qm\e\\" | ||
| output "\eP1\$r31;42m\e\\" | ||
|
|
||
| !DECRQSS on SGR ANSI hi-bright colours | ||
| PUSH "\e[0;93;104m" | ||
| PUSH "\eP\$qm\e\\" | ||
| output "\eP1\$r93;104m\e\\" | ||
|
|
||
| !DECRQSS on SGR 256-palette colours | ||
| PUSH "\e[0;38:5:56;48:5:78m" | ||
| PUSH "\eP\$qm\e\\" | ||
| output "\eP1\$r38:5:56;48:5:78m\e\\" | ||
|
|
||
| !DECRQSS on SGR RGB8 colours | ||
| PUSH "\e[0;38:2:24:68:112;48:2:13:57:101m" | ||
| PUSH "\eP\$qm\e\\" | ||
| output "\eP1\$r38:2:24:68:112;48:2:13:57:101m\e\\" | ||
|
|
||
| !S8C1T on DSR | ||
| PUSH "\e G" | ||
| PUSH "\e[5n" | ||
| output "\x{9b}0n" | ||
| PUSH "\e F" | ||
|
|
||
| !Truncation on attempted buffer overflow | ||
| PUSH "\e[6n" x 20 | ||
| output "\e[10;10R" x 7 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| INIT | ||
| WANTSTATE | ||
|
|
||
| RESET | ||
|
|
||
| !RIS homes cursor | ||
| PUSH "\e[5;5H" | ||
| ?cursor = 4,4 | ||
| WANTSTATE +m | ||
| PUSH "\ec" | ||
| ?cursor = 0,0 | ||
| WANTSTATE -m | ||
|
|
||
| !RIS cancels scrolling region | ||
| PUSH "\e[5;10r" | ||
| WANTSTATE +s | ||
| PUSH "\ec\e[25H\n" | ||
| scrollrect 0..25,0..80 => +1,+0 | ||
| WANTSTATE -s | ||
|
|
||
| !RIS erases screen | ||
| PUSH "ABCDE" | ||
| WANTSTATE +e | ||
| PUSH "\ec" | ||
| erase 0..25,0..80 | ||
| WANTSTATE -e | ||
|
|
||
| !RIS clears tabstops | ||
| PUSH "\e[5G\eH\e[G\t" | ||
| ?cursor = 0,4 | ||
| PUSH "\ec\t" | ||
| ?cursor = 0,8 |