aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc André Tanner <mat@brain-dump.org>2015-11-23 10:48:41 +0100
committerMarc André Tanner <mat@brain-dump.org>2015-11-23 14:18:27 +0100
commitc1584693cbb2d9ea2f2cfb4fc528da30b2554a91 (patch)
tree0cadc0bccd9ac91d9118c0e061e2566c7054e70b
parent0613073092b9f4172b5b87e9c7f243ff6d61f723 (diff)
downloadvis-c1584693cbb2d9ea2f2cfb4fc528da30b2554a91.tar.gz
vis-c1584693cbb2d9ea2f2cfb4fc528da30b2554a91.tar.xz
vis: improve replacement of combining characters
-rw-r--r--text-util.c29
-rw-r--r--text-util.h2
-rw-r--r--vis.c7
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
diff --git a/vis.c b/vis.c
index c84b415..03dcc61 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);