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-patched-8f1bef05025c0052603f7ca30552a43395b4c13f.tar.bz2 st-patched-8f1bef05025c0052603f7ca30552a43395b4c13f.tar.xz st-patched-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; |