commit 568577344a2ef6600cb15af56f77d4da3a9c3cb8
parent a94117c1f53bd34c5263b97bb81168517a162c20
Author: hhvn <dev@hhvn.uk>
Date: Sat, 6 Nov 2021 22:47:20 +0000
ui.c hirc.h: utf-8 input
Diffstat:
M | hirc.h | | | 2 | ++ |
M | ui.c | | | 82 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------- |
2 files changed, 73 insertions(+), 11 deletions(-)
diff --git a/hirc.h b/hirc.h
@@ -92,6 +92,8 @@ void handle_NICK(char *msg, char **params, struct Server *server, time_t timest
/* ui.c */
void ui_init(void);
void ui_read(void);
+int ui_input_insert(char c, int counter);
+int ui_input_delete(int num, int counter);
void ui_redraw(void);
void ui_draw_input(void);
void ui_draw_nicklist(void);
diff --git a/ui.c b/ui.c
@@ -157,10 +157,8 @@ ui_read(void) {
return;
case KEY_BACKSPACE:
if (input.counter) {
- memmove(&input.string[input.counter - 1],
- &input.string[input.counter],
- strlen(&input.string[input.counter]) + 1);
- input.counter--;
+ if (ui_input_delete(1, input.counter) > 0)
+ input.counter--;
}
break;
case KEY_LEFT:
@@ -177,11 +175,9 @@ ui_read(void) {
input.counter = 0;
break;
default:
- if (isprint(key) || iscntrl(key)) {
- memmove(&input.string[input.counter + 1],
- &input.string[input.counter],
- strlen(&input.string[input.counter]));
- input.string[input.counter++] = key;
+ if ((key & 0xFF80) == 0x80 || isprint(key) || iscntrl(key)) {
+ if (ui_input_insert(key, input.counter) > 0)
+ input.counter++;
}
break;
}
@@ -189,6 +185,58 @@ ui_read(void) {
needredraw = 1;
}
+int
+ui_input_insert(char c, int counter) {
+ char *p;
+ int i, bc;
+
+ for (bc=i=0, p = input.string; i != counter && bc < sizeof(input.string) && *p; p++, bc++) {
+ if ((*p & 0xC0) != 0x80)
+ i++;
+ }
+ while ((*p & 0xC0) == 0x80)
+ p++;
+
+ if (i != counter)
+ return -1;
+
+ if ((strlen(input.string)) > sizeof(input.string))
+ return -1;
+
+ memmove(p + 1, p, strlen(p) + 1);
+ memcpy(p, &c, 1);
+ return ((c & 0xC0) != 0x80);
+}
+
+
+int
+ui_input_delete(int num, int counter) {
+ char *dest, *p;
+ int i, bc;
+
+ if (num < 0)
+ return -1;
+
+ for (bc=i=0, dest = input.string; i != counter - 1 && bc < sizeof(input.string) && *dest; dest++, bc++) {
+ if ((*dest & 0xC0) != 0x80)
+ i++;
+ }
+
+ while ((*dest & 0xC0) == 0x80)
+ dest++;
+
+ p = dest;
+ do {
+ p++;
+ } while ((*p & 0xC0) == 0x80);
+
+ /* if (i != counter + num) */
+ /* return -1; */
+
+ memmove(dest, p, strlen(p) + 1);
+ return num;
+}
+
void
ui_redraw(void) {
int x = 0, rx = 0;
@@ -247,7 +295,9 @@ ui_redraw(void) {
void
ui_draw_input(void) {
+ char utfbuf[5];
char *p;
+ int utfc;
int offset;
int x;
@@ -257,12 +307,22 @@ ui_draw_input(void) {
* This gives "pages" that are each as long as the width of the input window */
offset = ((int) input.counter / windows[Win_input].w) * windows[Win_input].w;
for (x=0, p = input.string + offset; p && *p && x < windows[Win_input].w; p++, x++) {
- if (iscntrl(*p)) {
+ if ((*p & 0xC0) == 0xC0) {
+ /* see ui_wprintc */
+ memset(utfbuf, '\0', sizeof(utfbuf));
+ utfbuf[0] = *p;
+ for (utfc = 1, p++; (*p & 0xC0) != 0xC0 && (*p & 0x80) == 0x80 && utfc < sizeof(utfbuf); utfc++, p++)
+ utfbuf[utfc] = *p;
+ waddstr(windows[Win_input].window, utfbuf);
+ p--;
+ } else if (iscntrl(*p)) {
/* adding 64 will turn ^C into C */
wattron(windows[Win_input].window, A_REVERSE);
waddch(windows[Win_input].window, *p + 64);
wattroff(windows[Win_input].window, A_REVERSE);
- } else waddch(windows[Win_input].window, *p);
+ } else if (!(*p & 0x80)) {
+ waddch(windows[Win_input].window, *p);
+ }
}
wmove(windows[Win_input].window, 0, input.counter - offset);
}