Contiki 2.6

ctk-conio_arch-source.c

00001 /*
00002  * Copyright (c) 2007, Takahide Matsutsuka.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above
00011  *    copyright notice, this list of conditions and the following
00012  *    disclaimer in the documentation and/or other materials provided
00013  *    with the distribution.
00014  * 3. The name of the author may not be used to endorse or promote
00015  *    products derived from this software without specific prior
00016  *    written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
00019  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00020  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
00022  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00023  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00024  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00025  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00026  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00027  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00028  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  *
00030  * $Id: ctk-conio_arch-source.c,v 1.2 2007/09/29 04:10:00 matsutsuka Exp $
00031  *
00032  */
00033 
00034 /*
00035  * \file
00036  *      This is an original source file for
00037  *      ctk-conio_arch.c and ctk-conio_arch-asm.S
00038  * \author
00039  *      Takahide Matsutsuka <markn@markn.org>
00040  */
00041  
00042 
00043 #include "ctk/ctk.h"
00044 #include "ctk/ctk-draw.h"
00045 #include "contiki-conf.h"
00046 #include "ctk/ctk_arch.h"
00047 #include <string.h>
00048 
00049 #ifndef NULL
00050 #define NULL (void *)0
00051 #endif
00052 
00053 /*---------------------------------------------------------------------------*/
00054 static char cursx, cursy;
00055 static unsigned char reversed;
00056 static char cy1, cy2;
00057 
00058 unsigned char ctk_draw_windowtitle_height = 1;
00059 
00060 /*---------------------------------------------------------------------------*/
00061 #define revers(c) reversed = c
00062 #define clip(y1, y2) cy1 = y1; cy2 = y2
00063 #define OFFSET(x, y) y * SCREEN_WIDTH + x
00064 
00065 /*---------------------------------------------------------------------------*/
00066 void cputc(char c) {
00067   if (cursy >= cy1 && cursy <= cy2
00068       && cursy >= 0 && cursy <= SCREEN_HEIGHT
00069       && cursx >= 0 && cursx < SCREEN_WIDTH) {
00070     unsigned int offset = OFFSET(cursx, cursy);
00071     *((char *) VRAM_CHAR + offset) = c;
00072     *((char *) VRAM_ATTR + offset) = reversed ? COLOR_REVERSED : COLOR_NORMAL;
00073   }
00074   cursx++;
00075 }
00076 
00077 /*---------------------------------------------------------------------------*/
00078 void cputs(char *str) {
00079   while (*str != 0) {
00080     cputc(*str);
00081     str++;
00082   }
00083 }
00084 /*---------------------------------------------------------------------------*/
00085 void cputsn(char *str, unsigned char len) {
00086   while ((len > 0) && (*str != 0)) {
00087     cputc(*str);
00088     str++;
00089     len--;
00090   }
00091 }
00092 /*---------------------------------------------------------------------------*/
00093 void chline(unsigned char length) {
00094   while (length > 0) {
00095     cputc(CH_HOLILINE);
00096     length--;
00097   }
00098 }
00099 /*---------------------------------------------------------------------------*/
00100 /*  #define cvline(l)   while (l > 0) { cputc(CH_VERTLINE); */
00101 /*      ++cursy; --cursx; l--; } */
00102 
00103 void cvline(unsigned char length) {
00104   while (length > 0) {
00105     cputc(CH_VERTLINE);
00106     ++cursy;
00107     --cursx;
00108     length--;
00109   }
00110 }
00111 /*---------------------------------------------------------------------------*/
00112 void gotoxy(unsigned char x, unsigned char y) {
00113   cursx = x;
00114   cursy = y;
00115 }
00116 /*---------------------------------------------------------------------------*/
00117 void clearTo(char x) {
00118   while (cursx < x) {
00119     cputc(CH_SPACE);
00120   }
00121   cursx = x;
00122 }
00123 
00124 /*---------------------------------------------------------------------------*/
00125 void ctk_draw_clear(unsigned char clipy1, unsigned char clipy2) {
00126   while (clipy1 < clipy2) {
00127     gotoxy(0, clipy1);
00128     clearTo(SCREEN_WIDTH);
00129     clipy1++;
00130   }
00131 }
00132 
00133 /*---------------------------------------------------------------------------*/
00134 void ctk_draw_init(void) {
00135   clip(0, SCREEN_HEIGHT);
00136   ctk_draw_clear(0, SCREEN_HEIGHT);
00137 }
00138 /*---------------------------------------------------------------------------*/
00139 /*
00140  * w: widget
00141  * x, y:  screen position of client drawing area (left, top)
00142  * clipx, clipy: screen position of client drawing area (right, bottom)
00143  * clipy1, clipy2: min/max y position of screen
00144  * focus: boolean
00145  */
00146 void
00147 draw_widget(struct ctk_widget *w,
00148             unsigned char x, unsigned char y,
00149             unsigned char focus) {
00150   unsigned char xpos, ypos, xscroll;
00151   unsigned char i, j;
00152   char c, *text;
00153 #if CTK_CONF_ICONS
00154   unsigned char len;
00155 #endif /* CTK_CONF_ICONS */
00156 
00157   xpos = x + w->x;
00158   ypos = y + w->y;
00159     
00160   revers(focus & CTK_FOCUS_WIDGET);
00161   gotoxy(xpos, ypos);
00162 
00163   if (w->type == CTK_WIDGET_SEPARATOR) {
00164     chline(w->w);
00165   } else if (w->type == CTK_WIDGET_LABEL) {
00166     text = w->widget.label.text;
00167     for(i = 0; i < w->h; ++i) {
00168       gotoxy(xpos, ypos);
00169       cputsn(text, w->w);
00170       clearTo(xpos + w->w);
00171       ++ypos;
00172       text += w->w;
00173     }
00174   } else if (w->type == CTK_WIDGET_BUTTON) {
00175     cputc('[');
00176     cputsn(w->widget.button.text, w->w);
00177     cputc(']');
00178   } else if (w->type == CTK_WIDGET_HYPERLINK) {
00179     cputsn(w->widget.hyperlink.text, w->w);
00180   } else if (w->type == CTK_WIDGET_TEXTENTRY) {
00181     text = w->widget.textentry.text;
00182     xscroll = 0;
00183     if(w->widget.textentry.xpos >= w->w - 1) {
00184       xscroll = w->widget.textentry.xpos - w->w + 1;
00185     }
00186     for(j = 0; j < w->h; ++j) {
00187       gotoxy(xpos, ypos);
00188       if(w->widget.textentry.state == CTK_TEXTENTRY_EDIT &&
00189          w->widget.textentry.ypos == j) {
00190         revers(0);
00191         cputc('>');
00192         for(i = 0; i < w->w; ++i) {
00193           c = text[i + xscroll];
00194           revers(i == w->widget.textentry.xpos - xscroll);
00195           cputc((c == 0) ? CH_SPACE : c);
00196         }
00197         revers(0);
00198         cputc('<');
00199       } else {
00200         cputc(CH_VERTLINE);
00201         cputsn(text, w->w);
00202         clearTo(xpos + w->w + 1);
00203         cputc(CH_VERTLINE);
00204       }
00205       ++ypos;
00206       text += w->w;
00207     }
00208 #if CTK_CONF_ICONS
00209   } else if (w->type == CTK_WIDGET_ICON) {
00210     if(w->widget.icon.textmap != NULL) {
00211       for(i = 0; i < 3; ++i) {
00212         gotoxy(xpos, ypos);
00213         cputc(w->widget.icon.textmap[0 + 3 * i]);
00214         cputc(w->widget.icon.textmap[1 + 3 * i]);
00215         cputc(w->widget.icon.textmap[2 + 3 * i]);
00216         ++ypos;
00217       }
00218       x = xpos;
00219   
00220       len = strlen(w->widget.icon.title);
00221       if(x + len >= SCREEN_WIDTH) {
00222         x = SCREEN_WIDTH - len;
00223       }
00224       gotoxy(x, ypos);
00225       cputs(w->widget.icon.title);
00226     }
00227 #endif /* CTK_CONF_ICONS */
00228   }
00229   revers(0);
00230 
00231 }
00232 /*---------------------------------------------------------------------------*/
00233 void
00234 ctk_draw_widget(struct ctk_widget *w,
00235                 unsigned char focus,
00236                 unsigned char clipy1,
00237                 unsigned char clipy2) {
00238 
00239   struct ctk_window *win = w->window;
00240   unsigned char posx, posy;
00241   clip(clipy1, clipy2);
00242 
00243   posx = win->x + 1;
00244   posy = win->y + 2;
00245 
00246   if(w == win->focused) {
00247     focus |= CTK_FOCUS_WIDGET;
00248   }
00249   
00250   draw_widget(w, posx, posy, focus);
00251 }
00252 /*---------------------------------------------------------------------------*/
00253 void
00254 ctk_draw_clear_window(struct ctk_window *window,
00255                       unsigned char focus,
00256                       unsigned char clipy1,
00257                       unsigned char clipy2) {
00258 
00259   unsigned char i;
00260   unsigned char x1, x2, y1, y2;
00261   x1 = window->x + 1;
00262   x2 = x1 + window->w;
00263   y1 = window->y + 2;
00264   y2 = y1 + window->h;
00265 
00266   for(i = y1; i < y2; ++i) {
00267     gotoxy(x1, i);
00268     clearTo(x2);
00269   }
00270 }
00271 /*---------------------------------------------------------------------------*/
00272 void draw_window_sub(struct ctk_window *window, unsigned char focus) {
00273 
00274   unsigned char x, y;
00275   unsigned char x1, y1, x2;
00276   struct ctk_widget *w;
00277   unsigned char wfocus;
00278 
00279   x = window->x;
00280   y = window->y + 1;
00281 
00282   x1 = x + 1;
00283   y1 = y + 1;
00284   x2 = x1 + window->w;
00285 
00286   // |_
00287   gotoxy(x, y1);
00288   cvline(window->h);
00289   cputc(CH_LLCORNER);
00290   chline(window->w);
00291   cputc(CH_LRCORNER);
00292 
00293   // -
00294   gotoxy(x, y);
00295   cputc(CH_ULCORNER);
00296   chline(window->w);
00297   cputc(CH_URCORNER);
00298   // |
00299   gotoxy(x2, y1);
00300   cvline(window->h);
00301 
00302   /* Draw inactive widgets. */
00303   for(w = window->inactive; w != NULL; w = w->next) {
00304     draw_widget(w, x1, y1, focus);
00305   }
00306 
00307   /* Draw active widgets. */
00308   for(w = window->active; w != NULL; w = w->next) {
00309     wfocus = focus;
00310     if(w == window->focused) {
00311       wfocus |= CTK_FOCUS_WIDGET;
00312     }
00313     draw_widget(w, x1, y1, wfocus);
00314   }
00315 }
00316 /*---------------------------------------------------------------------------*/
00317 void
00318 ctk_draw_window(struct ctk_window *window, unsigned char focus,
00319                 unsigned char clipy1, unsigned char clipy2, unsigned char draw_borders) {
00320   clip(clipy1, clipy2);
00321 
00322   focus = focus & CTK_FOCUS_WINDOW;
00323   draw_window_sub(window, focus);
00324 }
00325 /*---------------------------------------------------------------------------*/
00326 void ctk_draw_dialog(struct ctk_window *dialog) {
00327   clip(0, SCREEN_HEIGHT);
00328 
00329   ctk_draw_clear_window(dialog, 0, 0, SCREEN_HEIGHT);
00330   draw_window_sub(dialog, CTK_FOCUS_DIALOG);
00331 }
00332 /*---------------------------------------------------------------------------*/
00333 #if CTK_CONF_MENUS
00334 void draw_menu(struct ctk_menu *m, struct ctk_menu *open) {
00335 #if CC_CONF_UNSIGNED_CHAR_BUGS
00336   unsigned char x2;
00337   unsigned int x, y;
00338 #else
00339   unsigned char x2;
00340   unsigned char x, y;
00341 #endif
00342   x = cursx;
00343   cputs(m->title);
00344   cputc(CH_SPACE);
00345 
00346   if (m == open) {
00347     x2 = cursx;
00348     if(x + CTK_CONF_MENUWIDTH > SCREEN_WIDTH) {
00349       x = SCREEN_WIDTH - CTK_CONF_MENUWIDTH;
00350     }
00351   
00352     for(y = 0; y < m->nitems; y++) {
00353       if(y == m->active) {
00354         revers(0);
00355       }
00356       gotoxy(x, y + 1);
00357       if(m->items[y].title[0] == '-') {
00358         chline(CTK_CONF_MENUWIDTH);
00359       } else {
00360         cputs(m->items[y].title);
00361       }
00362       clearTo(x + CTK_CONF_MENUWIDTH);
00363       revers(1);
00364     }
00365     gotoxy(x2, 0);
00366   }
00367 }
00368 /*---------------------------------------------------------------------------*/
00369 void ctk_draw_menus(struct ctk_menus *menus) {
00370   struct ctk_menu *m;  
00371   
00372   clip(0, SCREEN_HEIGHT);
00373   /* Draw menus */
00374   gotoxy(0, 0);
00375   revers(1);
00376   for(m = menus->menus->next; m != NULL; m = m->next) {
00377     draw_menu(m, menus->open);
00378   }
00379 
00380   clearTo(SCREEN_WIDTH - strlen(menus->desktopmenu->title) - 1);
00381 
00382   /* Draw desktopmenu */
00383   draw_menu(menus->desktopmenu, menus->open);
00384 
00385   revers(0);
00386 }
00387 #endif /* CTK_CONF_MENUS */
00388 /*---------------------------------------------------------------------------*/
00389 /* Returns width and height of screen. */
00390 unsigned char ctk_draw_width(void) {
00391   return SCREEN_WIDTH;
00392 }
00393 unsigned char ctk_draw_height(void) {
00394   return SCREEN_HEIGHT;
00395 }
00396