diff options
| -rw-r--r-- | st.c | 107 |
1 files changed, 45 insertions, 62 deletions
| @@ -383,20 +383,20 @@ static void tmoveato(int, int); | |||
| 383 | static void tnew(int, int); | 383 | static void tnew(int, int); |
| 384 | static void tnewline(int); | 384 | static void tnewline(int); |
| 385 | static void tputtab(int); | 385 | static void tputtab(int); |
| 386 | static void tputc(char *, int); | 386 | static void tputc(long); |
| 387 | static void treset(void); | 387 | static void treset(void); |
| 388 | static void tresize(int, int); | 388 | static void tresize(int, int); |
| 389 | static void tscrollup(int, int); | 389 | static void tscrollup(int, int); |
| 390 | static void tscrolldown(int, int); | 390 | static void tscrolldown(int, int); |
| 391 | static void tsetattr(int *, int); | 391 | static void tsetattr(int *, int); |
| 392 | static void tsetchar(char *, Glyph *, int, int); | 392 | static void tsetchar(long, Glyph *, int, int); |
| 393 | static void tsetscroll(int, int); | 393 | static void tsetscroll(int, int); |
| 394 | static void tswapscreen(void); | 394 | static void tswapscreen(void); |
| 395 | static void tsetdirt(int, int); | 395 | static void tsetdirt(int, int); |
| 396 | static void tsetdirtattr(int); | 396 | static void tsetdirtattr(int); |
| 397 | static void tsetmode(bool, bool, int *, int); | 397 | static void tsetmode(bool, bool, int *, int); |
| 398 | static void tfulldirt(void); | 398 | static void tfulldirt(void); |
| 399 | static void techo(char *, int); | 399 | static void techo(long); |
| 400 | static void tcontrolcode(uchar ); | 400 | static void tcontrolcode(uchar ); |
| 401 | static void tdectest(char ); | 401 | static void tdectest(char ); |
| 402 | static int32_t tdefcolor(int *, int *, int); | 402 | static int32_t tdefcolor(int *, int *, int); |
| @@ -1332,7 +1332,6 @@ ttyread(void) { | |||
| 1332 | static char buf[BUFSIZ]; | 1332 | static char buf[BUFSIZ]; |
| 1333 | static int buflen = 0; | 1333 | static int buflen = 0; |
| 1334 | char *ptr; | 1334 | char *ptr; |
| 1335 | char s[UTF_SIZ]; | ||
| 1336 | int charsize; /* size of utf8 char in bytes */ | 1335 | int charsize; /* size of utf8 char in bytes */ |
| 1337 | long unicodep; | 1336 | long unicodep; |
| 1338 | int ret; | 1337 | int ret; |
| @@ -1345,8 +1344,7 @@ ttyread(void) { | |||
| 1345 | buflen += ret; | 1344 | buflen += ret; |
| 1346 | ptr = buf; | 1345 | ptr = buf; |
| 1347 | while((charsize = utf8decode(ptr, &unicodep, buflen))) { | 1346 | while((charsize = utf8decode(ptr, &unicodep, buflen))) { |
| 1348 | utf8encode(unicodep, s); | 1347 | tputc(unicodep); |
| 1349 | tputc(s, charsize); | ||
| 1350 | ptr += charsize; | 1348 | ptr += charsize; |
| 1351 | buflen -= charsize; | 1349 | buflen -= charsize; |
| 1352 | } | 1350 | } |
| @@ -1363,9 +1361,16 @@ ttywrite(const char *s, size_t n) { | |||
| 1363 | 1361 | ||
| 1364 | void | 1362 | void |
| 1365 | ttysend(char *s, size_t n) { | 1363 | ttysend(char *s, size_t n) { |
| 1364 | int len; | ||
| 1365 | long u; | ||
| 1366 | |||
| 1366 | ttywrite(s, n); | 1367 | ttywrite(s, n); |
| 1367 | if(IS_SET(MODE_ECHO)) | 1368 | if(IS_SET(MODE_ECHO)) |
| 1368 | techo(s, n); | 1369 | while((len = utf8decode(s, &u, n)) > 0) { |
| 1370 | techo(u); | ||
| 1371 | n -= len; | ||
| 1372 | s += len; | ||
| 1373 | } | ||
| 1369 | } | 1374 | } |
| 1370 | 1375 | ||
| 1371 | void | 1376 | void |
| @@ -1614,7 +1619,7 @@ tmoveto(int x, int y) { | |||
| 1614 | } | 1619 | } |
| 1615 | 1620 | ||
| 1616 | void | 1621 | void |
| 1617 | tsetchar(char *c, Glyph *attr, int x, int y) { | 1622 | tsetchar(long u, Glyph *attr, int x, int y) { |
| 1618 | static char *vt100_0[62] = { /* 0x41 - 0x7e */ | 1623 | static char *vt100_0[62] = { /* 0x41 - 0x7e */ |
| 1619 | "↑", "↓", "→", "←", "█", "▚", "☃", /* A - G */ | 1624 | "↑", "↓", "→", "←", "█", "▚", "☃", /* A - G */ |
| 1620 | 0, 0, 0, 0, 0, 0, 0, 0, /* H - O */ | 1625 | 0, 0, 0, 0, 0, 0, 0, 0, /* H - O */ |
| @@ -1629,11 +1634,9 @@ tsetchar(char *c, Glyph *attr, int x, int y) { | |||
| 1629 | /* | 1634 | /* |
| 1630 | * The table is proudly stolen from rxvt. | 1635 | * The table is proudly stolen from rxvt. |
| 1631 | */ | 1636 | */ |
| 1632 | if(term.trantbl[term.charset] == CS_GRAPHIC0) { | 1637 | if(term.trantbl[term.charset] == CS_GRAPHIC0 && |
| 1633 | if(BETWEEN(c[0], 0x41, 0x7e) && vt100_0[c[0] - 0x41]) { | 1638 | BETWEEN(u, 0x41, 0x7e) && vt100_0[u - 0x41]) |
| 1634 | c = vt100_0[c[0] - 0x41]; | 1639 | utf8decode(vt100_0[u - 0x41], &u, UTF_SIZ); |
| 1635 | } | ||
| 1636 | } | ||
| 1637 | 1640 | ||
| 1638 | if(term.line[y][x].mode & ATTR_WIDE) { | 1641 | if(term.line[y][x].mode & ATTR_WIDE) { |
| 1639 | if(x+1 < term.col) { | 1642 | if(x+1 < term.col) { |
| @@ -1647,7 +1650,7 @@ tsetchar(char *c, Glyph *attr, int x, int y) { | |||
| 1647 | 1650 | ||
| 1648 | term.dirty[y] = 1; | 1651 | term.dirty[y] = 1; |
| 1649 | term.line[y][x] = *attr; | 1652 | term.line[y][x] = *attr; |
| 1650 | utf8decode(c, &term.line[y][x].u, UTF_SIZ); | 1653 | term.line[y][x].u = u; |
| 1651 | } | 1654 | } |
| 1652 | 1655 | ||
| 1653 | void | 1656 | void |
| @@ -2431,26 +2434,18 @@ tputtab(int n) { | |||
| 2431 | } | 2434 | } |
| 2432 | 2435 | ||
| 2433 | void | 2436 | void |
| 2434 | techo(char *buf, int len) { | 2437 | techo(long u) { |
| 2435 | for(; len > 0; buf++, len--) { | 2438 | if(ISCONTROL(u)) { /* control code */ |
| 2436 | char c = *buf; | 2439 | if(u & 0x80) { |
| 2437 | 2440 | u &= 0x7f; | |
| 2438 | if(ISCONTROL((uchar) c)) { /* control code */ | 2441 | tputc('^'); |
| 2439 | if(c & 0x80) { | 2442 | tputc('['); |
| 2440 | c &= 0x7f; | 2443 | } else if(u != '\n' && u != '\r' && u != '\t') { |
| 2441 | tputc("^", 1); | 2444 | u ^= 0x40; |
| 2442 | tputc("[", 1); | 2445 | tputc('^'); |
| 2443 | } else if(c != '\n' && c != '\r' && c != '\t') { | ||
| 2444 | c ^= 0x40; | ||
| 2445 | tputc("^", 1); | ||
| 2446 | } | ||
| 2447 | tputc(&c, 1); | ||
| 2448 | } else { | ||
| 2449 | break; | ||
| 2450 | } | 2446 | } |
| 2451 | } | 2447 | } |
| 2452 | if(len) | 2448 | tputc(u); |
| 2453 | tputc(buf, len); | ||
| 2454 | } | 2449 | } |
| 2455 | 2450 | ||
| 2456 | void | 2451 | void |
| @@ -2468,13 +2463,12 @@ tdeftran(char ascii) { | |||
| 2468 | 2463 | ||
| 2469 | void | 2464 | void |
| 2470 | tdectest(char c) { | 2465 | tdectest(char c) { |
| 2471 | static char E[UTF_SIZ] = "E"; | ||
| 2472 | int x, y; | 2466 | int x, y; |
| 2473 | 2467 | ||
| 2474 | if(c == '8') { /* DEC screen alignment test. */ | 2468 | if(c == '8') { /* DEC screen alignment test. */ |
| 2475 | for(x = 0; x < term.col; ++x) { | 2469 | for(x = 0; x < term.col; ++x) { |
| 2476 | for(y = 0; y < term.row; ++y) | 2470 | for(y = 0; y < term.row; ++y) |
| 2477 | tsetchar(E, &term.c.attr, x, y); | 2471 | tsetchar('E', &term.c.attr, x, y); |
| 2478 | } | 2472 | } |
| 2479 | } | 2473 | } |
| 2480 | } | 2474 | } |
| @@ -2502,8 +2496,6 @@ tstrsequence(uchar c) { | |||
| 2502 | 2496 | ||
| 2503 | void | 2497 | void |
| 2504 | tcontrolcode(uchar ascii) { | 2498 | tcontrolcode(uchar ascii) { |
| 2505 | static char question[UTF_SIZ] = "?"; | ||
| 2506 | |||
| 2507 | switch(ascii) { | 2499 | switch(ascii) { |
| 2508 | case '\t': /* HT */ | 2500 | case '\t': /* HT */ |
| 2509 | tputtab(1); | 2501 | tputtab(1); |
| @@ -2541,7 +2533,7 @@ tcontrolcode(uchar ascii) { | |||
| 2541 | term.charset = 1 - (ascii - '\016'); | 2533 | term.charset = 1 - (ascii - '\016'); |
| 2542 | return; | 2534 | return; |
| 2543 | case '\032': /* SUB */ | 2535 | case '\032': /* SUB */ |
| 2544 | tsetchar(question, &term.c.attr, term.c.x, term.c.y); | 2536 | tsetchar('?', &term.c.attr, term.c.x, term.c.y); |
| 2545 | case '\030': /* CAN */ | 2537 | case '\030': /* CAN */ |
| 2546 | csireset(); | 2538 | csireset(); |
| 2547 | break; | 2539 | break; |
| @@ -2665,28 +2657,21 @@ eschandle(uchar ascii) { | |||
| 2665 | } | 2657 | } |
| 2666 | 2658 | ||
| 2667 | void | 2659 | void |
| 2668 | tputc(char *c, int len) { | 2660 | tputc(long u) { |
| 2669 | uchar ascii; | 2661 | char c[UTF_SIZ]; |
| 2670 | bool control; | 2662 | bool control; |
| 2671 | long unicodep; | 2663 | int width, len; |
| 2672 | int width; | ||
| 2673 | Glyph *gp; | 2664 | Glyph *gp; |
| 2674 | 2665 | ||
| 2675 | if(len == 1) { | 2666 | len = utf8encode(u, c); |
| 2667 | if((width = wcwidth(u)) == -1) { | ||
| 2668 | memcpy(c, "\357\277\275", 4); /* UTF_INVALID */ | ||
| 2676 | width = 1; | 2669 | width = 1; |
| 2677 | unicodep = ascii = *c; | ||
| 2678 | } else { | ||
| 2679 | utf8decode(c, &unicodep, UTF_SIZ); | ||
| 2680 | if ((width = wcwidth(unicodep)) == -1) { | ||
| 2681 | c = "\357\277\275"; /* UTF_INVALID */ | ||
| 2682 | width = 1; | ||
| 2683 | } | ||
| 2684 | ascii = unicodep; | ||
| 2685 | } | 2670 | } |
| 2686 | 2671 | ||
| 2687 | if(IS_SET(MODE_PRINT)) | 2672 | if(IS_SET(MODE_PRINT)) |
| 2688 | tprinter(c, len); | 2673 | tprinter(c, len); |
| 2689 | control = ISCONTROL(unicodep); | 2674 | control = ISCONTROL(u); |
| 2690 | 2675 | ||
| 2691 | /* | 2676 | /* |
| 2692 | * STR sequence must be checked before anything else | 2677 | * STR sequence must be checked before anything else |
| @@ -2695,10 +2680,8 @@ tputc(char *c, int len) { | |||
| 2695 | * character. | 2680 | * character. |
| 2696 | */ | 2681 | */ |
| 2697 | if(term.esc & ESC_STR) { | 2682 | if(term.esc & ESC_STR) { |
| 2698 | if(len == 1 && | 2683 | if(u == '\a' || u == 030 || u == 032 || u == 033 || |
| 2699 | (ascii == '\a' || ascii == 030 || | 2684 | ISCONTROLC1(u)) { |
| 2700 | ascii == 032 || ascii == 033 || | ||
| 2701 | ISCONTROLC1(unicodep))) { | ||
| 2702 | term.esc &= ~(ESC_START|ESC_STR); | 2685 | term.esc &= ~(ESC_START|ESC_STR); |
| 2703 | term.esc |= ESC_STR_END; | 2686 | term.esc |= ESC_STR_END; |
| 2704 | } else if(strescseq.len + len < sizeof(strescseq.buf) - 1) { | 2687 | } else if(strescseq.len + len < sizeof(strescseq.buf) - 1) { |
| @@ -2729,15 +2712,15 @@ tputc(char *c, int len) { | |||
| 2729 | * they must not cause conflicts with sequences. | 2712 | * they must not cause conflicts with sequences. |
| 2730 | */ | 2713 | */ |
| 2731 | if(control) { | 2714 | if(control) { |
| 2732 | tcontrolcode(ascii); | 2715 | tcontrolcode(u); |
| 2733 | /* | 2716 | /* |
| 2734 | * control codes are not shown ever | 2717 | * control codes are not shown ever |
| 2735 | */ | 2718 | */ |
| 2736 | return; | 2719 | return; |
| 2737 | } else if(term.esc & ESC_START) { | 2720 | } else if(term.esc & ESC_START) { |
| 2738 | if(term.esc & ESC_CSI) { | 2721 | if(term.esc & ESC_CSI) { |
| 2739 | csiescseq.buf[csiescseq.len++] = ascii; | 2722 | csiescseq.buf[csiescseq.len++] = u; |
| 2740 | if(BETWEEN(ascii, 0x40, 0x7E) | 2723 | if(BETWEEN(u, 0x40, 0x7E) |
| 2741 | || csiescseq.len >= \ | 2724 | || csiescseq.len >= \ |
| 2742 | sizeof(csiescseq.buf)-1) { | 2725 | sizeof(csiescseq.buf)-1) { |
| 2743 | term.esc = 0; | 2726 | term.esc = 0; |
| @@ -2746,11 +2729,11 @@ tputc(char *c, int len) { | |||
| 2746 | } | 2729 | } |
| 2747 | return; | 2730 | return; |
| 2748 | } else if(term.esc & ESC_ALTCHARSET) { | 2731 | } else if(term.esc & ESC_ALTCHARSET) { |
| 2749 | tdeftran(ascii); | 2732 | tdeftran(u); |
| 2750 | } else if(term.esc & ESC_TEST) { | 2733 | } else if(term.esc & ESC_TEST) { |
| 2751 | tdectest(ascii); | 2734 | tdectest(u); |
| 2752 | } else { | 2735 | } else { |
| 2753 | if (!eschandle(ascii)) | 2736 | if (!eschandle(u)) |
| 2754 | return; | 2737 | return; |
| 2755 | /* sequence already finished */ | 2738 | /* sequence already finished */ |
| 2756 | } | 2739 | } |
| @@ -2779,7 +2762,7 @@ tputc(char *c, int len) { | |||
| 2779 | gp = &term.line[term.c.y][term.c.x]; | 2762 | gp = &term.line[term.c.y][term.c.x]; |
| 2780 | } | 2763 | } |
| 2781 | 2764 | ||
| 2782 | tsetchar(c, &term.c.attr, term.c.x, term.c.y); | 2765 | tsetchar(u, &term.c.attr, term.c.x, term.c.y); |
| 2783 | 2766 | ||
| 2784 | if(width == 2) { | 2767 | if(width == 2) { |
| 2785 | gp->mode |= ATTR_WIDE; | 2768 | gp->mode |= ATTR_WIDE; |
