From 3cea78b00dcebe76da9a69d58c33c8b2a58d41ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Andr=C3=A9=20Tanner?= Date: Tue, 24 May 2016 21:39:58 +0200 Subject: Add utility function to calculate display width of a string This is based on the implementation of text_line_width_get from text-motions.c. There might be an opportunity for code sharing. --- text-util.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'text-util.c') diff --git a/text-util.c b/text-util.c index 6794a78..c7a1349 100644 --- a/text-util.c +++ b/text-util.c @@ -2,6 +2,7 @@ #include "util.h" #include #include +#include bool text_range_valid(const Filerange *r) { return r->start != EPOS && r->end != EPOS && r->start <= r->end; @@ -75,3 +76,40 @@ int text_char_count(const char *data, size_t len) { } return count; } + +int text_string_width(const char *data, size_t len) { + + int width = 0; + mbstate_t ps = { 0 }; + const char *s = data; + + while (len > 0) { + char buf[MB_CUR_MAX]; + wchar_t wc; + size_t wclen = mbrtowc(&wc, s, len, &ps); + if (wclen == (size_t)-1 && errno == EILSEQ) { + /* assume a replacement symbol will be displayed */ + width++; + wclen = 1; + } else if (wclen == (size_t)-2) { + /* do nothing, advance to next character */ + wclen = 1; + } else if (wclen == 0) { + /* assume NUL byte will be displayed as ^@ */ + width += 2; + wclen = 1; + } else if (buf[0] == '\t') { + width++; + wclen = 1; + } else { + int w = wcwidth(wc); + if (w == -1) + w = 2; /* assume non-printable will be displayed as ^{char} */ + width += w; + } + len -= wclen; + s += wclen; + } + + return width; +} -- cgit v1.2.3