aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarkus Teich <markus.teich@stusta.mhn.de>2016-01-20 07:46:16 +0100
committerMarc André Tanner <mat@brain-dump.org>2016-01-20 10:35:44 +0100
commit0d4093c3371079c5f75055338f0341f684542465 (patch)
tree2bdab37770875bbb9e06e0f8f1ea371166167e19
parente1bf543ac6e9afb1be7f06c2ad02aad8e0b11fb5 (diff)
downloadvis-0d4093c3371079c5f75055338f0341f684542465.tar.gz
vis-0d4093c3371079c5f75055338f0341f684542465.tar.xz
Fix to/till movements
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.
-rw-r--r--text-motions.c11
-rw-r--r--vis-motions.c8
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
@@ -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--;
@@ -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
@@ -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;
@@ -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;
@@ -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])
@@ -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)