aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc André Tanner <mat@brain-dump.org>2015-08-01 19:42:15 +0200
committerMarc André Tanner <mat@brain-dump.org>2015-08-01 19:42:15 +0200
commit7c5c6581bca271f41c7ae3ac53107b89249a5fa9 (patch)
treec22ae8d18870172d30bd876338d74b4fe0cd2538
parent25beaeb21f3d0b2fcd9b6c612cd2d7cb25291a28 (diff)
downloadvis-7c5c6581bca271f41c7ae3ac53107b89249a5fa9.tar.gz
vis-7c5c6581bca271f41c7ae3ac53107b89249a5fa9.tar.xz
text-motion: fix text_find_{next,prev}
It is after all a stupid O(n*m) algorithm, hence restart after a failed partial match. Code like this would benefit from a proper test suite ...
-rw-r--r--text-motions.c17
1 files changed, 12 insertions, 5 deletions
diff --git a/text-motions.c b/text-motions.c
index 9d40c33..8b349c2 100644
--- a/text-motions.c
+++ b/text-motions.c
@@ -50,12 +50,16 @@ size_t text_find_next(Text *txt, size_t pos, const char *s) {
if (!s)
return pos;
size_t len = strlen(s), matched = 0;
- Iterator it = text_iterator_get(txt, pos);
+ Iterator it = text_iterator_get(txt, pos), sit;
for (char c; matched < len && text_iterator_byte_get(&it, &c); ) {
- if (c == s[matched])
+ if (c == s[matched]) {
+ if (matched == 0)
+ sit = it;
matched++;
- else
+ } else if (matched > 0) {
+ it = sit;
matched = 0;
+ }
text_iterator_byte_next(&it, NULL);
}
return matched == len ? it.pos - len : pos;
@@ -65,15 +69,18 @@ size_t text_find_prev(Text *txt, size_t pos, const char *s) {
if (!s)
return pos;
size_t len = strlen(s), matched = len - 1;
- Iterator it = text_iterator_get(txt, pos);
+ Iterator it = text_iterator_get(txt, pos), sit;
if (len == 0)
return pos;
for (char c; text_iterator_byte_get(&it, &c); ) {
if (c == s[matched]) {
if (matched == 0)
break;
+ if (matched == len - 1)
+ sit = it;
matched--;
- } else {
+ } else if (matched < len - 1) {
+ it = sit;
matched = len - 1;
}
text_iterator_byte_prev(&it, NULL);