]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lib/mbsalign: add function to calculate width
authorKarel Zak <kzak@redhat.com>
Wed, 22 Apr 2020 10:22:29 +0000 (12:22 +0200)
committerKarel Zak <kzak@redhat.com>
Wed, 22 Apr 2020 10:22:29 +0000 (12:22 +0200)
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>
include/mbsalign.h
lib/mbsalign.c

index 0c28e6f69dd4ab22b63a402f33171e6127ff39ad..4f5add8b8a8706ba4e99b5dd48e5107fffc69d38 100644 (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);
index e94b277b45a23551c0da5cc68c0a9e81c83ab89f..e251202afbe5e620f472d73a8656b8abebb9c64c 100644 (file)
 #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