diff options
| author | Marc André Tanner <mat@brain-dump.org> | 2015-11-23 10:48:41 +0100 |
|---|---|---|
| committer | Marc André Tanner <mat@brain-dump.org> | 2015-11-23 14:18:27 +0100 |
| commit | c1584693cbb2d9ea2f2cfb4fc528da30b2554a91 (patch) | |
| tree | 0cadc0bccd9ac91d9118c0e061e2566c7054e70b | |
| parent | 0613073092b9f4172b5b87e9c7f243ff6d61f723 (diff) | |
| download | vis-c1584693cbb2d9ea2f2cfb4fc528da30b2554a91.tar.gz vis-c1584693cbb2d9ea2f2cfb4fc528da30b2554a91.tar.xz | |
vis: improve replacement of combining characters
| -rw-r--r-- | text-util.c | 29 | ||||
| -rw-r--r-- | text-util.h | 2 | ||||
| -rw-r--r-- | vis.c | 7 |
3 files changed, 32 insertions, 6 deletions
diff --git a/text-util.c b/text-util.c index 2b48719..4d3406b 100644 --- a/text-util.c +++ b/text-util.c @@ -1,5 +1,7 @@ #include "text-util.h" #include "util.h" +#include <wchar.h> +#include <errno.h> bool text_range_valid(Filerange *r) { return r->start != EPOS && r->end != EPOS && r->start <= r->end; @@ -46,3 +48,30 @@ bool text_range_overlap(Filerange *r1, Filerange *r2) { bool text_range_contains(Filerange *r, size_t pos) { return text_range_valid(r) && r->start <= pos && pos <= r->end; } + +int text_char_count(const char *data, size_t len) { + int count = 0; + mbstate_t ps = { 0 }; + while (len > 0) { + wchar_t wc; + size_t wclen = mbrtowc(&wc, data, len, &ps); + if (wclen == (size_t)-1 && errno == EILSEQ) { + count++; + while (!ISUTF8(*data)) + data++, len--; + } else if (wclen == (size_t)-2) { + break; + } else if (wclen == 0) { + count++; + data++; + len--; + } else { + int width = wcwidth(wc); + if (width != 0) + count++; + data += wclen; + len -= wclen; + } + } + return count; +} diff --git a/text-util.h b/text-util.h index 80affd5..9bfa705 100644 --- a/text-util.h +++ b/text-util.h @@ -21,5 +21,7 @@ bool text_range_equal(Filerange*, Filerange*); bool text_range_overlap(Filerange*, Filerange*); /* test whether a given position is within a certain range */ bool text_range_contains(Filerange*, size_t pos); +/* count the number of graphemes in data */ +int text_char_count(const char *data, size_t len); #endif @@ -435,14 +435,9 @@ void vis_insert_key(Vis *vis, const char *data, size_t len) { } void vis_replace(Vis *vis, size_t pos, const char *data, size_t len) { - size_t chars = 0; - for (size_t i = 0; i < len; i++) { - if (ISUTF8(data[i])) - chars++; - } - Text *txt = vis->win->file->text; Iterator it = text_iterator_get(txt, pos); + int chars = text_char_count(data, len); for (char c; chars-- > 0 && text_iterator_byte_get(&it, &c) && c != '\r' && c != '\n'; ) text_iterator_char_next(&it, NULL); |
