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<hex>. Now we need also function that do not care
about encoding.

Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
Karel Zak 2020-04-22 12:22:29 +02:00
parent 7c16238c06
commit 0957fdca6a
2 changed files with 64 additions and 3 deletions

View File

@ -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);

View File

@ -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