[hackers] [vis] [PATCH] Fix to/till movements

From: Markus Teich <markus.teich_AT_stusta.mhn.de>
Date: Wed, 20 Jan 2016 07:46:16 +0100

Some corner cases allowed to move between lines with the to/till movements.

The change in find_prev serves two purposes. When searching for a string which
the cursor is already above the match, this match is returned (pos += len).
Secondly there was a failure when searching for strings with len == 1 which lead
to `matched == 0` which was always true, even if the string was not found,
therefore leading to a wrong return value.
---
 text-motions.c | 11 ++++++-----
 vis-motions.c  |  8 ++++++--
 2 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/text-motions.c b/text-motions.c
index 824f3a9..550466b 100644
--- a/text-motions.c
+++ b/text-motions.c
_AT_@ -79,13 +79,15 @@ static size_t find_prev(Text *txt, size_t pos, const char *s, bool line) {
 	if (!s)
 		return pos;
 	size_t len = strlen(s), matched = len - 1;
-	Iterator it = text_iterator_get(txt, pos), sit;
+	Iterator it, sit;
 	if (len == 0)
 		return pos;
-	for (char c; text_iterator_byte_get(&it, &c); ) {
+	pos += len;
+	it = text_iterator_get(txt, pos);
+	for (char c; text_iterator_byte_prev(&it, &c); ) {
 		if (c == s[matched]) {
 			if (matched == 0)
-				break;
+				return it.pos;
 			if (matched == len - 1)
 				sit = it;
 			matched--;
_AT_@ -93,11 +95,10 @@ static size_t find_prev(Text *txt, size_t pos, const char *s, bool line) {
 			it = sit;
 			matched = len - 1;
 		}
-		text_iterator_byte_prev(&it, NULL);
 		if (line && c == '\n')
 			break;
 	}
-	return matched == 0 ? it.pos : pos;
+	return pos;
 }
 
 size_t text_find_prev(Text *txt, size_t pos, const char *s) {
diff --git a/vis-motions.c b/vis-motions.c
index 0cb0252..3369051 100644
--- a/vis-motions.c
+++ b/vis-motions.c
_AT_@ -53,6 +53,8 @@ static size_t mark_line_goto(Vis *vis, File *file, size_t pos) {
 
 static size_t to(Vis *vis, Text *txt, size_t pos) {
 	char c;
+	if (pos == text_line_end(txt, pos))
+		return pos;
 	size_t hit = text_line_find_next(txt, pos+1, vis->search_char);
 	if (!text_byte_get(txt, hit, &c) || c != vis->search_char[0])
 		return pos;
_AT_@ -61,6 +63,8 @@ static size_t to(Vis *vis, Text *txt, size_t pos) {
 
 static size_t till(Vis *vis, Text *txt, size_t pos) {
 	size_t hit = to(vis, txt, pos+1);
+	if (pos == text_line_end(txt, pos))
+		return pos;
 	if (hit != pos)
 		return text_char_prev(txt, hit);
 	return pos;
_AT_@ -68,7 +72,7 @@ static size_t till(Vis *vis, Text *txt, size_t pos) {
 
 static size_t to_left(Vis *vis, Text *txt, size_t pos) {
 	char c;
-	if (pos == 0)
+	if (pos == text_line_begin(txt, pos))
 		return pos;
 	size_t hit = text_line_find_prev(txt, pos-1, vis->search_char);
 	if (!text_byte_get(txt, hit, &c) || c != vis->search_char[0])
_AT_@ -77,7 +81,7 @@ static size_t to_left(Vis *vis, Text *txt, size_t pos) {
 }
 
 static size_t till_left(Vis *vis, Text *txt, size_t pos) {
-	if (pos == 0)
+	if (pos == text_line_begin(txt, pos))
 		return pos;
 	size_t hit = to_left(vis, txt, pos-1);
 	if (hit != pos)
-- 
2.4.10
Received on Wed Jan 20 2016 - 07:46:16 CET

This archive was generated by hypermail 2.3.0 : Wed Jan 20 2016 - 07:48:29 CET