summaryrefslogtreecommitdiff
path: root/code/fe310/eos/eve/screen
diff options
context:
space:
mode:
Diffstat (limited to 'code/fe310/eos/eve/screen')
-rw-r--r--code/fe310/eos/eve/screen/Makefile17
-rw-r--r--code/fe310/eos/eve/screen/font.c61
-rw-r--r--code/fe310/eos/eve/screen/font.h14
-rw-r--r--code/fe310/eos/eve/screen/form.c109
-rw-r--r--code/fe310/eos/eve/screen/form.h15
-rw-r--r--code/fe310/eos/eve/screen/kbdwin.c39
-rw-r--r--code/fe310/eos/eve/screen/kbdwin.h14
-rw-r--r--code/fe310/eos/eve/screen/page.c100
-rw-r--r--code/fe310/eos/eve/screen/page.h30
-rw-r--r--code/fe310/eos/eve/screen/screen.c104
-rw-r--r--code/fe310/eos/eve/screen/screen.h21
-rw-r--r--code/fe310/eos/eve/screen/window.c116
-rw-r--r--code/fe310/eos/eve/screen/window.h36
13 files changed, 676 insertions, 0 deletions
diff --git a/code/fe310/eos/eve/screen/Makefile b/code/fe310/eos/eve/screen/Makefile
new file mode 100644
index 0000000..f6115df
--- /dev/null
+++ b/code/fe310/eos/eve/screen/Makefile
@@ -0,0 +1,17 @@
+include ../../../common.mk
+
+CFLAGS += -I. -I.. -I../..
+
+obj = font.o screen.o window.o kbdwin.o page.o form.o
+
+
+%.o: %.c %.h
+ $(CC) $(CFLAGS) -c $<
+
+%.o: %.S
+ $(CC) $(CFLAGS) -c $<
+
+all: $(obj)
+
+clean:
+ rm -f *.o \ No newline at end of file
diff --git a/code/fe310/eos/eve/screen/font.c b/code/fe310/eos/eve/screen/font.c
new file mode 100644
index 0000000..da02983
--- /dev/null
+++ b/code/fe310/eos/eve/screen/font.c
@@ -0,0 +1,61 @@
+#include <stdlib.h>
+
+#include "eve.h"
+#include "unicode.h"
+
+#include "font.h"
+
+void eve_font_init(EVEFont *font, uint8_t font_id) {
+ uint32_t p;
+
+ p = eve_read32(EVE_ROM_FONT_ADDR);
+ p += (148 * (font_id - 16));
+ font->id = font_id;
+ font->w = eve_read32(p + 136);
+ font->h = eve_read32(p + 140);
+ eve_readb(p, font->w_ch, 128);
+}
+
+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;
+
+ 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, utf8_t *buf, uint16_t buf_len) {
+ int i = 0;
+ uint16_t r = 0;
+ 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;
+}
+
+uint8_t eve_font_h(EVEFont *font) {
+ return font->h;
+} \ No newline at end of file
diff --git a/code/fe310/eos/eve/screen/font.h b/code/fe310/eos/eve/screen/font.h
new file mode 100644
index 0000000..aff038c
--- /dev/null
+++ b/code/fe310/eos/eve/screen/font.h
@@ -0,0 +1,14 @@
+#include <stdint.h>
+
+typedef struct EVEFont {
+ uint8_t id;
+ uint8_t w;
+ uint8_t h;
+ uint8_t w_ch[128];
+} EVEFont;
+
+void eve_font_init(EVEFont *font, uint8_t font_id);
+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
new file mode 100644
index 0000000..f7d37ee
--- /dev/null
+++ b/code/fe310/eos/eve/screen/form.c
@@ -0,0 +1,109 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "eve.h"
+#include "eve_kbd.h"
+#include "unicode.h"
+
+#include "screen.h"
+#include "window.h"
+#include "page.h"
+#include "font.h"
+#include "form.h"
+
+#include "widget/label.h"
+#include "widget/widget.h"
+
+int eve_form_init(EVEForm *form, EVEWindow *window, EVEWidget *widget, uint16_t widget_size, eve_page_open_t open, eve_page_close_t close) {
+ memset(form, 0, sizeof(EVEForm));
+ eve_page_init(&form->p, window, eve_form_touch, eve_form_draw, open, close, eve_form_handle_evt, eve_form_update_g);
+ form->widget = widget;
+ form->widget_size = widget_size;
+ eve_form_update_g(&form->p, NULL);
+}
+
+int eve_form_touch(EVEView *v, uint8_t tag0, int touch_idx) {
+ EVEForm *form = (EVEForm *)v;
+ EVEWidget *widget = form->widget;
+ int i, ret = 0;
+
+ if (touch_idx == 0) {
+ EVETouch *t;
+ uint16_t evt;
+
+ t = eve_touch_evt(tag0, touch_idx, form->p.v.window->tag, 1, &evt);
+ if (t && evt) {
+ eve_form_handle_evt(&form->p, NULL, t, evt, tag0, touch_idx);
+ if ((evt & EVE_TOUCH_ETYPE_POINT_UP) && (t->eevt == 0)) eve_page_set_focus(&form->p, NULL, NULL);
+ ret = 1;
+ }
+ }
+ for (i=0; i<form->widget_size; i++) {
+ if (eve_page_rect_visible(&form->p, &widget->g)) {
+ int r = widget->touch(widget, &form->p, tag0, touch_idx);
+ ret = ret || r;
+ }
+ widget = eve_widget_next(widget);
+ }
+
+ return ret;
+}
+
+uint8_t eve_form_draw(EVEView *v, uint8_t tag0) {
+ EVEForm *form = (EVEForm *)v;
+ EVEWidget *widget = form->widget;
+ int i;
+ uint8_t tagN = tag0;
+
+ eve_cmd_dl(SAVE_CONTEXT());
+ eve_cmd_dl(VERTEX_FORMAT(0));
+ eve_cmd_dl(VERTEX_TRANSLATE_X(eve_page_scr_x(&form->p, 0) * 16));
+ eve_cmd_dl(VERTEX_TRANSLATE_Y(eve_page_scr_y(&form->p, 0) * 16));
+
+ for (i=0; i<form->widget_size; i++) {
+ if (widget->label && eve_page_rect_visible(&form->p, &widget->label->g)) {
+ eve_cmd_dl(TAG_MASK(0));
+ eve_label_draw(widget->label);
+ eve_cmd_dl(TAG_MASK(1));
+ }
+ if (eve_page_rect_visible(&form->p, &widget->g)) tagN = widget->draw(widget, &form->p, tagN);
+ widget = eve_widget_next(widget);
+ }
+
+ eve_cmd_dl(RESTORE_CONTEXT());
+
+ for (i=tag0; i<tagN; i++) {
+ eve_touch_set_opt(i, eve_touch_get_opt(i) | EVE_TOUCH_OPT_TRACK | EVE_TOUCH_OPT_TRACK_XY | EVE_TOUCH_OPT_TRACK_EXT);
+ }
+ if (v->window->tag != EVE_TAG_NOTAG) eve_touch_set_opt(v->window->tag, eve_touch_get_opt(v->window->tag) | EVE_TOUCH_OPT_TRACK | EVE_TOUCH_OPT_TRACK_XY | EVE_TOUCH_OPT_TRACK_EXT);
+
+ return tagN;
+}
+
+void eve_form_handle_evt(EVEPage *page, EVEWidget *widget, EVETouch *touch, uint16_t evt, uint8_t tag0, int touch_idx) {
+ /*
+ if (evt & EVE_TOUCH_ETYPE_TRACK_Y) {
+ // do scroll
+ } else {
+ // go back / forward
+ }
+ */
+}
+
+void eve_form_update_g(EVEPage *page, EVEWidget *_widget) {
+ EVEForm *form = (EVEForm *)page;
+ EVEWidget *widget = form->widget;
+ int i;
+ uint16_t h = 0;
+
+ for (i=0; i<form->widget_size; i++) {
+ if (widget->label) {
+ widget->label->g.y = h;
+ if (widget->label->g.w + widget->g.w > form->p.v.window->g.w) h += widget->label->g.h;
+ }
+ widget->g.y = h;
+ h += widget->g.h;
+
+ widget = eve_widget_next(widget);
+ }
+}
diff --git a/code/fe310/eos/eve/screen/form.h b/code/fe310/eos/eve/screen/form.h
new file mode 100644
index 0000000..7742b8c
--- /dev/null
+++ b/code/fe310/eos/eve/screen/form.h
@@ -0,0 +1,15 @@
+#include <stdint.h>
+
+struct EVEWidget;
+
+typedef struct EVEForm {
+ EVEPage p;
+ struct EVEWidget *widget;
+ uint16_t widget_size;
+} EVEForm;
+
+int eve_form_init(EVEForm *form, EVEWindow *window, struct EVEWidget *widget, uint16_t widget_size, eve_page_open_t open, eve_page_close_t close);
+int eve_form_touch(EVEView *v, uint8_t tag0, int touch_idx);
+uint8_t eve_form_draw(EVEView *v, uint8_t tag0);
+void eve_form_handle_evt(EVEPage *page, struct EVEWidget *widget, EVETouch *touch, uint16_t evt, uint8_t tag0, int touch_idx);
+void eve_form_update_g(EVEPage *page, struct EVEWidget *widget);
diff --git a/code/fe310/eos/eve/screen/kbdwin.c b/code/fe310/eos/eve/screen/kbdwin.c
new file mode 100644
index 0000000..decedad
--- /dev/null
+++ b/code/fe310/eos/eve/screen/kbdwin.c
@@ -0,0 +1,39 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "eve.h"
+#include "eve_kbd.h"
+
+#include "screen.h"
+#include "window.h"
+#include "kbdwin.h"
+
+static int kbdwin_touch(EVEView *v, uint8_t tag0, int touch_idx) {
+ EVEKbdView *k_view = (EVEKbdView *)v;
+
+ return eve_kbd_touch(&k_view->kbd, tag0, touch_idx);
+}
+
+static uint8_t kbdwin_draw(EVEView *v, uint8_t tag0) {
+ EVEKbdView *k_view = (EVEKbdView *)v;
+
+ eve_kbd_draw(&k_view->kbd);
+ return tag0;
+}
+
+void eve_kbdwin_init(EVEKbdWin *kbd_win, EVEScreen *screen) {
+ EVEKbd *kbd = &kbd_win->view.kbd;
+
+ kbd_win->view.v.touch = kbdwin_touch;
+ kbd_win->view.v.draw = kbdwin_draw;
+ eve_kbd_init(kbd, NULL, screen->mem_next, &screen->mem_next);
+ eve_window_init(&kbd_win->win, &kbd->g, &kbd_win->view.v, screen);
+}
+
+void eve_kbdwin_append(EVEKbdWin *kbd_win) {
+ EVEKbd *kbd = &kbd_win->view.kbd;
+ EVEWindow *window = &kbd_win->win;
+
+ eve_screen_set_kbd(window->screen, kbd);
+ eve_window_append(window);
+}
diff --git a/code/fe310/eos/eve/screen/kbdwin.h b/code/fe310/eos/eve/screen/kbdwin.h
new file mode 100644
index 0000000..2cc14d9
--- /dev/null
+++ b/code/fe310/eos/eve/screen/kbdwin.h
@@ -0,0 +1,14 @@
+#include <stdint.h>
+
+typedef struct EVEKbdView {
+ EVEView v;
+ EVEKbd kbd;
+} EVEKbdView;
+
+typedef struct EVEKbdWin {
+ EVEWindow win;
+ EVEKbdView view;
+} EVEKbdWin;
+
+void eve_kbdwin_init(EVEKbdWin *kbd_win, EVEScreen *screen);
+void eve_kbdwin_append(EVEKbdWin *kbd_win);
diff --git a/code/fe310/eos/eve/screen/page.c b/code/fe310/eos/eve/screen/page.c
new file mode 100644
index 0000000..f54056c
--- /dev/null
+++ b/code/fe310/eos/eve/screen/page.c
@@ -0,0 +1,100 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "eve.h"
+#include "eve_kbd.h"
+#include "unicode.h"
+
+#include "screen.h"
+#include "window.h"
+#include "page.h"
+#include "font.h"
+
+#include "widget/label.h"
+#include "widget/widget.h"
+
+#define CH_EOF 0x1a
+
+void eve_page_init(EVEPage *page, EVEWindow *window, eve_view_touch_t touch, eve_view_draw_t draw, eve_page_open_t open, eve_page_close_t close, eve_page_evt_handler_t handle_evt, eve_page_g_updater_t update_g) {
+ memset(page, 0, sizeof(EVEPage));
+ page->v.touch = touch;
+ page->v.draw = draw;
+ page->v.window = window;
+ page->open = open;
+ page->close = close;
+ page->handle_evt = handle_evt;
+ page->update_g = update_g;
+ page->widget_f = NULL;
+ window->view = (EVEView *)page;
+}
+
+int16_t eve_page_x(EVEPage *page, int16_t x) {
+ return x + page->win_x - page->v.window->g.x;
+}
+
+int16_t eve_page_y(EVEPage *page, int16_t y) {
+ return y + page->win_y - page->v.window->g.y;
+}
+
+int16_t eve_page_scr_x(EVEPage *page, int16_t x) {
+ return x - page->win_x + page->v.window->g.x;
+}
+
+int16_t eve_page_scr_y(EVEPage *page, int16_t y) {
+ return y - page->win_y + page->v.window->g.y;
+}
+
+void eve_page_set_focus(EVEPage *page, EVEWidget *widget, EVERect *f) {
+ if (page->widget_f != widget) {
+ EVEKbd *kbd = eve_screen_get_kbd(page->v.window->screen);
+
+ if (kbd) {
+ EVEWidget *widget_f = page->widget_f;
+
+ if (widget_f && widget_f->putc) {
+ eve_screen_hide_kbd(page->v.window->screen);
+ widget_f->putc(page, CH_EOF);
+ }
+ if (widget && widget->putc) {
+ eve_kbd_set_handler(kbd, widget->putc, page);
+ eve_screen_show_kbd(page->v.window->screen);
+ } else {
+ eve_kbd_set_handler(kbd, NULL, NULL);
+ }
+ }
+ page->widget_f = widget;
+ }
+
+ if (f) {
+ EVERect g;
+
+ eve_window_visible_g(page->v.window, &g);
+ g.x -= page->v.window->g.x;
+ g.y -= page->v.window->g.y;
+
+ if (f->x < page->win_x + g.x) {
+ page->win_x = f->x - g.x;
+ }
+ if (f->y < page->win_y + g.y) {
+ page->win_y = f->y - g.y;
+ }
+ if ((f->x + f->w) > (page->win_x + g.x + g.w)) {
+ page->win_x = (f->x + f->w) - (g.x + g.w);
+ }
+ if ((f->y + f->h) > (page->win_y + g.y + g.h)) {
+ page->win_y = (f->y + f->h) - (g.y + g.h);
+ }
+ }
+}
+
+EVEWidget *eve_page_get_focus(EVEPage *page) {
+ return page->widget_f;
+}
+
+int eve_page_rect_visible(EVEPage *page, EVERect *g) {
+ uint16_t w = page->v.window->g.w;
+ uint16_t h = page->v.window->g.h;
+
+ if (((g->x + g->w) >= page->win_x) && ((g->y + g->h) >= page->win_y) && (g->x <= (page->win_x + w)) && (g->y <= (page->win_y + h))) return 1;
+ return 0;
+}
diff --git a/code/fe310/eos/eve/screen/page.h b/code/fe310/eos/eve/screen/page.h
new file mode 100644
index 0000000..eebedfd
--- /dev/null
+++ b/code/fe310/eos/eve/screen/page.h
@@ -0,0 +1,30 @@
+#include <stdint.h>
+
+struct EVEPage;
+struct EVEWidget;
+
+typedef void (*eve_page_open_t) (struct EVEPage *, struct EVEPage *);
+typedef void (*eve_page_close_t) (struct EVEPage *);
+typedef void (*eve_page_evt_handler_t) (struct EVEPage *, struct EVEWidget *, EVETouch *, uint16_t, uint8_t, int);
+typedef void (*eve_page_g_updater_t) (struct EVEPage *, struct EVEWidget *);
+
+typedef struct EVEPage {
+ EVEView v;
+ int16_t win_x;
+ int16_t win_y;
+ eve_page_open_t open;
+ eve_page_close_t close;
+ eve_page_evt_handler_t handle_evt;
+ eve_page_g_updater_t update_g;
+ struct EVEWidget *widget_f;
+} EVEPage;
+
+void eve_page_init(EVEPage *page, EVEWindow *window, eve_view_touch_t touch, eve_view_draw_t draw, eve_page_open_t open, eve_page_close_t close, eve_page_evt_handler_t handle_evt, eve_page_g_updater_t update_g);
+int16_t eve_page_x(EVEPage *page, int16_t x);
+int16_t eve_page_y(EVEPage *page, int16_t y);
+int16_t eve_page_scr_x(EVEPage *page, int16_t x);
+int16_t eve_page_scr_y(EVEPage *page, int16_t y);
+
+void eve_page_set_focus(EVEPage *page, struct EVEWidget *widget, EVERect *focus);
+struct EVEWidget *eve_page_get_focus(EVEPage *page);
+int eve_page_rect_visible(EVEPage *page, EVERect *g);
diff --git a/code/fe310/eos/eve/screen/screen.c b/code/fe310/eos/eve/screen/screen.c
new file mode 100644
index 0000000..f103b48
--- /dev/null
+++ b/code/fe310/eos/eve/screen/screen.c
@@ -0,0 +1,104 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "eve.h"
+#include "eve_kbd.h"
+
+#include "screen.h"
+#include "window.h"
+#include "kbdwin.h"
+
+int eve_screen_init(EVEScreen *screen, uint16_t w, uint16_t h) {
+ memset(screen, 0, sizeof(EVEScreen));
+ screen->w = w;
+ screen->h = h;
+ screen->mem_next = EVE_RAM_G;
+ eve_touch_set_handler(eve_screen_handle_touch, screen);
+}
+
+void eve_screen_set_kbd(EVEScreen *screen, EVEKbd *kbd) {
+ screen->kbd = kbd;
+}
+
+EVEKbd *eve_screen_get_kbd(EVEScreen *screen) {
+ return screen->kbd;
+}
+
+void eve_screen_show_kbd(EVEScreen *screen) {
+ EVEWindow *win = screen->win_tail;
+ EVEKbd *kbd = eve_screen_get_kbd(screen);
+
+ if (win) win->g.y = screen->h - kbd->g.h;
+}
+
+void eve_screen_hide_kbd(EVEScreen *screen) {
+ EVEWindow *win = screen->win_tail;
+
+ if (win) win->g.y = screen->h;
+}
+
+void eve_screen_draw(EVEScreen *screen) {
+ EVEWindow *win;
+ uint8_t tagN = 0x80;
+
+ eve_cmd_burst_start();
+ eve_cmd_dl(CMD_DLSTART);
+
+ win = screen->win_head;
+ while (win) {
+ if (eve_window_visible(win)) {
+ int16_t x = win->g.x;
+ int16_t y = win->g.y;
+ uint16_t w = win->g.w;
+ uint16_t h = win->g.h;
+
+ if (x < 0) {
+ w += x;
+ x = 0;
+ }
+ if (y < 0) {
+ h += y;
+ y = 0;
+ }
+ if (x + w > screen->w) w = screen->w - x;
+ if (y + h > screen->h) h = screen->h - y;
+ win->tag = tagN;
+
+ if (tagN != EVE_TAG_NOTAG) {
+ eve_cmd_dl(CLEAR_TAG(tagN));
+ tagN++;
+ }
+ eve_cmd_dl(CLEAR_COLOR_RGBC(win->color_bg));
+ eve_cmd_dl(SCISSOR_XY(x, y));
+ eve_cmd_dl(SCISSOR_SIZE(w, h));
+ eve_cmd_dl(CLEAR(1,1,1));
+ eve_cmd_dl(COLOR_RGBC(win->color_fg));
+ tagN = win->view->draw(win->view, tagN);
+ }
+ win = win->next;
+ }
+
+ eve_cmd_dl(DISPLAY());
+ eve_cmd_dl(CMD_SWAP);
+ eve_cmd_burst_end();
+ eve_cmd_exec(1);
+}
+
+void eve_screen_handle_touch(void *s, uint8_t tag0, int touch_idx) {
+ EVEScreen *screen = s;
+ EVEWindow *win;
+
+ eve_touch_clear_opt();
+
+ if (touch_idx >= 0) {
+ win = screen->win_tail;
+ while (win) {
+ if (eve_window_visible(win)) {
+ int a = win->view->touch(win->view, tag0, touch_idx);
+ }
+ win = win->prev;
+ }
+ }
+
+ eve_screen_draw(screen);
+}
diff --git a/code/fe310/eos/eve/screen/screen.h b/code/fe310/eos/eve/screen/screen.h
new file mode 100644
index 0000000..a9745ad
--- /dev/null
+++ b/code/fe310/eos/eve/screen/screen.h
@@ -0,0 +1,21 @@
+#include <stdint.h>
+
+struct EVEWindow;
+
+typedef struct EVEScreen {
+ uint16_t w;
+ uint16_t h;
+ uint32_t mem_next;
+ struct EVEWindow *win_head;
+ struct EVEWindow *win_tail;
+ EVEKbd *kbd;
+} EVEScreen;
+
+int eve_screen_init(EVEScreen *screen, uint16_t w, uint16_t h);
+void eve_screen_set_kbd(EVEScreen *screen, EVEKbd *kbd);
+EVEKbd *eve_screen_get_kbd(EVEScreen *screen);
+void eve_screen_show_kbd(EVEScreen *screen);
+void eve_screen_hide_kbd(EVEScreen *screen);
+
+void eve_screen_draw(EVEScreen *screen);
+void eve_screen_handle_touch(void *s, uint8_t tag0, int touch_idx);
diff --git a/code/fe310/eos/eve/screen/window.c b/code/fe310/eos/eve/screen/window.c
new file mode 100644
index 0000000..e49897f
--- /dev/null
+++ b/code/fe310/eos/eve/screen/window.c
@@ -0,0 +1,116 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "eve.h"
+#include "eve_kbd.h"
+
+#include "screen.h"
+#include "window.h"
+
+#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
+
+void eve_window_init(EVEWindow *window, EVERect *g, EVEView *view, EVEScreen *screen) {
+ memset(window, 0, sizeof(EVEWindow));
+
+ if (g) window->g = *g;
+ if (view) {
+ window->view = view;
+ window->view->window = window;
+ }
+ window->screen = screen;
+ window->color_fg = 0xffffff;
+}
+
+void eve_window_set_color_bg(EVEWindow *window, uint8_t r, uint8_t g, uint8_t b) {
+ window->color_bg = (r << 16) | (g << 8) | b;
+}
+
+void eve_window_set_color_fg(EVEWindow *window, uint8_t r, uint8_t g, uint8_t b) {
+ window->color_fg = (r << 16) | (g << 8) | b;
+}
+
+int eve_window_visible(EVEWindow *window) {
+ if (window->g.x >= window->screen->w) return 0;
+ if (window->g.y >= window->screen->h) return 0;
+ if ((window->g.x + window->g.w) <= 0) return 0;
+ if ((window->g.y + window->g.h) <= 0) return 0;
+ return 1;
+}
+
+void eve_window_visible_g(EVEWindow *window, EVERect *g) {
+ EVEWindow *w = window->next;
+
+ *g = window->g;
+ while (w) {
+ if (eve_window_visible(w)) {
+ if (w->g.x > g->x) g->w = MIN(g->w, w->g.x - g->x);
+ if (w->g.y > g->y) g->h = MIN(g->h, w->g.y - g->y);
+ if (w->g.x + w->g.w < g->x + g->w) {
+ uint16_t x0 = g->w - MIN(g->w, (g->x + g->w) - (w->g.x + w->g.w));
+ g->x += x0;
+ g->w -= x0;
+ }
+ if (w->g.y + w->g.h < g->y + g->h) {
+ uint16_t y0 = g->h - MIN(g->h, (g->y + g->h) - (w->g.y + w->g.h));
+ g->y += y0;
+ g->h -= y0;
+ }
+ }
+ w = w->next;
+ }
+}
+
+void eve_window_append(EVEWindow *window) {
+ EVEScreen *screen = window->screen;
+
+ window->prev = screen->win_tail;
+ if (screen->win_tail) {
+ screen->win_tail->next = window;
+ } else {
+ screen->win_head = window;
+ }
+ screen->win_tail = window;
+}
+
+void eve_window_insert_above(EVEWindow *window, EVEWindow *win_prev) {
+ EVEScreen *screen = window->screen;
+
+ window->prev = win_prev;
+ window->next = win_prev->next;
+
+ if (window->next) {
+ window->next->prev = window;
+ } else {
+ screen->win_tail = window;
+ }
+ win_prev->next = window;
+}
+
+void eve_window_insert_below(EVEWindow *window, EVEWindow *win_next) {
+ EVEScreen *screen = window->screen;
+
+ window->prev = win_next->prev;
+ window->next = win_next;
+
+ win_next->prev = window;
+ if (window->prev) {
+ window->prev->next = window;
+ } else {
+ screen->win_head = window;
+ }
+}
+
+void eve_window_remove(EVEWindow *window) {
+ EVEScreen *screen = window->screen;
+
+ if (window->prev) {
+ window->prev->next = window->next;
+ } else {
+ screen->win_head = window->next;
+ }
+ if (window->next) {
+ window->next->prev = window->prev;
+ } else {
+ screen->win_tail = window->prev;
+ }
+}
diff --git a/code/fe310/eos/eve/screen/window.h b/code/fe310/eos/eve/screen/window.h
new file mode 100644
index 0000000..7f14f18
--- /dev/null
+++ b/code/fe310/eos/eve/screen/window.h
@@ -0,0 +1,36 @@
+#include <stdint.h>
+
+struct EVEView;
+struct EVEWindow;
+
+typedef int (*eve_view_touch_t) (struct EVEView *, uint8_t, int);
+typedef uint8_t (*eve_view_draw_t) (struct EVEView *, uint8_t);
+
+typedef struct EVEView {
+ eve_view_touch_t touch;
+ eve_view_draw_t draw;
+ struct EVEWindow *window;
+} EVEView;
+
+typedef struct EVEWindow {
+ EVERect g;
+ EVEView *view;
+ EVEScreen *screen;
+ struct EVEWindow *next;
+ struct EVEWindow *prev;
+ uint32_t color_bg;
+ uint32_t color_fg;
+ uint8_t tag;
+} EVEWindow;
+
+void eve_window_init(EVEWindow *window, EVERect *g, EVEView *view, EVEScreen *screen);
+void eve_window_set_color_bg(EVEWindow *window, uint8_t r, uint8_t g, uint8_t b);
+void eve_window_set_color_fg(EVEWindow *window, uint8_t r, uint8_t g, uint8_t b);
+
+int eve_window_visible(EVEWindow *window);
+void eve_window_visible_g(EVEWindow *window, EVERect *g);
+
+void eve_window_append(EVEWindow *window);
+void eve_window_insert_above(EVEWindow *window, EVEWindow *win_prev);
+void eve_window_insert_below(EVEWindow *window, EVEWindow *win_next);
+void eve_window_remove(EVEWindow *window);