From 0957fdca6ac5b41fa95f4a08d06f402e53d7e324 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Wed, 22 Apr 2020 12:22:29 +0200 Subject: [PATCH] lib/mbsalign: add function to calculate width We already have mbs_safe_nwidth() but it assumes that all "bad" chars will be encoded by \x. Now we need also function that do not care about encoding. Signed-off-by: Karel Zak --- include/mbsalign.h | 3 +++ lib/mbsalign.c | 64 +++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/include/mbsalign.h b/include/mbsalign.h index 0c28e6f69..4f5add8b8 100644 --- a/include/mbsalign.h +++ b/include/mbsalign.h @@ -53,6 +53,9 @@ extern size_t mbsalign_with_padding (const char *src, char *dest, size_t dest_si extern size_t mbs_safe_nwidth(const char *buf, size_t bufsz, size_t *sz); extern size_t mbs_safe_width(const char *s); +extern size_t mbs_nwidth(const char *buf, size_t bufsz); +extern size_t mbs_width(const char *s); + extern char *mbs_safe_encode(const char *s, size_t *width); extern char *mbs_safe_encode_to_buffer(const char *s, size_t *width, char *buf, const char *safechars); extern size_t mbs_safe_encode_size(size_t bytes); diff --git a/lib/mbsalign.c b/lib/mbsalign.c index e94b277b4..e251202af 100644 --- a/lib/mbsalign.c +++ b/lib/mbsalign.c @@ -28,9 +28,67 @@ #include "strutils.h" #include "widechar.h" -/* Replace non printable chars. - Note \t and \n etc. are non printable. - Return 1 if replacement made, 0 otherwise. */ +/* + * Counts number of cells in multibyte string. All control and + * non-printable chars are ignored. + * + * Returns: number of cells. + */ +size_t mbs_nwidth(const char *buf, size_t bufsz) +{ + const char *p = buf, *last = buf; + size_t width = 0; + +#ifdef HAVE_WIDECHAR + mbstate_t st; + memset(&st, 0, sizeof(st)); +#endif + if (p && *p && bufsz) + last = p + (bufsz - 1); + + while (p && *p && p <= last) { + if (iscntrl((unsigned char) *p)) { + p++; + + /* try detect "\e[x;ym" and skip on success */ + if (*p && *p == '[') { + const char *e = p; + while (*e && e < last && *e != 'm') + e++; + if (*e == 'm') + p = e + 1; + } + continue; + } +#ifdef HAVE_WIDECHAR + wchar_t wc; + size_t len = mbrtowc(&wc, p, MB_CUR_MAX, &st); + + if (len == 0) + break; + if (len > 0 && iswprint(wc)) { + int x = wcwidth(wc); + if (x > 0) + width += x; + } else if (len == (size_t) -1 || len == (size_t) -2) + len = 1; + p += len; +#else + if (isprint((unsigned char) *p)) + width++; + p++; +#endif + } + + return width; +} + +size_t mbs_width(const char *s) +{ + if (!s || !*s) + return 0; + return mbs_nwidth(s, strlen(s)); +} /* * Counts number of cells in multibyte string. For all control and