aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--st.c365
1 files changed, 230 insertions, 135 deletions
diff --git a/st.c b/st.c
index 1ac7fde..f6c9f18 100644
--- a/st.c
+++ b/st.c
@@ -180,9 +180,9 @@ typedef struct {
180typedef struct { 180typedef struct {
181 int row; /* nb row */ 181 int row; /* nb row */
182 int col; /* nb col */ 182 int col; /* nb col */
183 Line* line; /* screen */ 183 Line *line; /* screen */
184 Line* alt; /* alternate screen */ 184 Line *alt; /* alternate screen */
185 bool* dirty; /* dirtyness of lines */ 185 bool *dirty; /* dirtyness of lines */
186 TCursor c; /* cursor */ 186 TCursor c; /* cursor */
187 int top; /* top scroll limit */ 187 int top; /* top scroll limit */
188 int bot; /* bottom scroll limit */ 188 int bot; /* bottom scroll limit */
@@ -242,7 +242,7 @@ typedef struct {
242 int descent; 242 int descent;
243 short lbearing; 243 short lbearing;
244 short rbearing; 244 short rbearing;
245 XftFont* xft_set; 245 XftFont *xft_set;
246} Font; 246} Font;
247 247
248/* Drawing Context */ 248/* Drawing Context */
@@ -252,7 +252,7 @@ typedef struct {
252 Font font, bfont, ifont, ibfont; 252 Font font, bfont, ifont, ibfont;
253} DC; 253} DC;
254 254
255static void die(const char*, ...); 255static void die(const char *, ...);
256static void draw(void); 256static void draw(void);
257static void redraw(void); 257static void redraw(void);
258static void drawregion(int, int, int, int); 258static void drawregion(int, int, int, int);
@@ -279,7 +279,7 @@ static void tmoveto(int, int);
279static void tnew(int, int); 279static void tnew(int, int);
280static void tnewline(int); 280static void tnewline(int);
281static void tputtab(bool); 281static void tputtab(bool);
282static void tputc(char*, int); 282static void tputc(char *, int);
283static void treset(void); 283static void treset(void);
284static int tresize(int, int); 284static int tresize(int, int);
285static void tscrollup(int, int); 285static void tscrollup(int, int);
@@ -313,7 +313,7 @@ static void xresize(int, int);
313static void expose(XEvent *); 313static void expose(XEvent *);
314static void visibility(XEvent *); 314static void visibility(XEvent *);
315static void unmap(XEvent *); 315static void unmap(XEvent *);
316static char* kmap(KeySym, uint); 316static char *kmap(KeySym, uint);
317static void kpress(XEvent *); 317static void kpress(XEvent *);
318static void cmessage(XEvent *); 318static void cmessage(XEvent *);
319static void resize(XEvent *); 319static void resize(XEvent *);
@@ -378,8 +378,10 @@ static char *opt_font = NULL;
378void * 378void *
379xmalloc(size_t len) { 379xmalloc(size_t len) {
380 void *p = malloc(len); 380 void *p = malloc(len);
381
381 if(!p) 382 if(!p)
382 die("Out of memory\n"); 383 die("Out of memory\n");
384
383 return p; 385 return p;
384} 386}
385 387
@@ -387,14 +389,17 @@ void *
387xrealloc(void *p, size_t len) { 389xrealloc(void *p, size_t len) {
388 if((p = realloc(p, len)) == NULL) 390 if((p = realloc(p, len)) == NULL)
389 die("Out of memory\n"); 391 die("Out of memory\n");
392
390 return p; 393 return p;
391} 394}
392 395
393void * 396void *
394xcalloc(size_t nmemb, size_t size) { 397xcalloc(size_t nmemb, size_t size) {
395 void *p = calloc(nmemb, size); 398 void *p = calloc(nmemb, size);
399
396 if(!p) 400 if(!p)
397 die("Out of memory\n"); 401 die("Out of memory\n");
402
398 return p; 403 return p;
399} 404}
400 405
@@ -455,8 +460,10 @@ utf8decode(char *s, long *u) {
455 } else if((c & (B7|B6|B5|B4|B3)) == (B7|B6|B5|B4)) { /* 11110xxx */ 460 } else if((c & (B7|B6|B5|B4|B3)) == (B7|B6|B5|B4)) { /* 11110xxx */
456 *u = c & (B2|B1|B0); 461 *u = c & (B2|B1|B0);
457 n = 3; 462 n = 3;
458 } else 463 } else {
459 goto invalid; 464 goto invalid;
465 }
466
460 for(i = n, ++s; i > 0; --i, ++rtn, ++s) { 467 for(i = n, ++s; i > 0; --i, ++rtn, ++s) {
461 c = *s; 468 c = *s;
462 if((c & (B7|B6)) != B7) /* 10xxxxxx */ 469 if((c & (B7|B6)) != B7) /* 10xxxxxx */
@@ -464,14 +471,18 @@ utf8decode(char *s, long *u) {
464 *u <<= 6; 471 *u <<= 6;
465 *u |= c & (B5|B4|B3|B2|B1|B0); 472 *u |= c & (B5|B4|B3|B2|B1|B0);
466 } 473 }
474
467 if((n == 1 && *u < 0x80) || 475 if((n == 1 && *u < 0x80) ||
468 (n == 2 && *u < 0x800) || 476 (n == 2 && *u < 0x800) ||
469 (n == 3 && *u < 0x10000) || 477 (n == 3 && *u < 0x10000) ||
470 (*u >= 0xD800 && *u <= 0xDFFF)) 478 (*u >= 0xD800 && *u <= 0xDFFF)) {
471 goto invalid; 479 goto invalid;
480 }
481
472 return rtn; 482 return rtn;
473invalid: 483invalid:
474 *u = 0xFFFD; 484 *u = 0xFFFD;
485
475 return rtn; 486 return rtn;
476} 487}
477 488
@@ -481,7 +492,7 @@ utf8encode(long *u, char *s) {
481 ulong uc; 492 ulong uc;
482 int i, n; 493 int i, n;
483 494
484 sp = (uchar*) s; 495 sp = (uchar *)s;
485 uc = *u; 496 uc = *u;
486 if(uc < 0x80) { 497 if(uc < 0x80) {
487 *sp = uc; /* 0xxxxxxx */ 498 *sp = uc; /* 0xxxxxxx */
@@ -498,14 +509,17 @@ utf8encode(long *u, char *s) {
498 } else { 509 } else {
499 goto invalid; 510 goto invalid;
500 } 511 }
512
501 for(i=n,++sp; i>0; --i,++sp) 513 for(i=n,++sp; i>0; --i,++sp)
502 *sp = ((uc >> 6*(i-1)) & (B5|B4|B3|B2|B1|B0)) | B7; /* 10xxxxxx */ 514 *sp = ((uc >> 6*(i-1)) & (B5|B4|B3|B2|B1|B0)) | B7; /* 10xxxxxx */
515
503 return n+1; 516 return n+1;
504invalid: 517invalid:
505 /* U+FFFD */ 518 /* U+FFFD */
506 *s++ = '\xEF'; 519 *s++ = '\xEF';
507 *s++ = '\xBF'; 520 *s++ = '\xBF';
508 *s = '\xBD'; 521 *s = '\xBD';
522
509 return 3; 523 return 3;
510} 524}
511 525
@@ -515,38 +529,40 @@ int
515isfullutf8(char *s, int b) { 529isfullutf8(char *s, int b) {
516 uchar *c1, *c2, *c3; 530 uchar *c1, *c2, *c3;
517 531
518 c1 = (uchar *) s; 532 c1 = (uchar *)s;
519 c2 = (uchar *) ++s; 533 c2 = (uchar *)++s;
520 c3 = (uchar *) ++s; 534 c3 = (uchar *)++s;
521 if(b < 1) 535 if(b < 1) {
522 return 0; 536 return 0;
523 else if((*c1&(B7|B6|B5)) == (B7|B6) && b == 1) 537 } else if((*c1&(B7|B6|B5)) == (B7|B6) && b == 1) {
524 return 0; 538 return 0;
525 else if((*c1&(B7|B6|B5|B4)) == (B7|B6|B5) && 539 } else if((*c1&(B7|B6|B5|B4)) == (B7|B6|B5) &&
526 ((b == 1) || 540 ((b == 1) ||
527 ((b == 2) && (*c2&(B7|B6)) == B7))) 541 ((b == 2) && (*c2&(B7|B6)) == B7))) {
528 return 0; 542 return 0;
529 else if((*c1&(B7|B6|B5|B4|B3)) == (B7|B6|B5|B4) && 543 } else if((*c1&(B7|B6|B5|B4|B3)) == (B7|B6|B5|B4) &&
530 ((b == 1) || 544 ((b == 1) ||
531 ((b == 2) && (*c2&(B7|B6)) == B7) || 545 ((b == 2) && (*c2&(B7|B6)) == B7) ||
532 ((b == 3) && (*c2&(B7|B6)) == B7 && (*c3&(B7|B6)) == B7))) 546 ((b == 3) && (*c2&(B7|B6)) == B7 && (*c3&(B7|B6)) == B7))) {
533 return 0; 547 return 0;
534 else 548 } else {
535 return 1; 549 return 1;
550 }
536} 551}
537 552
538int 553int
539utf8size(char *s) { 554utf8size(char *s) {
540 uchar c = *s; 555 uchar c = *s;
541 556
542 if(~c&B7) 557 if(~c&B7) {
543 return 1; 558 return 1;
544 else if((c&(B7|B6|B5)) == (B7|B6)) 559 } else if((c&(B7|B6|B5)) == (B7|B6)) {
545 return 2; 560 return 2;
546 else if((c&(B7|B6|B5|B4)) == (B7|B6|B5)) 561 } else if((c&(B7|B6|B5|B4)) == (B7|B6|B5)) {
547 return 3; 562 return 3;
548 else 563 } else {
549 return 4; 564 return 4;
565 }
550} 566}
551 567
552void 568void
@@ -563,13 +579,18 @@ selinit(void) {
563 579
564static inline bool 580static inline bool
565selected(int x, int y) { 581selected(int x, int y) {
582 int bx, ex;
583
566 if(sel.ey == y && sel.by == y) { 584 if(sel.ey == y && sel.by == y) {
567 int bx = MIN(sel.bx, sel.ex); 585 bx = MIN(sel.bx, sel.ex);
568 int ex = MAX(sel.bx, sel.ex); 586 ex = MAX(sel.bx, sel.ex);
569 return BETWEEN(x, bx, ex); 587 return BETWEEN(x, bx, ex);
570 } 588 }
571 return ((sel.b.y < y&&y < sel.e.y) || (y==sel.e.y && x<=sel.e.x)) 589
572 || (y==sel.b.y && x>=sel.b.x && (x<=sel.e.x || sel.b.y!=sel.e.y)); 590 return ((sel.b.y < y&&y < sel.e.y)
591 || (y==sel.e.y && x<=sel.e.x))
592 || (y==sel.b.y && x>=sel.b.x
593 && (x<=sel.e.x || sel.b.y!=sel.e.y));
573} 594}
574 595
575void 596void
@@ -621,9 +642,9 @@ mousereport(XEvent *e) {
621 642
622void 643void
623bpress(XEvent *e) { 644bpress(XEvent *e) {
624 if(IS_SET(MODE_MOUSE)) 645 if(IS_SET(MODE_MOUSE)) {
625 mousereport(e); 646 mousereport(e);
626 else if(e->xbutton.button == Button1) { 647 } else if(e->xbutton.button == Button1) {
627 if(sel.bx != -1) { 648 if(sel.bx != -1) {
628 sel.bx = -1; 649 sel.bx = -1;
629 tsetdirt(sel.b.y, sel.e.y); 650 tsetdirt(sel.b.y, sel.e.y);
@@ -637,22 +658,20 @@ bpress(XEvent *e) {
637 658
638void 659void
639selcopy(void) { 660selcopy(void) {
640 char *str, *ptr; 661 char *str, *ptr, *p;
641 int x, y, bufsize, is_selected = 0; 662 int x, y, bufsize, is_selected = 0, size;
663 Glyph *gp;
642 664
643 if(sel.bx == -1) 665 if(sel.bx == -1) {
644 str = NULL; 666 str = NULL;
645 667 } else {
646 else {
647 bufsize = (term.col+1) * (sel.e.y-sel.b.y+1) * UTF_SIZ; 668 bufsize = (term.col+1) * (sel.e.y-sel.b.y+1) * UTF_SIZ;
648 ptr = str = xmalloc(bufsize); 669 ptr = str = xmalloc(bufsize);
649 670
650 /* append every set & selected glyph to the selection */ 671 /* append every set & selected glyph to the selection */
651 for(y = 0; y < term.row; y++) { 672 for(y = 0; y < term.row; y++) {
652 for(x = 0; x < term.col; x++) { 673 for(x = 0; x < term.col; x++) {
653 int size; 674 gp = &term.line[y][x];
654 char *p;
655 Glyph *gp = &term.line[y][x];
656 675
657 if(!(is_selected = selected(x, y))) 676 if(!(is_selected = selected(x, y)))
658 continue; 677 continue;
@@ -694,8 +713,9 @@ selnotify(XEvent *e) {
694} 713}
695 714
696void 715void
697selpaste() { 716selpaste(void) {
698 XConvertSelection(xw.dpy, XA_PRIMARY, sel.xtarget, XA_PRIMARY, xw.win, CurrentTime); 717 XConvertSelection(xw.dpy, XA_PRIMARY, sel.xtarget, XA_PRIMARY,
718 xw.win, CurrentTime);
699} 719}
700 720
701void selclear(XEvent *e) { 721void selclear(XEvent *e) {
@@ -709,7 +729,7 @@ void
709selrequest(XEvent *e) { 729selrequest(XEvent *e) {
710 XSelectionRequestEvent *xsre; 730 XSelectionRequestEvent *xsre;
711 XSelectionEvent xev; 731 XSelectionEvent xev;
712 Atom xa_targets; 732 Atom xa_targets, string;
713 733
714 xsre = (XSelectionRequestEvent *) e; 734 xsre = (XSelectionRequestEvent *) e;
715 xev.type = SelectionNotify; 735 xev.type = SelectionNotify;
@@ -723,7 +743,7 @@ selrequest(XEvent *e) {
723 xa_targets = XInternAtom(xw.dpy, "TARGETS", 0); 743 xa_targets = XInternAtom(xw.dpy, "TARGETS", 0);
724 if(xsre->target == xa_targets) { 744 if(xsre->target == xa_targets) {
725 /* respond with the supported type */ 745 /* respond with the supported type */
726 Atom string = sel.xtarget; 746 string = sel.xtarget;
727 XChangeProperty(xsre->display, xsre->requestor, xsre->property, 747 XChangeProperty(xsre->display, xsre->requestor, xsre->property,
728 XA_ATOM, 32, PropModeReplace, 748 XA_ATOM, 32, PropModeReplace,
729 (uchar *) &string, 1); 749 (uchar *) &string, 1);
@@ -756,18 +776,20 @@ xsetsel(char *str) {
756 776
757void 777void
758brelease(XEvent *e) { 778brelease(XEvent *e) {
779 struct timeval now;
780
759 if(IS_SET(MODE_MOUSE)) { 781 if(IS_SET(MODE_MOUSE)) {
760 mousereport(e); 782 mousereport(e);
761 return; 783 return;
762 } 784 }
763 if(e->xbutton.button == Button2) 785
786 if(e->xbutton.button == Button2) {
764 selpaste(); 787 selpaste();
765 else if(e->xbutton.button == Button1) { 788 } else if(e->xbutton.button == Button1) {
766 sel.mode = 0; 789 sel.mode = 0;
767 getbuttoninfo(e, NULL, &sel.ex, &sel.ey); 790 getbuttoninfo(e, NULL, &sel.ex, &sel.ey);
768 term.dirty[sel.ey] = 1; 791 term.dirty[sel.ey] = 1;
769 if(sel.bx == sel.ex && sel.by == sel.ey) { 792 if(sel.bx == sel.ex && sel.by == sel.ey) {
770 struct timeval now;
771 sel.bx = -1; 793 sel.bx = -1;
772 gettimeofday(&now, NULL); 794 gettimeofday(&now, NULL);
773 795
@@ -781,34 +803,44 @@ brelease(XEvent *e) {
781 /* double click to select word */ 803 /* double click to select word */
782 sel.bx = sel.ex; 804 sel.bx = sel.ex;
783 while(sel.bx > 0 && term.line[sel.ey][sel.bx-1].state & GLYPH_SET && 805 while(sel.bx > 0 && term.line[sel.ey][sel.bx-1].state & GLYPH_SET &&
784 term.line[sel.ey][sel.bx-1].c[0] != ' ') sel.bx--; 806 term.line[sel.ey][sel.bx-1].c[0] != ' ') {
807 sel.bx--;
808 }
785 sel.b.x = sel.bx; 809 sel.b.x = sel.bx;
786 while(sel.ex < term.col-1 && term.line[sel.ey][sel.ex+1].state & GLYPH_SET && 810 while(sel.ex < term.col-1 && term.line[sel.ey][sel.ex+1].state & GLYPH_SET &&
787 term.line[sel.ey][sel.ex+1].c[0] != ' ') sel.ex++; 811 term.line[sel.ey][sel.ex+1].c[0] != ' ') {
812 sel.ex++;
813 }
788 sel.e.x = sel.ex; 814 sel.e.x = sel.ex;
789 sel.b.y = sel.e.y = sel.ey; 815 sel.b.y = sel.e.y = sel.ey;
790 selcopy(); 816 selcopy();
791 } 817 }
792 } else 818 } else {
793 selcopy(); 819 selcopy();
820 }
794 } 821 }
822
795 memcpy(&sel.tclick2, &sel.tclick1, sizeof(struct timeval)); 823 memcpy(&sel.tclick2, &sel.tclick1, sizeof(struct timeval));
796 gettimeofday(&sel.tclick1, NULL); 824 gettimeofday(&sel.tclick1, NULL);
797} 825}
798 826
799void 827void
800bmotion(XEvent *e) { 828bmotion(XEvent *e) {
829 int starty, endy, oldey, oldex;
830
801 if(IS_SET(MODE_MOUSE)) { 831 if(IS_SET(MODE_MOUSE)) {
802 mousereport(e); 832 mousereport(e);
803 return; 833 return;
804 } 834 }
835
805 if(sel.mode) { 836 if(sel.mode) {
806 int oldey = sel.ey, oldex = sel.ex; 837 oldey = sel.ey;
838 oldex = sel.ex;
807 getbuttoninfo(e, NULL, &sel.ex, &sel.ey); 839 getbuttoninfo(e, NULL, &sel.ex, &sel.ey);
808 840
809 if(oldey != sel.ey || oldex != sel.ex) { 841 if(oldey != sel.ey || oldex != sel.ex) {
810 int starty = MIN(oldey, sel.ey); 842 starty = MIN(oldey, sel.ey);
811 int endy = MAX(oldey, sel.ey); 843 endy = MAX(oldey, sel.ey);
812 tsetdirt(starty, endy); 844 tsetdirt(starty, endy);
813 } 845 }
814 } 846 }
@@ -864,9 +896,9 @@ sigchld(int a) {
864void 896void
865ttynew(void) { 897ttynew(void) {
866 int m, s; 898 int m, s;
899 struct winsize w = {term.row, term.col, 0, 0};
867 900
868 /* seems to work fine on linux, openbsd and freebsd */ 901 /* seems to work fine on linux, openbsd and freebsd */
869 struct winsize w = {term.row, term.col, 0, 0};
870 if(openpty(&m, &s, NULL, NULL, &w) < 0) 902 if(openpty(&m, &s, NULL, NULL, &w) < 0)
871 die("openpty failed: %s\n", SERRNO); 903 die("openpty failed: %s\n", SERRNO);
872 904
@@ -905,6 +937,7 @@ ttynew(void) {
905void 937void
906dump(char c) { 938dump(char c) {
907 static int col; 939 static int col;
940
908 fprintf(stderr, " %02x '%c' ", c, isprint(c)?c:'.'); 941 fprintf(stderr, " %02x '%c' ", c, isprint(c)?c:'.');
909 if(++col % 10 == 0) 942 if(++col % 10 == 0)
910 fprintf(stderr, "\n"); 943 fprintf(stderr, "\n");
@@ -931,7 +964,7 @@ ttyread(void) {
931 charsize = utf8decode(ptr, &utf8c); 964 charsize = utf8decode(ptr, &utf8c);
932 utf8encode(&utf8c, s); 965 utf8encode(&utf8c, s);
933 tputc(s, charsize); 966 tputc(s, charsize);
934 ptr += charsize; 967 ptr += charsize;
935 buflen -= charsize; 968 buflen -= charsize;
936 } 969 }
937 970
@@ -958,8 +991,7 @@ ttyresize(void) {
958} 991}
959 992
960void 993void
961tsetdirt(int top, int bot) 994tsetdirt(int top, int bot) {
962{
963 int i; 995 int i;
964 996
965 LIMIT(top, 0, term.row-1); 997 LIMIT(top, 0, term.row-1);
@@ -970,8 +1002,7 @@ tsetdirt(int top, int bot)
970} 1002}
971 1003
972void 1004void
973tfulldirt(void) 1005tfulldirt(void) {
974{
975 tsetdirt(0, term.row-1); 1006 tsetdirt(0, term.row-1);
976} 1007}
977 1008
@@ -979,15 +1010,18 @@ void
979tcursor(int mode) { 1010tcursor(int mode) {
980 static TCursor c; 1011 static TCursor c;
981 1012
982 if(mode == CURSOR_SAVE) 1013 if(mode == CURSOR_SAVE) {
983 c = term.c; 1014 c = term.c;
984 else if(mode == CURSOR_LOAD) 1015 } else if(mode == CURSOR_LOAD) {
985 term.c = c, tmoveto(c.x, c.y); 1016 term.c = c;
1017 tmoveto(c.x, c.y);
1018 }
986} 1019}
987 1020
988void 1021void
989treset(void) { 1022treset(void) {
990 uint i; 1023 uint i;
1024
991 term.c = (TCursor){{ 1025 term.c = (TCursor){{
992 .mode = ATTR_NULL, 1026 .mode = ATTR_NULL,
993 .fg = DefaultFG, 1027 .fg = DefaultFG,
@@ -1024,7 +1058,8 @@ tnew(int col, int row) {
1024 1058
1025void 1059void
1026tswapscreen(void) { 1060tswapscreen(void) {
1027 Line* tmp = term.line; 1061 Line *tmp = term.line;
1062
1028 term.line = term.alt; 1063 term.line = term.alt;
1029 term.alt = tmp; 1064 term.alt = tmp;
1030 term.mode ^= MODE_ALTSCREEN; 1065 term.mode ^= MODE_ALTSCREEN;
@@ -1098,10 +1133,12 @@ selscroll(int orig, int n) {
1098void 1133void
1099tnewline(int first_col) { 1134tnewline(int first_col) {
1100 int y = term.c.y; 1135 int y = term.c.y;
1101 if(y == term.bot) 1136
1137 if(y == term.bot) {
1102 tscrollup(term.top, 1); 1138 tscrollup(term.top, 1);
1103 else 1139 } else {
1104 y++; 1140 y++;
1141 }
1105 tmoveto(first_col ? 0 : term.c.x, y); 1142 tmoveto(first_col ? 0 : term.c.x, y);
1106} 1143}
1107 1144
@@ -1119,11 +1156,12 @@ csiparse(void) {
1119 csiescseq.arg[csiescseq.narg] *= 10; 1156 csiescseq.arg[csiescseq.narg] *= 10;
1120 csiescseq.arg[csiescseq.narg] += *p++ - '0'/*, noarg = 0 */; 1157 csiescseq.arg[csiescseq.narg] += *p++ - '0'/*, noarg = 0 */;
1121 } 1158 }
1122 if(*p == ';' && csiescseq.narg+1 < ESC_ARG_SIZ) 1159 if(*p == ';' && csiescseq.narg+1 < ESC_ARG_SIZ) {
1123 csiescseq.narg++, p++; 1160 csiescseq.narg++, p++;
1124 else { 1161 } else {
1125 csiescseq.mode = *p; 1162 csiescseq.mode = *p;
1126 csiescseq.narg++; 1163 csiescseq.narg++;
1164
1127 return; 1165 return;
1128 } 1166 }
1129 } 1167 }
@@ -1140,21 +1178,21 @@ tmoveto(int x, int y) {
1140 1178
1141void 1179void
1142tsetchar(char *c) { 1180tsetchar(char *c) {
1181 char *vt100_0[62] = { /* 0x41 - 0x7e */
1182 "↑", "↓", "→", "←", "█", "▚", "☃", /* A - G */
1183 0, 0, 0, 0, 0, 0, 0, 0, /* H - O */
1184 0, 0, 0, 0, 0, 0, 0, 0, /* P - W */
1185 0, 0, 0, 0, 0, 0, 0, " ", /* X - _ */
1186 "◆", "▒", "␉", "␌", "␍", "␊", "°", "±", /* ` - g */
1187 "␤", "␋", "┘", "┐", "┌", "└", "┼", "⎺", /* h - o */
1188 "⎻", "─", "⎼", "⎽", "├", "┤", "┴", "┬", /* p - w */
1189 "│", "≤", "≥", "π", "≠", "£", "·", /* x - ~ */
1190 };
1191
1143 /* 1192 /*
1144 * The table is proudly stolen from rxvt. 1193 * The table is proudly stolen from rxvt.
1145 */ 1194 */
1146 if(term.c.attr.mode & ATTR_GFX) { 1195 if(term.c.attr.mode & ATTR_GFX) {
1147 char *vt100_0[62] = { /* 0x41 - 0x7e */
1148 "↑", "↓", "→", "←", "█", "▚", "☃", /* A - G */
1149 0, 0, 0, 0, 0, 0, 0, 0, /* H - O */
1150 0, 0, 0, 0, 0, 0, 0, 0, /* P - W */
1151 0, 0, 0, 0, 0, 0, 0, " ", /* X - _ */
1152 "◆", "▒", "␉", "␌", "␍", "␊", "°", "±", /* ` - g */
1153 "␤", "␋", "┘", "┐", "┌", "└", "┼", "⎺", /* h - o */
1154 "⎻", "─", "⎼", "⎽", "├", "┤", "┴", "┬", /* p - w */
1155 "│", "≤", "≥", "π", "≠", "£", "·", /* x - ~ */
1156 };
1157
1158 if(c[0] >= 0x41 && c[0] <= 0x7e 1196 if(c[0] >= 0x41 && c[0] <= 0x7e
1159 && vt100_0[c[0] - 0x41]) { 1197 && vt100_0[c[0] - 0x41]) {
1160 c = vt100_0[c[0] - 0x41]; 1198 c = vt100_0[c[0] - 0x41];
@@ -1200,7 +1238,9 @@ tdeletechar(int n) {
1200 tclearregion(term.c.x, term.c.y, term.col-1, term.c.y); 1238 tclearregion(term.c.x, term.c.y, term.col-1, term.c.y);
1201 return; 1239 return;
1202 } 1240 }
1203 memmove(&term.line[term.c.y][dst], &term.line[term.c.y][src], size * sizeof(Glyph)); 1241
1242 memmove(&term.line[term.c.y][dst], &term.line[term.c.y][src],
1243 size * sizeof(Glyph));
1204 tclearregion(term.col-n, term.c.y, term.col-1, term.c.y); 1244 tclearregion(term.col-n, term.c.y, term.col-1, term.c.y);
1205} 1245}
1206 1246
@@ -1216,7 +1256,9 @@ tinsertblank(int n) {
1216 tclearregion(term.c.x, term.c.y, term.col-1, term.c.y); 1256 tclearregion(term.c.x, term.c.y, term.col-1, term.c.y);
1217 return; 1257 return;
1218 } 1258 }
1219 memmove(&term.line[term.c.y][dst], &term.line[term.c.y][src], size * sizeof(Glyph)); 1259
1260 memmove(&term.line[term.c.y][dst], &term.line[term.c.y][src],
1261 size * sizeof(Glyph));
1220 tclearregion(src, term.c.y, dst - 1, term.c.y); 1262 tclearregion(src, term.c.y, dst - 1, term.c.y);
1221} 1263}
1222 1264
@@ -1282,13 +1324,18 @@ tsetattr(int *attr, int l) {
1282 case 38: 1324 case 38:
1283 if(i + 2 < l && attr[i + 1] == 5) { 1325 if(i + 2 < l && attr[i + 1] == 5) {
1284 i += 2; 1326 i += 2;
1285 if(BETWEEN(attr[i], 0, 255)) 1327 if(BETWEEN(attr[i], 0, 255)) {
1286 term.c.attr.fg = attr[i]; 1328 term.c.attr.fg = attr[i];
1287 else 1329 } else {
1288 fprintf(stderr, "erresc: bad fgcolor %d\n", attr[i]); 1330 fprintf(stderr,
1331 "erresc: bad fgcolor %d\n",
1332 attr[i]);
1333 }
1334 } else {
1335 fprintf(stderr,
1336 "erresc(38): gfx attr %d unknown\n",
1337 attr[i]);
1289 } 1338 }
1290 else
1291 fprintf(stderr, "erresc(38): gfx attr %d unknown\n", attr[i]);
1292 break; 1339 break;
1293 case 39: 1340 case 39:
1294 term.c.attr.fg = DefaultFG; 1341 term.c.attr.fg = DefaultFG;
@@ -1296,28 +1343,36 @@ tsetattr(int *attr, int l) {
1296 case 48: 1343 case 48:
1297 if(i + 2 < l && attr[i + 1] == 5) { 1344 if(i + 2 < l && attr[i + 1] == 5) {
1298 i += 2; 1345 i += 2;
1299 if(BETWEEN(attr[i], 0, 255)) 1346 if(BETWEEN(attr[i], 0, 255)) {
1300 term.c.attr.bg = attr[i]; 1347 term.c.attr.bg = attr[i];
1301 else 1348 } else {
1302 fprintf(stderr, "erresc: bad bgcolor %d\n", attr[i]); 1349 fprintf(stderr,
1350 "erresc: bad bgcolor %d\n",
1351 attr[i]);
1352 }
1353 } else {
1354 fprintf(stderr,
1355 "erresc(48): gfx attr %d unknown\n",
1356 attr[i]);
1303 } 1357 }
1304 else
1305 fprintf(stderr, "erresc(48): gfx attr %d unknown\n", attr[i]);
1306 break; 1358 break;
1307 case 49: 1359 case 49:
1308 term.c.attr.bg = DefaultBG; 1360 term.c.attr.bg = DefaultBG;
1309 break; 1361 break;
1310 default: 1362 default:
1311 if(BETWEEN(attr[i], 30, 37)) 1363 if(BETWEEN(attr[i], 30, 37)) {
1312 term.c.attr.fg = attr[i] - 30; 1364 term.c.attr.fg = attr[i] - 30;
1313 else if(BETWEEN(attr[i], 40, 47)) 1365 } else if(BETWEEN(attr[i], 40, 47)) {
1314 term.c.attr.bg = attr[i] - 40; 1366 term.c.attr.bg = attr[i] - 40;
1315 else if(BETWEEN(attr[i], 90, 97)) 1367 } else if(BETWEEN(attr[i], 90, 97)) {
1316 term.c.attr.fg = attr[i] - 90 + 8; 1368 term.c.attr.fg = attr[i] - 90 + 8;
1317 else if(BETWEEN(attr[i], 100, 107)) 1369 } else if(BETWEEN(attr[i], 100, 107)) {
1318 term.c.attr.bg = attr[i] - 100 + 8; 1370 term.c.attr.bg = attr[i] - 100 + 8;
1319 else 1371 } else {
1320 fprintf(stderr, "erresc(default): gfx attr %d unknown\n", attr[i]), csidump(); 1372 fprintf(stderr,
1373 "erresc(default): gfx attr %d unknown\n",
1374 attr[i]), csidump();
1375 }
1321 break; 1376 break;
1322 } 1377 }
1323 } 1378 }
@@ -1573,9 +1628,9 @@ csihandle(void) {
1573 tsetattr(csiescseq.arg, csiescseq.narg); 1628 tsetattr(csiescseq.arg, csiescseq.narg);
1574 break; 1629 break;
1575 case 'r': /* DECSTBM -- Set Scrolling Region */ 1630 case 'r': /* DECSTBM -- Set Scrolling Region */
1576 if(csiescseq.priv) 1631 if(csiescseq.priv) {
1577 goto unknown; 1632 goto unknown;
1578 else { 1633 } else {
1579 DEFAULT(csiescseq.arg[0], 1); 1634 DEFAULT(csiescseq.arg[0], 1);
1580 DEFAULT(csiescseq.arg[1], term.row); 1635 DEFAULT(csiescseq.arg[1], term.row);
1581 tsetscroll(csiescseq.arg[0]-1, csiescseq.arg[1]-1); 1636 tsetscroll(csiescseq.arg[0]-1, csiescseq.arg[1]-1);
@@ -1594,14 +1649,22 @@ csihandle(void) {
1594void 1649void
1595csidump(void) { 1650csidump(void) {
1596 int i; 1651 int i;
1652 uint c;
1653
1597 printf("ESC["); 1654 printf("ESC[");
1598 for(i = 0; i < csiescseq.len; i++) { 1655 for(i = 0; i < csiescseq.len; i++) {
1599 uint c = csiescseq.buf[i] & 0xff; 1656 c = csiescseq.buf[i] & 0xff;
1600 if(isprint(c)) putchar(c); 1657 if(isprint(c)) {
1601 else if(c == '\n') printf("(\\n)"); 1658 putchar(c);
1602 else if(c == '\r') printf("(\\r)"); 1659 } else if(c == '\n') {
1603 else if(c == 0x1b) printf("(\\e)"); 1660 printf("(\\n)");
1604 else printf("(%02x)", c); 1661 } else if(c == '\r') {
1662 printf("(\\r)");
1663 } else if(c == 0x1b) {
1664 printf("(\\e)");
1665 } else {
1666 printf("(%02x)", c);
1667 }
1605 } 1668 }
1606 putchar('\n'); 1669 putchar('\n');
1607} 1670}
@@ -1672,14 +1735,22 @@ strparse(void) {
1672void 1735void
1673strdump(void) { 1736strdump(void) {
1674 int i; 1737 int i;
1738 uint c;
1739
1675 printf("ESC%c", strescseq.type); 1740 printf("ESC%c", strescseq.type);
1676 for(i = 0; i < strescseq.len; i++) { 1741 for(i = 0; i < strescseq.len; i++) {
1677 uint c = strescseq.buf[i] & 0xff; 1742 c = strescseq.buf[i] & 0xff;
1678 if(isprint(c)) putchar(c); 1743 if(isprint(c)) {
1679 else if(c == '\n') printf("(\\n)"); 1744 putchar(c);
1680 else if(c == '\r') printf("(\\r)"); 1745 } else if(c == '\n') {
1681 else if(c == 0x1b) printf("(\\e)"); 1746 printf("(\\n)");
1682 else printf("(%02x)", c); 1747 } else if(c == '\r') {
1748 printf("(\\r)");
1749 } else if(c == 0x1b) {
1750 printf("(\\e)");
1751 } else {
1752 printf("(%02x)", c);
1753 }
1683 } 1754 }
1684 printf("ESC\\\n"); 1755 printf("ESC\\\n");
1685} 1756}
@@ -1746,7 +1817,8 @@ tputc(char *c, int len) {
1746 if(term.esc & ESC_START) { 1817 if(term.esc & ESC_START) {
1747 if(term.esc & ESC_CSI) { 1818 if(term.esc & ESC_CSI) {
1748 csiescseq.buf[csiescseq.len++] = ascii; 1819 csiescseq.buf[csiescseq.len++] = ascii;
1749 if(BETWEEN(ascii, 0x40, 0x7E) || csiescseq.len >= ESC_BUF_SIZ) { 1820 if(BETWEEN(ascii, 0x40, 0x7E)
1821 || csiescseq.len >= ESC_BUF_SIZ) {
1750 term.esc = 0; 1822 term.esc = 0;
1751 csiparse(), csihandle(); 1823 csiparse(), csihandle();
1752 } 1824 }
@@ -1811,10 +1883,11 @@ tputc(char *c, int len) {
1811 term.esc = 0; 1883 term.esc = 0;
1812 break; 1884 break;
1813 case 'D': /* IND -- Linefeed */ 1885 case 'D': /* IND -- Linefeed */
1814 if(term.c.y == term.bot) 1886 if(term.c.y == term.bot) {
1815 tscrollup(term.top, 1); 1887 tscrollup(term.top, 1);
1816 else 1888 } else {
1817 tmoveto(term.c.x, term.c.y+1); 1889 tmoveto(term.c.x, term.c.y+1);
1890 }
1818 term.esc = 0; 1891 term.esc = 0;
1819 break; 1892 break;
1820 case 'E': /* NEL -- Next line */ 1893 case 'E': /* NEL -- Next line */
@@ -1826,10 +1899,11 @@ tputc(char *c, int len) {
1826 term.esc = 0; 1899 term.esc = 0;
1827 break; 1900 break;
1828 case 'M': /* RI -- Reverse index */ 1901 case 'M': /* RI -- Reverse index */
1829 if(term.c.y == term.top) 1902 if(term.c.y == term.top) {
1830 tscrolldown(term.top, 1); 1903 tscrolldown(term.top, 1);
1831 else 1904 } else {
1832 tmoveto(term.c.x, term.c.y-1); 1905 tmoveto(term.c.x, term.c.y-1);
1906 }
1833 term.esc = 0; 1907 term.esc = 0;
1834 break; 1908 break;
1835 case 'c': /* RIS -- Reset to inital state */ 1909 case 'c': /* RIS -- Reset to inital state */
@@ -1859,7 +1933,7 @@ tputc(char *c, int len) {
1859 break; 1933 break;
1860 default: 1934 default:
1861 fprintf(stderr, "erresc: unknown sequence ESC 0x%02X '%c'\n", 1935 fprintf(stderr, "erresc: unknown sequence ESC 0x%02X '%c'\n",
1862 (uchar) ascii, isprint(ascii)?ascii:'.'); 1936 (uchar) ascii, isprint(ascii)? ascii:'.');
1863 term.esc = 0; 1937 term.esc = 0;
1864 } 1938 }
1865 } 1939 }
@@ -1870,10 +1944,11 @@ tputc(char *c, int len) {
1870 if(IS_SET(MODE_WRAP) && term.c.state & CURSOR_WRAPNEXT) 1944 if(IS_SET(MODE_WRAP) && term.c.state & CURSOR_WRAPNEXT)
1871 tnewline(1); /* always go to first col */ 1945 tnewline(1); /* always go to first col */
1872 tsetchar(c); 1946 tsetchar(c);
1873 if(term.c.x+1 < term.col) 1947 if(term.c.x+1 < term.col) {
1874 tmoveto(term.c.x+1, term.c.y); 1948 tmoveto(term.c.x+1, term.c.y);
1875 else 1949 } else {
1876 term.c.state |= CURSOR_WRAPNEXT; 1950 term.c.state |= CURSOR_WRAPNEXT;
1951 }
1877 } 1952 }
1878 } 1953 }
1879} 1954}
@@ -1884,6 +1959,7 @@ tresize(int col, int row) {
1884 int minrow = MIN(row, term.row); 1959 int minrow = MIN(row, term.row);
1885 int mincol = MIN(col, term.col); 1960 int mincol = MIN(col, term.col);
1886 int slide = term.c.y - row + 1; 1961 int slide = term.c.y - row + 1;
1962 bool *bp;
1887 1963
1888 if(col < 1 || row < 1) 1964 if(col < 1 || row < 1)
1889 return 0; 1965 return 0;
@@ -1930,7 +2006,7 @@ tresize(int col, int row) {
1930 term.alt [i] = xcalloc(col, sizeof(Glyph)); 2006 term.alt [i] = xcalloc(col, sizeof(Glyph));
1931 } 2007 }
1932 if(col > term.col) { 2008 if(col > term.col) {
1933 bool *bp = term.tabs + term.col; 2009 bp = term.tabs + term.col;
1934 2010
1935 memset(bp, 0, sizeof(*term.tabs) * (col - term.col)); 2011 memset(bp, 0, sizeof(*term.tabs) * (col - term.col));
1936 while(--bp > term.tabs && !*bp) 2012 while(--bp > term.tabs && !*bp)
@@ -1987,7 +2063,8 @@ xloadcols(void) {
1987 2063
1988 for(r = 0; r < 24; r++, i++) { 2064 for(r = 0; r < 24; r++, i++) {
1989 xft_color.red = xft_color.green = xft_color.blue = 0x0808 + 0x0a0a * r; 2065 xft_color.red = xft_color.green = xft_color.blue = 0x0808 + 0x0a0a * r;
1990 if(!XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &xft_color, &dc.xft_col[i])) { 2066 if(!XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &xft_color,
2067 &dc.xft_col[i])) {
1991 die("Could not allocate color %d\n", i); 2068 die("Could not allocate color %d\n", i);
1992 } 2069 }
1993 } 2070 }
@@ -2263,8 +2340,7 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) {
2263 2340
2264void 2341void
2265xdrawcursor(void) { 2342xdrawcursor(void) {
2266 static int oldx = 0; 2343 static int oldx = 0, oldy = 0;
2267 static int oldy = 0;
2268 int sl; 2344 int sl;
2269 Glyph g = {{' '}, ATTR_NULL, DefaultBG, DefaultCS, 0}; 2345 Glyph g = {{' '}, ATTR_NULL, DefaultBG, DefaultCS, 0};
2270 2346
@@ -2277,9 +2353,11 @@ xdrawcursor(void) {
2277 /* remove the old cursor */ 2353 /* remove the old cursor */
2278 if(term.line[oldy][oldx].state & GLYPH_SET) { 2354 if(term.line[oldy][oldx].state & GLYPH_SET) {
2279 sl = utf8size(term.line[oldy][oldx].c); 2355 sl = utf8size(term.line[oldy][oldx].c);
2280 xdraws(term.line[oldy][oldx].c, term.line[oldy][oldx], oldx, oldy, 1, sl); 2356 xdraws(term.line[oldy][oldx].c, term.line[oldy][oldx], oldx,
2281 } else 2357 oldy, 1, sl);
2358 } else {
2282 xtermclear(oldx, oldy, oldx, oldy); 2359 xtermclear(oldx, oldy, oldx, oldy);
2360 }
2283 2361
2284 /* draw the new one */ 2362 /* draw the new one */
2285 if(!(term.c.state & CURSOR_HIDE)) { 2363 if(!(term.c.state & CURSOR_HIDE)) {
@@ -2334,6 +2412,7 @@ drawregion(int x1, int y1, int x2, int y2) {
2334 for(y = y1; y < y2; y++) { 2412 for(y = y1; y < y2; y++) {
2335 if(!term.dirty[y]) 2413 if(!term.dirty[y])
2336 continue; 2414 continue;
2415
2337 xtermclear(0, y, term.col, y); 2416 xtermclear(0, y, term.col, y);
2338 term.dirty[y] = 0; 2417 term.dirty[y] = 0;
2339 base = term.line[y][0]; 2418 base = term.line[y][0];
@@ -2342,8 +2421,9 @@ drawregion(int x1, int y1, int x2, int y2) {
2342 new = term.line[y][x]; 2421 new = term.line[y][x];
2343 if(ena_sel && *(new.c) && selected(x, y)) 2422 if(ena_sel && *(new.c) && selected(x, y))
2344 new.mode ^= ATTR_REVERSE; 2423 new.mode ^= ATTR_REVERSE;
2345 if(ib > 0 && (!(new.state & GLYPH_SET) || ATTRCMP(base, new) || 2424 if(ib > 0 && (!(new.state & GLYPH_SET)
2346 ib >= DRAW_BUF_SIZ-UTF_SIZ)) { 2425 || ATTRCMP(base, new)
2426 || ib >= DRAW_BUF_SIZ-UTF_SIZ)) {
2347 xdraws(buf, base, ox, y, ic, ib); 2427 xdraws(buf, base, ox, y, ic, ib);
2348 ic = ib = 0; 2428 ic = ib = 0;
2349 } 2429 }
@@ -2367,6 +2447,7 @@ drawregion(int x1, int y1, int x2, int y2) {
2367void 2447void
2368expose(XEvent *ev) { 2448expose(XEvent *ev) {
2369 XExposeEvent *e = &ev->xexpose; 2449 XExposeEvent *e = &ev->xexpose;
2450
2370 if(xw.state & WIN_REDRAW) { 2451 if(xw.state & WIN_REDRAW) {
2371 if(!e->count) 2452 if(!e->count)
2372 xw.state &= ~WIN_REDRAW; 2453 xw.state &= ~WIN_REDRAW;
@@ -2376,11 +2457,13 @@ expose(XEvent *ev) {
2376void 2457void
2377visibility(XEvent *ev) { 2458visibility(XEvent *ev) {
2378 XVisibilityEvent *e = &ev->xvisibility; 2459 XVisibilityEvent *e = &ev->xvisibility;
2379 if(e->state == VisibilityFullyObscured) 2460
2461 if(e->state == VisibilityFullyObscured) {
2380 xw.state &= ~WIN_VISIBLE; 2462 xw.state &= ~WIN_VISIBLE;
2381 else if(!(xw.state & WIN_VISIBLE)) 2463 } else if(!(xw.state & WIN_VISIBLE)) {
2382 /* need a full redraw for next Expose, not just a buf copy */ 2464 /* need a full redraw for next Expose, not just a buf copy */
2383 xw.state |= WIN_VISIBLE | WIN_REDRAW; 2465 xw.state |= WIN_VISIBLE | WIN_REDRAW;
2466 }
2384} 2467}
2385 2468
2386void 2469void
@@ -2391,6 +2474,7 @@ unmap(XEvent *ev) {
2391void 2474void
2392xseturgency(int add) { 2475xseturgency(int add) {
2393 XWMHints *h = XGetWMHints(xw.dpy, xw.win); 2476 XWMHints *h = XGetWMHints(xw.dpy, xw.win);
2477
2394 h->flags = add ? (h->flags | XUrgencyHint) : (h->flags & ~XUrgencyHint); 2478 h->flags = add ? (h->flags | XUrgencyHint) : (h->flags & ~XUrgencyHint);
2395 XSetWMHints(xw.dpy, xw.win, h); 2479 XSetWMHints(xw.dpy, xw.win, h);
2396 XFree(h); 2480 XFree(h);
@@ -2401,18 +2485,24 @@ focus(XEvent *ev) {
2401 if(ev->type == FocusIn) { 2485 if(ev->type == FocusIn) {
2402 xw.state |= WIN_FOCUSED; 2486 xw.state |= WIN_FOCUSED;
2403 xseturgency(0); 2487 xseturgency(0);
2404 } else 2488 } else {
2405 xw.state &= ~WIN_FOCUSED; 2489 xw.state &= ~WIN_FOCUSED;
2490 }
2406} 2491}
2407 2492
2408char* 2493char*
2409kmap(KeySym k, uint state) { 2494kmap(KeySym k, uint state) {
2410 int i; 2495 int i;
2496 uint mask;
2497
2411 state &= ~Mod2Mask; 2498 state &= ~Mod2Mask;
2412 for(i = 0; i < LEN(key); i++) { 2499 for(i = 0; i < LEN(key); i++) {
2413 uint mask = key[i].mask; 2500 mask = key[i].mask;
2414 if(key[i].k == k && ((state & mask) == mask || (mask == XK_NO_MOD && !state))) 2501
2502 if(key[i].k == k && ((state & mask) == mask
2503 || (mask == XK_NO_MOD && !state))) {
2415 return (char*)key[i].s; 2504 return (char*)key[i].s;
2505 }
2416 } 2506 }
2417 return NULL; 2507 return NULL;
2418} 2508}
@@ -2430,22 +2520,25 @@ kpress(XEvent *ev) {
2430 2520
2431 if (IS_SET(MODE_KBDLOCK)) 2521 if (IS_SET(MODE_KBDLOCK))
2432 return; 2522 return;
2523
2433 meta = e->state & Mod1Mask; 2524 meta = e->state & Mod1Mask;
2434 shift = e->state & ShiftMask; 2525 shift = e->state & ShiftMask;
2435 len = XmbLookupString(xw.xic, e, buf, sizeof(buf), &ksym, &status); 2526 len = XmbLookupString(xw.xic, e, buf, sizeof(buf), &ksym, &status);
2436 2527
2437 /* 1. custom keys from config.h */ 2528 /* 1. custom keys from config.h */
2438 if((customkey = kmap(ksym, e->state))) 2529 if((customkey = kmap(ksym, e->state))) {
2439 ttywrite(customkey, strlen(customkey)); 2530 ttywrite(customkey, strlen(customkey));
2440 /* 2. hardcoded (overrides X lookup) */ 2531 /* 2. hardcoded (overrides X lookup) */
2441 else 2532 } else {
2442 switch(ksym) { 2533 switch(ksym) {
2443 case XK_Up: 2534 case XK_Up:
2444 case XK_Down: 2535 case XK_Down:
2445 case XK_Left: 2536 case XK_Left:
2446 case XK_Right: 2537 case XK_Right:
2447 /* XXX: shift up/down doesn't work */ 2538 /* XXX: shift up/down doesn't work */
2448 sprintf(buf, "\033%c%c", IS_SET(MODE_APPKEYPAD) ? 'O' : '[', (shift ? "dacb":"DACB")[ksym - XK_Left]); 2539 sprintf(buf, "\033%c%c",
2540 IS_SET(MODE_APPKEYPAD) ? 'O' : '[',
2541 (shift ? "dacb":"DACB")[ksym - XK_Left]);
2449 ttywrite(buf, 3); 2542 ttywrite(buf, 3);
2450 break; 2543 break;
2451 case XK_Insert: 2544 case XK_Insert:
@@ -2453,10 +2546,11 @@ kpress(XEvent *ev) {
2453 selpaste(); 2546 selpaste();
2454 break; 2547 break;
2455 case XK_Return: 2548 case XK_Return:
2456 if(IS_SET(MODE_CRLF)) 2549 if(IS_SET(MODE_CRLF)) {
2457 ttywrite("\r\n", 2); 2550 ttywrite("\r\n", 2);
2458 else 2551 } else {
2459 ttywrite("\r", 1); 2552 ttywrite("\r", 1);
2553 }
2460 break; 2554 break;
2461 /* 3. X lookup */ 2555 /* 3. X lookup */
2462 default: 2556 default:
@@ -2467,6 +2561,7 @@ kpress(XEvent *ev) {
2467 } 2561 }
2468 break; 2562 break;
2469 } 2563 }
2564 }
2470} 2565}
2471 2566
2472void 2567void
@@ -2618,7 +2713,7 @@ main(int argc, char *argv[]) {
2618 } 2713 }
2619 } 2714 }
2620 2715
2621 run: 2716run:
2622 setlocale(LC_CTYPE, ""); 2717 setlocale(LC_CTYPE, "");
2623 tnew(80, 24); 2718 tnew(80, 24);
2624 ttynew(); 2719 ttynew();