aboutsummaryrefslogtreecommitdiff
path: root/linenoise.c
diff options
context:
space:
mode:
authorSteve Bennett <steveb@workware.net.au>2016-09-04 10:11:48 +1000
committerSteve Bennett <steveb@workware.net.au>2016-09-05 09:40:26 +1000
commit3b0b2e2ad6bdc1ab341107e9488537b3bf9bd106 (patch)
tree5476ed3b80ec43a28ef8d8db6111bf63b4ee37db /linenoise.c
parented4923bc71b7630cc34328b32704e806bb10c614 (diff)
downloadjimtcl-3b0b2e2ad6bdc1ab341107e9488537b3bf9bd106.zip
jimtcl-3b0b2e2ad6bdc1ab341107e9488537b3bf9bd106.tar.gz
jimtcl-3b0b2e2ad6bdc1ab341107e9488537b3bf9bd106.tar.bz2
linenoise: Add support for utf-8 wide chars
Signed-off-by: Steve Bennett <steveb@workware.net.au>
Diffstat (limited to 'linenoise.c')
-rw-r--r--linenoise.c27
1 files changed, 18 insertions, 9 deletions
diff --git a/linenoise.c b/linenoise.c
index 4fcf4e8..ae1f166 100644
--- a/linenoise.c
+++ b/linenoise.c
@@ -853,12 +853,14 @@ static void refreshLine(const char *prompt, struct current *current)
int b;
int ch;
int n;
+ int width;
+ int bufwidth;
/* Should intercept SIGWINCH. For now, just get the size every time */
getWindowSize(current);
plen = strlen(prompt);
- pchars = utf8_strlen(prompt, plen);
+ pchars = utf8_strwidth(prompt, utf8_strlen(prompt, plen));
/* Scan the prompt for embedded ansi color control sequences and
* discount them as characters/columns.
@@ -872,7 +874,7 @@ static void refreshLine(const char *prompt, struct current *current)
/* How many cols are required to the left of 'pos'?
* The prompt, plus one extra for each control char
*/
- n = pchars + utf8_strlen(buf, current->len);
+ n = pchars + utf8_strwidth(buf, utf8_strlen(buf, current->len));
b = 0;
for (i = 0; i < pos; i++) {
b += utf8_tounicode(buf + b, &ch);
@@ -881,20 +883,21 @@ static void refreshLine(const char *prompt, struct current *current)
}
}
- /* If too many are needed, strip chars off the front of 'buf'
- * until it fits. Note that if the current char is a control character,
- * we need one extra col.
- */
+ /* Pluse one if the current char is a control character */
if (current->pos < current->chars && get_char(current, current->pos) < ' ') {
n++;
}
+ /* If too many are needed, strip chars off the front of 'buf'
+ * until it fits. Note that if the current char is a control character,
+ * we need one extra col.
+ */
while (n >= current->cols && pos > 0) {
b = utf8_tounicode(buf, &ch);
if (ch < ' ') {
n--;
}
- n--;
+ n -= utf8_width(ch);
buf += b;
pos--;
chars--;
@@ -911,13 +914,19 @@ static void refreshLine(const char *prompt, struct current *current)
*/
b = 0; /* unwritted bytes */
n = 0; /* How many control chars were written */
+ width = 0; /* current display width */
+ bufwidth = utf8_strwidth(buf, pos);
+
for (i = 0; i < chars; i++) {
int ch;
int w = utf8_tounicode(buf + b, &ch);
if (ch < ' ') {
n++;
}
- if (pchars + i + n >= current->cols) {
+
+ width += utf8_width(ch);
+
+ if (pchars + width + n >= current->cols) {
break;
}
if (ch < ' ') {
@@ -938,7 +947,7 @@ static void refreshLine(const char *prompt, struct current *current)
/* Erase to right, move cursor to original position */
eraseEol(current);
- setCursorPos(current, pos + pchars + backup);
+ setCursorPos(current, bufwidth + pchars + backup);
}
static void set_current(struct current *current, const char *str)