diff options
| author | Marc André Tanner <mat@brain-dump.org> | 2014-09-14 10:34:39 +0200 |
|---|---|---|
| committer | Marc André Tanner <mat@brain-dump.org> | 2014-09-14 10:34:39 +0200 |
| commit | 6b7a6dce18c88b4b8977679e9179a5d1af525c60 (patch) | |
| tree | 222aced794311227b576fe84c8a0d576f3bb68e9 | |
| parent | 7338b80cc8d6eb2e49f6559d1ede9b7f6714808d (diff) | |
| download | vis-6b7a6dce18c88b4b8977679e9179a5d1af525c60.tar.gz vis-6b7a6dce18c88b4b8977679e9179a5d1af525c60.tar.xz | |
Make byte based iterator API handle the whole range [0, size]
Before this commit the valid range was [0, size) which represents
the file content. For the position at EOF (=size) a NUL byte is
returned which is not actually part of the underlying file.
This should fix various movements / editing operations at the end
of the file. For example Ctrl+w at the end of the command prompt.
| -rw-r--r-- | text.c | 33 | ||||
| -rw-r--r-- | text.h | 7 |
2 files changed, 34 insertions, 6 deletions
@@ -426,9 +426,20 @@ static Location piece_get_intern(Text *txt, size_t pos) { } /* similiar to piece_get_intern but usable as a public API. returns the piece - * holding the text at byte offset pos. never returns a sentinel piece. */ + * holding the text at byte offset pos. never returns a sentinel piece. + * it pos is the end of file (== text_size()) and the file is not empty then + * the last piece holding data is returned. + */ static Location piece_get_extern(Text *txt, size_t pos) { size_t cur = 0; + + if (pos > 0 && pos == txt->size) { + Piece *p = txt->begin.next; + while (p->next->next) + p = p->next; + return (Location){ .piece = p, .off = p->len }; + } + for (Piece *p = txt->begin.next; p->next; p = p->next) { if (cur <= pos && pos < cur + p->len) return (Location){ .piece = p, .off = pos - cur }; @@ -833,9 +844,14 @@ Iterator text_iterator_get(Text *txt, size_t pos) { } bool text_iterator_byte_get(Iterator *it, char *b) { - if (text_iterator_valid(it) && it->start <= it->text && it->text < it->end) { - *b = *it->text; - return true; + if (text_iterator_valid(it)) { + if (it->start <= it->text && it->text < it->end) { + *b = *it->text; + return true; + } else if (it->pos == it->piece->text->size) { /* EOF */ + *b = '\0'; + return true; + } } return false; } @@ -857,7 +873,14 @@ bool text_iterator_byte_next(Iterator *it, char *b) { if (!text_iterator_valid(it)) return false; it->text++; - while (it->text == it->end) { + /* special case for advancement to EOF */ + if (it->text == it->end && !it->piece->next->text) { + it->pos++; + if (b) + *b = '\0'; + return true; + } + while (it->text >= it->end) { if (!text_iterator_next(it)) return false; it->text = it->start; @@ -56,9 +56,14 @@ bool text_iterator_valid(const Iterator*); bool text_iterator_next(Iterator*); bool text_iterator_prev(Iterator*); +/* get byte at current iterator position, if this is at EOF a NUL + * byte (which is not actually part of the file) is read. */ bool text_iterator_byte_get(Iterator*, char *b); -bool text_iterator_byte_next(Iterator*, char *b); +/* advance iterator by one byte and get byte at new position. */ bool text_iterator_byte_prev(Iterator*, char *b); +/* if the new position is at EOF a NUL byte (which is not actually + * part of the file) is read. */ +bool text_iterator_byte_next(Iterator*, char *b); bool text_iterator_char_next(Iterator*, char *c); bool text_iterator_char_prev(Iterator*, char *c); |
