/* * Copyright (c) 2007, Takahide Matsutsuka. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $Id: ctk-conio_arch-source.c,v 1.2 2007/09/29 04:10:00 matsutsuka Exp $ * */ /* * \file * This is an original source file for * ctk-conio_arch.c and ctk-conio_arch-asm.S * \author * Takahide Matsutsuka */ #include "ctk/ctk.h" #include "ctk/ctk-draw.h" #include "contiki-conf.h" #include "ctk/ctk_arch.h" #include #ifndef NULL #define NULL (void *)0 #endif /*---------------------------------------------------------------------------*/ static char cursx, cursy; static unsigned char reversed; static char cy1, cy2; unsigned char ctk_draw_windowtitle_height = 1; /*---------------------------------------------------------------------------*/ #define revers(c) reversed = c #define clip(y1, y2) cy1 = y1; cy2 = y2 #define OFFSET(x, y) y * SCREEN_WIDTH + x /*---------------------------------------------------------------------------*/ void cputc(char c) { if (cursy >= cy1 && cursy <= cy2 && cursy >= 0 && cursy <= SCREEN_HEIGHT && cursx >= 0 && cursx < SCREEN_WIDTH) { unsigned int offset = OFFSET(cursx, cursy); *((char *) VRAM_CHAR + offset) = c; *((char *) VRAM_ATTR + offset) = reversed ? COLOR_REVERSED : COLOR_NORMAL; } cursx++; } /*---------------------------------------------------------------------------*/ void cputs(char *str) { while (*str != 0) { cputc(*str); str++; } } /*---------------------------------------------------------------------------*/ void cputsn(char *str, unsigned char len) { while ((len > 0) && (*str != 0)) { cputc(*str); str++; len--; } } /*---------------------------------------------------------------------------*/ void chline(unsigned char length) { while (length > 0) { cputc(CH_HOLILINE); length--; } } /*---------------------------------------------------------------------------*/ /* #define cvline(l) while (l > 0) { cputc(CH_VERTLINE); */ /* ++cursy; --cursx; l--; } */ void cvline(unsigned char length) { while (length > 0) { cputc(CH_VERTLINE); ++cursy; --cursx; length--; } } /*---------------------------------------------------------------------------*/ void gotoxy(unsigned char x, unsigned char y) { cursx = x; cursy = y; } /*---------------------------------------------------------------------------*/ void clearTo(char x) { while (cursx < x) { cputc(CH_SPACE); } cursx = x; } /*---------------------------------------------------------------------------*/ void ctk_draw_clear(unsigned char clipy1, unsigned char clipy2) { while (clipy1 < clipy2) { gotoxy(0, clipy1); clearTo(SCREEN_WIDTH); clipy1++; } } /*---------------------------------------------------------------------------*/ void ctk_draw_init(void) { clip(0, SCREEN_HEIGHT); ctk_draw_clear(0, SCREEN_HEIGHT); } /*---------------------------------------------------------------------------*/ /* * w: widget * x, y: screen position of client drawing area (left, top) * clipx, clipy: screen position of client drawing area (right, bottom) * clipy1, clipy2: min/max y position of screen * focus: boolean */ void draw_widget(struct ctk_widget *w, unsigned char x, unsigned char y, unsigned char focus) { unsigned char xpos, ypos, xscroll; unsigned char i, j; char c, *text; #if CTK_CONF_ICONS unsigned char len; #endif /* CTK_CONF_ICONS */ xpos = x + w->x; ypos = y + w->y; revers(focus & CTK_FOCUS_WIDGET); gotoxy(xpos, ypos); if (w->type == CTK_WIDGET_SEPARATOR) { chline(w->w); } else if (w->type == CTK_WIDGET_LABEL) { text = w->widget.label.text; for(i = 0; i < w->h; ++i) { gotoxy(xpos, ypos); cputsn(text, w->w); clearTo(xpos + w->w); ++ypos; text += w->w; } } else if (w->type == CTK_WIDGET_BUTTON) { cputc('['); cputsn(w->widget.button.text, w->w); cputc(']'); } else if (w->type == CTK_WIDGET_HYPERLINK) { cputsn(w->widget.hyperlink.text, w->w); } else if (w->type == CTK_WIDGET_TEXTENTRY) { text = w->widget.textentry.text; xscroll = 0; if(w->widget.textentry.xpos >= w->w - 1) { xscroll = w->widget.textentry.xpos - w->w + 1; } for(j = 0; j < w->h; ++j) { gotoxy(xpos, ypos); if(w->widget.textentry.state == CTK_TEXTENTRY_EDIT && w->widget.textentry.ypos == j) { revers(0); cputc('>'); for(i = 0; i < w->w; ++i) { c = text[i + xscroll]; revers(i == w->widget.textentry.xpos - xscroll); cputc((c == 0) ? CH_SPACE : c); } revers(0); cputc('<'); } else { cputc(CH_VERTLINE); cputsn(text, w->w); clearTo(xpos + w->w + 1); cputc(CH_VERTLINE); } ++ypos; text += w->w; } #if CTK_CONF_ICONS } else if (w->type == CTK_WIDGET_ICON) { if(w->widget.icon.textmap != NULL) { for(i = 0; i < 3; ++i) { gotoxy(xpos, ypos); cputc(w->widget.icon.textmap[0 + 3 * i]); cputc(w->widget.icon.textmap[1 + 3 * i]); cputc(w->widget.icon.textmap[2 + 3 * i]); ++ypos; } x = xpos; len = strlen(w->widget.icon.title); if(x + len >= SCREEN_WIDTH) { x = SCREEN_WIDTH - len; } gotoxy(x, ypos); cputs(w->widget.icon.title); } #endif /* CTK_CONF_ICONS */ } revers(0); } /*---------------------------------------------------------------------------*/ void ctk_draw_widget(struct ctk_widget *w, unsigned char focus, unsigned char clipy1, unsigned char clipy2) { struct ctk_window *win = w->window; unsigned char posx, posy; clip(clipy1, clipy2); posx = win->x + 1; posy = win->y + 2; if(w == win->focused) { focus |= CTK_FOCUS_WIDGET; } draw_widget(w, posx, posy, focus); } /*---------------------------------------------------------------------------*/ void ctk_draw_clear_window(struct ctk_window *window, unsigned char focus, unsigned char clipy1, unsigned char clipy2) { unsigned char i; unsigned char x1, x2, y1, y2; x1 = window->x + 1; x2 = x1 + window->w; y1 = window->y + 2; y2 = y1 + window->h; for(i = y1; i < y2; ++i) { gotoxy(x1, i); clearTo(x2); } } /*---------------------------------------------------------------------------*/ void draw_window_sub(struct ctk_window *window, unsigned char focus) { unsigned char x, y; unsigned char x1, y1, x2; struct ctk_widget *w; unsigned char wfocus; x = window->x; y = window->y + 1; x1 = x + 1; y1 = y + 1; x2 = x1 + window->w; // |_ gotoxy(x, y1); cvline(window->h); cputc(CH_LLCORNER); chline(window->w); cputc(CH_LRCORNER); // - gotoxy(x, y); cputc(CH_ULCORNER); chline(window->w); cputc(CH_URCORNER); // | gotoxy(x2, y1); cvline(window->h); /* Draw inactive widgets. */ for(w = window->inactive; w != NULL; w = w->next) { draw_widget(w, x1, y1, focus); } /* Draw active widgets. */ for(w = window->active; w != NULL; w = w->next) { wfocus = focus; if(w == window->focused) { wfocus |= CTK_FOCUS_WIDGET; } draw_widget(w, x1, y1, wfocus); } } /*---------------------------------------------------------------------------*/ void ctk_draw_window(struct ctk_window *window, unsigned char focus, unsigned char clipy1, unsigned char clipy2, unsigned char draw_borders) { clip(clipy1, clipy2); focus = focus & CTK_FOCUS_WINDOW; draw_window_sub(window, focus); } /*---------------------------------------------------------------------------*/ void ctk_draw_dialog(struct ctk_window *dialog) { clip(0, SCREEN_HEIGHT); ctk_draw_clear_window(dialog, 0, 0, SCREEN_HEIGHT); draw_window_sub(dialog, CTK_FOCUS_DIALOG); } /*---------------------------------------------------------------------------*/ #if CTK_CONF_MENUS void draw_menu(struct ctk_menu *m, struct ctk_menu *open) { #if CC_CONF_UNSIGNED_CHAR_BUGS unsigned char x2; unsigned int x, y; #else unsigned char x2; unsigned char x, y; #endif x = cursx; cputs(m->title); cputc(CH_SPACE); if (m == open) { x2 = cursx; if(x + CTK_CONF_MENUWIDTH > SCREEN_WIDTH) { x = SCREEN_WIDTH - CTK_CONF_MENUWIDTH; } for(y = 0; y < m->nitems; y++) { if(y == m->active) { revers(0); } gotoxy(x, y + 1); if(m->items[y].title[0] == '-') { chline(CTK_CONF_MENUWIDTH); } else { cputs(m->items[y].title); } clearTo(x + CTK_CONF_MENUWIDTH); revers(1); } gotoxy(x2, 0); } } /*---------------------------------------------------------------------------*/ void ctk_draw_menus(struct ctk_menus *menus) { struct ctk_menu *m; clip(0, SCREEN_HEIGHT); /* Draw menus */ gotoxy(0, 0); revers(1); for(m = menus->menus->next; m != NULL; m = m->next) { draw_menu(m, menus->open); } clearTo(SCREEN_WIDTH - strlen(menus->desktopmenu->title) - 1); /* Draw desktopmenu */ draw_menu(menus->desktopmenu, menus->open); revers(0); } #endif /* CTK_CONF_MENUS */ /*---------------------------------------------------------------------------*/ /* Returns width and height of screen. */ unsigned char ctk_draw_width(void) { return SCREEN_WIDTH; } unsigned char ctk_draw_height(void) { return SCREEN_HEIGHT; }