From e33a0b6dbec351c188cf51934dd63250aab654df Mon Sep 17 00:00:00 2001 From: Benno Schulenberg Date: Mon, 6 Jun 2016 13:20:04 +0200 Subject: [PATCH] screen: avoid converting each character twice from multibyte to wide --- src/chars.c | 12 +++++++++--- src/proto.h | 2 +- src/winio.c | 10 ++++------ 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/chars.c b/src/chars.c index eb070794..e2852cee 100644 --- a/src/chars.c +++ b/src/chars.c @@ -230,8 +230,9 @@ char control_mbrep(const char *c) /* Assess how many bytes the given (multibyte) character occupies. Return -1 * if the byte sequence is invalid, and return the number of bytes minus 8 - * when the byte sequence encodes an invalid codepoint. */ -int length_of_char(const char *c) + * when it encodes an invalid codepoint. Also, in the second parameter, + * return the number of columns that the character occupies. */ +int length_of_char(const char *c, int *width) { assert(c != NULL); @@ -249,8 +250,13 @@ int length_of_char(const char *c) /* If the codepoint is invalid... */ if (!is_valid_unicode(wc)) return charlen - 8; - else + else { + *width = wcwidth(wc); + /* If the codepoint is unassigned, assume a width of one. */ + if (*width < 0) + *width = 1; return charlen; + } } else #endif return 1; diff --git a/src/proto.h b/src/proto.h index 470df16a..3e201e16 100644 --- a/src/proto.h +++ b/src/proto.h @@ -188,7 +188,7 @@ bool is_punct_mbchar(const char *c); bool is_word_mbchar(const char *c, bool allow_punct); char control_rep(const signed char c); char control_mbrep(const char *c); -int length_of_char(const char *c); +int length_of_char(const char *c, int *width); int mbwidth(const char *c); int mb_cur_max(void); char *make_mbchar(long chr, int *chr_mb_len); diff --git a/src/winio.c b/src/winio.c index 0ad2140c..4552db0f 100644 --- a/src/winio.c +++ b/src/winio.c @@ -1780,7 +1780,7 @@ char *display_string(const char *buf, size_t start_col, size_t len, bool } while (*buf != '\0') { - int charlength; + int charlength, charwidth = 1; if (*buf == ' ') { /* Show a space as a visible character, or as a space. */ @@ -1817,7 +1817,7 @@ char *display_string(const char *buf, size_t start_col, size_t len, bool continue; } - charlength = length_of_char(buf); + charlength = length_of_char(buf, &charwidth); /* If buf contains a control character, represent it. */ if (is_cntrl_mbchar(buf)) { @@ -1830,13 +1830,11 @@ char *display_string(const char *buf, size_t start_col, size_t len, bool /* If buf contains a valid non-control character, simply copy it. */ if (charlength > 0) { - int width = mbwidth(buf); - for (; charlength > 0; charlength--) converted[index++] = *(buf++); - start_col += width; - if (width > 1) + start_col += charwidth; + if (charwidth > 1) seen_wide = TRUE; continue;