diff options
Diffstat (limited to 'fw/fe310/eos/eve/widget')
-rw-r--r-- | fw/fe310/eos/eve/widget/Makefile | 17 | ||||
-rw-r--r-- | fw/fe310/eos/eve/widget/freew.c | 54 | ||||
-rw-r--r-- | fw/fe310/eos/eve/widget/freew.h | 25 | ||||
-rw-r--r-- | fw/fe310/eos/eve/widget/label.c | 23 | ||||
-rw-r--r-- | fw/fe310/eos/eve/widget/label.h | 10 | ||||
-rw-r--r-- | fw/fe310/eos/eve/widget/pagew.c | 59 | ||||
-rw-r--r-- | fw/fe310/eos/eve/widget/pagew.h | 20 | ||||
-rw-r--r-- | fw/fe310/eos/eve/widget/selectw.c | 248 | ||||
-rw-r--r-- | fw/fe310/eos/eve/widget/selectw.h | 30 | ||||
-rw-r--r-- | fw/fe310/eos/eve/widget/spacerw.c | 36 | ||||
-rw-r--r-- | fw/fe310/eos/eve/widget/spacerw.h | 14 | ||||
-rw-r--r-- | fw/fe310/eos/eve/widget/strw.c | 446 | ||||
-rw-r--r-- | fw/fe310/eos/eve/widget/strw.h | 43 | ||||
-rw-r--r-- | fw/fe310/eos/eve/widget/textw.c | 545 | ||||
-rw-r--r-- | fw/fe310/eos/eve/widget/textw.h | 46 | ||||
-rw-r--r-- | fw/fe310/eos/eve/widget/widget.c | 77 | ||||
-rw-r--r-- | fw/fe310/eos/eve/widget/widget.h | 31 | ||||
-rw-r--r-- | fw/fe310/eos/eve/widget/widgets.h | 39 |
18 files changed, 1763 insertions, 0 deletions
diff --git a/fw/fe310/eos/eve/widget/Makefile b/fw/fe310/eos/eve/widget/Makefile new file mode 100644 index 0000000..95af16d --- /dev/null +++ b/fw/fe310/eos/eve/widget/Makefile @@ -0,0 +1,17 @@ +include ../../../common.mk + +CFLAGS += -I.. -I../.. + +obj = label.o widget.o freew.o spacerw.o pagew.o strw.o textw.o selectw.o + + +%.o: %.c %.h + $(CC) $(CFLAGS) -c $< + +%.o: %.S + $(CC) $(CFLAGS) -c $< + +all: $(obj) + +clean: + rm -f *.o diff --git a/fw/fe310/eos/eve/widget/freew.c b/fw/fe310/eos/eve/widget/freew.c new file mode 100644 index 0000000..86c2686 --- /dev/null +++ b/fw/fe310/eos/eve/widget/freew.c @@ -0,0 +1,54 @@ +#include <stdlib.h> +#include <string.h> + +#include "eve.h" +#include "eve_kbd.h" +#include "eve_font.h" + +#include "screen/window.h" +#include "screen/page.h" + +#include "label.h" +#include "widget.h" +#include "freew.h" + +int eve_freew_create(EVEFreeWidget *widget, EVERect *g, EVEPage *page, EVEFreeSpec *spec) { + eve_freew_init(widget, g, page, spec->draw, spec->touch, spec->putc); + + return EVE_OK; +} + +void eve_freew_init(EVEFreeWidget *widget, EVERect *g, EVEPage *page, eve_freew_draw_t draw, eve_freew_touch_t touch, eve_kbd_input_handler_t putc) { + EVEWidget *_widget = &widget->w; + + memset(widget, 0, sizeof(EVEFreeWidget)); + eve_widget_init(_widget, EVE_WIDGET_TYPE_FREE, g, page, eve_freew_draw, eve_freew_touch, putc); + widget->_draw = draw; + widget->_touch = touch; + widget->w.putc = putc; +} + +void eve_freew_tag(EVEFreeWidget *widget) { + EVEWidget *_widget = &widget->w; + + if (_widget->tagN != EVE_NOTAG) { + eve_cmd_dl(TAG(_widget->tagN)); + _widget->tagN++; + } +} + +uint8_t eve_freew_draw(EVEWidget *_widget, uint8_t tag0) { + EVEFreeWidget *widget = (EVEFreeWidget *)_widget; + + _widget->tag0 = tag0; + _widget->tagN = tag0; + widget->_draw(widget); + + return _widget->tagN; +} + +int eve_freew_touch(EVEWidget *_widget, EVETouch *touch, uint16_t evt) { + EVEFreeWidget *widget = (EVEFreeWidget *)_widget; + + return widget->_touch(widget, touch, evt); +} diff --git a/fw/fe310/eos/eve/widget/freew.h b/fw/fe310/eos/eve/widget/freew.h new file mode 100644 index 0000000..7eda8c1 --- /dev/null +++ b/fw/fe310/eos/eve/widget/freew.h @@ -0,0 +1,25 @@ +#include <stdint.h> + +struct EVEFreeWidget; + +typedef void (*eve_freew_draw_t) (struct EVEFreeWidget *); +typedef int (*eve_freew_touch_t) (struct EVEFreeWidget *, EVETouch *, uint16_t); + +typedef struct EVEFreeWidget { + EVEWidget w; + eve_freew_draw_t _draw; + eve_freew_touch_t _touch; +} EVEFreeWidget; + +typedef struct EVEFreeSpec { + eve_freew_draw_t draw; + eve_freew_touch_t touch; + eve_kbd_input_handler_t putc; +} EVEFreeSpec; + +int eve_freew_create(EVEFreeWidget *widget, EVERect *g, EVEPage *page, EVEFreeSpec *spec); +void eve_freew_init(EVEFreeWidget *widget, EVERect *g, EVEPage *page, eve_freew_draw_t draw, eve_freew_touch_t touch, eve_kbd_input_handler_t putc); + +void eve_freew_tag(EVEFreeWidget *widget); +uint8_t eve_freew_draw(EVEWidget *_widget, uint8_t tag0); +int eve_freew_touch(EVEWidget *_widget, EVETouch *touch, uint16_t evt); diff --git a/fw/fe310/eos/eve/widget/label.c b/fw/fe310/eos/eve/widget/label.c new file mode 100644 index 0000000..f2d2e8e --- /dev/null +++ b/fw/fe310/eos/eve/widget/label.c @@ -0,0 +1,23 @@ +#include <stdlib.h> +#include <string.h> + +#include "eve.h" +#include "eve_kbd.h" +#include "eve_font.h" + +#include "screen/window.h" +#include "screen/page.h" + +#include "label.h" + +void eve_label_init(EVELabel *label, EVERect *g, EVEFont *font, char *title) { + memset(label, 0, sizeof(EVELabel)); + if (g) label->g = *g; + label->font = font; + label->title = title; + if (label->g.h == 0) label->g.h = eve_font_h(font); +} + +void eve_label_draw(EVELabel *label) { + eve_cmd(CMD_TEXT, "hhhhs", label->g.x, label->g.y, label->font->id, 0, label->title); +}
\ No newline at end of file diff --git a/fw/fe310/eos/eve/widget/label.h b/fw/fe310/eos/eve/widget/label.h new file mode 100644 index 0000000..659c057 --- /dev/null +++ b/fw/fe310/eos/eve/widget/label.h @@ -0,0 +1,10 @@ +#include <stdint.h> + +typedef struct EVELabel { + EVERect g; + EVEFont *font; + char *title; +} EVELabel; + +void eve_label_init(EVELabel *label, EVERect *g, EVEFont *font, char *title); +void eve_label_draw(EVELabel *label);
\ No newline at end of file diff --git a/fw/fe310/eos/eve/widget/pagew.c b/fw/fe310/eos/eve/widget/pagew.c new file mode 100644 index 0000000..bd7819f --- /dev/null +++ b/fw/fe310/eos/eve/widget/pagew.c @@ -0,0 +1,59 @@ +#include <stdlib.h> +#include <string.h> + +#include "eve.h" +#include "eve_kbd.h" +#include "eve_font.h" + +#include "screen/window.h" +#include "screen/page.h" + +#include "label.h" +#include "widget.h" +#include "pagew.h" + +int eve_pagew_create(EVEPageWidget *widget, EVERect *g, EVEPage *page, EVEPageSpec *spec) { + EVEFont *font = spec->font ? spec->font : eve_window_font(page->v.window); + + eve_pagew_init(widget, g, page, font, spec->title, spec->constructor); + + return EVE_OK; +} + +void eve_pagew_init(EVEPageWidget *widget, EVERect *g, EVEPage *page, EVEFont *font, char *title, eve_view_constructor_t constructor) { + EVEWidget *_widget = &widget->w; + + memset(widget, 0, sizeof(EVEPageWidget)); + eve_widget_init(_widget, EVE_WIDGET_TYPE_PAGE, g, page, eve_pagew_draw, eve_pagew_touch, NULL); + widget->font = font; + widget->title = title; + widget->constructor = constructor; + if (_widget->g.h == 0) _widget->g.h = eve_font_h(widget->font); +} + +uint8_t eve_pagew_draw(EVEWidget *_widget, uint8_t tag0) { + EVEPageWidget *widget = (EVEPageWidget *)_widget; + + _widget->tag0 = tag0; + if (tag0 != EVE_NOTAG) { + eve_cmd_dl(TAG(tag0)); + tag0++; + } + _widget->tagN = tag0; + + eve_cmd(CMD_TEXT, "hhhhs", _widget->g.x, _widget->g.y, widget->font->id, 0, widget->title); + + return _widget->tagN; +} + +int eve_pagew_touch(EVEWidget *_widget, EVETouch *touch, uint16_t evt) { + EVEPage *parent = _widget->page; + EVEPageWidget *widget = (EVEPageWidget *)_widget; + + if (evt & EVE_TOUCH_ETYPE_TAG_UP) { + eve_page_open(parent, widget->constructor); + return 1; + } + + return 0; +} diff --git a/fw/fe310/eos/eve/widget/pagew.h b/fw/fe310/eos/eve/widget/pagew.h new file mode 100644 index 0000000..76ac0d2 --- /dev/null +++ b/fw/fe310/eos/eve/widget/pagew.h @@ -0,0 +1,20 @@ +#include <stdint.h> + +typedef struct EVEPageWidget { + EVEWidget w; + EVEFont *font; + char *title; + eve_view_constructor_t constructor; +} EVEPageWidget; + +typedef struct EVEPageSpec { + EVEFont *font; + char *title; + eve_view_constructor_t constructor; +} EVEPageSpec; + +int eve_pagew_create(EVEPageWidget *widget, EVERect *g, EVEPage *page, EVEPageSpec *spec); +void eve_pagew_init(EVEPageWidget *widget, EVERect *g, EVEPage *page, EVEFont *font, char *title, eve_view_constructor_t constructor); + +uint8_t eve_pagew_draw(EVEWidget *_widget, uint8_t tag0); +int eve_pagew_touch(EVEWidget *_widget, EVETouch *touch, uint16_t evt); diff --git a/fw/fe310/eos/eve/widget/selectw.c b/fw/fe310/eos/eve/widget/selectw.c new file mode 100644 index 0000000..46ed3d1 --- /dev/null +++ b/fw/fe310/eos/eve/widget/selectw.c @@ -0,0 +1,248 @@ +#include <stdlib.h> +#include <string.h> + +#include "eve.h" +#include "eve_kbd.h" +#include "eve_font.h" + +#include "screen/window.h" +#include "screen/page.h" + +#include "label.h" +#include "widget.h" +#include "selectw.h" + +#define SELECTW_NOSELECT 0xffffffff + +#define DIVC(x,y) ((x) / (y) + ((x) % (y) != 0)) + +static int selectw_verify(utf8_t *option, uint16_t option_size) { + int o_len; + uint16_t o_curr; + int rv; + + o_curr = 0; + while (o_curr < option_size) { + rv = utf8_verify(option + o_curr, option_size - o_curr, &o_len); + if (rv) return EVE_ERR; + if (o_len == 0) return EVE_OK; + o_curr += o_len + 1; + } + + return EVE_OK; +} + +static int selectw_count(EVESelectWidget *widget) { + int o_len; + int o_curr; + int i; + + o_curr = 0; + i = 0; + do { + o_len = strnlen(widget->option + o_curr, widget->option_size - o_curr); + if (o_len == widget->option_size - o_curr) return i; + if (o_len) { + o_curr += o_len + 1; + i++; + } + } while (o_len); + + return i; +} + +static void selectw_update_sz(EVESelectWidget *widget, int uievt) { + EVEWidget *_widget = &widget->w; + EVEPage *page = _widget->page; + + _widget->g.h = widget->option_count * widget->font->h; + if (uievt) eve_view_uievt_push(&page->v, EVE_UIEVT_WIDGET_UPDATE_G, _widget); +} + +int eve_selectw_create(EVESelectWidget *widget, EVERect *g, EVEPage *page, EVESelectSpec *spec) { + EVEFont *font = spec->font ? spec->font : eve_window_font(page->v.window); + utf8_t *option; + + option = eve_malloc(spec->option_size); + if (option == NULL) { + return EVE_ERR_NOMEM; + } + memset(option, 0, spec->option_size); + + eve_selectw_init(widget, g, page, font, option, spec->option_size, spec->multi); + + return EVE_OK; +} + +void eve_selectw_init(EVESelectWidget *widget, EVERect *g, EVEPage *page, EVEFont *font, utf8_t *option, uint16_t option_size, uint8_t multi) { + EVEWidget *_widget = &widget->w; + int rv; + + memset(widget, 0, sizeof(EVESelectWidget)); + eve_widget_init(_widget, EVE_WIDGET_TYPE_SELECT, g, page, eve_selectw_draw, eve_selectw_touch, NULL); + widget->font = font; + rv = selectw_verify(option, option_size); + if (rv == EVE_OK) { + widget->option = option; + widget->option_size = option_size; + widget->option_count = selectw_count(widget); + selectw_update_sz(widget, 0); + } + widget->multi = multi; + widget->select = widget->multi ? 0 : SELECTW_NOSELECT; +} + +void eve_selectw_destroy(EVESelectWidget *widget) { + eve_free(widget->option); +} + +uint8_t eve_selectw_draw(EVEWidget *_widget, uint8_t tag0) { + EVEPage *page = _widget->page; + EVESelectWidget *widget = (EVESelectWidget *)_widget; + int o_len; + int o_curr; + int i, s; + int16_t x1, x2, y1, y2; + uint16_t new_h; + + int line0, lineN; + + line0 = -((int)eve_page_win_y(page, _widget->g.y)) / widget->font->h; + lineN = DIVC((-((int)eve_page_win_y(page, _widget->g.y)) + page->v.window->g.h), widget->font->h); + if (line0 < 0) line0 = 0; + if (lineN < 0) lineN = 0; + if (line0 > widget->option_count) line0 = widget->option_count; + if (lineN > widget->option_count) lineN = widget->option_count; + + _widget->tag0 = tag0; + _widget->tagN = tag0; + widget->line0 = line0; + + o_curr = 0; + i = 0; + do { + o_len = strnlen(widget->option + o_curr, widget->option_size - o_curr); + if (!o_len || (o_len == widget->option_size - o_curr)) break; + if ((i >= line0) && (i < lineN)) { + if (_widget->tagN != EVE_NOTAG) { + eve_cmd_dl(TAG(_widget->tagN)); + _widget->tagN++; + } + s = widget->multi ? widget->select & (0x1 << i) : widget->select == i; + x1 = _widget->g.x; + x2 = x1 + _widget->g.w; + y1 = _widget->g.y + i * widget->font->h; + y2 = y1 + widget->font->h; + eve_cmd_dl(BEGIN(EVE_RECTS)); + if (!s) eve_cmd_dl(COLOR_MASK(0 ,0 ,0 ,0)); + eve_cmd_dl(VERTEX2F(x1, y1)); + eve_cmd_dl(VERTEX2F(x2, y2)); + if (!s) { + eve_cmd_dl(COLOR_MASK(1 ,1 ,1 ,1)); + eve_cmd_dl(BEGIN(EVE_LINES)); + eve_cmd_dl(VERTEX2F(x1, y2)); + eve_cmd_dl(VERTEX2F(x2, y2)); + } + eve_cmd_dl(END()); + if (s) eve_cmd_dl(COLOR_RGBC(page->v.color_bg)); + eve_cmd(CMD_TEXT, "hhhhs", x1, y1, widget->font->id, 0, widget->option + o_curr); + if (s) eve_cmd_dl(COLOR_RGBC(page->v.color_fg)); + } + + o_curr += o_len + 1; + i++; + } while (o_len); + + return _widget->tagN; +} + +int eve_selectw_touch(EVEWidget *_widget, EVETouch *touch, uint16_t evt) { + EVESelectWidget *widget = (EVESelectWidget *)_widget; + + if (evt & EVE_TOUCH_ETYPE_TAG_UP) { + int i = touch->tag0 - _widget->tag0 + widget->line0; + if (widget->multi) { + uint32_t f = (0x1 << i); + + if (widget->select & f) { + widget->select &= ~f; + } else { + widget->select |= f; + } + } else { + if (widget->select == i) { + widget->select = SELECTW_NOSELECT; + } else { + widget->select = i; + } + } + return 1; + } + return 0; +} + +utf8_t *eve_selectw_option_get(EVESelectWidget *widget, int idx) { + int o_len; + int o_curr; + int i; + + o_curr = 0; + i = 0; + do { + o_len = strnlen(widget->option + o_curr, widget->option_size - o_curr); + if (o_len == widget->option_size - o_curr) return NULL; + if (o_len && (i == idx)) return widget->option + o_curr; + o_curr += o_len + 1; + i++; + } while (o_len); + + return NULL; +} + +utf8_t *eve_selectw_option_get_select(EVESelectWidget *widget) { + return eve_selectw_option_get(widget, widget->select); +} + +int eve_selectw_option_add(EVESelectWidget *widget, utf8_t *option) { + int o_len; + int o_curr; + int rv, i; + + rv = utf8_verify(option, strlen(option) + 1, NULL); + if (rv) return EVE_ERR; + + o_curr = 0; + i = 0; + do { + o_len = strnlen(widget->option + o_curr, widget->option_size - o_curr); + if (o_len == widget->option_size - o_curr) return EVE_ERR_FULL; + if (o_len) { + o_curr += o_len + 1; + i++; + } + } while (o_len); + + if (o_curr + strlen(option) + 1 > widget->option_size) return EVE_ERR_FULL; + strcpy(widget->option + o_curr, option); + + widget->option_count = i + 1; + selectw_update_sz(widget, 1); + + return EVE_OK; +} + +int eve_selectw_option_set(EVESelectWidget *widget, utf8_t *option, uint16_t option_size) { + int rv, i; + + rv = selectw_verify(option, option_size); + if (rv) return rv; + if (option_size > widget->option_size) return EVE_ERR_FULL; + + memcpy(widget->option, option, option_size); + memset(widget->option + option_size, 0, widget->option_size - option_size); + + widget->option_count = selectw_count(widget); + selectw_update_sz(widget, 1); + + return EVE_OK; +} diff --git a/fw/fe310/eos/eve/widget/selectw.h b/fw/fe310/eos/eve/widget/selectw.h new file mode 100644 index 0000000..939e362 --- /dev/null +++ b/fw/fe310/eos/eve/widget/selectw.h @@ -0,0 +1,30 @@ +#include <stdint.h> + +typedef struct EVESelectWidget { + EVEWidget w; + EVEFont *font; + utf8_t *option; + uint16_t option_size; + uint16_t option_count; + uint32_t select; + uint16_t line0; + uint8_t multi; +} EVESelectWidget; + +typedef struct EVESelectSpec { + EVEFont *font; + uint16_t option_size; + uint8_t multi; +} EVESelectSpec; + +int eve_selectw_create(EVESelectWidget *widget, EVERect *g, EVEPage *page, EVESelectSpec *spec); +void eve_selectw_init(EVESelectWidget *widget, EVERect *g, EVEPage *page, EVEFont *font, utf8_t *option, uint16_t option_size, uint8_t multi); +void eve_selectw_destroy(EVESelectWidget *widget); + +uint8_t eve_selectw_draw(EVEWidget *_widget, uint8_t tag0); +int eve_selectw_touch(EVEWidget *_widget, EVETouch *touch, uint16_t evt); + +utf8_t *eve_selectw_option_get(EVESelectWidget *widget, int idx); +utf8_t *eve_selectw_option_get_select(EVESelectWidget *widget); +int eve_selectw_option_add(EVESelectWidget *widget, utf8_t *option); +int eve_selectw_option_set(EVESelectWidget *widget, utf8_t *option, uint16_t option_size); diff --git a/fw/fe310/eos/eve/widget/spacerw.c b/fw/fe310/eos/eve/widget/spacerw.c new file mode 100644 index 0000000..d9f9104 --- /dev/null +++ b/fw/fe310/eos/eve/widget/spacerw.c @@ -0,0 +1,36 @@ +#include <stdlib.h> +#include <string.h> + +#include "eve.h" +#include "eve_kbd.h" +#include "eve_font.h" + +#include "screen/window.h" +#include "screen/page.h" + +#include "label.h" +#include "widget.h" +#include "spacerw.h" + +int eve_spacerw_create(EVESpacerWidget *widget, EVERect *g, EVEPage *page, EVESpacerSpec *spec) { + eve_spacerw_init(widget, g, page); + + return EVE_OK; +} + +void eve_spacerw_init(EVESpacerWidget *widget, EVERect *g, EVEPage *page) { + EVEWidget *_widget = &widget->w; + + memset(widget, 0, sizeof(EVESpacerWidget)); + eve_widget_init(_widget, EVE_WIDGET_TYPE_SPACER, g, page, eve_spacerw_draw, eve_spacerw_touch, NULL); +} + +uint8_t eve_spacerw_draw(EVEWidget *_widget, uint8_t tag0) { + _widget->tag0 = tag0; + _widget->tagN = tag0; + return _widget->tagN; +} + +int eve_spacerw_touch(EVEWidget *_widget, EVETouch *touch, uint16_t evt) { + return 0; +} diff --git a/fw/fe310/eos/eve/widget/spacerw.h b/fw/fe310/eos/eve/widget/spacerw.h new file mode 100644 index 0000000..9dafa8b --- /dev/null +++ b/fw/fe310/eos/eve/widget/spacerw.h @@ -0,0 +1,14 @@ +#include <stdint.h> + +typedef struct EVESpacerWidget { + EVEWidget w; +} EVESpacerWidget; + +typedef struct EVESpacerSpec { +} EVESpacerSpec; + +int eve_spacerw_create(EVESpacerWidget *widget, EVERect *g, EVEPage *page, EVESpacerSpec *spec); +void eve_spacerw_init(EVESpacerWidget *widget, EVERect *g, EVEPage *page); + +uint8_t eve_spacerw_draw(EVEWidget *_widget, uint8_t tag0); +int eve_spacerw_touch(EVEWidget *_widget, EVETouch *touch, uint16_t evt); diff --git a/fw/fe310/eos/eve/widget/strw.c b/fw/fe310/eos/eve/widget/strw.c new file mode 100644 index 0000000..e78cf46 --- /dev/null +++ b/fw/fe310/eos/eve/widget/strw.c @@ -0,0 +1,446 @@ +#include <stdlib.h> +#include <string.h> + +#include "clipb.h" + +#include "eve.h" +#include "eve_kbd.h" +#include "eve_font.h" + +#include "screen/window.h" +#include "screen/page.h" + +#include "label.h" +#include "widget.h" +#include "strw.h" + +#define STRW_TOUCH_OPT EVE_TOUCH_OPT_TRACK | EVE_TOUCH_OPT_TRACK_X | EVE_TOUCH_OPT_TRACK_EXT_X | EVE_TOUCH_OPT_LPRESS + +#define STRW_TMODE_NONE 0 +#define STRW_TMODE_CRSR 1 +#define STRW_TMODE_TXT 2 + +#define CH_BS 0x08 +#define CH_DEL 0x7f + +#define CH_CTRLX 0x18 +#define CH_CTRLC 0x03 +#define CH_CTRLV 0x16 + +#define CHAR_VALID_INPUT(c) ((c >= 0x20) && (c < 0x7f)) + +int eve_strw_create(EVEStrWidget *widget, EVERect *g, EVEPage *page, EVEStrSpec *spec) { + EVEFont *font = spec->font ? spec->font : eve_window_font(page->v.window); + utf8_t *str; + uint16_t *line; + + str = eve_malloc(spec->str_size); + if (str == NULL) return EVE_ERR_NOMEM; + str[0] = '\0'; + + eve_strw_init(widget, g, page, font, str, spec->str_size); + + return EVE_OK; +} + +void eve_strw_init(EVEStrWidget *widget, EVERect *g, EVEPage *page, EVEFont *font, utf8_t *str, uint16_t str_size) { + EVEWidget *_widget = &widget->w; + int rv, str_len; + + memset(widget, 0, sizeof(EVEStrWidget)); + eve_widget_init(_widget, EVE_WIDGET_TYPE_STR, g, page, eve_strw_draw, eve_strw_touch, eve_strw_putc); + widget->font = font; + rv = utf8_verify(str, str_size, &str_len); + if (rv != UTF_OK) { + if (str_len >= str_size) str_len = 0; + str[str_len] = '\0'; + } + widget->str = str; + widget->str_size = str_size; + widget->str_len = str_len; + widget->str_g.w = eve_font_str_w(widget->font, str); + if (_widget->g.h == 0) _widget->g.h = eve_font_h(widget->font); +} + +int eve_strw_update(EVEStrWidget *widget) { + int rv, str_len; + + rv = utf8_verify(widget->str, widget->str_size, &str_len); + if (rv != UTF_OK) { + if (str_len >= widget->str_size) str_len = 0; + widget->str[str_len] = '\0'; + } + widget->str_len = str_len; + return (rv == UTF_OK) ? EVE_OK : EVE_ERR; +} + +void eve_strw_destroy(EVEStrWidget *widget) { + eve_free(widget->str); +} + +static void set_focus(EVEStrWidget *widget) { + EVEWidget *_widget = &widget->w; + EVERect focus; + + focus.x = _widget->g.x; + focus.y = _widget->g.y; + focus.w = _widget->g.w; + focus.h = 2 * widget->font->h; + eve_widget_focus(_widget, &focus); +} + +static EVEStrCursor *cursor_prox(EVEStrWidget *widget, EVEStrCursor *cursor, EVETouch *touch, short *dx) { + EVEWidget *_widget = &widget->w; + EVEPage *page = _widget->page; + int x = eve_page_x(page, touch->x0) - _widget->g.x + widget->str_g.x; + int _dx; + + *dx = cursor->x - x; + _dx = *dx < 0 ? -(*dx) : *dx; + + if (_dx <= widget->font->w) return cursor; + return NULL; +} + +static void draw_string(EVEStrWidget *widget, uint16_t ch, uint16_t len, uint16_t x1, uint16_t x2, char s) { + int16_t x; + EVEWidget *_widget = &widget->w; + EVEPage *page = _widget->page; + + x = _widget->g.x - widget->str_g.x; + if (x1 != x2) { + eve_cmd_dl(BEGIN(EVE_RECTS)); + if (!s) eve_cmd_dl(COLOR_MASK(0 ,0 ,0 ,0)); + eve_cmd_dl(VERTEX2F(x + x1, _widget->g.y)); + eve_cmd_dl(VERTEX2F(x + x2, _widget->g.y + widget->font->h)); + if (!s) { + eve_cmd_dl(COLOR_MASK(1 ,1 ,1 ,1)); + eve_cmd_dl(BEGIN(EVE_LINES)); + eve_cmd_dl(VERTEX2F(x + x1, _widget->g.y + widget->font->h)); + eve_cmd_dl(VERTEX2F(x + x2, _widget->g.y + widget->font->h)); + } + eve_cmd_dl(END()); + if (len) { + if (s) eve_cmd_dl(COLOR_RGBC(page->v.color_bg)); + eve_cmd(CMD_TEXT, "hhhhpb", x + x1, _widget->g.y, widget->font->id, 0, widget->str + ch, len, 0); + if (s) eve_cmd_dl(COLOR_RGBC(page->v.color_fg)); + } + } +} + +static void draw_cursor(EVEStrWidget *widget, EVEStrCursor *cursor) { + uint16_t x, y; + EVEWidget *_widget = &widget->w; + + x = _widget->g.x - widget->str_g.x + cursor->x; + y = _widget->g.y; + eve_cmd_dl(BEGIN(EVE_LINES)); + eve_cmd_dl(VERTEX2F(x, y)); + eve_cmd_dl(VERTEX2F(x, y + widget->font->h)); + eve_cmd_dl(END()); +} + +uint8_t eve_strw_draw(EVEWidget *_widget, uint8_t tag0) { + EVEStrWidget *widget = (EVEStrWidget *)_widget; + char cut = widget->str_g.x || (widget->str_g.w > _widget->g.w); + + _widget->tag0 = tag0; + if (tag0 != EVE_NOTAG) { + eve_cmd_dl(TAG(tag0)); + eve_touch_set_opt(tag0, STRW_TOUCH_OPT); + tag0++; + } + _widget->tagN = tag0; + + if (cut) { + EVEPage *page = _widget->page; + EVEWindow *window = page->v.window; + int16_t x = eve_page_scr_x(page, _widget->g.x); + int16_t y = eve_page_scr_y(page, _widget->g.y); + uint16_t w = _widget->g.w; + uint16_t h = _widget->g.h; + int16_t win_x1 = window->g.x; + int16_t win_y1 = window->g.y; + int16_t win_x2 = win_x1 + window->g.w; + int16_t win_y2 = win_y1 + window->g.h; + + if (win_x1 < 0) win_x1 = 0; + if (win_y1 < 0) win_y1 = 0; + if (win_x2 > window->root->w.g.w) win_x2 = window->root->w.g.w; + if (win_y2 > window->root->w.g.h) win_y2 = window->root->w.g.h; + if (x < win_x1) { + w += x - win_x1; + x = win_x1; + } + if (y < win_y1) { + h += y - win_y1; + y = win_y1; + } + if (x + w > win_x2) w = win_x2 - x; + if (y + h > win_y2) h = win_y2 - y; + + eve_cmd_dl(SAVE_CONTEXT()); + eve_cmd_dl(SCISSOR_XY(x, y)); + eve_cmd_dl(SCISSOR_SIZE(w, h)); + } + + if (widget->cursor2.on) { + EVEStrCursor *c1, *c2; + int l1, l2, l3; + + if (widget->cursor1.ch <= widget->cursor2.ch) { + c1 = &widget->cursor1; + c2 = &widget->cursor2; + } else { + c1 = &widget->cursor2; + c2 = &widget->cursor1; + } + + l1 = c1->ch; + l2 = c2->ch - c1->ch; + l3 = widget->str_len - c2->ch; + draw_string(widget, 0, l1, 0, c1->x, 0); + draw_string(widget, c1->ch, l2, c1->x, c2->x, 1); + draw_string(widget, c2->ch, l3, c2->x, widget->str_g.x + _widget->g.w, 0); + } else { + if (widget->cursor1.on) draw_cursor(widget, &widget->cursor1); + draw_string(widget, 0, widget->str_len, 0, widget->str_g.x + _widget->g.w, 0); + } + + if (cut) { + eve_cmd_dl(RESTORE_CONTEXT()); + } + + return _widget->tagN; +} + +int eve_strw_touch(EVEWidget *_widget, EVETouch *touch, uint16_t evt) { + EVEPage *page = _widget->page; + EVEStrWidget *widget = (EVEStrWidget *)_widget; + EVEStrCursor *t_cursor = NULL; + short dx; + int ret = 0; + + if (evt & (EVE_TOUCH_ETYPE_LPRESS | EVE_TOUCH_ETYPE_TRACK_START)) { + if (widget->cursor2.on) { + t_cursor = cursor_prox(widget, &widget->cursor2, touch, &dx); + } + if ((t_cursor == NULL) && widget->cursor1.on) { + t_cursor = cursor_prox(widget, &widget->cursor1, touch, &dx); + } + if (evt & EVE_TOUCH_ETYPE_TRACK_START) { + if (t_cursor) { + widget->track.mode = STRW_TMODE_CRSR; + widget->track.cursor = t_cursor; + widget->track.dx = dx; + } else if (touch->eevt & EVE_TOUCH_EETYPE_TRACK_X) { + widget->track.mode = STRW_TMODE_TXT; + } + } + } + + if (widget->track.mode) { + int x, w1; + + if (evt & EVE_TOUCH_ETYPE_TRACK) { + switch (widget->track.mode) { + case STRW_TMODE_TXT: + if (evt & EVE_TOUCH_ETYPE_TRACK_START) { + widget->str_g.x0 = widget->str_g.x; + } + x = widget->str_g.x0 + touch->x0 - touch->x; + w1 = _widget->g.w - widget->font->w; + if (x > widget->str_g.w - w1) x = widget->str_g.w - w1; + if (x < 0) x = 0; + widget->str_g.x = x; + break; + + case STRW_TMODE_CRSR: + eve_strw_cursor_set(widget, widget->track.cursor, eve_page_x(page, touch->x) + widget->track.dx); + break; + } + } + ret = 1; + } else { + if (evt & EVE_TOUCH_ETYPE_LPRESS) { + if (widget->cursor2.on) { + // copy + } else if (widget->cursor1.on) { + if (t_cursor) { + // paste + } else { + eve_strw_cursor_set(widget, &widget->cursor2, eve_page_x(page, touch->x)); + } + } else { + // select + } + ret = 1; + } + if ((evt & EVE_TOUCH_ETYPE_POINT_UP) && !(touch->eevt & (EVE_TOUCH_EETYPE_TRACK_XY | EVE_TOUCH_EETYPE_ABORT | EVE_TOUCH_EETYPE_LPRESS))) { + eve_strw_cursor_set(widget, &widget->cursor1, eve_page_x(page, touch->x0)); + if (widget->cursor2.on) eve_strw_cursor_clear(widget, &widget->cursor2); + set_focus(widget); + ret = 1; + } + } + + if (evt & EVE_TOUCH_ETYPE_TRACK_STOP) { + widget->track.mode = STRW_TMODE_NONE; + widget->track.cursor = NULL; + widget->track.dx = 0; + } + + return ret; +} + +void eve_strw_putc(void *w, int c) { + EVEStrWidget *widget = (EVEStrWidget *)w; + EVEWidget *_widget = &widget->w; + EVEStrCursor *cursor1 = &widget->cursor1; + EVEStrCursor *cursor2 = &widget->cursor2; + utf8_t *str; + utf8_t *clipb = NULL; + int w0 = widget->font->w; + int w1 = _widget->g.w - widget->font->w; + int ins_c = 0, del_c = 0; + int ins_w = 0, del_w = 0; + + + if (c == EVE_PAGE_KBDCH_CLOSE) { + if (cursor1->on) eve_strw_cursor_clear(widget, cursor1); + if (cursor2->on) eve_strw_cursor_clear(widget, cursor2); + return; + } + + if (!cursor1->on) return; + + if (!cursor2->on && ((c == CH_BS) || (c == CH_DEL))) { + utf32_t uc; + + 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]; + + 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; + } + } + + 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) { + int rv, clipb_len = 0; + + clipb = eve_clipb_get(); + if (clipb) { + rv = utf8_verify(clipb, EVE_CLIPB_SIZE_BUF, &clipb_len); + if (rv != UTF_OK) { + clipb = NULL; + clipb_len = 0; + } + } + ins_c = clipb_len; + 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 = utf8_buf[0]; + } + c1->ch += ins_c; + c1->x += ins_w; + } + widget->str_len += ins_c - del_c; + widget->str_g.w += ins_w - del_w; + if (c1 == cursor2) widget->cursor1 = widget->cursor2; + 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; + if (cursor1->x - widget->str_g.x > w1) widget->str_g.x = cursor1->x - w1; +} + +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; + 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) { + _x -= ch_w; + i -= ch_l; + } + break; + } else { + _d = x - _x; + } + } + cursor->x = _x; + cursor->ch = i; + cursor->on = 1; +} + +void eve_strw_cursor_clear(EVEStrWidget *widget, EVEStrCursor *cursor) { + cursor->on = 0; +} diff --git a/fw/fe310/eos/eve/widget/strw.h b/fw/fe310/eos/eve/widget/strw.h new file mode 100644 index 0000000..44e5e2d --- /dev/null +++ b/fw/fe310/eos/eve/widget/strw.h @@ -0,0 +1,43 @@ +#include <stdint.h> + +typedef struct EVEStrCursor { + char on; + uint16_t x; + uint16_t ch; +} EVEStrCursor; + +typedef struct EVEStrWidget { + EVEWidget w; + EVEFont *font; + utf8_t *str; + uint16_t str_size; + uint16_t str_len; + struct { + int16_t x; + int16_t x0; + uint16_t w; + } str_g; + EVEStrCursor cursor1; + EVEStrCursor cursor2; + struct { + EVEStrCursor *cursor; + short dx; + char mode; + } track; +} EVEStrWidget; + +typedef struct EVEStrSpec { + EVEFont *font; + uint16_t str_size; +} EVEStrSpec; + +int eve_strw_create(EVEStrWidget *widget, EVERect *g, EVEPage *page, EVEStrSpec *spec); +void eve_strw_init(EVEStrWidget *widget, EVERect *g, EVEPage *page, EVEFont *font, utf8_t *str, uint16_t str_size); +void eve_strw_destroy(EVEStrWidget *widget); +int eve_strw_update(EVEStrWidget *widget); + +uint8_t eve_strw_draw(EVEWidget *_widget, uint8_t tag0); +int eve_strw_touch(EVEWidget *_widget, EVETouch *touch, uint16_t evt); +void eve_strw_putc(void *_page, int c); +void eve_strw_cursor_set(EVEStrWidget *widget, EVEStrCursor *cursor, int16_t x); +void eve_strw_cursor_clear(EVEStrWidget *widget, EVEStrCursor *cursor);
\ No newline at end of file diff --git a/fw/fe310/eos/eve/widget/textw.c b/fw/fe310/eos/eve/widget/textw.c new file mode 100644 index 0000000..e994c0e --- /dev/null +++ b/fw/fe310/eos/eve/widget/textw.c @@ -0,0 +1,545 @@ +#include <stdlib.h> +#include <string.h> + +#include "clipb.h" + +#include "eve.h" +#include "eve_kbd.h" +#include "eve_font.h" + +#include "screen/window.h" +#include "screen/page.h" + +#include "label.h" +#include "widget.h" +#include "textw.h" + +#define TEXTW_TOUCH_OPT EVE_TOUCH_OPT_TRACK | EVE_TOUCH_OPT_TRACK_XY | EVE_TOUCH_OPT_TRACK_EXT_XY | EVE_TOUCH_OPT_LPRESS + +#define CH_BS 0x08 +#define CH_DEL 0x7f + +#define CH_CTRLX 0x18 +#define CH_CTRLC 0x03 +#define CH_CTRLV 0x16 + +#define LINE_LEN(w,l) ((l) ? (w->line[l] ? w->line[l] - w->line[(l) - 1] - 1 : 0) : w->line[l]) +#define LINE_START(w,l) ((l) ? w->line[(l) - 1] + 1 : 0) +#define LINE_END(w,l) (w->line[l]) +#define LINE_EMPTY 0xffff + +#define CHAR_VALID_INPUT(c) (((c >= 0x20) && (c < 0x7f)) || (c == '\n')) + +#define DIVC(x,y) ((x) / (y) + ((x) % (y) != 0)) + +int eve_textw_create(EVETextWidget *widget, EVERect *g, EVEPage *page, EVETextSpec *spec) { + EVEFont *font = spec->font ? spec->font : eve_window_font(page->v.window); + utf8_t *text; + uint16_t *line; + + text = eve_malloc(spec->text_size); + if (text == NULL) { + return EVE_ERR_NOMEM; + } + text[0] = '\0'; + line = eve_malloc(sizeof(uint16_t) * spec->line_size); + if (line == NULL) { + free(text); + return EVE_ERR_NOMEM; + } + + eve_textw_init(widget, g, page, font, text, spec->text_size, line, spec->line_size); + + return EVE_OK; +} + +void eve_textw_init(EVETextWidget *widget, EVERect *g, EVEPage *page, EVEFont *font, utf8_t *text, uint16_t text_size, uint16_t *line, uint16_t line_size) { + EVEWidget *_widget = &widget->w; + int rv, text_len; + + memset(widget, 0, sizeof(EVETextWidget)); + eve_widget_init(_widget, EVE_WIDGET_TYPE_TEXT, g, page, eve_textw_draw, eve_textw_touch, eve_textw_putc); + widget->font = font; + rv = utf8_verify(text, text_size, &text_len); + if (rv != UTF_OK) { + if (text_len >= text_size) text_len = 0; + text[text_len] = '\0'; + } + widget->text = text; + widget->text_size = text_size; + widget->text_len = text_len; + widget->line = line; + widget->line_size = line_size; + memset(widget->line, 0xff, line_size * sizeof(uint16_t)); + eve_textw_text_update(widget, 0, 0); +} + +void eve_textw_destroy(EVETextWidget *widget) { + eve_free(widget->line); + eve_free(widget->text); +} + +static void set_focus(EVETextWidget *widget, EVETextCursor *cursor) { + EVEWidget *_widget = &widget->w; + EVERect focus; + + focus.x = _widget->g.x; + focus.y = _widget->g.y + cursor->line * widget->font->h; + focus.w = _widget->g.w; + focus.h = 2 * widget->font->h; + eve_widget_focus(_widget, &focus); +} + +static EVETextCursor *cursor_prox(EVETextWidget *widget, EVETextCursor *cursor, EVETouch *touch, short *dx, short *dl) { + EVEWidget *_widget = &widget->w; + EVEPage *page = _widget->page; + int x = eve_page_x(page, touch->x0) - _widget->g.x; + int l = (int)touch->tag0 - _widget->tag0 + widget->line0; + int _dx, _dl; + + *dx = cursor->x - x; + *dl = cursor->line - l; + + _dx = *dx < 0 ? -(*dx) : *dx; + _dl = *dl < 0 ? -(*dl) : *dl; + + if ((_dx <= widget->font->h) && (_dl <= 1)) return cursor; + return NULL; +} + +static void draw_line(EVETextWidget *widget, uint16_t l, uint16_t ch, uint16_t len, uint16_t x1, uint16_t x2, char s) { + EVEWidget *_widget = &widget->w; + EVEPage *page = _widget->page; + + if (x1 != x2) { + eve_cmd_dl(BEGIN(EVE_RECTS)); + if (!s) eve_cmd_dl(COLOR_MASK(0 ,0 ,0 ,0)); + eve_cmd_dl(VERTEX2F(_widget->g.x + x1, _widget->g.y + l * widget->font->h)); + eve_cmd_dl(VERTEX2F(_widget->g.x + x2, _widget->g.y + (l + 1) * widget->font->h)); + if (!s) { + eve_cmd_dl(COLOR_MASK(1 ,1 ,1 ,1)); + eve_cmd_dl(BEGIN(EVE_LINES)); + eve_cmd_dl(VERTEX2F(_widget->g.x + x1, _widget->g.y + (l + 1) * widget->font->h)); + eve_cmd_dl(VERTEX2F(_widget->g.x + x2, _widget->g.y + (l + 1) * widget->font->h)); + } + eve_cmd_dl(END()); + if (len) { + if (s) eve_cmd_dl(COLOR_RGBC(page->v.color_bg)); + eve_cmd(CMD_TEXT, "hhhhpb", _widget->g.x + x1, _widget->g.y + l * widget->font->h, widget->font->id, 0, widget->text + ch, len, 0); + if (s) eve_cmd_dl(COLOR_RGBC(page->v.color_fg)); + } + } +} + +static void draw_cursor(EVETextWidget *widget, EVETextCursor *cursor) { + uint16_t x, y; + EVEWidget *_widget = &widget->w; + + x = _widget->g.x + cursor->x; + y = _widget->g.y + cursor->line * widget->font->h; + eve_cmd_dl(BEGIN(EVE_LINES)); + eve_cmd_dl(VERTEX2F(x, y)); + eve_cmd_dl(VERTEX2F(x, y + widget->font->h)); + eve_cmd_dl(END()); +} + +uint8_t eve_textw_draw(EVEWidget *_widget, uint8_t tag0) { + EVEPage *page = _widget->page; + EVETextWidget *widget = (EVETextWidget *)_widget; + int line0, lineN; + int _line0, _lineN; + char lineNvisible; + + _line0 = line0 = -((int)eve_page_win_y(page, _widget->g.y)) / widget->font->h; + _lineN = lineN = DIVC((-((int)eve_page_win_y(page, _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; + if (lineN > widget->line_len) lineN = widget->line_len; + lineNvisible = (lineN >= _line0) && (lineN < _lineN); + + if (lineNvisible || (line0 < lineN)) { + int i; + char s = 0; + EVETextCursor *c1, *c2; + + widget->line0 = line0; + _widget->tag0 = tag0; + _widget->tagN = tag0; + + if (widget->cursor2.on) { + if (widget->cursor1.ch <= widget->cursor2.ch) { + c1 = &widget->cursor1; + c2 = &widget->cursor2; + } else { + c1 = &widget->cursor2; + c2 = &widget->cursor1; + } + } else { + c1 = NULL; + c2 = NULL; + } + + for (i=line0; i<lineN; i++) { + if (_widget->tagN != EVE_NOTAG) { + eve_cmd_dl(TAG(_widget->tagN)); + eve_touch_set_opt(_widget->tagN, TEXTW_TOUCH_OPT); + _widget->tagN++; + } + if (!s && c1 && (c1->line == i)) { + int l1, l2, l3; + + l1 = c1->ch - LINE_START(widget, i); + if (c2->line == i) { + l2 = c2->ch - c1->ch; + l3 = LINE_START(widget, i) + LINE_LEN(widget, i) - c2->ch; + } else { + l2 = LINE_START(widget, i) + LINE_LEN(widget, i) - c1->ch; + l3 = 0; + s = 1; + } + draw_line(widget, i, LINE_START(widget, i), l1, 0, c1->x, 0); + draw_line(widget, i, c1->ch, l2, c1->x, s ? _widget->g.w : c2->x, 1); + if (!s) { + draw_line(widget, i, c2->ch, l3, c2->x, _widget->g.w, 0); + c1 = NULL; + c2 = NULL; + } + } else if (s && (c2->line == i)) { + int l1 = c2->ch - LINE_START(widget, i); + int l2 = LINE_START(widget, i) + LINE_LEN(widget, i) - c2->ch; + + draw_line(widget, i, LINE_START(widget, i), l1, 0, c2->x, 1); + draw_line(widget, i, c2->ch, l2, c2->x, _widget->g.w, 0); + c1 = NULL; + c2 = NULL; + s = 0; + } else { + if (widget->cursor1.on && (widget->cursor1.line == i)) draw_cursor(widget, &widget->cursor1); + draw_line(widget, i, LINE_START(widget, i), LINE_LEN(widget, i), 0, _widget->g.w, s); + } + } + if (lineNvisible) { + if (_widget->tagN != EVE_NOTAG) { + eve_cmd_dl(TAG(_widget->tagN)); + eve_touch_set_opt(_widget->tagN, TEXTW_TOUCH_OPT); + _widget->tagN++; + } + draw_line(widget, lineN, 0, 0, 0, _widget->g.w, 0); + } + } else { + widget->line0 = 0; + _widget->tag0 = EVE_NOTAG; + _widget->tagN = EVE_NOTAG; + } + + return _widget->tagN; +} + +int eve_textw_touch(EVEWidget *_widget, EVETouch *touch, uint16_t evt) { + EVEPage *page = _widget->page; + EVETextWidget *widget = (EVETextWidget *)_widget; + EVETextCursor *t_cursor = NULL; + short dx, dl; + int ret = 0; + + if (evt & (EVE_TOUCH_ETYPE_LPRESS | EVE_TOUCH_ETYPE_TRACK_START)) { + if (widget->cursor2.on) { + t_cursor = cursor_prox(widget, &widget->cursor2, touch, &dx, &dl); + } + if ((t_cursor == NULL) && widget->cursor1.on) { + t_cursor = cursor_prox(widget, &widget->cursor1, touch, &dx, &dl); + } + if (t_cursor && (evt & EVE_TOUCH_ETYPE_TRACK_START)) { + widget->track.cursor = t_cursor; + widget->track.dx = dx; + widget->track.dl = dl; + } + } + + if (widget->track.cursor) { + if (evt & EVE_TOUCH_ETYPE_TRACK) eve_textw_cursor_set(widget, widget->track.cursor, touch->tag + widget->track.dl, eve_page_x(page, touch->x) + widget->track.dx); + ret = 1; + } else { + if (evt & EVE_TOUCH_ETYPE_LPRESS) { + if (widget->cursor2.on) { + // copy + } else if (widget->cursor1.on) { + if (t_cursor && (dl == 0)) { + // paste + } else { + eve_textw_cursor_set(widget, &widget->cursor2, touch->tag, eve_page_x(page, touch->x)); + } + } else { + // select + } + ret = 1; + } + if ((evt & EVE_TOUCH_ETYPE_POINT_UP) && !(touch->eevt & (EVE_TOUCH_EETYPE_TRACK_XY | EVE_TOUCH_EETYPE_ABORT | EVE_TOUCH_EETYPE_LPRESS))) { + eve_textw_cursor_set(widget, &widget->cursor1, touch->tag_up, eve_page_x(page, touch->x0)); + if (widget->cursor2.on) eve_textw_cursor_clear(widget, &widget->cursor2); + set_focus(widget, &widget->cursor1); + ret = 1; + } + } + + if (evt & EVE_TOUCH_ETYPE_TRACK_STOP) { + widget->track.cursor = NULL; + widget->track.dx = 0; + widget->track.dl = 0; + } + + return ret; +} + +void eve_textw_putc(void *w, int c) { + EVETextWidget *widget = (EVETextWidget *)w; + EVEWidget *_widget = &widget->w; + EVETextCursor *cursor1 = &widget->cursor1; + EVETextCursor *cursor2 = &widget->cursor2; + utf8_t *text; + utf8_t *clipb = NULL; + int i, r; + int ins_c = 0, del_c = 0; + int ch_w = 0; + + if (c == EVE_PAGE_KBDCH_CLOSE) { + if (cursor1->on) eve_textw_cursor_clear(widget, cursor1); + if (cursor2->on) eve_textw_cursor_clear(widget, cursor2); + return; + } + + if (!cursor1->on) return; + + if (!cursor2->on && ((c == CH_BS) || (c == CH_DEL))) { + utf32_t uc; + + 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; + 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) { + int rv, clipb_len = 0; + + clipb = eve_clipb_get(); + if (clipb) { + rv = utf8_verify(clipb, EVE_CLIPB_SIZE_BUF, &clipb_len); + if (rv != UTF_OK) { + clipb = NULL; + clipb_len = 0; + } + } + ins_c = clipb_len; + 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 = utf8_buf[0]; + } + c1->ch += ins_c; + } + if (c1 == cursor2) widget->cursor1 = widget->cursor2; + if (cursor2->on) eve_textw_cursor_clear(widget, cursor2); + } + + if ((ins_c == 0) && (del_c == 0)) return; + + widget->text_len += ins_c - del_c; + for (i=cursor1->line; i<widget->line_len; i++) { + widget->line[i] += ins_c - del_c; + } + + r = cursor1->line; + if (cursor1->line) r = eve_textw_text_update(widget, cursor1->line - 1, 1); + if ((cursor1->line == 0) || (r == cursor1->line - 1)) r = eve_textw_text_update(widget, cursor1->line, 1); + + if (cursor1->line && (cursor1->ch < LINE_START(widget, cursor1->line))) { + cursor1->line--; + eve_textw_cursor_update(widget, cursor1); + set_focus(widget, cursor1); + } else if (cursor1->ch > LINE_END(widget, cursor1->line)) { + while (cursor1->ch > LINE_END(widget, cursor1->line)) cursor1->line++; + eve_textw_cursor_update(widget, cursor1); + set_focus(widget, cursor1); + } else { + cursor1->x += ch_w; + } +} + +uint16_t eve_textw_text_update(EVETextWidget *widget, uint16_t line, int uievt) { + int i; + 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; + EVEPage *page = _widget->page; + + word_w = 0; + line_w = 0; + line_b = LINE_EMPTY; + + 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; + widget->line[line] = i; + line++; + if ((ch == '\0') || (line == widget->line_size)) break; + word_w = 0; + line_w = 0; + line_b = LINE_EMPTY; + } else if (ch == ' ') { + word_w = 0; + line_w += ch_w; + line_b = i; + } + } else { + word_w += ch_w; + line_w += ch_w; + } + if ((line_w > _widget->g.w) && (line_b != LINE_EMPTY)) { + if (widget->line[line] == line_b) return line; + widget->line[line] = line_b; + line++; + if (line == widget->line_size) { + i = line_b; + break; + } + line_w = word_w; + line_b = LINE_EMPTY; + } + i += ch_l; + } + + for (i=line; i<widget->line_size; i++) { + widget->line[i] = LINE_EMPTY; + } + + if (uievt && (widget->line_len != line)) { + eve_view_uievt_push(&page->v, EVE_UIEVT_WIDGET_UPDATE_G, _widget); + } + widget->line_len = line; + _widget->g.h = (widget->line_len + 1) * widget->font->h; + + return line; +} + +void eve_textw_cursor_update(EVETextWidget *widget, EVETextCursor *cursor) { + int i = LINE_START(widget, cursor->line); + uint16_t x = 0; + utf32_t ch; + uint8_t ch_l; + EVEWidget *_widget = &widget->w; + + 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; +} + +void eve_textw_cursor_set(EVETextWidget *widget, EVETextCursor *cursor, uint8_t tag, int16_t x) { + 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_NOTAG) || (tag < _widget->tagN))) c_line = tag - _widget->tag0 + widget->line0; + if (c_line < widget->line_len) { + cursor->line = c_line; + } else if (c_line == widget->line_len) { + cursor->line = c_line - 1; + } else if (!cursor->on) { + return; + } + + x -= _widget->g.x; + + _x = 0; + _d = x; + 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) { + _x -= ch_w; + i -= ch_l; + } + break; + } else { + _d = x - _x; + } + } + cursor->x = _x; + cursor->ch = i; + cursor->on = 1; +} + +void eve_textw_cursor_clear(EVETextWidget *widget, EVETextCursor *cursor) { + cursor->on = 0; +} diff --git a/fw/fe310/eos/eve/widget/textw.h b/fw/fe310/eos/eve/widget/textw.h new file mode 100644 index 0000000..570bba8 --- /dev/null +++ b/fw/fe310/eos/eve/widget/textw.h @@ -0,0 +1,46 @@ +#include <stdint.h> + +typedef struct EVETextCursor { + char on; + uint16_t x; + uint16_t line; + uint16_t ch; +} EVETextCursor; + +typedef struct EVETextWidget { + EVEWidget w; + EVEFont *font; + utf8_t *text; + uint16_t text_size; + uint16_t text_len; + uint16_t *line; + uint16_t line_size; + uint16_t line_len; + EVETextCursor cursor1; + EVETextCursor cursor2; + uint16_t line0; + struct { + EVETextCursor *cursor; + short dx; + short dl; + } track; +} EVETextWidget; + +typedef struct EVETextSpec { + EVEFont *font; + uint16_t text_size; + uint16_t line_size; +} EVETextSpec; + +int eve_textw_create(EVETextWidget *widget, EVERect *g, EVEPage *page, EVETextSpec *spec); +void eve_textw_init(EVETextWidget *widget, EVERect *g, EVEPage *page, EVEFont *font, utf8_t *text, uint16_t text_size, uint16_t *line, uint16_t line_size); +void eve_textw_destroy(EVETextWidget *widget); + +uint8_t eve_textw_draw(EVEWidget *_widget, uint8_t tag0); +int eve_textw_touch(EVEWidget *_widget, EVETouch *touch, uint16_t evt); +void eve_textw_putc(void *_w, int c); + +uint16_t eve_textw_text_update(EVETextWidget *widget, uint16_t line, int uievt); +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/fw/fe310/eos/eve/widget/widget.c b/fw/fe310/eos/eve/widget/widget.c new file mode 100644 index 0000000..96d2ddf --- /dev/null +++ b/fw/fe310/eos/eve/widget/widget.c @@ -0,0 +1,77 @@ +#include <stdlib.h> +#include <string.h> + +#include "eve.h" +#include "eve_kbd.h" +#include "eve_font.h" + +#include "screen/window.h" +#include "screen/page.h" + +#include "widgets.h" + +static const size_t _widget_size[] = { + 0, + sizeof(EVEFreeWidget), + sizeof(EVESpacerWidget), + sizeof(EVEPageWidget), + sizeof(EVEStrWidget), + sizeof(EVETextWidget), + sizeof(EVESelectWidget), +}; + +static const eve_widget_create_t _widget_create[] = { + NULL, + (eve_widget_create_t)eve_freew_create, + (eve_widget_create_t)eve_spacerw_create, + (eve_widget_create_t)eve_pagew_create, + (eve_widget_create_t)eve_strw_create, + (eve_widget_create_t)eve_textw_create, + (eve_widget_create_t)eve_selectw_create, +}; + +static const eve_widget_destroy_t _widget_destroy[] = { + NULL, + NULL, + NULL, + NULL, + (eve_widget_destroy_t)eve_strw_destroy, + (eve_widget_destroy_t)eve_textw_destroy, + (eve_widget_destroy_t)eve_selectw_destroy, +}; + +void eve_widget_init(EVEWidget *widget, uint8_t type, EVERect *g, EVEPage *page, eve_widget_draw_t draw, eve_widget_touch_t touch, eve_kbd_input_handler_t putc) { + if (g) widget->g = *g; + widget->page = page; + widget->draw = draw; + widget->touch = touch; + widget->putc = putc; + widget->type = type; +} + +size_t eve_widget_size(uint8_t type) { + return _widget_size[type]; +} + +void eve_widget_set_label(EVEWidget *widget, EVELabel *label) { + widget->label = label; +} + +EVEWidget *eve_widget_next(EVEWidget *widget) { + char *_w = (char *)widget; + return (EVEWidget *)(_w + _widget_size[widget->type]); +} + +int eve_widget_create(EVEWidget *widget, uint8_t type, EVERect *g, EVEPage *page, EVEWidgetSpecT *spec) { + return _widget_create[type](widget, g, page, spec); +} + +void eve_widget_destroy(EVEWidget *widget) { + if (_widget_destroy[widget->type]) _widget_destroy[widget->type](widget); +} + +void eve_widget_focus(EVEWidget *widget, EVERect *rect) { + EVEPage *page = widget->page; + + eve_page_focus_widget(page, widget, rect); +} diff --git a/fw/fe310/eos/eve/widget/widget.h b/fw/fe310/eos/eve/widget/widget.h new file mode 100644 index 0000000..f081b4c --- /dev/null +++ b/fw/fe310/eos/eve/widget/widget.h @@ -0,0 +1,31 @@ +#include <stdint.h> + +#define EVE_WIDGET_TYPE_FREE 1 +#define EVE_WIDGET_TYPE_SPACER 2 +#define EVE_WIDGET_TYPE_PAGE 3 +#define EVE_WIDGET_TYPE_STR 4 +#define EVE_WIDGET_TYPE_TEXT 5 +#define EVE_WIDGET_TYPE_SELECT 6 + +struct EVEWidget; + +typedef uint8_t (*eve_widget_draw_t) (struct EVEWidget *, uint8_t); +typedef int (*eve_widget_touch_t) (struct EVEWidget *, EVETouch *, uint16_t); + +typedef struct EVEWidget { + EVERect g; + EVEPage *page; + eve_widget_draw_t draw; + eve_widget_touch_t touch; + eve_kbd_input_handler_t putc; + EVELabel *label; + uint8_t type; + uint8_t tag0; + uint8_t tagN; +} EVEWidget; + +void eve_widget_init(EVEWidget *widget, uint8_t type, EVERect *g, EVEPage *page, eve_widget_draw_t draw, eve_widget_touch_t touch, eve_kbd_input_handler_t putc); +size_t eve_widget_size(uint8_t type); +void eve_widget_set_label(EVEWidget *widget, EVELabel *label); +EVEWidget *eve_widget_next(EVEWidget *widget); +void eve_widget_focus(EVEWidget *widget, EVERect *rect);
\ No newline at end of file diff --git a/fw/fe310/eos/eve/widget/widgets.h b/fw/fe310/eos/eve/widget/widgets.h new file mode 100644 index 0000000..2f8d3ca --- /dev/null +++ b/fw/fe310/eos/eve/widget/widgets.h @@ -0,0 +1,39 @@ +#include "label.h" +#include "widget.h" + +#include "freew.h" +#include "spacerw.h" +#include "pagew.h" +#include "strw.h" +#include "textw.h" +#include "selectw.h" + +typedef union EVEWidgetSpecT { + EVEFreeSpec free; + EVESpacerSpec spacer; + EVEPageSpec page; + EVEStrSpec str; + EVETextSpec text; + EVESelectSpec select; +} EVEWidgetSpecT; + +typedef struct EVELabelSpec { + EVERect g; + EVEFont *font; + char *title; +} APPLabelSpec; + +typedef struct EVEWidgetSpec { + APPLabelSpec label; + struct { + EVERect g; + EVEWidgetSpecT spec; + uint8_t type; + } widget; +} EVEWidgetSpec; + +typedef int (*eve_widget_create_t) (EVEWidget *, EVERect *, EVEPage *, EVEWidgetSpecT *); +typedef void (*eve_widget_destroy_t) (EVEWidget *); + +int eve_widget_create(EVEWidget *widget, uint8_t type, EVERect *g, EVEPage *page, EVEWidgetSpecT *spec); +void eve_widget_destroy(EVEWidget *widget); |