From c1584693cbb2d9ea2f2cfb4fc528da30b2554a91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Andr=C3=A9=20Tanner?= Date: Mon, 23 Nov 2015 10:48:41 +0100 Subject: [PATCH] vis: improve replacement of combining characters --- text-util.c | 29 +++++++++++++++++++++++++++++ text-util.h | 2 ++ vis.c | 7 +------ 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/text-util.c b/text-util.c index 2b48719b7..4d3406b7e 100644 --- a/text-util.c +++ b/text-util.c @@ -1,5 +1,7 @@ #include "text-util.h" #include "util.h" +#include +#include 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 80affd5c9..9bfa705dd 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 diff --git a/vis.c b/vis.c index c84b4158d..03dcc6112 100644 --- a/vis.c +++ b/vis.c @@ -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);