diff options
| -rw-r--r-- | st.c | 79 |
1 files changed, 62 insertions, 17 deletions
| @@ -137,6 +137,7 @@ enum term_mode { | |||
| 137 | MODE_MOUSEMANY = 1 << 18, | 137 | MODE_MOUSEMANY = 1 << 18, |
| 138 | MODE_BRCKTPASTE = 1 << 19, | 138 | MODE_BRCKTPASTE = 1 << 19, |
| 139 | MODE_PRINT = 1 << 20, | 139 | MODE_PRINT = 1 << 20, |
| 140 | MODE_UTF8 = 1 << 21, | ||
| 140 | MODE_MOUSE = MODE_MOUSEBTN|MODE_MOUSEMOTION|MODE_MOUSEX10\ | 141 | MODE_MOUSE = MODE_MOUSEBTN|MODE_MOUSEMOTION|MODE_MOUSEX10\ |
| 141 | |MODE_MOUSEMANY, | 142 | |MODE_MOUSEMANY, |
| 142 | }; | 143 | }; |
| @@ -158,6 +159,7 @@ enum escape_state { | |||
| 158 | ESC_ALTCHARSET = 8, | 159 | ESC_ALTCHARSET = 8, |
| 159 | ESC_STR_END = 16, /* a final string was encountered */ | 160 | ESC_STR_END = 16, /* a final string was encountered */ |
| 160 | ESC_TEST = 32, /* Enter in test mode */ | 161 | ESC_TEST = 32, /* Enter in test mode */ |
| 162 | ESC_UTF8 = 64, | ||
| 161 | }; | 163 | }; |
| 162 | 164 | ||
| 163 | enum window_state { | 165 | enum window_state { |
| @@ -412,6 +414,7 @@ static void tfulldirt(void); | |||
| 412 | static void techo(Rune); | 414 | static void techo(Rune); |
| 413 | static void tcontrolcode(uchar ); | 415 | static void tcontrolcode(uchar ); |
| 414 | static void tdectest(char ); | 416 | static void tdectest(char ); |
| 417 | static void tdefutf8(char); | ||
| 415 | static int32_t tdefcolor(int *, int *, int); | 418 | static int32_t tdefcolor(int *, int *, int); |
| 416 | static void tdeftran(char); | 419 | static void tdeftran(char); |
| 417 | static inline int match(uint, uint); | 420 | static inline int match(uint, uint); |
| @@ -1478,17 +1481,29 @@ ttyread(void) | |||
| 1478 | if ((ret = read(cmdfd, buf+buflen, LEN(buf)-buflen)) < 0) | 1481 | if ((ret = read(cmdfd, buf+buflen, LEN(buf)-buflen)) < 0) |
| 1479 | die("Couldn't read from shell: %s\n", strerror(errno)); | 1482 | die("Couldn't read from shell: %s\n", strerror(errno)); |
| 1480 | 1483 | ||
| 1481 | /* process every complete utf8 char */ | ||
| 1482 | buflen += ret; | 1484 | buflen += ret; |
| 1483 | ptr = buf; | 1485 | ptr = buf; |
| 1484 | while ((charsize = utf8decode(ptr, &unicodep, buflen))) { | ||
| 1485 | tputc(unicodep); | ||
| 1486 | ptr += charsize; | ||
| 1487 | buflen -= charsize; | ||
| 1488 | } | ||
| 1489 | 1486 | ||
| 1487 | for (;;) { | ||
| 1488 | if (IS_SET(MODE_UTF8)) { | ||
| 1489 | /* process a complete utf8 char */ | ||
| 1490 | charsize = utf8decode(ptr, &unicodep, buflen); | ||
| 1491 | if (charsize == 0) | ||
| 1492 | break; | ||
| 1493 | tputc(unicodep); | ||
| 1494 | ptr += charsize; | ||
| 1495 | buflen -= charsize; | ||
| 1496 | |||
| 1497 | } else { | ||
| 1498 | if (buflen <= 0) | ||
| 1499 | break; | ||
| 1500 | tputc(*ptr++ & 0xFF); | ||
| 1501 | buflen--; | ||
| 1502 | } | ||
| 1503 | } | ||
| 1490 | /* keep any uncomplete utf8 char for the next call */ | 1504 | /* keep any uncomplete utf8 char for the next call */ |
| 1491 | memmove(buf, ptr, buflen); | 1505 | if (buflen > 0) |
| 1506 | memmove(buf, ptr, buflen); | ||
| 1492 | 1507 | ||
| 1493 | return ret; | 1508 | return ret; |
| 1494 | } | 1509 | } |
| @@ -1554,15 +1569,26 @@ void | |||
| 1554 | ttysend(char *s, size_t n) | 1569 | ttysend(char *s, size_t n) |
| 1555 | { | 1570 | { |
| 1556 | int len; | 1571 | int len; |
| 1572 | char *t, *lim; | ||
| 1557 | Rune u; | 1573 | Rune u; |
| 1558 | 1574 | ||
| 1559 | ttywrite(s, n); | 1575 | ttywrite(s, n); |
| 1560 | if (IS_SET(MODE_ECHO)) | 1576 | if (!IS_SET(MODE_ECHO)) |
| 1561 | while ((len = utf8decode(s, &u, n)) > 0) { | 1577 | return; |
| 1562 | techo(u); | 1578 | |
| 1563 | n -= len; | 1579 | lim = &s[n]; |
| 1564 | s += len; | 1580 | for (t = s; t < lim; t += len) { |
| 1581 | if (IS_SET(MODE_UTF8)) { | ||
| 1582 | len = utf8decode(t, &u, n); | ||
| 1583 | } else { | ||
| 1584 | u = *t & 0xFF; | ||
| 1585 | len = 1; | ||
| 1565 | } | 1586 | } |
| 1587 | if (len <= 0) | ||
| 1588 | break; | ||
| 1589 | techo(u); | ||
| 1590 | n -= len; | ||
| 1591 | } | ||
| 1566 | } | 1592 | } |
| 1567 | 1593 | ||
| 1568 | void | 1594 | void |
| @@ -1656,7 +1682,7 @@ treset(void) | |||
| 1656 | term.tabs[i] = 1; | 1682 | term.tabs[i] = 1; |
| 1657 | term.top = 0; | 1683 | term.top = 0; |
| 1658 | term.bot = term.row - 1; | 1684 | term.bot = term.row - 1; |
| 1659 | term.mode = MODE_WRAP; | 1685 | term.mode = MODE_WRAP|MODE_UTF8; |
| 1660 | memset(term.trantbl, CS_USA, sizeof(term.trantbl)); | 1686 | memset(term.trantbl, CS_USA, sizeof(term.trantbl)); |
| 1661 | term.charset = 0; | 1687 | term.charset = 0; |
| 1662 | 1688 | ||
| @@ -2690,6 +2716,15 @@ techo(Rune u) | |||
| 2690 | } | 2716 | } |
| 2691 | 2717 | ||
| 2692 | void | 2718 | void |
| 2719 | tdefutf8(char ascii) | ||
| 2720 | { | ||
| 2721 | if (ascii == 'G') | ||
| 2722 | term.mode |= MODE_UTF8; | ||
| 2723 | else if (ascii == '@') | ||
| 2724 | term.mode &= ~MODE_UTF8; | ||
| 2725 | } | ||
| 2726 | |||
| 2727 | void | ||
| 2693 | tdeftran(char ascii) | 2728 | tdeftran(char ascii) |
| 2694 | { | 2729 | { |
| 2695 | static char cs[] = "0B"; | 2730 | static char cs[] = "0B"; |
| @@ -2851,6 +2886,9 @@ eschandle(uchar ascii) | |||
| 2851 | case '#': | 2886 | case '#': |
| 2852 | term.esc |= ESC_TEST; | 2887 | term.esc |= ESC_TEST; |
| 2853 | return 0; | 2888 | return 0; |
| 2889 | case '%': | ||
| 2890 | term.esc |= ESC_UTF8; | ||
| 2891 | return 0; | ||
| 2854 | case 'P': /* DCS -- Device Control String */ | 2892 | case 'P': /* DCS -- Device Control String */ |
| 2855 | case '_': /* APC -- Application Program Command */ | 2893 | case '_': /* APC -- Application Program Command */ |
| 2856 | case '^': /* PM -- Privacy Message */ | 2894 | case '^': /* PM -- Privacy Message */ |
| @@ -2930,10 +2968,15 @@ tputc(Rune u) | |||
| 2930 | Glyph *gp; | 2968 | Glyph *gp; |
| 2931 | 2969 | ||
| 2932 | control = ISCONTROL(u); | 2970 | control = ISCONTROL(u); |
| 2933 | len = utf8encode(u, c); | 2971 | if (!IS_SET(MODE_UTF8)) { |
| 2934 | if (!control && (width = wcwidth(u)) == -1) { | 2972 | c[0] = u; |
| 2935 | memcpy(c, "\357\277\275", 4); /* UTF_INVALID */ | 2973 | width = len = 1; |
| 2936 | width = 1; | 2974 | } else { |
| 2975 | len = utf8encode(u, c); | ||
| 2976 | if (!control && (width = wcwidth(u)) == -1) { | ||
| 2977 | memcpy(c, "\357\277\275", 4); /* UTF_INVALID */ | ||
| 2978 | width = 1; | ||
| 2979 | } | ||
| 2937 | } | 2980 | } |
| 2938 | 2981 | ||
| 2939 | if (IS_SET(MODE_PRINT)) | 2982 | if (IS_SET(MODE_PRINT)) |
| @@ -2994,6 +3037,8 @@ tputc(Rune u) | |||
| 2994 | csihandle(); | 3037 | csihandle(); |
| 2995 | } | 3038 | } |
| 2996 | return; | 3039 | return; |
| 3040 | } else if (term.esc & ESC_UTF8) { | ||
| 3041 | tdefutf8(u); | ||
| 2997 | } else if (term.esc & ESC_ALTCHARSET) { | 3042 | } else if (term.esc & ESC_ALTCHARSET) { |
| 2998 | tdeftran(u); | 3043 | tdeftran(u); |
| 2999 | } else if (term.esc & ESC_TEST) { | 3044 | } else if (term.esc & ESC_TEST) { |
