summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--code/fe310/eos/eve/Makefile2
-rw-r--r--code/fe310/eos/eve/eve.h1
-rw-r--r--code/fe310/eos/eve/screen/font.c38
-rw-r--r--code/fe310/eos/eve/screen/font.h5
-rw-r--r--code/fe310/eos/eve/screen/form.c1
-rw-r--r--code/fe310/eos/eve/screen/page.c1
-rw-r--r--code/fe310/eos/eve/unicode.c103
-rw-r--r--code/fe310/eos/eve/unicode.h10
-rw-r--r--code/fe310/eos/eve/widget/clipb.c6
-rw-r--r--code/fe310/eos/eve/widget/clipb.h4
-rw-r--r--code/fe310/eos/eve/widget/label.c1
-rw-r--r--code/fe310/eos/eve/widget/pagew.c1
-rw-r--r--code/fe310/eos/eve/widget/strw.c181
-rw-r--r--code/fe310/eos/eve/widget/strw.h4
-rw-r--r--code/fe310/eos/eve/widget/textw.c197
-rw-r--r--code/fe310/eos/eve/widget/textw.h6
-rw-r--r--code/fe310/eos/eve/widget/widget.c1
17 files changed, 344 insertions, 218 deletions
diff --git a/code/fe310/eos/eve/Makefile b/code/fe310/eos/eve/Makefile
index 0a737cc..3355dd5 100644
--- a/code/fe310/eos/eve/Makefile
+++ b/code/fe310/eos/eve/Makefile
@@ -2,7 +2,7 @@ include ../../common.mk
CFLAGS += -I.. -I../../include
-obj = eve.o eve_touch.o eve_track.o eve_kbd.o eve_text.o eve_platform.o
+obj = eve.o eve_touch.o eve_track.o eve_kbd.o eve_text.o eve_platform.o unicode.o
%.o: %.c %.h
diff --git a/code/fe310/eos/eve/eve.h b/code/fe310/eos/eve/eve.h
index 0fd5ede..eb59959 100644
--- a/code/fe310/eos/eve/eve.h
+++ b/code/fe310/eos/eve/eve.h
@@ -7,7 +7,6 @@
#define EVE_OK 0
#define EVE_ERR -1
-#define EVE_ERR_TEXT -100
#define EVE_PSTATE_ACTIVE 0
#define EVE_PSTATE_STANDBY 1
diff --git a/code/fe310/eos/eve/screen/font.c b/code/fe310/eos/eve/screen/font.c
index 6fc7d39..da02983 100644
--- a/code/fe310/eos/eve/screen/font.c
+++ b/code/fe310/eos/eve/screen/font.c
@@ -1,6 +1,8 @@
#include <stdlib.h>
#include "eve.h"
+#include "unicode.h"
+
#include "font.h"
void eve_font_init(EVEFont *font, uint8_t font_id) {
@@ -14,23 +16,41 @@ void eve_font_init(EVEFont *font, uint8_t font_id) {
eve_readb(p, font->w_ch, 128);
}
-uint16_t eve_font_str_w(EVEFont *font, char *s) {
+uint8_t eve_font_ch_w(EVEFont *font, utf32_t ch) {
+ if (ch < 128) return font->w_ch[ch];
+ return 0;
+}
+
+uint16_t eve_font_str_w(EVEFont *font, utf8_t *str) {
uint16_t r = 0;
+ utf32_t ch;
+ uint8_t ch_w;
+ uint8_t ch_l;
- while (*s) {
- r += font->w_ch[*s];
- s++;
+ if (str == NULL) return 0;
+
+ while (*str) {
+ ch_l = utf8_dec(str, &ch);
+ ch_w = eve_font_ch_w(font, ch);
+ r += ch_w;
+ str += ch_l;
}
return r;
}
-uint16_t eve_font_buf_w(EVEFont *font, char *buf, uint16_t buf_len) {
- int i;
+uint16_t eve_font_buf_w(EVEFont *font, utf8_t *buf, uint16_t buf_len) {
+ int i = 0;
uint16_t r = 0;
-
- for (i=0; i<buf_len; i++) {
- r += font->w_ch[*(buf + i)];
+ utf32_t ch;
+ uint8_t ch_w;
+ uint8_t ch_l;
+
+ while (i < buf_len) {
+ ch_l = utf8_dec(buf + i, &ch);
+ ch_w = eve_font_ch_w(font, ch);
+ r += ch_w;
+ i += ch_l;
}
return r;
diff --git a/code/fe310/eos/eve/screen/font.h b/code/fe310/eos/eve/screen/font.h
index 525e669..aff038c 100644
--- a/code/fe310/eos/eve/screen/font.h
+++ b/code/fe310/eos/eve/screen/font.h
@@ -8,6 +8,7 @@ typedef struct EVEFont {
} EVEFont;
void eve_font_init(EVEFont *font, uint8_t font_id);
-uint16_t eve_font_str_w(EVEFont *font, char *s);
-uint16_t eve_font_buf_w(EVEFont *font, char *buf, uint16_t buf_len);
+uint8_t eve_font_ch_w(EVEFont *font, utf32_t ch);
+uint16_t eve_font_str_w(EVEFont *font, utf8_t *str);
+uint16_t eve_font_buf_w(EVEFont *font, utf8_t *buf, uint16_t buf_len);
uint8_t eve_font_h(EVEFont *font);
diff --git a/code/fe310/eos/eve/screen/form.c b/code/fe310/eos/eve/screen/form.c
index 096cfa3..f7d37ee 100644
--- a/code/fe310/eos/eve/screen/form.c
+++ b/code/fe310/eos/eve/screen/form.c
@@ -3,6 +3,7 @@
#include "eve.h"
#include "eve_kbd.h"
+#include "unicode.h"
#include "screen.h"
#include "window.h"
diff --git a/code/fe310/eos/eve/screen/page.c b/code/fe310/eos/eve/screen/page.c
index 7631c95..f54056c 100644
--- a/code/fe310/eos/eve/screen/page.c
+++ b/code/fe310/eos/eve/screen/page.c
@@ -3,6 +3,7 @@
#include "eve.h"
#include "eve_kbd.h"
+#include "unicode.h"
#include "screen.h"
#include "window.h"
diff --git a/code/fe310/eos/eve/unicode.c b/code/fe310/eos/eve/unicode.c
new file mode 100644
index 0000000..62b1714
--- /dev/null
+++ b/code/fe310/eos/eve/unicode.c
@@ -0,0 +1,103 @@
+#include "unicode.h"
+
+uint8_t utf8_enc(utf32_t ch, utf8_t *str) {
+ if (ch <= 0x7f) {
+ str[0] = ch;
+ return 1;
+ } else if (ch <= 0x7ff) {
+ str[0] = 0xc0 | (ch >> 6);
+ str[1] = 0x80 | (ch & 0x3f);
+ return 2;
+ } else if (ch <= 0xffff) {
+ if ((ch >= 0xd800) && (ch <= 0xdfff)) return 0;
+ str[0] = 0xe0 | (ch >> 12);
+ str[1] = 0x80 | ((ch >> 6) & 0x3f);
+ str[2] = 0x80 | (ch & 0x3f);
+ return 3;
+ } else if (ch <= 0x10ffff) {
+ str[0] = 0xf0 | (ch >> 18);
+ str[1] = 0x80 | ((ch >> 12) & 0x3f);
+ str[2] = 0x80 | ((ch >> 6) & 0x3f);
+ str[3] = 0x80 | (ch & 0x3f);
+ return 4;
+ } else {
+ return 0;
+ }
+}
+
+uint8_t utf8_dec(utf8_t *str, utf32_t *ch) {
+ if ((str[0] & 0x80) == 0x00) {
+ *ch = str[0];
+ return 1;
+ } else if ((str[0] & 0xe0) == 0xc0) {
+ if ((str[1] & 0xc0) != 0x80) return 0;
+ *ch = (utf32_t)(str[0] & 0x1f) << 6;
+ *ch |= (utf32_t)(str[1] & 0x3f);
+ if (*ch < 0x80) return 0;
+ return 2;
+ } else if ((str[0] & 0xf0) == 0xe0) {
+ if (((str[1] & 0xc0) != 0x80) || ((str[2] & 0xc0) != 0x80)) return 0;
+ *ch = (utf32_t)(str[0] & 0x0f) << 12;
+ *ch |= (utf32_t)(str[1] & 0x3f) << 6;
+ *ch |= (utf32_t)(str[2] & 0x3f);
+ if ((*ch >= 0xd800) && (*ch <= 0xdfff)) return 0;
+ if (*ch < 0x800) return 0;
+ return 3;
+ } else if ((str[0] & 0xf8) == 0xf0) {
+ if (((str[1] & 0xc0) != 0x80) || ((str[2] & 0xc0) != 0x80) || ((str[3] & 0xc0) != 0x80)) return 0;
+ *ch = (utf32_t)(str[0] & 0x07) << 18;
+ *ch |= (utf32_t)(str[1] & 0x0f) << 12;
+ *ch |= (utf32_t)(str[2] & 0x3f) << 6;
+ *ch |= (utf32_t)(str[3] & 0x3f);
+ if (*ch < 0x010000) return 0;
+ if (*ch > 0x10ffff) return 0;
+ return 4;
+ } else {
+ return 0;
+ }
+}
+
+int utf8_seek(utf8_t *str, int off, utf32_t *ch) {
+ int i;
+ int len = 0;
+
+ if (off < 0) {
+ off = -off;
+ for (i=0; i<off; i++) {
+ len--;
+ while ((*(str + len) & 0xc0) == 0x80) len--;
+ }
+ utf8_dec(str + len, ch);
+ } else {
+ for (i=0; i<off; i++) {
+ len += utf8_dec(str + len, ch);
+ }
+ }
+ return len;
+}
+
+int utf8_verify(utf8_t *str, int sz) {
+ utf32_t ch;
+ uint8_t ch_l;
+ int len = 0;
+
+ while (len < sz) {
+ if (sz - len < 4) {
+ if (((str[len] & 0xf8) == 0xf0) ||
+ (((str[len] & 0xf0) == 0xe0) && (sz - len < 3)) ||
+ (((str[len] & 0xe0) == 0xc0) && (sz - len < 2))) {
+ str[len] = '\0';
+ break;
+ }
+ }
+ ch_l = utf8_dec(str + len, &ch);
+ if (ch_l) {
+ if (ch == 0) break;
+ len += ch_l;
+ } else {
+ str[len] = '\0';
+ break;
+ }
+ }
+ return len;
+}
diff --git a/code/fe310/eos/eve/unicode.h b/code/fe310/eos/eve/unicode.h
new file mode 100644
index 0000000..6452822
--- /dev/null
+++ b/code/fe310/eos/eve/unicode.h
@@ -0,0 +1,10 @@
+#include <stdint.h>
+
+typedef uint8_t utf8_t;
+typedef uint16_t utf16_t;
+typedef uint32_t utf32_t;
+
+uint8_t utf8_enc(utf32_t ch, utf8_t *str);
+uint8_t utf8_dec(utf8_t *str, utf32_t *ch);
+int utf8_seek(utf8_t *str, int off, utf32_t *ch);
+int utf8_verify(utf8_t *str, int sz); \ No newline at end of file
diff --git a/code/fe310/eos/eve/widget/clipb.c b/code/fe310/eos/eve/widget/clipb.c
index f480d83..04c9a46 100644
--- a/code/fe310/eos/eve/widget/clipb.c
+++ b/code/fe310/eos/eve/widget/clipb.c
@@ -3,9 +3,9 @@
#include "eve.h"
#include "clipb.h"
-static char _clipb[EVE_CLIPB_SIZE_BUF];
+static uint8_t _clipb[EVE_CLIPB_SIZE_BUF];
-int eve_clipb_push(char *str, uint16_t len) {
+int eve_clipb_push(uint8_t *str, uint16_t len) {
if (len >= EVE_CLIPB_SIZE_BUF) return EVE_ERR;
memcpy(_clipb, str, len);
@@ -14,6 +14,6 @@ int eve_clipb_push(char *str, uint16_t len) {
return EVE_OK;
}
-char *eve_clipb_get(void) {
+uint8_t *eve_clipb_get(void) {
return _clipb;
} \ No newline at end of file
diff --git a/code/fe310/eos/eve/widget/clipb.h b/code/fe310/eos/eve/widget/clipb.h
index 8b3e980..2d6fae6 100644
--- a/code/fe310/eos/eve/widget/clipb.h
+++ b/code/fe310/eos/eve/widget/clipb.h
@@ -2,5 +2,5 @@
#define EVE_CLIPB_SIZE_BUF 256
-int eve_clipb_push(char *str, uint16_t len);
-char *eve_clipb_get(void); \ No newline at end of file
+int eve_clipb_push(uint8_t *str, uint16_t len);
+uint8_t *eve_clipb_get(void); \ No newline at end of file
diff --git a/code/fe310/eos/eve/widget/label.c b/code/fe310/eos/eve/widget/label.c
index 44b63b0..ebea823 100644
--- a/code/fe310/eos/eve/widget/label.c
+++ b/code/fe310/eos/eve/widget/label.c
@@ -3,6 +3,7 @@
#include "eve.h"
#include "eve_kbd.h"
+#include "unicode.h"
#include "screen/screen.h"
#include "screen/window.h"
diff --git a/code/fe310/eos/eve/widget/pagew.c b/code/fe310/eos/eve/widget/pagew.c
index 8c3b515..c64c477 100644
--- a/code/fe310/eos/eve/widget/pagew.c
+++ b/code/fe310/eos/eve/widget/pagew.c
@@ -3,6 +3,7 @@
#include "eve.h"
#include "eve_kbd.h"
+#include "unicode.h"
#include "screen/screen.h"
#include "screen/window.h"
diff --git a/code/fe310/eos/eve/widget/strw.c b/code/fe310/eos/eve/widget/strw.c
index 519f171..da57bab 100644
--- a/code/fe310/eos/eve/widget/strw.c
+++ b/code/fe310/eos/eve/widget/strw.c
@@ -1,9 +1,9 @@
#include <stdlib.h>
#include <string.h>
-#include <math.h>
#include "eve.h"
#include "eve_kbd.h"
+#include "unicode.h"
#include "screen/screen.h"
#include "screen/window.h"
@@ -29,7 +29,7 @@
#define CHAR_VALID_INPUT(c) ((c >= 0x20) && (c < 0x7f))
-void eve_strw_init(EVEStrWidget *widget, EVERect *g, EVEFont *font, char *str, uint16_t str_size) {
+void eve_strw_init(EVEStrWidget *widget, EVERect *g, EVEFont *font, utf8_t *str, uint16_t str_size) {
EVEWidget *_widget = &widget->w;
memset(widget, 0, sizeof(EVEStrWidget));
@@ -37,7 +37,7 @@ void eve_strw_init(EVEStrWidget *widget, EVERect *g, EVEFont *font, char *str, u
widget->font = font;
widget->str = str;
widget->str_size = str_size;
- widget->str_len = strlen(str);
+ widget->str_len = utf8_verify(str, str_size);
widget->str_g.w = eve_font_str_w(font, str);
if (_widget->g.h == 0) _widget->g.h = eve_font_h(font);
}
@@ -243,13 +243,13 @@ uint8_t eve_strw_draw(EVEWidget *_widget, EVEPage *page, uint8_t tag0) {
l1 = c1->ch;
l2 = c2->ch - c1->ch;
- l3 = strlen(widget->str) - c2->ch;
+ l3 = widget->str_len - c2->ch;
_draw_str(widget, page->v.window, 0, l1, 0, c1->x, 0);
_draw_str(widget, page->v.window, c1->ch, l2, c1->x, c2->x, 1);
_draw_str(widget, page->v.window, c2->ch, l3, c2->x, widget->str_g.x + _widget->g.w, 0);
} else {
if (widget->cursor1.on) _draw_cursor(widget, &widget->cursor1);
- _draw_str(widget, page->v.window, 0, strlen(widget->str), 0, widget->str_g.x + _widget->g.w, 0);
+ _draw_str(widget, page->v.window, 0, widget->str_len, 0, widget->str_g.x + _widget->g.w, 0);
}
if (cut) {
@@ -264,10 +264,13 @@ void eve_strw_putc(void *_page, int c) {
EVEStrWidget *widget = (EVEStrWidget *)eve_page_get_focus(page);
EVEStrCursor *cursor1 = &widget->cursor1;
EVEStrCursor *cursor2 = &widget->cursor2;
- char *str;
- char *clipb = NULL;
+ utf8_t *str;
+ utf8_t *clipb = NULL;
int w0 = widget->font->w;
int w1 = widget->w.g.w - widget->font->w;
+ int ins_c = 0, del_c = 0;
+ int ins_w = 0, del_w = 0;
+
if (c == CH_EOF) {
if (cursor1->on) eve_strw_cursor_clear(widget, cursor1);
@@ -277,107 +280,85 @@ void eve_strw_putc(void *_page, int c) {
if (!cursor1->on) return;
- if (cursor2->on) {
- EVEStrCursor *c1;
- EVEStrCursor *c2;
- int ins_c = 0, del_c = 0;
- int ins_ch_w = 0, del_ch_w = 0;
+ if (!cursor2->on && ((c == CH_BS) || (c == CH_DEL))) {
+ utf32_t uc;
- if (cursor1->ch <= cursor2->ch) {
- c1 = cursor1;
- c2 = cursor2;
- } else {
- c1 = cursor2;
- c2 = cursor1;
+ str = widget->str + cursor1->ch;
+ switch (c) {
+ case CH_BS:
+ if (cursor1->ch > 0) {
+ del_c = utf8_seek(str, -1, &uc);
+ del_w = eve_font_ch_w(widget->font, uc);
+ memmove(str - del_c, str, widget->str_len - cursor1->ch + 1);
+ widget->str_len -= del_c;
+ widget->str_g.w -= del_w;
+ cursor1->ch -= del_c;
+ cursor1->x -= del_w;
+ }
+ break;
+
+ case CH_DEL:
+ if (cursor1->ch < widget->str_len) {
+ del_c = utf8_dec(str, &uc);
+ del_w = eve_font_ch_w(widget->font, uc);
+ memmove(str, str + del_c, widget->str_len - cursor1->ch - del_c + 1);
+ widget->str_len -= del_c;
+ widget->str_g.w -= del_w;
+ }
+ break;
+ }
+ if (widget->str_g.w - widget->str_g.x < w1) {
+ widget->str_g.x -= del_w;
+ if (widget->str_g.x < 0) widget->str_g.x = 0;
}
+ } else {
+ EVEStrCursor *c1 = cursor1;
+ EVEStrCursor *c2 = cursor1;
+ utf8_t utf8_buf[4];
- str = widget->str + c1->ch;
- del_c = c2->ch - c1->ch;
- del_ch_w = eve_font_buf_w(widget->font, str, del_c);
- if ((c == CH_CTRLX) || (c == CH_CTRLC)) {
- eve_clipb_push(str, del_c);
- if (c == CH_CTRLC) return;
+ if (cursor2->on) {
+ if (cursor1->ch <= cursor2->ch) {
+ c2 = cursor2;
+ } else {
+ c1 = cursor2;
+ }
+ del_c = c2->ch - c1->ch;
+ del_w = eve_font_buf_w(widget->font, str, del_c);
+ if ((c == CH_CTRLX) || (c == CH_CTRLC)) {
+ eve_clipb_push(str, del_c);
+ if (c == CH_CTRLC) return;
+ }
}
- if (CHAR_VALID_INPUT(c) && (widget->str_len < widget->str_size + del_c - 1)) {
- ins_c = 1;
- ins_ch_w = widget->font->w_ch[c];
+
+ str = widget->str + c1->ch;
+ if (CHAR_VALID_INPUT(c)) {
+ ins_c = utf8_enc(c, utf8_buf);
+ ins_w = eve_font_ch_w(widget->font, c);
} else if (c == CH_CTRLV) {
clipb = eve_clipb_get();
- ins_c = clipb ? strlen(clipb) : 0;
- if (widget->str_len >= widget->str_size - (ins_c - del_c)) ins_c = widget->str_size - widget->str_len + del_c - 1;
- ins_ch_w = eve_font_buf_w(widget->font, clipb, ins_c);
+ ins_c = clipb ? utf8_verify(clipb, EVE_CLIPB_SIZE_BUF) : 0;
+ ins_w = eve_font_str_w(widget->font, clipb);
+ }
+ if (widget->str_len + ins_c >= widget->str_size + del_c) {
+ ins_c = 0;
+ ins_w = 0;
}
if (ins_c != del_c) memmove(str + ins_c, str + del_c, widget->str_len - c2->ch + 1);
if (ins_c) {
if (c == CH_CTRLV) {
memcpy(str, clipb, ins_c);
+ } else if (ins_c > 1) {
+ memcpy(str, utf8_buf, ins_c);
} else {
- *str = c;
+ *str = utf8_buf[0];
}
c1->ch += ins_c;
- c1->x += ins_ch_w;
+ c1->x += ins_w;
}
widget->str_len += ins_c - del_c;
- widget->str_g.w += ins_ch_w - del_ch_w;
+ widget->str_g.w += ins_w - del_w;
if (c1 == cursor2) widget->cursor1 = widget->cursor2;
- eve_strw_cursor_clear(widget, cursor2);
- } else {
- int ch_w = 0;
- int c_len;
-
- str = widget->str + cursor1->ch;
- switch (c) {
- case CH_BS:
- if (cursor1->ch > 0) {
- ch_w = widget->font->w_ch[*(str - 1)];
- memmove(str - 1, str, widget->str_len - cursor1->ch + 1);
- widget->str_len--;
- widget->str_g.w -= ch_w;
- cursor1->ch--;
- cursor1->x -= ch_w;
- }
- break;
-
- case CH_DEL:
- if (cursor1->ch < widget->str_len) {
- ch_w = widget->font->w_ch[*str];
- memmove(str, str + 1, widget->str_len - cursor1->ch);
- widget->str_len--;
- widget->str_g.w -= ch_w;
- }
- break;
-
- case CH_CTRLV:
- clipb = eve_clipb_get();
- c_len = clipb ? strlen(clipb) : 0;
- if (widget->str_len >= widget->str_size - c_len) c_len = widget->str_size - widget->str_len - 1;
- ch_w = eve_font_buf_w(widget->font, clipb, c_len);
- if (c_len) {
- memmove(str + c_len, str, widget->str_len - cursor1->ch + 1);
- memcpy(str, clipb, c_len);
- widget->str_len += c_len;
- widget->str_g.w += ch_w;
- cursor1->ch += c_len;
- cursor1->x += ch_w;
- }
- break;
-
- default:
- if (CHAR_VALID_INPUT(c) && (widget->str_len < widget->str_size - 1)) {
- ch_w = widget->font->w_ch[c];
- memmove(str + 1, str, widget->str_len - cursor1->ch + 1);
- *str = c;
- widget->str_len++;
- widget->str_g.w += ch_w;
- cursor1->ch++;
- cursor1->x += ch_w;
- }
- break;
- }
- if (((c == CH_BS) || (c == CH_DEL)) && (widget->str_g.w - widget->str_g.x < w1)) {
- widget->str_g.x -= ch_w;
- if (widget->str_g.x < 0) widget->str_g.x = 0;
- }
+ if (cursor2->on) eve_strw_cursor_clear(widget, cursor2);
}
if (cursor1->x - widget->str_g.x < w0) widget->str_g.x = cursor1->x > w0 ? cursor1->x - w0 : 0;
@@ -387,19 +368,25 @@ void eve_strw_putc(void *_page, int c) {
void eve_strw_cursor_set(EVEStrWidget *widget, EVEStrCursor *cursor, int16_t x) {
int i;
int16_t _x, _d;
+ utf32_t ch;
+ uint8_t ch_w;
+ uint8_t ch_l;
EVEWidget *_widget = &widget->w;
x = x - _widget->g.x + widget->str_g.x;
_x = 0;
_d = x;
- for (i=0; i<widget->str_len; i++) {
- _x += widget->font->w_ch[widget->str[i]];
+ i = 0;
+ while (i < widget->str_len) {
+ ch_l = utf8_dec(widget->str + i, &ch);
+ ch_w = eve_font_ch_w(widget->font, ch);
+ _x += ch_w;
+ i += ch_l;
if (_x >= x) {
- if (_x - x < _d) {
- i++;
- } else {
- _x -= widget->font->w_ch[widget->str[i]];
+ if (_x - x > _d) {
+ _x -= ch_w;
+ i -= ch_l;
}
break;
} else {
diff --git a/code/fe310/eos/eve/widget/strw.h b/code/fe310/eos/eve/widget/strw.h
index 1277c20..72fc6aa 100644
--- a/code/fe310/eos/eve/widget/strw.h
+++ b/code/fe310/eos/eve/widget/strw.h
@@ -9,7 +9,7 @@ typedef struct EVEStrCursor {
typedef struct EVEStrWidget {
EVEWidget w;
EVEFont *font;
- char *str;
+ utf8_t *str;
uint16_t str_size;
uint16_t str_len;
struct {
@@ -27,7 +27,7 @@ typedef struct EVEStrWidget {
} track;
} EVEStrWidget;
-void eve_strw_init(EVEStrWidget *widget, EVERect *g, EVEFont *font, char *str, uint16_t str_size);
+void eve_strw_init(EVEStrWidget *widget, EVERect *g, EVEFont *font, utf8_t *str, uint16_t str_size);
int eve_strw_touch(EVEWidget *_widget, EVEPage *page, uint8_t tag0, int touch_idx);
uint8_t eve_strw_draw(EVEWidget *_widget, EVEPage *page, uint8_t tag0);
void eve_strw_putc(void *_page, int c);
diff --git a/code/fe310/eos/eve/widget/textw.c b/code/fe310/eos/eve/widget/textw.c
index e72bb8c..f14e4f6 100644
--- a/code/fe310/eos/eve/widget/textw.c
+++ b/code/fe310/eos/eve/widget/textw.c
@@ -1,9 +1,9 @@
#include <stdlib.h>
#include <string.h>
-#include <math.h>
#include "eve.h"
#include "eve_kbd.h"
+#include "unicode.h"
#include "screen/screen.h"
#include "screen/window.h"
@@ -33,7 +33,9 @@
#define CHAR_VALID_INPUT(c) (((c >= 0x20) && (c < 0x7f)) || (c == '\n'))
-void eve_textw_init(EVETextWidget *widget, EVERect *g, EVEFont *font, char *text, uint16_t text_size, uint16_t *line, uint16_t line_size) {
+#define DIVC(x,y) ((x) / (y) + ((x) % (y) != 0))
+
+void eve_textw_init(EVETextWidget *widget, EVERect *g, EVEFont *font, utf8_t *text, uint16_t text_size, uint16_t *line, uint16_t line_size) {
EVEWidget *_widget = &widget->w;
memset(widget, 0, sizeof(EVETextWidget));
@@ -41,9 +43,11 @@ void eve_textw_init(EVETextWidget *widget, EVERect *g, EVEFont *font, char *text
widget->font = font;
widget->text = text;
widget->text_size = text_size;
+ widget->text_len = utf8_verify(text, text_size);
widget->line = line;
widget->line_size = line_size;
- if (text_size && line_size) eve_textw_update(widget, NULL, 0);
+ memset(widget->line, 0xff, line_size * sizeof(uint16_t));
+ eve_textw_update(widget, NULL, 0);
}
static void set_focus(EVETextWidget *widget, EVETextCursor *cursor, EVEPage *page) {
@@ -186,7 +190,7 @@ uint8_t eve_textw_draw(EVEWidget *_widget, EVEPage *page, uint8_t tag0) {
char lineNvisible;
_line0 = line0 = ((int)page->win_y - _widget->g.y) / widget->font->h;
- _lineN = lineN = ceil((double)((int)page->win_y - _widget->g.y + page->v.window->g.h) / widget->font->h);
+ _lineN = lineN = DIVC(((int)page->win_y - _widget->g.y + page->v.window->g.h), widget->font->h);
if (line0 < 0) line0 = 0;
if (lineN < 0) lineN = 0;
if (line0 > widget->line_len) line0 = widget->line_len;
@@ -278,8 +282,8 @@ void eve_textw_putc(void *_page, int c) {
EVETextWidget *widget = (EVETextWidget *)eve_page_get_focus(page);
EVETextCursor *cursor1 = &widget->cursor1;
EVETextCursor *cursor2 = &widget->cursor2;
- char *text;
- char *clipb = NULL;
+ utf8_t *text;
+ utf8_t *clipb = NULL;
int i, r;
int ins_c = 0, del_c = 0;
int ch_w = 0;
@@ -292,86 +296,72 @@ void eve_textw_putc(void *_page, int c) {
if (!cursor1->on) return;
- if (cursor2->on) {
- EVETextCursor *c1;
- EVETextCursor *c2;
+ if (!cursor2->on && ((c == CH_BS) || (c == CH_DEL))) {
+ utf32_t uc;
- if (cursor1->ch <= cursor2->ch) {
- c1 = cursor1;
- c2 = cursor2;
- } else {
- c1 = cursor2;
- c2 = cursor1;
+ text = widget->text + cursor1->ch;
+ switch (c) {
+ case CH_BS:
+ if (cursor1->ch > 0) {
+ del_c = utf8_seek(text, -1, &uc);
+ ch_w = eve_font_ch_w(widget->font, uc);
+ memmove(text - del_c, text, widget->text_len - cursor1->ch + 1);
+ cursor1->ch -= del_c;
+ }
+ break;
+
+ case CH_DEL:
+ if (cursor1->ch < widget->text_len) {
+ del_c = utf8_dec(text, &uc);
+ ch_w = eve_font_ch_w(widget->font, uc);
+ memmove(text, text + del_c, widget->text_len - cursor1->ch - del_c + 1);
+ }
+ break;
+ }
+ } else {
+ EVETextCursor *c1 = cursor1;
+ EVETextCursor *c2 = cursor1;
+ utf8_t utf8_buf[4];
+
+ if (cursor2->on) {
+ if (cursor1->ch <= cursor2->ch) {
+ c2 = cursor2;
+ } else {
+ c1 = cursor2;
+ }
+ del_c = c2->ch - c1->ch;
+ if ((c == CH_CTRLX) || (c == CH_CTRLC)) {
+ eve_clipb_push(text, del_c);
+ if (c == CH_CTRLC) return;
+ }
}
text = widget->text + c1->ch;
- del_c = c2->ch - c1->ch;
- if ((c == CH_CTRLX) || (c == CH_CTRLC)) {
- eve_clipb_push(text, del_c);
- if (c == CH_CTRLC) return;
- }
- if (CHAR_VALID_INPUT(c) && (widget->text_len < widget->text_size + del_c - 1)) {
- ins_c = 1;
- ch_w = widget->font->w_ch[c];
+ if (CHAR_VALID_INPUT(c)) {
+ ins_c = utf8_enc(c, utf8_buf);
+ ch_w = eve_font_ch_w(widget->font, c);
} else if (c == CH_CTRLV) {
clipb = eve_clipb_get();
- ins_c = clipb ? strlen(clipb) : 0;
- if (widget->text_len >= widget->text_size - (ins_c - del_c)) ins_c = widget->text_size - widget->text_len + del_c - 1;
- ch_w = eve_font_buf_w(widget->font, clipb, ins_c);
+ ins_c = clipb ? utf8_verify(clipb, EVE_CLIPB_SIZE_BUF) : 0;
+ ch_w = eve_font_str_w(widget->font, clipb);
+ }
+ if (widget->text_len + ins_c >= widget->text_size + del_c) {
+ ins_c = 0;
+ ch_w = 0;
}
if (ins_c != del_c) memmove(text + ins_c, text + del_c, widget->text_len - c2->ch + 1);
if (ins_c) {
if (c == CH_CTRLV) {
memcpy(text, clipb, ins_c);
+ } else if (ins_c > 1) {
+ memcpy(text, utf8_buf, ins_c);
} else {
- *text = c;
+ *text = utf8_buf[0];
}
c1->ch += ins_c;
}
if (c1 == cursor2) widget->cursor1 = widget->cursor2;
- eve_textw_cursor_clear(widget, cursor2);
- } else {
- text = widget->text + cursor1->ch;
-
- switch (c) {
- case CH_BS:
- if (cursor1->ch > 0) {
- ch_w = -widget->font->w_ch[*(text - 1)];
- memmove(text - 1, text, widget->text_len - cursor1->ch + 1);
- cursor1->ch--;
- del_c = 1;
- }
- break;
-
- case CH_DEL:
- if (cursor1->ch < widget->text_len) {
- memmove(text, text + 1, widget->text_len - cursor1->ch);
- del_c = 1;
- }
- break;
-
- case CH_CTRLV:
- clipb = eve_clipb_get();
- ins_c = clipb ? strlen(clipb) : 0;
- if (widget->text_len >= widget->text_size - ins_c) ins_c = widget->text_size - widget->text_len - 1;
- ch_w = eve_font_buf_w(widget->font, clipb, ins_c);
- if (ins_c) {
- memmove(text + ins_c, text, widget->text_len - cursor1->ch + 1);
- memcpy(text, clipb, ins_c);
- cursor1->ch += ins_c;
- }
- break;
-
- default:
- if (CHAR_VALID_INPUT(c) && (widget->text_len < widget->text_size - 1)) {
- ch_w = widget->font->w_ch[c];
- memmove(text + 1, text, widget->text_len - cursor1->ch + 1);
- *text = c;
- cursor1->ch++;
- ins_c = 1;
- }
- break;
- }
+ if (cursor2->on) eve_textw_cursor_clear(widget, cursor2);
}
if ((ins_c == 0) && (del_c == 0)) return;
@@ -384,7 +374,6 @@ void eve_textw_putc(void *_page, int c) {
r = cursor1->line;
if (cursor1->line) r = eve_textw_update(widget, page, cursor1->line - 1);
if ((cursor1->line == 0) || (r == cursor1->line - 1)) r = eve_textw_update(widget, page, cursor1->line);
- if (r < 0) return;
if (cursor1->line && (cursor1->ch < LINE_START(widget, cursor1->line))) {
cursor1->line--;
@@ -399,10 +388,11 @@ void eve_textw_putc(void *_page, int c) {
}
}
-int eve_textw_update(EVETextWidget *widget, EVEPage *page, uint16_t line) {
+uint16_t eve_textw_update(EVETextWidget *widget, EVEPage *page, uint16_t line) {
int i;
- char ch;
+ utf32_t ch;
uint8_t ch_w;
+ uint8_t ch_l;
uint16_t word_w, line_w, line_b;
uint16_t new_h;
EVEWidget *_widget = &widget->w;
@@ -410,9 +400,18 @@ int eve_textw_update(EVETextWidget *widget, EVEPage *page, uint16_t line) {
word_w = 0;
line_w = 0;
line_b = LINE_EMPTY;
- for (i=LINE_START(widget, line); i<widget->text_size; i++) {
- ch = widget->text[i];
- if (ch < 128) ch_w = widget->font->w_ch[ch];
+
+ i = LINE_START(widget, line);
+ while (i < widget->text_size) {
+ ch_l = utf8_dec(widget->text + i, &ch);
+ if (!CHAR_VALID_INPUT(ch) && ch) {
+ ch = 0;
+ widget->text[i] = '\0';
+ widget->text_len = i;
+ widget->line[line] = LINE_EMPTY;
+ }
+
+ ch_w = eve_font_ch_w(widget->font, ch);
if (ch <= 0x20) {
if ((ch == '\n') || (ch == '\0')) {
if (widget->line[line] == i) return line;
@@ -426,14 +425,10 @@ int eve_textw_update(EVETextWidget *widget, EVEPage *page, uint16_t line) {
word_w = 0;
line_w += ch_w;
line_b = i;
- } else {
- return EVE_ERR_TEXT;
}
- } else if (ch < 0x7f) {
+ } else {
word_w += ch_w;
line_w += ch_w;
- } else {
- return EVE_ERR_TEXT;
}
if ((line_w > _widget->g.w) && (line_b != LINE_EMPTY)) {
if (widget->line[line] == line_b) return line;
@@ -446,12 +441,9 @@ int eve_textw_update(EVETextWidget *widget, EVEPage *page, uint16_t line) {
line_w = word_w;
line_b = LINE_EMPTY;
}
+ i += ch_l;
}
- if (i == widget->text_size) i--;
- widget->text[i] = '\0';
- widget->text_len = i;
-
widget->line_len = line;
new_h = (line + 1) * widget->font->h;
for (i=line; i<widget->line_size; i++) {
@@ -467,13 +459,15 @@ int eve_textw_update(EVETextWidget *widget, EVEPage *page, uint16_t line) {
}
void eve_textw_cursor_update(EVETextWidget *widget, EVETextCursor *cursor) {
- int i;
- uint16_t x;
-
- x = 0;
- for (i=LINE_START(widget, cursor->line); i<LINE_END(widget, cursor->line); i++) {
- if (cursor->ch == i) break;
- x += widget->font->w_ch[widget->text[i]];
+ int i = LINE_START(widget, cursor->line);
+ uint16_t x = 0;
+ utf32_t ch;
+ uint8_t ch_l;
+
+ while ((i < cursor->ch) && (i < LINE_END(widget, cursor->line))) {
+ ch_l = utf8_dec(widget->text + i, &ch);
+ x += eve_font_ch_w(widget->font, ch);
+ i += ch_l;
}
cursor->x = x;
}
@@ -482,6 +476,9 @@ void eve_textw_cursor_set(EVETextWidget *widget, EVETextCursor *cursor, uint8_t
int i;
int16_t _x, _d;
uint16_t c_line = LINE_EMPTY;
+ utf32_t ch;
+ uint8_t ch_w;
+ uint8_t ch_l;
EVEWidget *_widget = &widget->w;
if ((tag >= widget->tag0) && ((widget->tagN == EVE_TAG_NOTAG) || (tag < widget->tagN))) c_line = tag - widget->tag0 + widget->line0;
@@ -494,15 +491,19 @@ void eve_textw_cursor_set(EVETextWidget *widget, EVETextCursor *cursor, uint8_t
}
x -= _widget->g.x;
+
_x = 0;
_d = x;
- for (i=LINE_START(widget, cursor->line); i<LINE_END(widget, cursor->line); i++) {
- _x += widget->font->w_ch[widget->text[i]];
+ i = LINE_START(widget, cursor->line);
+ while (i < LINE_END(widget, cursor->line)) {
+ ch_l = utf8_dec(widget->text + i, &ch);
+ ch_w = eve_font_ch_w(widget->font, ch);
+ _x += ch_w;
+ i += ch_l;
if (_x >= x) {
- if (_x - x < _d) {
- i++;
- } else {
- _x -= widget->font->w_ch[widget->text[i]];
+ if (_x - x > _d) {
+ _x -= ch_w;
+ i -= ch_l;
}
break;
} else {
diff --git a/code/fe310/eos/eve/widget/textw.h b/code/fe310/eos/eve/widget/textw.h
index ee3eefb..cd46ea3 100644
--- a/code/fe310/eos/eve/widget/textw.h
+++ b/code/fe310/eos/eve/widget/textw.h
@@ -10,7 +10,7 @@ typedef struct EVETextCursor {
typedef struct EVETextWidget {
EVEWidget w;
EVEFont *font;
- char *text;
+ utf8_t *text;
uint16_t text_size;
uint16_t text_len;
uint16_t *line;
@@ -29,11 +29,11 @@ typedef struct EVETextWidget {
} track;
} EVETextWidget;
-void eve_textw_init(EVETextWidget *widget, EVERect *g, EVEFont *font, char *text, uint16_t text_size, uint16_t *line, uint16_t line_size);
+void eve_textw_init(EVETextWidget *widget, EVERect *g, EVEFont *font, utf8_t *text, uint16_t text_size, uint16_t *line, uint16_t line_size);
int eve_textw_touch(EVEWidget *_widget, EVEPage *page, uint8_t tag0, int touch_idx);
uint8_t eve_textw_draw(EVEWidget *_widget, EVEPage *page, uint8_t tag0);
void eve_textw_putc(void *_w, int c);
-int eve_textw_update(EVETextWidget *widget, EVEPage *page, uint16_t line);
+uint16_t eve_textw_update(EVETextWidget *widget, EVEPage *page, uint16_t line);
void eve_textw_cursor_update(EVETextWidget *widget, EVETextCursor *cursor);
void eve_textw_cursor_set(EVETextWidget *widget, EVETextCursor *cursor, uint8_t tag, int16_t x);
void eve_textw_cursor_clear(EVETextWidget *widget, EVETextCursor *cursor);
diff --git a/code/fe310/eos/eve/widget/widget.c b/code/fe310/eos/eve/widget/widget.c
index e33a7d6..ab121d8 100644
--- a/code/fe310/eos/eve/widget/widget.c
+++ b/code/fe310/eos/eve/widget/widget.c
@@ -3,6 +3,7 @@
#include "eve.h"
#include "eve_kbd.h"
+#include "unicode.h"
#include "screen/screen.h"
#include "screen/window.h"