diff options
Diffstat (limited to 'st.c')
| -rw-r--r-- | st.c | 389 |
1 files changed, 190 insertions, 199 deletions
| @@ -20,11 +20,12 @@ | |||
| 20 | #include <X11/keysym.h> | 20 | #include <X11/keysym.h> |
| 21 | #include <X11/Xutil.h> | 21 | #include <X11/Xutil.h> |
| 22 | 22 | ||
| 23 | #define TNAME "st" | 23 | #define TNAME "xterm" |
| 24 | 24 | ||
| 25 | /* Arbitrary sizes */ | 25 | /* Arbitrary sizes */ |
| 26 | #define TITLESIZ 256 | ||
| 26 | #define ESCSIZ 256 | 27 | #define ESCSIZ 256 |
| 27 | #define ESCARG 16 | 28 | #define ESCARGSIZ 16 |
| 28 | #define MAXDRAWBUF 1024 | 29 | #define MAXDRAWBUF 1024 |
| 29 | 30 | ||
| 30 | #define SERRNO strerror(errno) | 31 | #define SERRNO strerror(errno) |
| @@ -40,7 +41,8 @@ | |||
| 40 | enum { ATnone=0 , ATreverse=1 , ATunderline=2, ATbold=4 }; | 41 | enum { ATnone=0 , ATreverse=1 , ATunderline=2, ATbold=4 }; |
| 41 | enum { CSup, CSdown, CSright, CSleft, CShide, CSdraw, CSwrap, CSsave, CSload }; | 42 | enum { CSup, CSdown, CSright, CSleft, CShide, CSdraw, CSwrap, CSsave, CSload }; |
| 42 | enum { CRset=1, CRupdate=2 }; | 43 | enum { CRset=1, CRupdate=2 }; |
| 43 | enum { TMwrap=1, TMinsert=2 }; | 44 | enum { TMwrap=1, TMinsert=2, TMtitle=4 }; |
| 45 | enum { ESCin = 1, ESCcsi = 2, ESCosc = 4, ESCtitle = 8 }; | ||
| 44 | enum { SCupdate, SCredraw }; | 46 | enum { SCupdate, SCredraw }; |
| 45 | 47 | ||
| 46 | typedef int Color; | 48 | typedef int Color; |
| @@ -62,17 +64,16 @@ typedef struct { | |||
| 62 | int y; | 64 | int y; |
| 63 | } TCursor; | 65 | } TCursor; |
| 64 | 66 | ||
| 65 | /* Escape sequence structs */ | 67 | /* CSI Escape sequence structs */ |
| 66 | /* ESC <pre> [[ [<priv>] <arg> [;]] <mode>] */ | 68 | /* ESC '[' [[ [<priv>] <arg> [;]] <mode>] */ |
| 67 | typedef struct { | 69 | typedef struct { |
| 68 | char buf[ESCSIZ+1]; /* raw string */ | 70 | char buf[ESCSIZ]; /* raw string */ |
| 69 | int len; /* raw string length */ | 71 | int len; /* raw string length */ |
| 70 | char pre; | ||
| 71 | char priv; | 72 | char priv; |
| 72 | int arg[ESCARG+1]; | 73 | int arg[ESCARGSIZ]; |
| 73 | int narg; /* nb of args */ | 74 | int narg; /* nb of args */ |
| 74 | char mode; | 75 | char mode; |
| 75 | } Escseq; | 76 | } CSIEscape; |
| 76 | 77 | ||
| 77 | /* Internal representation of the screen */ | 78 | /* Internal representation of the screen */ |
| 78 | typedef struct { | 79 | typedef struct { |
| @@ -83,6 +84,9 @@ typedef struct { | |||
| 83 | int top; /* top scroll limit */ | 84 | int top; /* top scroll limit */ |
| 84 | int bot; /* bottom scroll limit */ | 85 | int bot; /* bottom scroll limit */ |
| 85 | int mode; /* terminal mode */ | 86 | int mode; /* terminal mode */ |
| 87 | int esc; | ||
| 88 | char title[TITLESIZ]; | ||
| 89 | int titlelen; | ||
| 86 | } Term; | 90 | } Term; |
| 87 | 91 | ||
| 88 | /* Purely graphic info */ | 92 | /* Purely graphic info */ |
| @@ -116,12 +120,10 @@ static void execsh(void); | |||
| 116 | static void sigchld(int); | 120 | static void sigchld(int); |
| 117 | static void run(void); | 121 | static void run(void); |
| 118 | 122 | ||
| 119 | static int escaddc(char); | 123 | static void csidump(void); |
| 120 | static int escfinal(char); | 124 | static void csihandle(void); |
| 121 | static void escdump(void); | 125 | static void csiparse(void); |
| 122 | static void eschandle(void); | 126 | static void csireset(void); |
| 123 | static void escparse(void); | ||
| 124 | static void escreset(void); | ||
| 125 | 127 | ||
| 126 | static void tclearregion(int, int, int, int); | 128 | static void tclearregion(int, int, int, int); |
| 127 | static void tcpos(int); | 129 | static void tcpos(int); |
| @@ -168,7 +170,7 @@ static void (*handler[LASTEvent])(XEvent *) = { | |||
| 168 | static DC dc; | 170 | static DC dc; |
| 169 | static XWindow xw; | 171 | static XWindow xw; |
| 170 | static Term term; | 172 | static Term term; |
| 171 | static Escseq escseq; | 173 | static CSIEscape escseq; |
| 172 | static int cmdfd; | 174 | static int cmdfd; |
| 173 | static pid_t pid; | 175 | static pid_t pid; |
| 174 | static int running; | 176 | static int running; |
| @@ -269,7 +271,7 @@ ttynew(void) { | |||
| 269 | void | 271 | void |
| 270 | dump(char c) { | 272 | dump(char c) { |
| 271 | static int col; | 273 | static int col; |
| 272 | fprintf(stderr, " %02x %c ", c, isprint(c)?c:'.'); | 274 | fprintf(stderr, " %02x '%c' ", c, isprint(c)?c:'.'); |
| 273 | if(++col % 10 == 0) | 275 | if(++col % 10 == 0) |
| 274 | fprintf(stderr, "\n"); | 276 | fprintf(stderr, "\n"); |
| 275 | } | 277 | } |
| @@ -305,24 +307,6 @@ ttyresize(int x, int y) { | |||
| 305 | fprintf(stderr, "Couldn't set window size: %s\n", SERRNO); | 307 | fprintf(stderr, "Couldn't set window size: %s\n", SERRNO); |
| 306 | } | 308 | } |
| 307 | 309 | ||
| 308 | int | ||
| 309 | escfinal(char c) { | ||
| 310 | if(escseq.len == 1) | ||
| 311 | switch(c) { | ||
| 312 | case '[': | ||
| 313 | case ']': | ||
| 314 | case '(': | ||
| 315 | return 0; | ||
| 316 | case '=': | ||
| 317 | case '>': | ||
| 318 | default: | ||
| 319 | return 1; | ||
| 320 | } | ||
| 321 | else if(BETWEEN(c, 0x40, 0x7E)) | ||
| 322 | return 1; | ||
| 323 | return 0; | ||
| 324 | } | ||
| 325 | |||
| 326 | void | 310 | void |
| 327 | tcpos(int mode) { | 311 | tcpos(int mode) { |
| 328 | static int x = 0; | 312 | static int x = 0; |
| @@ -372,44 +356,27 @@ tnewline(void) { | |||
| 372 | tmoveto(0, y); | 356 | tmoveto(0, y); |
| 373 | } | 357 | } |
| 374 | 358 | ||
| 375 | int | ||
| 376 | escaddc(char c) { | ||
| 377 | escseq.buf[escseq.len++] = c; | ||
| 378 | if(escfinal(c) || escseq.len >= ESCSIZ) { | ||
| 379 | escparse(), eschandle(); | ||
| 380 | return 0; | ||
| 381 | } | ||
| 382 | return 1; | ||
| 383 | } | ||
| 384 | |||
| 385 | void | 359 | void |
| 386 | escparse(void) { | 360 | csiparse(void) { |
| 387 | /* int noarg = 1; */ | 361 | /* int noarg = 1; */ |
| 388 | char *p = escseq.buf; | 362 | char *p = escseq.buf; |
| 389 | 363 | ||
| 390 | escseq.narg = 0; | 364 | escseq.narg = 0; |
| 391 | switch(escseq.pre = *p++) { | 365 | if(*p == '?') |
| 392 | case '[': /* CSI */ | 366 | escseq.priv = 1, p++; |
| 393 | if(*p == '?') | 367 | |
| 394 | escseq.priv = 1, p++; | 368 | while(p < escseq.buf+escseq.len) { |
| 395 | 369 | while(isdigit(*p)) { | |
| 396 | while(p < escseq.buf+escseq.len) { | 370 | escseq.arg[escseq.narg] *= 10; |
| 397 | while(isdigit(*p)) { | 371 | escseq.arg[escseq.narg] += *p++ - '0'/*, noarg = 0 */; |
| 398 | escseq.arg[escseq.narg] *= 10; | 372 | } |
| 399 | escseq.arg[escseq.narg] += *(p++) - '0'/*, noarg = 0 */; | 373 | if(*p == ';' && escseq.narg+1 < ESCARGSIZ) |
| 400 | } | 374 | escseq.narg++, p++; |
| 401 | if(*p == ';') | 375 | else { |
| 402 | escseq.narg++, p++; | 376 | escseq.mode = *p; |
| 403 | else { | 377 | escseq.narg++; |
| 404 | escseq.mode = *p; | 378 | return; |
| 405 | escseq.narg++; | ||
| 406 | return; | ||
| 407 | } | ||
| 408 | } | 379 | } |
| 409 | break; | ||
| 410 | case '(': | ||
| 411 | /* XXX: graphic character set */ | ||
| 412 | break; | ||
| 413 | } | 380 | } |
| 414 | } | 381 | } |
| 415 | 382 | ||
| @@ -625,146 +592,141 @@ tsetscroll(int t, int b) { | |||
| 625 | } | 592 | } |
| 626 | 593 | ||
| 627 | void | 594 | void |
| 628 | eschandle(void) { | 595 | csihandle(void) { |
| 629 | switch(escseq.pre) { | 596 | switch(escseq.mode) { |
| 630 | default: | 597 | default: |
| 631 | goto unknown_seq; | 598 | fprintf(stderr, "erresc: unknown sequence\n"); |
| 632 | case '[': | 599 | csidump(); |
| 633 | switch(escseq.mode) { | 600 | /* die(""); */ |
| 634 | default: | 601 | break; |
| 635 | unknown_seq: | 602 | case '@': /* Insert <n> blank char */ |
| 636 | fprintf(stderr, "erresc: unknown sequence\n"); | 603 | DEFAULT(escseq.arg[0], 1); |
| 637 | escdump(); | 604 | tinsertblank(escseq.arg[0]); |
| 638 | break; | 605 | break; |
| 639 | case '@': /* Insert <n> blank char */ | 606 | case 'A': /* Cursor <n> Up */ |
| 640 | DEFAULT(escseq.arg[0], 1); | 607 | case 'e': |
| 641 | tinsertblank(escseq.arg[0]); | 608 | DEFAULT(escseq.arg[0], 1); |
| 642 | break; | 609 | tmoveto(term.c.x, term.c.y-escseq.arg[0]); |
| 643 | case 'A': /* Cursor <n> Up */ | 610 | break; |
| 644 | case 'e': | 611 | case 'B': /* Cursor <n> Down */ |
| 645 | DEFAULT(escseq.arg[0], 1); | 612 | DEFAULT(escseq.arg[0], 1); |
| 646 | tmoveto(term.c.x, term.c.y-escseq.arg[0]); | 613 | tmoveto(term.c.x, term.c.y+escseq.arg[0]); |
| 647 | break; | 614 | break; |
| 648 | case 'B': /* Cursor <n> Down */ | 615 | case 'C': /* Cursor <n> Forward */ |
| 649 | DEFAULT(escseq.arg[0], 1); | 616 | case 'a': |
| 650 | tmoveto(term.c.x, term.c.y+escseq.arg[0]); | 617 | DEFAULT(escseq.arg[0], 1); |
| 651 | break; | 618 | tmoveto(term.c.x+escseq.arg[0], term.c.y); |
| 652 | case 'C': /* Cursor <n> Forward */ | 619 | break; |
| 653 | case 'a': | 620 | case 'D': /* Cursor <n> Backward */ |
| 654 | DEFAULT(escseq.arg[0], 1); | 621 | DEFAULT(escseq.arg[0], 1); |
| 655 | tmoveto(term.c.x+escseq.arg[0], term.c.y); | 622 | tmoveto(term.c.x-escseq.arg[0], term.c.y); |
| 656 | break; | 623 | break; |
| 657 | case 'D': /* Cursor <n> Backward */ | 624 | case 'E': /* Cursor <n> Down and first col */ |
| 658 | DEFAULT(escseq.arg[0], 1); | 625 | DEFAULT(escseq.arg[0], 1); |
| 659 | tmoveto(term.c.x-escseq.arg[0], term.c.y); | 626 | tmoveto(0, term.c.y+escseq.arg[0]); |
| 660 | break; | 627 | break; |
| 661 | case 'E': /* Cursor <n> Down and first col */ | 628 | case 'F': /* Cursor <n> Up and first col */ |
| 662 | DEFAULT(escseq.arg[0], 1); | 629 | DEFAULT(escseq.arg[0], 1); |
| 663 | tmoveto(0, term.c.y+escseq.arg[0]); | 630 | tmoveto(0, term.c.y-escseq.arg[0]); |
| 664 | break; | 631 | break; |
| 665 | case 'F': /* Cursor <n> Up and first col */ | 632 | case 'G': /* Move to <col> */ |
| 666 | DEFAULT(escseq.arg[0], 1); | 633 | case '`': |
| 667 | tmoveto(0, term.c.y-escseq.arg[0]); | 634 | DEFAULT(escseq.arg[0], 1); |
| 668 | break; | 635 | tmoveto(escseq.arg[0]-1, term.c.y); |
| 669 | case 'G': /* Move to <col> */ | 636 | break; |
| 670 | case '`': | 637 | case 'H': /* Move to <row> <col> */ |
| 671 | DEFAULT(escseq.arg[0], 1); | 638 | case 'f': |
| 672 | tmoveto(escseq.arg[0]-1, term.c.y); | 639 | DEFAULT(escseq.arg[0], 1); |
| 640 | DEFAULT(escseq.arg[1], 1); | ||
| 641 | tmoveto(escseq.arg[1]-1, escseq.arg[0]-1); | ||
| 642 | break; | ||
| 643 | case 'J': /* Clear screen */ | ||
| 644 | switch(escseq.arg[0]) { | ||
| 645 | case 0: /* below */ | ||
| 646 | tclearregion(term.c.x, term.c.y, term.col-1, term.row-1); | ||
| 673 | break; | 647 | break; |
| 674 | case 'H': /* Move to <row> <col> */ | 648 | case 1: /* above */ |
| 675 | case 'f': | 649 | tclearregion(0, 0, term.c.x, term.c.y); |
| 676 | DEFAULT(escseq.arg[0], 1); | ||
| 677 | DEFAULT(escseq.arg[1], 1); | ||
| 678 | tmoveto(escseq.arg[1]-1, escseq.arg[0]-1); | ||
| 679 | break; | 650 | break; |
| 680 | case 'J': /* Clear screen */ | 651 | case 2: /* all */ |
| 681 | switch(escseq.arg[0]) { | 652 | tclearregion(0, 0, term.col-1, term.row-1); |
| 682 | case 0: /* below */ | 653 | break; |
| 683 | tclearregion(term.c.x, term.c.y, term.col-1, term.row-1); | 654 | } |
| 684 | break; | 655 | break; |
| 685 | case 1: /* above */ | 656 | case 'K': /* Clear line */ |
| 686 | tclearregion(0, 0, term.c.x, term.c.y); | 657 | switch(escseq.arg[0]) { |
| 687 | break; | 658 | case 0: /* right */ |
| 688 | case 2: /* all */ | 659 | tclearregion(term.c.x, term.c.y, term.col-1, term.c.y); |
| 689 | tclearregion(0, 0, term.col-1, term.row-1); | ||
| 690 | break; | ||
| 691 | } | ||
| 692 | break; | 660 | break; |
| 693 | case 'K': /* Clear line */ | 661 | case 1: /* left */ |
| 694 | switch(escseq.arg[0]) { | 662 | tclearregion(0, term.c.y, term.c.x, term.c.y); |
| 695 | case 0: /* right */ | ||
| 696 | tclearregion(term.c.x, term.c.y, term.col-1, term.c.y); | ||
| 697 | break; | ||
| 698 | case 1: /* left */ | ||
| 699 | tclearregion(0, term.c.y, term.c.x, term.c.y); | ||
| 700 | break; | ||
| 701 | case 2: /* all */ | ||
| 702 | tclearregion(0, term.c.y, term.col-1, term.c.y); | ||
| 703 | break; | ||
| 704 | } | ||
| 705 | break; | 663 | break; |
| 706 | case 'L': /* Insert <n> blank lines */ | 664 | case 2: /* all */ |
| 707 | DEFAULT(escseq.arg[0], 1); | 665 | tclearregion(0, term.c.y, term.col-1, term.c.y); |
| 708 | tinsertblankline(escseq.arg[0]); | ||
| 709 | break; | 666 | break; |
| 710 | case 'l': | 667 | } |
| 711 | if(escseq.priv && escseq.arg[0] == 25) | 668 | break; |
| 669 | case 'S': | ||
| 670 | case 'L': /* Insert <n> blank lines */ | ||
| 671 | DEFAULT(escseq.arg[0], 1); | ||
| 672 | tinsertblankline(escseq.arg[0]); | ||
| 673 | break; | ||
| 674 | case 'l': | ||
| 675 | if(escseq.priv && escseq.arg[0] == 25) | ||
| 712 | term.c.hidden = 1; | 676 | term.c.hidden = 1; |
| 713 | break; | 677 | break; |
| 714 | case 'M': /* Delete <n> lines */ | 678 | case 'M': /* Delete <n> lines */ |
| 715 | DEFAULT(escseq.arg[0], 1); | 679 | DEFAULT(escseq.arg[0], 1); |
| 716 | tdeleteline(escseq.arg[0]); | 680 | tdeleteline(escseq.arg[0]); |
| 717 | break; | 681 | break; |
| 718 | case 'P': /* Delete <n> char */ | 682 | case 'X': |
| 719 | DEFAULT(escseq.arg[0], 1); | 683 | case 'P': /* Delete <n> char */ |
| 720 | tdeletechar(escseq.arg[0]); | 684 | DEFAULT(escseq.arg[0], 1); |
| 721 | break; | 685 | tdeletechar(escseq.arg[0]); |
| 722 | case 'd': /* Move to <row> */ | 686 | break; |
| 687 | case 'd': /* Move to <row> */ | ||
| 688 | DEFAULT(escseq.arg[0], 1); | ||
| 689 | tmoveto(term.c.x, escseq.arg[0]-1); | ||
| 690 | break; | ||
| 691 | case 'h': /* Set terminal mode */ | ||
| 692 | if(escseq.priv && escseq.arg[0] == 25) | ||
| 693 | term.c.hidden = 0; | ||
| 694 | break; | ||
| 695 | case 'm': /* Terminal attribute (color) */ | ||
| 696 | tsetattr(escseq.arg, escseq.narg); | ||
| 697 | break; | ||
| 698 | case 'r': | ||
| 699 | if(escseq.priv) | ||
| 700 | ; | ||
| 701 | else { | ||
| 723 | DEFAULT(escseq.arg[0], 1); | 702 | DEFAULT(escseq.arg[0], 1); |
| 724 | tmoveto(term.c.x, escseq.arg[0]-1); | 703 | DEFAULT(escseq.arg[1], term.row); |
| 725 | break; | 704 | tsetscroll(escseq.arg[0]-1, escseq.arg[1]-1); |
| 726 | case 'h': /* Set terminal mode */ | ||
| 727 | if(escseq.priv && escseq.arg[0] == 25) | ||
| 728 | term.c.hidden = 0; | ||
| 729 | break; | ||
| 730 | case 'm': /* Terminal attribute (color) */ | ||
| 731 | tsetattr(escseq.arg, escseq.narg); | ||
| 732 | break; | ||
| 733 | case 'r': | ||
| 734 | if(escseq.priv) | ||
| 735 | ; | ||
| 736 | else { | ||
| 737 | DEFAULT(escseq.arg[0], 1); | ||
| 738 | DEFAULT(escseq.arg[1], term.row); | ||
| 739 | tsetscroll(escseq.arg[0]-1, escseq.arg[1]-1); | ||
| 740 | } | ||
| 741 | break; | ||
| 742 | case 's': /* Save cursor position */ | ||
| 743 | tcpos(CSsave); | ||
| 744 | break; | ||
| 745 | case 'u': /* Load cursor position */ | ||
| 746 | tcpos(CSload); | ||
| 747 | break; | ||
| 748 | } | 705 | } |
| 749 | break; | 706 | break; |
| 707 | case 's': /* Save cursor position */ | ||
| 708 | tcpos(CSsave); | ||
| 709 | break; | ||
| 710 | case 'u': /* Load cursor position */ | ||
| 711 | tcpos(CSload); | ||
| 712 | break; | ||
| 750 | } | 713 | } |
| 751 | } | 714 | } |
| 752 | 715 | ||
| 753 | void | 716 | void |
| 754 | escdump(void) { | 717 | csidump(void) { |
| 755 | int i; | 718 | int i; |
| 756 | printf("rawbuf : %s\n", escseq.buf); | 719 | printf("ESC [ %s", escseq.priv ? "? " : ""); |
| 757 | printf("prechar : %c\n", escseq.pre); | ||
| 758 | printf("private : %c\n", escseq.priv ? '?' : ' '); | ||
| 759 | printf("narg : %d\n", escseq.narg); | ||
| 760 | if(escseq.narg) | 720 | if(escseq.narg) |
| 761 | for(i = 0; i < escseq.narg; i++) | 721 | for(i = 0; i < escseq.narg; i++) |
| 762 | printf("\targ %d = %d\n", i, escseq.arg[i]); | 722 | printf("%d ", escseq.arg[i]); |
| 763 | printf("mode : %c\n", escseq.mode); | 723 | if(escseq.mode) |
| 724 | putchar(escseq.mode); | ||
| 725 | putchar('\n'); | ||
| 764 | } | 726 | } |
| 765 | 727 | ||
| 766 | void | 728 | void |
| 767 | escreset(void) { | 729 | csireset(void) { |
| 768 | memset(&escseq, 0, sizeof(escseq)); | 730 | memset(&escseq, 0, sizeof(escseq)); |
| 769 | } | 731 | } |
| 770 | 732 | ||
| @@ -781,21 +743,41 @@ tputtab(void) { | |||
| 781 | 743 | ||
| 782 | void | 744 | void |
| 783 | tputc(char c) { | 745 | tputc(char c) { |
| 784 | static int inesc = 0; | ||
| 785 | #if 0 | 746 | #if 0 |
| 786 | dump(c); | 747 | dump(c); |
| 787 | #endif | 748 | #endif |
| 788 | /* start of escseq */ | 749 | if(term.esc & ESCin) { |
| 789 | if(c == '\033') | 750 | if(term.esc & ESCcsi) { |
| 790 | escreset(), inesc = 1; | 751 | escseq.buf[escseq.len++] = c; |
| 791 | else if(inesc) { | 752 | if(BETWEEN(c, 0x40, 0x7E) || escseq.len >= ESCSIZ) { |
| 792 | inesc = escaddc(c); | 753 | term.esc = 0; |
| 793 | } /* normal char */ | 754 | csiparse(), csihandle(); |
| 794 | else switch(c) { | 755 | } |
| 795 | default: | 756 | } else if (term.esc & ESCosc) { |
| 796 | tsetchar(c); | 757 | if(c == ';') { |
| 797 | tcursor(CSright); | 758 | term.titlelen = 0; |
| 798 | break; | 759 | term.esc = ESCin | ESCtitle; |
| 760 | } | ||
| 761 | } else if(term.esc & ESCtitle) { | ||
| 762 | if(c == '\a' || term.titlelen+1 >= TITLESIZ) { | ||
| 763 | term.esc = 0; | ||
| 764 | term.title[term.titlelen] = '\0'; | ||
| 765 | XStoreName(xw.dis, xw.win, term.title); | ||
| 766 | } else { | ||
| 767 | term.title[term.titlelen++] = c; | ||
| 768 | } | ||
| 769 | } else { | ||
| 770 | switch(c) { | ||
| 771 | case '[': | ||
| 772 | term.esc |= ESCcsi; | ||
| 773 | break; | ||
| 774 | case ']': | ||
| 775 | term.esc |= ESCosc; | ||
| 776 | break; | ||
| 777 | } | ||
| 778 | } | ||
| 779 | } else { | ||
| 780 | switch(c) { | ||
| 799 | case '\t': | 781 | case '\t': |
| 800 | tputtab(); | 782 | tputtab(); |
| 801 | break; | 783 | break; |
| @@ -811,6 +793,15 @@ tputc(char c) { | |||
| 811 | case '\a': | 793 | case '\a': |
| 812 | xbell(); | 794 | xbell(); |
| 813 | break; | 795 | break; |
| 796 | case '\033': | ||
| 797 | csireset(); | ||
| 798 | term.esc = ESCin; | ||
| 799 | break; | ||
| 800 | default: | ||
| 801 | tsetchar(c); | ||
| 802 | tcursor(CSright); | ||
| 803 | break; | ||
| 804 | } | ||
| 814 | } | 805 | } |
| 815 | } | 806 | } |
| 816 | 807 | ||
