aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--st.c167
1 files changed, 88 insertions, 79 deletions
diff --git a/st.c b/st.c
index 8ddfa8b..9a8fa35 100644
--- a/st.c
+++ b/st.c
@@ -1,4 +1,4 @@
1/* See LICENSE for licence details. */ 1/* See LICENSE for licence details. */
2#include "st.h" 2#include "st.h"
3 3
4/* Globals */ 4/* Globals */
@@ -27,11 +27,10 @@ execsh(void) {
27} 27}
28 28
29void 29void
30xbell(void) { /* visual bell */ 30xbell(void) { /* visual bell */
31 XRectangle r = { 0, 0, xw.w, xw.h }; 31 XRectangle r = { 0, 0, xw.w, xw.h };
32 XSetForeground(xw.dis, dc.gc, dc.col[BellCol]); 32 XSetForeground(xw.dis, dc.gc, dc.col[BellCol]);
33 XFillRectangles(xw.dis, xw.win, dc.gc, &r, 1); 33 XFillRectangles(xw.dis, xw.win, dc.gc, &r, 1);
34 XFlush(xw.dis);
35 usleep(30000); 34 usleep(30000);
36 draw(SCredraw); 35 draw(SCredraw);
37} 36}
@@ -127,7 +126,7 @@ escfinal(char c) {
127 } 126 }
128 else if(BETWEEN(c, 0x40, 0x7E)) 127 else if(BETWEEN(c, 0x40, 0x7E))
129 return 1; 128 return 1;
130 return 0; 129 return 0;
131} 130}
132 131
133void 132void
@@ -168,7 +167,7 @@ tscroll(void) {
168 term.line[i] = term.line[i+1]; 167 term.line[i] = term.line[i+1];
169 memset(temp, 0, sizeof(Glyph) * term.col); 168 memset(temp, 0, sizeof(Glyph) * term.col);
170 term.line[term.bot] = temp; 169 term.line[term.bot] = temp;
171 xscroll(); 170 xscroll();
172} 171}
173 172
174void 173void
@@ -372,13 +371,13 @@ tsetattr(int *attr, int l) {
372 term.c.attr.bg = DefaultBG; 371 term.c.attr.bg = DefaultBG;
373 break; 372 break;
374 case 1: 373 case 1:
375 term.c.attr.mode |= ATbold; 374 term.c.attr.mode |= ATbold;
376 break; 375 break;
377 case 4: 376 case 4:
378 term.c.attr.mode |= ATunderline; 377 term.c.attr.mode |= ATunderline;
379 break; 378 break;
380 case 7: 379 case 7:
381 term.c.attr.mode |= ATreverse; 380 term.c.attr.mode |= ATreverse;
382 break; 381 break;
383 case 8: 382 case 8:
384 term.c.hidden = CShide; 383 term.c.hidden = CShide;
@@ -390,7 +389,7 @@ tsetattr(int *attr, int l) {
390 term.c.attr.mode &= ~ATunderline; 389 term.c.attr.mode &= ~ATunderline;
391 break; 390 break;
392 case 27: 391 case 27:
393 term.c.attr.mode &= ~ATreverse; 392 term.c.attr.mode &= ~ATreverse;
394 break; 393 break;
395 case 39: 394 case 39:
396 term.c.attr.fg = DefaultFG; 395 term.c.attr.fg = DefaultFG;
@@ -420,7 +419,7 @@ tsetscroll(int t, int b) {
420 b = temp; 419 b = temp;
421 } 420 }
422 term.top = t; 421 term.top = t;
423 term.bot = b; 422 term.bot = b;
424} 423}
425 424
426 425
@@ -481,7 +480,7 @@ eschandle(void) {
481 break; 480 break;
482 case 2: /* all */ 481 case 2: /* all */
483 tclearregion(0, 0, term.col-1, term.row-1); 482 tclearregion(0, 0, term.col-1, term.row-1);
484 break; 483 break;
485 } 484 }
486 break; 485 break;
487 case 'K': /* Clear line */ 486 case 'K': /* Clear line */
@@ -501,6 +500,10 @@ eschandle(void) {
501 DEFAULT(escseq.arg[0], 1); 500 DEFAULT(escseq.arg[0], 1);
502 tinsertblankline(escseq.arg[0]); 501 tinsertblankline(escseq.arg[0]);
503 break; 502 break;
503 case 'l':
504 if(escseq.priv && escseq.arg[0] == 25)
505 term.c.hidden = 1;
506 break;
504 case 'M': /* Delete <n> lines */ 507 case 'M': /* Delete <n> lines */
505 DEFAULT(escseq.arg[0], 1); 508 DEFAULT(escseq.arg[0], 1);
506 tdeleteline(escseq.arg[0]); 509 tdeleteline(escseq.arg[0]);
@@ -514,6 +517,8 @@ eschandle(void) {
514 tmoveto(term.c.x, escseq.arg[0]-1); 517 tmoveto(term.c.x, escseq.arg[0]-1);
515 break; 518 break;
516 case 'h': /* Set terminal mode */ 519 case 'h': /* Set terminal mode */
520 if(escseq.priv && escseq.arg[0] == 25)
521 term.c.hidden = 0;
517 break; 522 break;
518 case 'm': /* Terminal attribute (color) */ 523 case 'm': /* Terminal attribute (color) */
519 tsetattr(escseq.arg, escseq.narg); 524 tsetattr(escseq.arg, escseq.narg);
@@ -542,15 +547,15 @@ void
542escdump(void) { 547escdump(void) {
543 int i; 548 int i;
544 puts("------"); 549 puts("------");
545 printf("rawbuf : %s\n", escseq.buf); 550 printf("rawbuf : %s\n", escseq.buf);
546 printf("prechar : %c\n", escseq.pre); 551 printf("prechar : %c\n", escseq.pre);
547 printf("private : %c\n", escseq.priv ? '?' : ' '); 552 printf("private : %c\n", escseq.priv ? '?' : ' ');
548 printf("narg : %d\n", escseq.narg); 553 printf("narg : %d\n", escseq.narg);
549 if(escseq.narg) { 554 if(escseq.narg) {
550 for(i = 0; i < escseq.narg; i++) 555 for(i = 0; i < escseq.narg; i++)
551 printf("\targ %d = %d\n", i, escseq.arg[i]); 556 printf("\targ %d = %d\n", i, escseq.arg[i]);
552 } 557 }
553 printf("mode : %c\n", escseq.mode); 558 printf("mode : %c\n", escseq.mode);
554} 559}
555 560
556void 561void
@@ -560,20 +565,21 @@ escreset(void) {
560 565
561void 566void
562tputtab(void) { 567tputtab(void) {
563 int space = TAB - term.c.x % TAB; 568 int space = TAB - term.c.x % TAB;
564 569
565 if(term.c.x + space >= term.col) 570 if(term.c.x + space >= term.col)
566 space--; 571 space--;
567 572
568 for(; space > 0; space--) 573 for(; space > 0; space--)
569 tcursor(CSright); 574 tcursor(CSright);
570} 575}
571 576
572void 577void
573tputc(char c) { 578tputc(char c) {
574 static int inesc = 0; 579 static int inesc = 0;
575 580#if 0
576 //dump(c); 581 dump(c);
582#endif
577 /* start of escseq */ 583 /* start of escseq */
578 if(c == '\033') 584 if(c == '\033')
579 escreset(), inesc = 1; 585 escreset(), inesc = 1;
@@ -585,9 +591,9 @@ tputc(char c) {
585 tsetchar(c); 591 tsetchar(c);
586 tcursor(CSright); 592 tcursor(CSright);
587 break; 593 break;
588 case '\t': 594 case '\t':
589 tputtab(); 595 tputtab();
590 break; 596 break;
591 case '\b': 597 case '\b':
592 tcursor(CSleft); 598 tcursor(CSleft);
593 break; 599 break;
@@ -636,24 +642,24 @@ tresize(int col, int row) {
636 642
637 if(col < 1 || row < 1) 643 if(col < 1 || row < 1)
638 return; 644 return;
639 /* alloc */ 645 /* alloc */
640 line = calloc(row, sizeof(Line)); 646 line = calloc(row, sizeof(Line));
641 for(i = 0 ; i < row; i++) 647 for(i = 0 ; i < row; i++)
642 line[i] = calloc(col, sizeof(Glyph)); 648 line[i] = calloc(col, sizeof(Glyph));
643 /* copy */ 649 /* copy */
644 for(i = 0 ; i < minrow; i++) 650 for(i = 0 ; i < minrow; i++)
645 memcpy(line[i], term.line[i], mincol * sizeof(Glyph)); 651 memcpy(line[i], term.line[i], mincol * sizeof(Glyph));
646 /* free */ 652 /* free */
647 for(i = 0; i < term.row; i++) 653 for(i = 0; i < term.row; i++)
648 free(term.line[i]); 654 free(term.line[i]);
649 free(term.line); 655 free(term.line);
650 656
651 LIMIT(term.c.x, 0, col-1); 657 LIMIT(term.c.x, 0, col-1);
652 LIMIT(term.c.y, 0, row-1); 658 LIMIT(term.c.y, 0, row-1);
653 LIMIT(term.top, 0, row-1); 659 LIMIT(term.top, 0, row-1);
654 LIMIT(term.bot, 0, row-1); 660 LIMIT(term.bot, 0, row-1);
655 661
656 term.bot = row-1; 662 term.bot = row-1;
657 term.line = line; 663 term.line = line;
658 term.col = col, term.row = row; 664 term.col = col, term.row = row;
659} 665}
@@ -706,12 +712,12 @@ xinit(void) {
706 712
707 xw.dis = XOpenDisplay(NULL); 713 xw.dis = XOpenDisplay(NULL);
708 xw.scr = XDefaultScreen(xw.dis); 714 xw.scr = XDefaultScreen(xw.dis);
709 if(!xw.dis) 715 if(!xw.dis)
710 die("can not open display"); 716 die("can not open display");
711 717
712 /* font */ 718 /* font */
713 if(!(dc.font = XLoadQueryFont(xw.dis, FONT))) 719 if(!(dc.font = XLoadQueryFont(xw.dis, FONT)))
714 die("can not find font " FONT); 720 die("can not find font " FONT);
715 721
716 xw.cw = dc.font->max_bounds.rbearing - dc.font->min_bounds.lbearing; 722 xw.cw = dc.font->max_bounds.rbearing - dc.font->min_bounds.lbearing;
717 xw.ch = dc.font->ascent + dc.font->descent + LINESPACE; 723 xw.ch = dc.font->ascent + dc.font->descent + LINESPACE;
@@ -724,7 +730,7 @@ xinit(void) {
724 term.c.attr.bg = DefaultBG; 730 term.c.attr.bg = DefaultBG;
725 term.c.attr.mode = ATnone; 731 term.c.attr.mode = ATnone;
726 /* windows */ 732 /* windows */
727 xw.h = term.row * xw.ch; 733 xw.h = term.row * xw.ch;
728 xw.w = term.col * xw.cw; 734 xw.w = term.col * xw.cw;
729 /* XXX: this BORDER is useless after the first resize, handle it in xdraws() */ 735 /* XXX: this BORDER is useless after the first resize, handle it in xdraws() */
730 xw.win = XCreateSimpleWindow(xw.dis, XRootWindow(xw.dis, xw.scr), 0, 0, 736 xw.win = XCreateSimpleWindow(xw.dis, XRootWindow(xw.dis, xw.scr), 0, 0,
@@ -746,7 +752,6 @@ xinit(void) {
746 XSetWMProperties(xw.dis, xw.win, NULL, NULL, &args[0], 0, &shint, &wmhint, &chint); 752 XSetWMProperties(xw.dis, xw.win, NULL, NULL, &args[0], 0, &shint, &wmhint, &chint);
747 XStoreName(xw.dis, xw.win, TNAME); 753 XStoreName(xw.dis, xw.win, TNAME);
748 XSync(xw.dis, 0); 754 XSync(xw.dis, 0);
749
750} 755}
751 756
752void 757void
@@ -765,7 +770,7 @@ xdrawc(int x, int y, Glyph g) {
765 /* string */ 770 /* string */
766 XSetForeground(xw.dis, dc.gc, xfg); 771 XSetForeground(xw.dis, dc.gc, xfg);
767 XDrawString(xw.dis, xw.win, dc.gc, r.x, r.y+dc.font->ascent, &(g.c), 1); 772 XDrawString(xw.dis, xw.win, dc.gc, r.x, r.y+dc.font->ascent, &(g.c), 1);
768 if(g.mode & ATbold) /* XXX: bold hack (draw again at x+1) */ 773 if(g.mode & ATbold) /* XXX: bold hack (draw again at x+1) */
769 XDrawString(xw.dis, xw.win, dc.gc, r.x+1, r.y+dc.font->ascent, &(g.c), 1); 774 XDrawString(xw.dis, xw.win, dc.gc, r.x+1, r.y+dc.font->ascent, &(g.c), 1);
770 /* underline */ 775 /* underline */
771 if(g.mode & ATunderline) { 776 if(g.mode & ATunderline) {
@@ -779,10 +784,10 @@ xcursor(int mode) {
779 static int oldx = 0; 784 static int oldx = 0;
780 static int oldy = 0; 785 static int oldy = 0;
781 Glyph g = {' ', ATnone, DefaultBG, DefaultCS, 0}; 786 Glyph g = {' ', ATnone, DefaultBG, DefaultCS, 0};
782 787
783 LIMIT(oldx, 0, term.col-1); 788 LIMIT(oldx, 0, term.col-1);
784 LIMIT(oldy, 0, term.row-1); 789 LIMIT(oldy, 0, term.row-1);
785 790
786 if(term.line[term.c.y][term.c.x].state & CRset) 791 if(term.line[term.c.y][term.c.x].state & CRset)
787 g.c = term.line[term.c.y][term.c.x].c; 792 g.c = term.line[term.c.y][term.c.x].c;
788 /* remove the old cursor */ 793 /* remove the old cursor */
@@ -825,7 +830,7 @@ kpress(XKeyEvent *e) {
825 int meta; 830 int meta;
826 int shift; 831 int shift;
827 832
828 meta = e->state & Mod4Mask; 833 meta = e->state & Mod1Mask;
829 shift = e->state & ShiftMask; 834 shift = e->state & ShiftMask;
830 len = XLookupString(e, buf, sizeof(buf), &ksym, NULL); 835 len = XLookupString(e, buf, sizeof(buf), &ksym, NULL);
831 if(len > 0) { 836 if(len > 0) {
@@ -836,11 +841,9 @@ kpress(XKeyEvent *e) {
836 return; 841 return;
837 } 842 }
838 switch(ksym) { 843 switch(ksym) {
839#ifdef DEBUG1
840 default: 844 default:
841 printf("errkey: %d\n", (int)ksym); 845 fprintf(stderr, "errkey: %d\n", (int)ksym);
842 break; 846 break;
843#endif
844 case XK_Up: 847 case XK_Up:
845 case XK_Down: 848 case XK_Down:
846 case XK_Left: 849 case XK_Left:
@@ -849,13 +852,14 @@ kpress(XKeyEvent *e) {
849 ttywrite(buf, 3); 852 ttywrite(buf, 3);
850 break; 853 break;
851 case XK_Delete: ttywrite(KEYDELETE, sizeof(KEYDELETE)-1); break; 854 case XK_Delete: ttywrite(KEYDELETE, sizeof(KEYDELETE)-1); break;
852 case XK_Home: ttywrite( KEYHOME, sizeof( KEYHOME)-1); break; 855 case XK_Home: ttywrite(KEYHOME, sizeof(KEYHOME)-1); break;
853 case XK_End: ttywrite( KEYEND, sizeof( KEYEND)-1); break; 856 case XK_End: ttywrite(KEYEND, sizeof(KEYEND) -1); break;
854 case XK_Prior: ttywrite( KEYPREV, sizeof( KEYPREV)-1); break; 857 case XK_Prior: ttywrite(KEYPREV, sizeof(KEYPREV)-1); break;
855 case XK_Next: ttywrite( KEYNEXT, sizeof( KEYNEXT)-1); break; 858 case XK_Next: ttywrite(KEYNEXT, sizeof(KEYNEXT)-1); break;
856 case XK_Insert: 859 case XK_Insert:
857 /* XXX: paste X clipboard */ 860 /* XXX: paste X clipboard */
858 if(shift); 861 if(shift)
862 ;
859 break; 863 break;
860 } 864 }
861} 865}
@@ -865,7 +869,7 @@ resize(XEvent *e) {
865 int col, row; 869 int col, row;
866 col = e->xconfigure.width / xw.cw; 870 col = e->xconfigure.width / xw.cw;
867 row = e->xconfigure.height / xw.ch; 871 row = e->xconfigure.height / xw.ch;
868 872
869 if(term.col != col || term.row != row) { 873 if(term.col != col || term.row != row) {
870 tresize(col, row); 874 tresize(col, row);
871 ttyresize(col, row); 875 ttyresize(col, row);
@@ -881,37 +885,42 @@ run(void) {
881 int ret; 885 int ret;
882 XEvent ev; 886 XEvent ev;
883 fd_set rfd; 887 fd_set rfd;
884 struct timeval tv = {0, 10000}; 888 int xfd = XConnectionNumber(xw.dis);
885 889
886 running = 1; 890 running = 1;
887 XSelectInput(xw.dis, xw.win, ExposureMask | KeyPressMask | StructureNotifyMask); 891 XSelectInput(xw.dis, xw.win, ExposureMask | KeyPressMask | StructureNotifyMask);
888 XResizeWindow(xw.dis, xw.win, xw.w , xw.h); /* seems to fix the resize bug in wmii */ 892 XResizeWindow(xw.dis, xw.win, xw.w , xw.h); /* seems to fix the resize bug in wmii */
893
889 while(running) { 894 while(running) {
890 while(XPending(xw.dis)) {
891 XNextEvent(xw.dis, &ev);
892 switch (ev.type) {
893 default:
894 break;
895 case KeyPress:
896 kpress(&ev.xkey);
897 break;
898 case Expose:
899 draw(SCredraw);
900 break;
901 case ConfigureNotify:
902 resize(&ev);
903 break;
904 }
905 }
906 FD_ZERO(&rfd); 895 FD_ZERO(&rfd);
907 FD_SET(cmdfd, &rfd); 896 FD_SET(cmdfd, &rfd);
908 ret = select(cmdfd+1, &rfd, NULL, NULL, &tv); 897 FD_SET(xfd, &rfd);
898 XFlush(xw.dis);
899 ret = select(MAX(xfd, cmdfd)+1, &rfd, NULL, NULL, NULL);
900
909 if(ret < 0) { 901 if(ret < 0) {
910 fprintf(stderr, "select: %m\n"); 902 fprintf(stderr, "select: %m\n");
911 running = 0; 903 running = 0;
912 } 904 }
913 if(!ret) 905
914 continue; 906 if(FD_ISSET(xfd, &rfd)) {
907 while(XPending(xw.dis)) {
908 XNextEvent(xw.dis, &ev);
909 switch (ev.type) {
910 default:
911 break;
912 case KeyPress:
913 kpress(&ev.xkey);
914 break;
915 case Expose:
916 draw(SCredraw);
917 break;
918 case ConfigureNotify:
919 resize(&ev);
920 break;
921 }
922 }
923 }
915 if(FD_ISSET(cmdfd, &rfd)) { 924 if(FD_ISSET(cmdfd, &rfd)) {
916 ttyread(); 925 ttyread();
917 draw(SCupdate); 926 draw(SCupdate);
@@ -926,9 +935,9 @@ main(int argc, char *argv[]) {
926 else if(argc != 1) 935 else if(argc != 1)
927 die("usage: st [-v]\n"); 936 die("usage: st [-v]\n");
928 setlocale(LC_CTYPE, ""); 937 setlocale(LC_CTYPE, "");
929 tnew(80, 24); 938 tnew(80, 24);
930 ttynew(); 939 ttynew();
931 xinit(); 940 xinit();
932 run(); 941 run();
933 return 0; 942 return 0;
934} 943}