X-Git-Url: https://git.xinqibao.xyz/st.git/blobdiff_plain/c6fcb78b3a9a73b691875048848430c18870a0fc..6fd887077e29efd789499e06193314d7abdcac38:/st.c

diff --git a/st.c b/st.c
index 11d01df..8b65450 100644
--- a/st.c
+++ b/st.c
@@ -441,7 +441,7 @@ static void selclear(XEvent *);
 static void selrequest(XEvent *);
 
 static void selinit(void);
-static void selsort(void);
+static void selnormalize(void);
 static inline bool selected(int, int);
 static char *getsel(void);
 static void selcopy(void);
@@ -657,9 +657,20 @@ y2row(int y) {
 	return LIMIT(y, 0, term.row-1);
 }
 
+static int tlinelen(int y) {
+	int i = term.col;
+
+	while (i > 0 && term.line[y][i - 1].c[0] == ' ')
+		--i;
+
+	return i;
+}
+
 static void
-selsort(void) {
-	if(sel.ob.y == sel.oe.y) {
+selnormalize(void) {
+	int i;
+
+	if(sel.ob.y == sel.oe.y || sel.type == SEL_RECTANGULAR) {
 		sel.nb.x = MIN(sel.ob.x, sel.oe.x);
 		sel.ne.x = MAX(sel.ob.x, sel.oe.x);
 	} else {
@@ -668,6 +679,15 @@ selsort(void) {
 	}
 	sel.nb.y = MIN(sel.ob.y, sel.oe.y);
 	sel.ne.y = MAX(sel.ob.y, sel.oe.y);
+
+	/* expand selection over line breaks */
+	if (sel.type == SEL_RECTANGULAR)
+		return;
+	i = tlinelen(sel.nb.y);
+	if (i < sel.nb.x)
+		sel.nb.x = i;
+	if (tlinelen(sel.ne.y) <= sel.ne.x)
+		sel.ne.x = term.col - 1;
 }
 
 static inline bool
@@ -683,8 +703,6 @@ selected(int x, int y) {
 
 void
 selsnap(int mode, int *x, int *y, int direction) {
-	int i;
-
 	switch(mode) {
 	case SNAP_WORD:
 		/*
@@ -716,7 +734,7 @@ selsnap(int mode, int *x, int *y, int direction) {
 				continue;
 			}
 
-			if(strchr(worddelimiters,
+			if(*x >= tlinelen(*y) || strchr(worddelimiters,
 					term.line[*y][*x+direction].c[0])) {
 				break;
 			}
@@ -747,18 +765,6 @@ selsnap(int mode, int *x, int *y, int direction) {
 			}
 		}
 		break;
-	default:
-		/*
-		 * Select the whole line when the end of line is reached.
-		 */
-		if(direction > 0) {
-			i = term.col;
-			while(--i > 0 && term.line[*y][i].c[0] == ' ')
-				/* nothing */;
-			if(i > 0 && i < *x)
-				*x = term.col - 1;
-		}
-		break;
 	}
 }
 
@@ -780,7 +786,7 @@ getbuttoninfo(XEvent *e) {
 		selsnap(sel.snap, &sel.oe.x, &sel.oe.y, -1);
 		selsnap(sel.snap, &sel.ob.x, &sel.ob.y, +1);
 	}
-	selsort();
+	selnormalize();
 
 	sel.type = SEL_REGULAR;
 	for(type = 1; type < LEN(selmasks); ++type) {
@@ -896,7 +902,7 @@ bpress(XEvent *e) {
 		}
 		selsnap(sel.snap, &sel.ob.x, &sel.ob.y, -1);
 		selsnap(sel.snap, &sel.oe.x, &sel.oe.y, +1);
-		selsort();
+		selnormalize();
 
 		/*
 		 * Draw selection, unless it's regular and we don't want to
@@ -914,7 +920,7 @@ bpress(XEvent *e) {
 char *
 getsel(void) {
 	char *str, *ptr;
-	int x, y, bufsize, size, i, ex;
+	int x, y, bufsize, size, ex;
 	Glyph *gp, *last;
 
 	if(sel.ob.x == -1)
@@ -959,13 +965,10 @@ getsel(void) {
 		 * after the visible text '\n' is appended.
 		 */
 		if(y == sel.ne.y) {
-			i = term.col;
-			while(--i > 0 && term.line[y][i].c[0] == ' ')
-				/* nothing */;
 			ex = sel.ne.x;
 			if(sel.nb.y == sel.ne.y && sel.ne.x < sel.nb.x)
 				ex = sel.nb.x;
-			if(i < ex)
+			if(tlinelen(y) < ex)
 				*ptr++ = '\n';
 		}
 	}
@@ -1451,7 +1454,7 @@ selscroll(int orig, int n) {
 				sel.oe.x = term.col;
 			}
 		}
-		selsort();
+		selnormalize();
 	}
 }