diff --git a/src/fe-common/core/utf8.c b/src/fe-common/core/utf8.c index 2d07ea8e..49efae63 100644 --- a/src/fe-common/core/utf8.c +++ b/src/fe-common/core/utf8.c @@ -22,5 +22,56 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include #include "module.h" +/* + * Return the width (number of columns when displayed) of the character pointed + * by c. + */ +int get_utf8_char_width(const gchar *c) { + gunichar uc; + int char_width; + uc = g_utf8_get_char(c); + char_width = g_unichar_isprint(uc) ? (1 + g_unichar_iswide(uc)) : 0; + return char_width; +} + +/* + * Return the number of columns taken by the s string, assuming its end is + * marked with a '\0' character and assuming it is a UTF-8 (multibyte) string. + * If s is NULL, this function returns -1. + * By default, this function takes care to validate s by calling + * g_utf8_validate(s, -1, NULL). If this check is deemed unnecessary, passing a + * non-zero value as skip_validation will skip that step. If the validation + * fails, this function returns -1. Otherwise, it will strive to provide a + * value as close as possible to what is expected. + */ +int get_utf8_string_width(const gchar *s, int skip_validation) { + const gchar *c; + int str_width; + + /* Ensure s is non-NULL: */ + if (!s) { + return -1; + } + + /* Validate the string, unless required otherwise: */ + if (!skip_validation) { + if (!g_utf8_validate(s, -1, NULL)) { + /* Another possibility here would be to return strlen(s). */ + return -1; + } + } + + /* Iterate over characters to determine the width: */ + str_width = 0; + for (c = s; *c; c = g_utf8_next_char(c)) { + str_width += get_utf8_char_width(c); + } + /* Note: there probably are some Unicode subtleties (Fitzpatrick + * modifiers?) that make the above implementation somewhat naive, but we + * have to start somewhere. + */ + return str_width; +} diff --git a/src/fe-common/core/utf8.h b/src/fe-common/core/utf8.h index 3c15dc7d..31ee5117 100644 --- a/src/fe-common/core/utf8.h +++ b/src/fe-common/core/utf8.h @@ -11,6 +11,10 @@ /* Returns width for character (0-2). */ int mk_wcwidth(unichar c); +/* Return the number of columns occupied by a given string. */ +int get_utf8_char_width(const gchar *); +int get_utf8_string_width(const gchar *); + #define unichar_isprint(c) (((c) & ~0x80) >= 32) #define is_utf8_leading(c) (((c) & 0xc0) != 0x80)