aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc André Tanner <mat@brain-dump.org>2014-08-28 13:50:15 +0200
committerMarc André Tanner <mat@brain-dump.org>2014-08-28 13:50:15 +0200
commit8a33f6ab4edaf9e43388f99b75229aab1ee7ba23 (patch)
treeebf94e4cd47f30624bb477bc7ee6083b89235f15
parentb5d121dc1ca4edc0cfff888ba411f0837e6e0ebc (diff)
downloadvis-8a33f6ab4edaf9e43388f99b75229aab1ee7ba23.tar.gz
vis-8a33f6ab4edaf9e43388f99b75229aab1ee7ba23.tar.xz
Improve text motions
-rw-r--r--text-motions.c44
-rw-r--r--text-motions.h13
2 files changed, 45 insertions, 12 deletions
diff --git a/text-motions.c b/text-motions.c
index 1313c94..8154e2b 100644
--- a/text-motions.c
+++ b/text-motions.c
@@ -1,8 +1,41 @@
#include <ctype.h>
#include "text-motions.h"
+#include "util.h"
// TODO: consistent usage of iterators either char or byte based where appropriate.
+size_t text_find_char_next(Text *txt, size_t pos, const char *s, size_t len) {
+ char c;
+ size_t matched = 0;
+ Iterator it = text_iterator_get(txt, pos);
+ while (matched < len && text_iterator_byte_get(&it, &c)) {
+ if (c == s[matched])
+ matched++;
+ else
+ matched = 0;
+ text_iterator_byte_next(&it, NULL);
+ }
+ return it.pos - (matched == len ? len : 0);
+}
+
+size_t text_find_char_prev(Text *txt, size_t pos, const char *s, size_t len) {
+ char c;
+ size_t matched = len - 1;
+ Iterator it = text_iterator_get(txt, pos);
+ if (len == 0)
+ return pos;
+ while (text_iterator_byte_get(&it, &c)) {
+ if (c == s[matched]) {
+ if (matched-- == 0)
+ break;
+ } else {
+ matched = len - 1;
+ }
+ text_iterator_byte_next(&it, NULL);
+ }
+ return it.pos;
+}
+
size_t text_line_begin(Text *txt, size_t pos) {
char c;
Iterator it = text_iterator_get(txt, pos);
@@ -19,7 +52,7 @@ size_t text_line_begin(Text *txt, size_t pos) {
}
text_iterator_byte_prev(&it, NULL);
}
- return pos;
+ return it.pos;
}
size_t text_line_start(Text *txt, size_t pos) {
@@ -35,18 +68,15 @@ size_t text_line_finish(Text *txt, size_t pos) {
Iterator it = text_iterator_get(txt, text_line_end(txt, pos));
do text_iterator_byte_prev(&it, NULL);
while (text_iterator_byte_get(&it, &c) && c != '\n' && c != '\r' && isspace(c));
+ if (!isutf8(c))
+ text_iterator_char_prev(&it, &c);
return it.pos;
}
size_t text_line_end(Text *txt, size_t pos) {
- char c;
- Iterator it = text_iterator_get(txt, pos);
- while (text_iterator_byte_get(&it, &c) && c != '\n')
- text_iterator_byte_next(&it, NULL);
- return it.pos;
+ return text_find_char_next(txt, pos, "\n", 1);
}
-
size_t text_word_boundry_start_next(Text *txt, size_t pos, int (*isboundry)(int)) {
char c;
Iterator it = text_iterator_get(txt, pos);
diff --git a/text-motions.h b/text-motions.h
index bbeca49..234376c 100644
--- a/text-motions.h
+++ b/text-motions.h
@@ -4,11 +4,14 @@
#include <stddef.h>
#include "text.h"
-/* begin finish
- * v v
- * | I am a line! |
- * ^ ^
- * start end
+size_t text_find_char_next(Text*, size_t pos, const char *s, size_t len);
+size_t text_find_char_prev(Text*, size_t pos, const char *s, size_t len);
+
+/* begin finish
+ * v v
+ * \n[\r] I am a line! \n[\r]
+ * ^ ^
+ * start end
*/
size_t text_line_begin(Text*, size_t pos);
size_t text_line_start(Text*, size_t pos);