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