diff options
| author | Christoph Lohmann <20h@r-36.net> | 2012-10-06 09:58:45 +0200 |
|---|---|---|
| committer | Christoph Lohmann <20h@r-36.net> | 2012-10-06 09:58:45 +0200 |
| commit | 4eddf19fdc2f3845c927291b99d3faefe73f98f3 (patch) | |
| tree | fd46de72bb2892a09fb1dc2cfaa73704128cd072 | |
| parent | 7efa4514d104d51793c4dd01ddedd4976080be07 (diff) | |
| download | st-4eddf19fdc2f3845c927291b99d3faefe73f98f3.tar.gz st-4eddf19fdc2f3845c927291b99d3faefe73f98f3.zip | |
The style inquisition was here. Yes, making it a unified style. The last
infidels will be squashed too!
| -rw-r--r-- | st.c | 365 |
1 files changed, 230 insertions, 135 deletions
| @@ -180,9 +180,9 @@ typedef struct { | |||
| 180 | typedef struct { | 180 | typedef 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 | ||
| 255 | static void die(const char*, ...); | 255 | static void die(const char *, ...); |
| 256 | static void draw(void); | 256 | static void draw(void); |
| 257 | static void redraw(void); | 257 | static void redraw(void); |
| 258 | static void drawregion(int, int, int, int); | 258 | static void drawregion(int, int, int, int); |
| @@ -279,7 +279,7 @@ static void tmoveto(int, int); | |||
| 279 | static void tnew(int, int); | 279 | static void tnew(int, int); |
| 280 | static void tnewline(int); | 280 | static void tnewline(int); |
| 281 | static void tputtab(bool); | 281 | static void tputtab(bool); |
| 282 | static void tputc(char*, int); | 282 | static void tputc(char *, int); |
| 283 | static void treset(void); | 283 | static void treset(void); |
| 284 | static int tresize(int, int); | 284 | static int tresize(int, int); |
| 285 | static void tscrollup(int, int); | 285 | static void tscrollup(int, int); |
| @@ -313,7 +313,7 @@ static void xresize(int, int); | |||
| 313 | static void expose(XEvent *); | 313 | static void expose(XEvent *); |
| 314 | static void visibility(XEvent *); | 314 | static void visibility(XEvent *); |
| 315 | static void unmap(XEvent *); | 315 | static void unmap(XEvent *); |
| 316 | static char* kmap(KeySym, uint); | 316 | static char *kmap(KeySym, uint); |
| 317 | static void kpress(XEvent *); | 317 | static void kpress(XEvent *); |
| 318 | static void cmessage(XEvent *); | 318 | static void cmessage(XEvent *); |
| 319 | static void resize(XEvent *); | 319 | static void resize(XEvent *); |
| @@ -378,8 +378,10 @@ static char *opt_font = NULL; | |||
| 378 | void * | 378 | void * |
| 379 | xmalloc(size_t len) { | 379 | xmalloc(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 * | |||
| 387 | xrealloc(void *p, size_t len) { | 389 | xrealloc(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 | ||
| 393 | void * | 396 | void * |
| 394 | xcalloc(size_t nmemb, size_t size) { | 397 | xcalloc(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; |
| 473 | invalid: | 483 | invalid: |
| 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; |
| 504 | invalid: | 517 | invalid: |
| 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 | |||
| 515 | isfullutf8(char *s, int b) { | 529 | isfullutf8(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 | ||
| 538 | int | 553 | int |
| 539 | utf8size(char *s) { | 554 | utf8size(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 | ||
| 552 | void | 568 | void |
| @@ -563,13 +579,18 @@ selinit(void) { | |||
| 563 | 579 | ||
| 564 | static inline bool | 580 | static inline bool |
| 565 | selected(int x, int y) { | 581 | selected(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 | ||
| 575 | void | 596 | void |
| @@ -621,9 +642,9 @@ mousereport(XEvent *e) { | |||
| 621 | 642 | ||
| 622 | void | 643 | void |
| 623 | bpress(XEvent *e) { | 644 | bpress(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 | ||
| 638 | void | 659 | void |
| 639 | selcopy(void) { | 660 | selcopy(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 | ||
| 696 | void | 715 | void |
| 697 | selpaste() { | 716 | selpaste(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 | ||
| 701 | void selclear(XEvent *e) { | 721 | void selclear(XEvent *e) { |
| @@ -709,7 +729,7 @@ void | |||
| 709 | selrequest(XEvent *e) { | 729 | selrequest(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 | ||
| 757 | void | 777 | void |
| 758 | brelease(XEvent *e) { | 778 | brelease(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 | ||
| 799 | void | 827 | void |
| 800 | bmotion(XEvent *e) { | 828 | bmotion(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) { | |||
| 864 | void | 896 | void |
| 865 | ttynew(void) { | 897 | ttynew(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) { | |||
| 905 | void | 937 | void |
| 906 | dump(char c) { | 938 | dump(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 | ||
| 960 | void | 993 | void |
| 961 | tsetdirt(int top, int bot) | 994 | tsetdirt(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 | ||
| 972 | void | 1004 | void |
| 973 | tfulldirt(void) | 1005 | tfulldirt(void) { |
| 974 | { | ||
| 975 | tsetdirt(0, term.row-1); | 1006 | tsetdirt(0, term.row-1); |
| 976 | } | 1007 | } |
| 977 | 1008 | ||
| @@ -979,15 +1010,18 @@ void | |||
| 979 | tcursor(int mode) { | 1010 | tcursor(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 | ||
| 988 | void | 1021 | void |
| 989 | treset(void) { | 1022 | treset(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 | ||
| 1025 | void | 1059 | void |
| 1026 | tswapscreen(void) { | 1060 | tswapscreen(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) { | |||
| 1098 | void | 1133 | void |
| 1099 | tnewline(int first_col) { | 1134 | tnewline(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 | ||
| 1141 | void | 1179 | void |
| 1142 | tsetchar(char *c) { | 1180 | tsetchar(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) { | |||
| 1594 | void | 1649 | void |
| 1595 | csidump(void) { | 1650 | csidump(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) { | |||
| 1672 | void | 1735 | void |
| 1673 | strdump(void) { | 1736 | strdump(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 | ||
| 2264 | void | 2341 | void |
| 2265 | xdrawcursor(void) { | 2342 | xdrawcursor(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) { | |||
| 2367 | void | 2447 | void |
| 2368 | expose(XEvent *ev) { | 2448 | expose(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) { | |||
| 2376 | void | 2457 | void |
| 2377 | visibility(XEvent *ev) { | 2458 | visibility(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 | ||
| 2386 | void | 2469 | void |
| @@ -2391,6 +2474,7 @@ unmap(XEvent *ev) { | |||
| 2391 | void | 2474 | void |
| 2392 | xseturgency(int add) { | 2475 | xseturgency(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 | ||
| 2408 | char* | 2493 | char* |
| 2409 | kmap(KeySym k, uint state) { | 2494 | kmap(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 | ||
| 2472 | void | 2567 | void |
| @@ -2618,7 +2713,7 @@ main(int argc, char *argv[]) { | |||
| 2618 | } | 2713 | } |
| 2619 | } | 2714 | } |
| 2620 | 2715 | ||
| 2621 | run: | 2716 | run: |
| 2622 | setlocale(LC_CTYPE, ""); | 2717 | setlocale(LC_CTYPE, ""); |
| 2623 | tnew(80, 24); | 2718 | tnew(80, 24); |
| 2624 | ttynew(); | 2719 | ttynew(); |
