diff options
| author | Christoph Lohmann <20h@r-36.net> | 2013-05-26 13:07:26 +0200 |
|---|---|---|
| committer | Christoph Lohmann <20h@r-36.net> | 2013-05-26 13:07:26 +0200 |
| commit | 8f1bef05025c0052603f7ca30552a43395b4c13f (patch) | |
| tree | 4c78d6f84f83880cc70e43988a73d2f50eb34138 | |
| parent | 8f47c4a4dea7272d72833d2ae26eacc3896d8f5c (diff) | |
| download | st-8f1bef05025c0052603f7ca30552a43395b4c13f.tar.gz st-8f1bef05025c0052603f7ca30552a43395b4c13f.zip | |
Fixing the selection scrolling and the selection naming.
Thanks p37sitdu@lavabit.com!
| -rw-r--r-- | st.c | 174 |
1 files changed, 89 insertions, 85 deletions
| @@ -249,11 +249,17 @@ typedef struct { | |||
| 249 | int mode; | 249 | int mode; |
| 250 | int type; | 250 | int type; |
| 251 | int snap; | 251 | int snap; |
| 252 | int bx, by; | 252 | /* |
| 253 | int ex, ey; | 253 | * Selection variables: |
| 254 | * nb – normalized coordinates of the beginning of the selection | ||
| 255 | * ne – normalized coordinates of the end of the selection | ||
| 256 | * ob – original coordinates of the beginning of the selection | ||
| 257 | * oe – original coordinates of the end of the selection | ||
| 258 | */ | ||
| 254 | struct { | 259 | struct { |
| 255 | int x, y; | 260 | int x, y; |
| 256 | } b, e; | 261 | } nb, ne, ob, oe; |
| 262 | |||
| 257 | char *clip; | 263 | char *clip; |
| 258 | Atom xtarget; | 264 | Atom xtarget; |
| 259 | bool alt; | 265 | bool alt; |
| @@ -390,6 +396,7 @@ static void selclear(XEvent *); | |||
| 390 | static void selrequest(XEvent *); | 396 | static void selrequest(XEvent *); |
| 391 | 397 | ||
| 392 | static void selinit(void); | 398 | static void selinit(void); |
| 399 | static void selsort(void); | ||
| 393 | static inline bool selected(int, int); | 400 | static inline bool selected(int, int); |
| 394 | static void selcopy(void); | 401 | static void selcopy(void); |
| 395 | static void selscroll(int, int); | 402 | static void selscroll(int, int); |
| @@ -630,12 +637,12 @@ utf8size(char *s) { | |||
| 630 | } | 637 | } |
| 631 | } | 638 | } |
| 632 | 639 | ||
| 633 | void | 640 | static void |
| 634 | selinit(void) { | 641 | selinit(void) { |
| 635 | memset(&sel.tclick1, 0, sizeof(sel.tclick1)); | 642 | memset(&sel.tclick1, 0, sizeof(sel.tclick1)); |
| 636 | memset(&sel.tclick2, 0, sizeof(sel.tclick2)); | 643 | memset(&sel.tclick2, 0, sizeof(sel.tclick2)); |
| 637 | sel.mode = 0; | 644 | sel.mode = 0; |
| 638 | sel.bx = -1; | 645 | sel.ob.x = -1; |
| 639 | sel.clip = NULL; | 646 | sel.clip = NULL; |
| 640 | sel.xtarget = XInternAtom(xw.dpy, "UTF8_STRING", 0); | 647 | sel.xtarget = XInternAtom(xw.dpy, "UTF8_STRING", 0); |
| 641 | if(sel.xtarget == None) | 648 | if(sel.xtarget == None) |
| @@ -658,25 +665,28 @@ y2row(int y) { | |||
| 658 | return LIMIT(y, 0, term.row-1); | 665 | return LIMIT(y, 0, term.row-1); |
| 659 | } | 666 | } |
| 660 | 667 | ||
| 668 | static void | ||
| 669 | selsort(void) { | ||
| 670 | sel.nb.x = sel.ob.y < sel.oe.y ? sel.ob.x : sel.oe.x; | ||
| 671 | sel.nb.y = MIN(sel.ob.y, sel.oe.y); | ||
| 672 | sel.ne.x = sel.ob.y < sel.oe.y ? sel.oe.x : sel.ob.x; | ||
| 673 | sel.ne.y = MAX(sel.ob.y, sel.oe.y); | ||
| 674 | } | ||
| 675 | |||
| 661 | static inline bool | 676 | static inline bool |
| 662 | selected(int x, int y) { | 677 | selected(int x, int y) { |
| 663 | int bx, ex; | 678 | if(sel.ne.y == y && sel.nb.y == y) |
| 664 | 679 | return BETWEEN(x, sel.nb.x, sel.ne.y); | |
| 665 | if(sel.ey == y && sel.by == y) { | ||
| 666 | bx = MIN(sel.bx, sel.ex); | ||
| 667 | ex = MAX(sel.bx, sel.ex); | ||
| 668 | |||
| 669 | return BETWEEN(x, bx, ex); | ||
| 670 | } | ||
| 671 | 680 | ||
| 672 | if(sel.type == SEL_RECTANGULAR) { | 681 | if(sel.type == SEL_RECTANGULAR) { |
| 673 | return ((sel.b.y <= y && y <= sel.e.y) | 682 | return ((sel.nb.y <= y && y <= sel.ne.y) |
| 674 | && (sel.b.x <= x && x <= sel.e.x)); | 683 | && (sel.nb.x <= x && x <= sel.ne.x)); |
| 675 | } | 684 | } |
| 676 | return ((sel.b.y < y && y < sel.e.y) | 685 | |
| 677 | || (y == sel.e.y && x <= sel.e.x)) | 686 | return ((sel.nb.y < y && y < sel.ne.y) |
| 678 | || (y == sel.b.y && x >= sel.b.x | 687 | || (y == sel.ne.y && x <= sel.ne.x)) |
| 679 | && (x <= sel.e.x || sel.b.y != sel.e.y)); | 688 | || (y == sel.nb.y && x >= sel.nb.x |
| 689 | && (x <= sel.ne.x || sel.nb.y != sel.ne.y)); | ||
| 680 | } | 690 | } |
| 681 | 691 | ||
| 682 | void | 692 | void |
| @@ -762,22 +772,19 @@ getbuttoninfo(XEvent *e) { | |||
| 762 | 772 | ||
| 763 | sel.alt = IS_SET(MODE_ALTSCREEN); | 773 | sel.alt = IS_SET(MODE_ALTSCREEN); |
| 764 | 774 | ||
| 765 | sel.ex = x2col(e->xbutton.x); | 775 | sel.oe.x = x2col(e->xbutton.x); |
| 766 | sel.ey = y2row(e->xbutton.y); | 776 | sel.oe.y = y2row(e->xbutton.y); |
| 767 | 777 | ||
| 768 | if (sel.by < sel.ey | 778 | if (sel.ob.y < sel.oe.y |
| 769 | || (sel.by == sel.ey && sel.bx < sel.ex)) { | 779 | || (sel.ob.y == sel.oe.y && sel.ob.x < sel.oe.x)) { |
| 770 | selsnap(sel.snap, &sel.bx, &sel.by, -1); | 780 | selsnap(sel.snap, &sel.ob.x, &sel.ob.y, -1); |
| 771 | selsnap(sel.snap, &sel.ex, &sel.ey, +1); | 781 | selsnap(sel.snap, &sel.oe.x, &sel.oe.y, +1); |
| 772 | } else { | 782 | } else { |
| 773 | selsnap(sel.snap, &sel.ex, &sel.ey, -1); | 783 | selsnap(sel.snap, &sel.oe.x, &sel.oe.y, -1); |
| 774 | selsnap(sel.snap, &sel.bx, &sel.by, +1); | 784 | selsnap(sel.snap, &sel.ob.x, &sel.ob.y, +1); |
| 775 | } | 785 | } |
| 776 | 786 | ||
| 777 | sel.b.x = sel.by < sel.ey ? sel.bx : sel.ex; | 787 | selsort(); |
| 778 | sel.b.y = MIN(sel.by, sel.ey); | ||
| 779 | sel.e.x = sel.by < sel.ey ? sel.ex : sel.bx; | ||
| 780 | sel.e.y = MAX(sel.by, sel.ey); | ||
| 781 | 788 | ||
| 782 | sel.type = SEL_REGULAR; | 789 | sel.type = SEL_REGULAR; |
| 783 | for(type = 1; type < LEN(selmasks); ++type) { | 790 | for(type = 1; type < LEN(selmasks); ++type) { |
| @@ -801,7 +808,8 @@ mousereport(XEvent *e) { | |||
| 801 | if(!IS_SET(MODE_MOUSEMOTION) || (x == ox && y == oy)) | 808 | if(!IS_SET(MODE_MOUSEMOTION) || (x == ox && y == oy)) |
| 802 | return; | 809 | return; |
| 803 | button = ob + 32; | 810 | button = ob + 32; |
| 804 | ox = x, oy = y; | 811 | ox = x; |
| 812 | oy = y; | ||
| 805 | } else if(!IS_SET(MODE_MOUSESGR) | 813 | } else if(!IS_SET(MODE_MOUSESGR) |
| 806 | && (e->xbutton.type == ButtonRelease | 814 | && (e->xbutton.type == ButtonRelease |
| 807 | || button == AnyButton)) { | 815 | || button == AnyButton)) { |
| @@ -812,7 +820,8 @@ mousereport(XEvent *e) { | |||
| 812 | button += 64 - 3; | 820 | button += 64 - 3; |
| 813 | if(e->xbutton.type == ButtonPress) { | 821 | if(e->xbutton.type == ButtonPress) { |
| 814 | ob = button; | 822 | ob = button; |
| 815 | ox = x, oy = y; | 823 | ox = x; |
| 824 | oy = y; | ||
| 816 | } | 825 | } |
| 817 | } | 826 | } |
| 818 | 827 | ||
| @@ -859,15 +868,15 @@ bpress(XEvent *e) { | |||
| 859 | gettimeofday(&now, NULL); | 868 | gettimeofday(&now, NULL); |
| 860 | 869 | ||
| 861 | /* Clear previous selection, logically and visually. */ | 870 | /* Clear previous selection, logically and visually. */ |
| 862 | if(sel.bx != -1) { | 871 | if(sel.ob.x != -1) { |
| 863 | sel.bx = -1; | 872 | sel.ob.x = -1; |
| 864 | tsetdirt(sel.b.y, sel.e.y); | 873 | tsetdirt(sel.nb.y, sel.ne.y); |
| 865 | draw(); | 874 | draw(); |
| 866 | } | 875 | } |
| 867 | sel.mode = 1; | 876 | sel.mode = 1; |
| 868 | sel.type = SEL_REGULAR; | 877 | sel.type = SEL_REGULAR; |
| 869 | sel.ex = sel.bx = x2col(e->xbutton.x); | 878 | sel.oe.x = sel.ob.x = x2col(e->xbutton.x); |
| 870 | sel.ey = sel.by = y2row(e->xbutton.y); | 879 | sel.oe.y = sel.ob.y = y2row(e->xbutton.y); |
| 871 | 880 | ||
| 872 | /* | 881 | /* |
| 873 | * If the user clicks below predefined timeouts specific | 882 | * If the user clicks below predefined timeouts specific |
| @@ -880,12 +889,9 @@ bpress(XEvent *e) { | |||
| 880 | } else { | 889 | } else { |
| 881 | sel.snap = 0; | 890 | sel.snap = 0; |
| 882 | } | 891 | } |
| 883 | selsnap(sel.snap, &sel.bx, &sel.by, -1); | 892 | selsnap(sel.snap, &sel.ob.x, &sel.ob.y, -1); |
| 884 | selsnap(sel.snap, &sel.ex, &sel.ey, +1); | 893 | selsnap(sel.snap, &sel.oe.x, &sel.oe.y, +1); |
| 885 | sel.b.x = sel.bx; | 894 | selsort(); |
| 886 | sel.b.y = sel.by; | ||
| 887 | sel.e.x = sel.ex; | ||
| 888 | sel.e.y = sel.ey; | ||
| 889 | 895 | ||
| 890 | /* | 896 | /* |
| 891 | * Draw selection, unless it's regular and we don't want to | 897 | * Draw selection, unless it's regular and we don't want to |
| @@ -893,7 +899,7 @@ bpress(XEvent *e) { | |||
| 893 | */ | 899 | */ |
| 894 | if(sel.snap != 0) { | 900 | if(sel.snap != 0) { |
| 895 | sel.mode++; | 901 | sel.mode++; |
| 896 | tsetdirt(sel.b.y, sel.e.y); | 902 | tsetdirt(sel.nb.y, sel.ne.y); |
| 897 | draw(); | 903 | draw(); |
| 898 | } | 904 | } |
| 899 | sel.tclick2 = sel.tclick1; | 905 | sel.tclick2 = sel.tclick1; |
| @@ -907,14 +913,14 @@ selcopy(void) { | |||
| 907 | int x, y, bufsize, size, i, ex; | 913 | int x, y, bufsize, size, i, ex; |
| 908 | Glyph *gp, *last; | 914 | Glyph *gp, *last; |
| 909 | 915 | ||
| 910 | if(sel.bx == -1) { | 916 | if(sel.ob.x == -1) { |
| 911 | str = NULL; | 917 | str = NULL; |
| 912 | } else { | 918 | } else { |
| 913 | bufsize = (term.col+1) * (sel.e.y-sel.b.y+1) * UTF_SIZ; | 919 | bufsize = (term.col+1) * (sel.ne.y-sel.nb.y+1) * UTF_SIZ; |
| 914 | ptr = str = xmalloc(bufsize); | 920 | ptr = str = xmalloc(bufsize); |
| 915 | 921 | ||
| 916 | /* append every set & selected glyph to the selection */ | 922 | /* append every set & selected glyph to the selection */ |
| 917 | for(y = sel.b.y; y < sel.e.y + 1; y++) { | 923 | for(y = sel.nb.y; y < sel.ne.y + 1; y++) { |
| 918 | gp = &term.line[y][0]; | 924 | gp = &term.line[y][0]; |
| 919 | last = gp + term.col; | 925 | last = gp + term.col; |
| 920 | 926 | ||
| @@ -940,20 +946,20 @@ selcopy(void) { | |||
| 940 | * st. | 946 | * st. |
| 941 | * FIXME: Fix the computer world. | 947 | * FIXME: Fix the computer world. |
| 942 | */ | 948 | */ |
| 943 | if(y < sel.e.y && !((gp-1)->mode & ATTR_WRAP)) | 949 | if(y < sel.ne.y && !((gp-1)->mode & ATTR_WRAP)) |
| 944 | *ptr++ = '\n'; | 950 | *ptr++ = '\n'; |
| 945 | 951 | ||
| 946 | /* | 952 | /* |
| 947 | * If the last selected line expands in the selection | 953 | * If the last selected line expands in the selection |
| 948 | * after the visible text '\n' is appended. | 954 | * after the visible text '\n' is appended. |
| 949 | */ | 955 | */ |
| 950 | if(y == sel.e.y) { | 956 | if(y == sel.ne.y) { |
| 951 | i = term.col; | 957 | i = term.col; |
| 952 | while(--i > 0 && term.line[y][i].c[0] == ' ') | 958 | while(--i > 0 && term.line[y][i].c[0] == ' ') |
| 953 | /* nothing */; | 959 | /* nothing */; |
| 954 | ex = sel.e.x; | 960 | ex = sel.ne.x; |
| 955 | if(sel.b.y == sel.e.y && sel.e.x < sel.b.x) | 961 | if(sel.nb.y == sel.ne.y && sel.ne.x < sel.nb.x) |
| 956 | ex = sel.b.x; | 962 | ex = sel.nb.x; |
| 957 | if(i < ex) | 963 | if(i < ex) |
| 958 | *ptr++ = '\n'; | 964 | *ptr++ = '\n'; |
| 959 | } | 965 | } |
| @@ -1016,10 +1022,10 @@ clippaste(const Arg *dummy) { | |||
| 1016 | 1022 | ||
| 1017 | void | 1023 | void |
| 1018 | selclear(XEvent *e) { | 1024 | selclear(XEvent *e) { |
| 1019 | if(sel.bx == -1) | 1025 | if(sel.ob.x == -1) |
| 1020 | return; | 1026 | return; |
| 1021 | sel.bx = -1; | 1027 | sel.ob.x = -1; |
| 1022 | tsetdirt(sel.b.y, sel.e.y); | 1028 | tsetdirt(sel.nb.y, sel.ne.y); |
| 1023 | } | 1029 | } |
| 1024 | 1030 | ||
| 1025 | void | 1031 | void |
| @@ -1082,13 +1088,13 @@ brelease(XEvent *e) { | |||
| 1082 | selpaste(NULL); | 1088 | selpaste(NULL); |
| 1083 | } else if(e->xbutton.button == Button1) { | 1089 | } else if(e->xbutton.button == Button1) { |
| 1084 | if(sel.mode < 2) { | 1090 | if(sel.mode < 2) { |
| 1085 | sel.bx = -1; | 1091 | sel.ob.x = -1; |
| 1086 | } else { | 1092 | } else { |
| 1087 | getbuttoninfo(e); | 1093 | getbuttoninfo(e); |
| 1088 | selcopy(); | 1094 | selcopy(); |
| 1089 | } | 1095 | } |
| 1090 | sel.mode = 0; | 1096 | sel.mode = 0; |
| 1091 | term.dirty[sel.ey] = 1; | 1097 | term.dirty[sel.oe.y] = 1; |
| 1092 | } | 1098 | } |
| 1093 | } | 1099 | } |
| 1094 | 1100 | ||
| @@ -1105,15 +1111,14 @@ bmotion(XEvent *e) { | |||
| 1105 | return; | 1111 | return; |
| 1106 | 1112 | ||
| 1107 | sel.mode++; | 1113 | sel.mode++; |
| 1108 | oldey = sel.ey; | 1114 | oldey = sel.oe.y; |
| 1109 | oldex = sel.ex; | 1115 | oldex = sel.oe.x; |
| 1110 | oldsby = sel.b.y; | 1116 | oldsby = sel.nb.y; |
| 1111 | oldsey = sel.e.y; | 1117 | oldsey = sel.ne.y; |
| 1112 | getbuttoninfo(e); | 1118 | getbuttoninfo(e); |
| 1113 | 1119 | ||
| 1114 | if(oldey != sel.ey || oldex != sel.ex) { | 1120 | if(oldey != sel.oe.y || oldex != sel.oe.x) |
| 1115 | tsetdirt(MIN(sel.b.y, oldsby), MAX(sel.e.y, oldsey)); | 1121 | tsetdirt(MIN(sel.nb.y, oldsby), MAX(sel.ne.y, oldsey)); |
| 1116 | } | ||
| 1117 | } | 1122 | } |
| 1118 | 1123 | ||
| 1119 | void | 1124 | void |
| @@ -1411,31 +1416,30 @@ tscrollup(int orig, int n) { | |||
| 1411 | 1416 | ||
| 1412 | void | 1417 | void |
| 1413 | selscroll(int orig, int n) { | 1418 | selscroll(int orig, int n) { |
| 1414 | if(sel.bx == -1) | 1419 | if(sel.ob.x == -1) |
| 1415 | return; | 1420 | return; |
| 1416 | 1421 | ||
| 1417 | if(BETWEEN(sel.by, orig, term.bot) || BETWEEN(sel.ey, orig, term.bot)) { | 1422 | if(BETWEEN(sel.ob.y, orig, term.bot) || BETWEEN(sel.oe.y, orig, term.bot)) { |
| 1418 | if((sel.by += n) > term.bot || (sel.ey += n) < term.top) { | 1423 | if((sel.ob.y += n) > term.bot || (sel.oe.y += n) < term.top) { |
| 1419 | sel.bx = -1; | 1424 | sel.ob.x = -1; |
| 1420 | return; | 1425 | return; |
| 1421 | } | 1426 | } |
| 1422 | if(sel.type == SEL_RECTANGULAR) { | 1427 | if(sel.type == SEL_RECTANGULAR) { |
| 1423 | if(sel.by < term.top) | 1428 | if(sel.ob.y < term.top) |
| 1424 | sel.by = term.top; | 1429 | sel.ob.y = term.top; |
| 1425 | if(sel.ey > term.bot) | 1430 | if(sel.oe.y > term.bot) |
| 1426 | sel.ey = term.bot; | 1431 | sel.oe.y = term.bot; |
| 1427 | } else { | 1432 | } else { |
| 1428 | if(sel.by < term.top) { | 1433 | if(sel.ob.y < term.top) { |
| 1429 | sel.by = term.top; | 1434 | sel.ob.y = term.top; |
| 1430 | sel.bx = 0; | 1435 | sel.ob.x = 0; |
| 1431 | } | 1436 | } |
| 1432 | if(sel.ey > term.bot) { | 1437 | if(sel.oe.y > term.bot) { |
| 1433 | sel.ey = term.bot; | 1438 | sel.oe.y = term.bot; |
| 1434 | sel.ex = term.col; | 1439 | sel.oe.x = term.col; |
| 1435 | } | 1440 | } |
| 1436 | } | 1441 | } |
| 1437 | sel.b.y = sel.by, sel.b.x = sel.bx; | 1442 | selsort(); |
| 1438 | sel.e.y = sel.ey, sel.e.x = sel.ex; | ||
| 1439 | } | 1443 | } |
| 1440 | } | 1444 | } |
| 1441 | 1445 | ||
| @@ -1905,7 +1909,7 @@ csihandle(void) { | |||
| 1905 | tputtab(1); | 1909 | tputtab(1); |
| 1906 | break; | 1910 | break; |
| 1907 | case 'J': /* ED -- Clear screen */ | 1911 | case 'J': /* ED -- Clear screen */ |
| 1908 | sel.bx = -1; | 1912 | sel.ob.x = -1; |
| 1909 | switch(csiescseq.arg[0]) { | 1913 | switch(csiescseq.arg[0]) { |
| 1910 | case 0: /* below */ | 1914 | case 0: /* below */ |
| 1911 | tclearregion(term.c.x, term.c.y, term.col-1, term.c.y); | 1915 | tclearregion(term.c.x, term.c.y, term.col-1, term.c.y); |
| @@ -2401,8 +2405,8 @@ tputc(char *c, int len) { | |||
| 2401 | */ | 2405 | */ |
| 2402 | if(control && !(term.c.attr.mode & ATTR_GFX)) | 2406 | if(control && !(term.c.attr.mode & ATTR_GFX)) |
| 2403 | return; | 2407 | return; |
| 2404 | if(sel.bx != -1 && BETWEEN(term.c.y, sel.by, sel.ey)) | 2408 | if(sel.ob.x != -1 && BETWEEN(term.c.y, sel.ob.y, sel.oe.y)) |
| 2405 | sel.bx = -1; | 2409 | sel.ob.x = -1; |
| 2406 | if(IS_SET(MODE_WRAP) && (term.c.state & CURSOR_WRAPNEXT)) { | 2410 | if(IS_SET(MODE_WRAP) && (term.c.state & CURSOR_WRAPNEXT)) { |
| 2407 | term.line[term.c.y][term.c.x].mode |= ATTR_WRAP; | 2411 | term.line[term.c.y][term.c.x].mode |= ATTR_WRAP; |
| 2408 | tnewline(1); | 2412 | tnewline(1); |
| @@ -3212,7 +3216,7 @@ drawregion(int x1, int y1, int x2, int y2) { | |||
| 3212 | int ic, ib, x, y, ox, sl; | 3216 | int ic, ib, x, y, ox, sl; |
| 3213 | Glyph base, new; | 3217 | Glyph base, new; |
| 3214 | char buf[DRAW_BUF_SIZ]; | 3218 | char buf[DRAW_BUF_SIZ]; |
| 3215 | bool ena_sel = sel.bx != -1; | 3219 | bool ena_sel = sel.ob.x != -1; |
| 3216 | 3220 | ||
| 3217 | if(sel.alt ^ IS_SET(MODE_ALTSCREEN)) | 3221 | if(sel.alt ^ IS_SET(MODE_ALTSCREEN)) |
| 3218 | ena_sel = 0; | 3222 | ena_sel = 0; |
