aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/calcurse.h1
-rw-r--r--src/custom.c2
-rw-r--r--src/keys.c18
-rw-r--r--src/utf8.c39
4 files changed, 47 insertions, 13 deletions
diff --git a/src/calcurse.h b/src/calcurse.h
index c362055..0d77e8f 100644
--- a/src/calcurse.h
+++ b/src/calcurse.h
@@ -1119,6 +1119,7 @@ int utf8_decode(const char *);
int utf8_width(char *);
int utf8_strwidth(char *);
int utf8_chop(char *, int);
+char *utf8_encode(int);
/* utils.c */
void exit_calcurse(int) __attribute__ ((__noreturn__));
diff --git a/src/custom.c b/src/custom.c
index 246af1d..9443365 100644
--- a/src/custom.c
+++ b/src/custom.c
@@ -908,7 +908,7 @@ print_keys_bindings(WINDOW * win, int selected_row, int selected_elm,
mvwprintw(win, y, pos,
"%s ", key);
noelm++;
- pos += strlen(key) + 1;
+ pos += utf8_strwidth((char *)key) + 1;
}
} else {
mvwaddstr(win, y, KEYPOS,
diff --git a/src/keys.c b/src/keys.c
index e609cb5..36bd64c 100644
--- a/src/keys.c
+++ b/src/keys.c
@@ -395,9 +395,6 @@ int keys_str2int(const char *key)
else if (strcmp(key, "KEY_END") == 0)
return KEY_END;
- /* UTF-8 multibyte keys. */
- if (starts_with(key, "U+"))
- return strtol(&key[strlen("U+")], NULL, 16) + KEY_MAX;
/* Lookup in the keynames table. */
for (int i = 1; i < 128; i++)
@@ -407,8 +404,8 @@ int keys_str2int(const char *key)
if (strcmp(key, keynames[i]) == 0)
return i;
-
- return -1;
+ /* UTF-8 multibyte keys. */
+ return utf8_decode(key) + KEY_MAX;
}
char *keys_int2str(int key)
@@ -421,7 +418,7 @@ char *keys_int2str(int key)
else
return mem_strdup(keynames[key]);
} else {
- asprintf(&res, "U+%04X", key - KEY_MAX);
+ asprintf(&res, "%s", utf8_encode(key - KEY_MAX));
return res;
}
}
@@ -476,7 +473,7 @@ char *keys_action_allkeys(enum key action)
static char *keys_format_label(char *key, int keylen)
{
static char fmtkey[BUFSIZ];
- const int len = strlen(key);
+ const int len = utf8_strwidth(key);
const char dot = '.';
int i;
@@ -520,7 +517,7 @@ keys_display_bindings_bar(WINDOW * win, int *bindings, int count,
const int label_pos_x = key_pos_x + KEYS_KEYLEN + 1;
const int label_pos_y = key_pos_y;
- char key[KEYS_KEYLEN + 1], *fmtkey;
+ char key[UTF8_MAXLEN + 1], *fmtkey;
int binding_key;
@@ -532,9 +529,8 @@ keys_display_bindings_bar(WINDOW * win, int *bindings, int count,
const char *label;
if (binding_key < NBKEYS) {
- strncpy(key, keys_action_firstkey(binding_key),
- KEYS_KEYLEN);
- key[KEYS_KEYLEN] = '\0';
+ strncpy(key, keys_action_firstkey(binding_key), UTF8_MAXLEN);
+ key[UTF8_MAXLEN] = '\0';
label = gettext(keydef[binding_key].sb_label);
} else {
switch (binding_key) {
diff --git a/src/utf8.c b/src/utf8.c
index 6b04331..b1976af 100644
--- a/src/utf8.c
+++ b/src/utf8.c
@@ -291,7 +291,44 @@ int utf8_decode(const char *s)
}
}
-/* Get the width of a UTF-8 character. */
+/*
+ * Encode a Unicode code point.
+ * Return a pointer to the resulting UTF-8 encoded character.
+ */
+char *utf8_encode(int u)
+{
+ static char c[5]; /* 4 bytes + string termination */
+
+ /* 0x0000 - 0x007F: 0xxxxxxx */
+ if (u < 0x80) {
+ *(c + 1) = '\0';
+ *c = u;
+ /* 0x0080 - 0x07FF: 110xxxxx 10xxxxxx */
+ } else if (u < 0x800) {
+ *(c + 2) = '\0';
+ *(c + 1) = (u & 0x3F) | 0x80;
+ *c = (u >> 6) | 0xC0;
+ /* 0x0800 - 0xFFFF: 1110xxxx 10xxxxxx 10xxxxxx */
+ } else if (u < 0x10000) {
+ *(c + 3) = '\0';
+ *(c + 2) = (u & 0x3F) | 0x80;
+ *(c + 1) = (u >> 6 & 0x3F) | 0x80;
+ *c = (u >> 12) | 0xE0;
+ } else if (u < 0x110000) {
+ /* 0x10000 - 0x10FFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
+ *(c + 4) = '\0';
+ *(c + 3) = (u & 0x3F) | 0x80;
+ *(c + 2) = (u >> 6 & 0x3F) | 0x80;
+ *(c + 1) = (u >> 12 & 0x3F) | 0x80;
+ *c = (u >> 18) | 0xF0;
+ } else {
+ return NULL;
+ }
+
+ return c;
+}
+
+/* Get the display width of a UTF-8 character. */
int utf8_width(char *s)
{
int val, low, high, cur;