vis

a vi-like editor based on Plan 9's structural regular expressions

git clone https://9o.is/git/vis.git

commit 86152eec235661fcb2f562c3e8113a98d1f33c86
parent fac773ba6220d04858b9739bc9b032c92e179ee4
Author: Marc André Tanner <mat@brain-dump.org>
Date:   Tue, 24 May 2016 21:39:58 +0200

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.

Diffstat:
Mtext-util.c | 38++++++++++++++++++++++++++++++++++++++
Mtext-util.h | 2++
2 files changed, 40 insertions(+), 0 deletions(-)

diff --git a/text-util.c b/text-util.c @@ -2,6 +2,7 @@ #include "util.h" #include <wchar.h> #include <errno.h> +#include <stdlib.h> 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; +} diff --git a/text-util.h b/text-util.h @@ -23,5 +23,7 @@ bool text_range_overlap(const Filerange*, const Filerange*); bool text_range_contains(const Filerange*, size_t pos); /* count the number of graphemes in data */ int text_char_count(const char *data, size_t len); +/* get the approximate display width of data */ +int text_string_width(const char *data, size_t len); #endif