+/* Returns the number of display columns that would be occupied by the LENGTH
+ bytes of UTF-8 starting at S. */
+size_t
+utf8_count_columns (const char *s_, size_t length)
+{
+ const uint8_t *s = CHAR_CAST (const uint8_t *, s_);
+
+ size_t columns = 0;
+ for (int ofs = 0; ofs < length; )
+ {
+ ucs4_t uc;
+ ofs += u8_mbtouc (&uc, s + ofs, length - ofs);
+ if (uc != '\t')
+ {
+ int width = uc_width (uc, "UTF-8");
+ if (width > 0)
+ columns += width;
+ }
+ else
+ columns = ROUND_UP (columns + 1, 8);
+ }
+ return columns;
+}
+
+/* Returns the byte offset in LENGTH-byte UTF-8 string S that is N_COLUMNS
+ display columns into the string. */
+size_t
+utf8_columns_to_bytes (const char *s_, size_t length, size_t n_columns)
+{
+ const uint8_t *s = CHAR_CAST (const uint8_t *, s_);
+
+ size_t columns = 0;
+ int ofs;
+ for (ofs = 0; ofs < length && columns < n_columns; )
+ {
+ ucs4_t uc;
+ ofs += u8_mbtouc (&uc, s + ofs, length - ofs);
+ if (uc != '\t')
+ {
+ int width = uc_width (uc, "UTF-8");
+ if (width > 0)
+ columns += width;
+ }
+ else
+ columns = ROUND_UP (columns + 1, 8);
+ }
+ return ofs;
+}
+