The fix is for st HEAD.

First of all, how to reproduce:
1. Run "man man" or just "less" with some scrollable file.
2. Select some part of text by pressing LMB somewhere and moving cursor
up.
3. Scroll with "j" and "k".

The result is: http://postimg.org/image/ec04tz7u5/

The problem is that if you select this way, sel.e.y is less than
sel.b.x.  selected() function expects sel.b.y and sel.e.y to be the
"sorted" version of sel.bx, ..., sel.ey variables.

To fix this problem, I moved the code that sorts these variables to
separate function "selsort" and replaced code that just copied sel.bx,
.., sel.ey to sel.b.x, ..., sel.e.y with the call to selsort.

This also fixes another problem with rectangular selection.  If you
select backwards with alt pressed and then scroll, rectangular selection
just disappears.

Patch is attached.
diff --git a/st.c b/st.c
index 8475878..99c3468 100644
--- a/st.c
+++ b/st.c
@@ -249,11 +249,10 @@ typedef struct {
        int mode;
        int type;
        int snap;
-       int bx, by;
-       int ex, ey;
+       int bx, by, ex, ey;
        struct {
                int x, y;
-       } b, e;
+       } b, e; /* same as bx, ..., ey, but swapped if by > ey */
        char *clip;
        Atom xtarget;
        bool alt;
@@ -390,6 +389,7 @@ static void selclear(XEvent *);
 static void selrequest(XEvent *);
 
 static void selinit(void);
+static void selsort(void);
 static inline bool selected(int, int);
 static void selcopy(void);
 static void selscroll(int, int);
@@ -658,21 +658,23 @@ y2row(int y) {
        return LIMIT(y, 0, term.row-1);
 }
 
+static void
+selsort(void) {
+       sel.b.x = sel.by < sel.ey ? sel.bx : sel.ex;
+       sel.b.y = MIN(sel.by, sel.ey);
+       sel.e.x = sel.by < sel.ey ? sel.ex : sel.bx;
+       sel.e.y = MAX(sel.by, sel.ey);
+}
+
 static inline bool
 selected(int x, int y) {
-       int bx, ex;
-
-       if(sel.ey == y && sel.by == y) {
-               bx = MIN(sel.bx, sel.ex);
-               ex = MAX(sel.bx, sel.ex);
-
-               return BETWEEN(x, bx, ex);
-       }
+       if(sel.e.y == y && sel.b.y == y)
+               return BETWEEN(x, sel.b.x, sel.e.x);
 
-       if(sel.type == SEL_RECTANGULAR) {
+       if(sel.type == SEL_RECTANGULAR)
                return ((sel.b.y <= y && y <= sel.e.y)
                        && (sel.b.x <= x && x <= sel.e.x));
-       }
+
        return ((sel.b.y < y && y < sel.e.y)
                || (y == sel.e.y && x <= sel.e.x))
                || (y == sel.b.y && x >= sel.b.x
@@ -774,11 +776,7 @@ getbuttoninfo(XEvent *e) {
                selsnap(sel.snap, &sel.bx, &sel.by, +1);
        }
 
-       sel.b.x = sel.by < sel.ey ? sel.bx : sel.ex;
-       sel.b.y = MIN(sel.by, sel.ey);
-       sel.e.x = sel.by < sel.ey ? sel.ex : sel.bx;
-       sel.e.y = MAX(sel.by, sel.ey);
-
+       selsort();
        sel.type = SEL_REGULAR;
        for(type = 1; type < LEN(selmasks); ++type) {
                if(match(selmasks[type], state)) {
@@ -882,10 +880,8 @@ bpress(XEvent *e) {
                }
                selsnap(sel.snap, &sel.bx, &sel.by, -1);
                selsnap(sel.snap, &sel.ex, &sel.ey, +1);
-               sel.b.x = sel.bx;
-               sel.b.y = sel.by;
-               sel.e.x = sel.ex;
-               sel.e.y = sel.ey;
+
+               selsort();
 
                /*
                 * Draw selection, unless it's regular and we don't want to
@@ -1111,9 +1107,8 @@ bmotion(XEvent *e) {
        oldsey = sel.e.y;
        getbuttoninfo(e);
 
-       if(oldey != sel.ey || oldex != sel.ex) {
+       if(oldey != sel.ey || oldex != sel.ex)
                tsetdirt(MIN(sel.b.y, oldsby), MAX(sel.e.y, oldsey));
-       }
 }
 
 void
@@ -1434,8 +1429,7 @@ selscroll(int orig, int n) {
                                sel.ex = term.col;
                        }
                }
-               sel.b.y = sel.by, sel.b.x = sel.bx;
-               sel.e.y = sel.ey, sel.e.x = sel.ex;
+               selsort();
        }
 }
 

Reply via email to