Contiki 2.6

ctk-conio.c

00001 /*
00002  * Copyright (c) 2002, Adam Dunkels.
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  * This file is part of the "ctk" console GUI toolkit for cc65
00031  *
00032  * $Id: ctk-conio.c,v 1.14 2010/07/20 22:19:23 oliverschmidt Exp $
00033  *
00034  */
00035 
00036 #include <string.h>
00037 #include <ctype.h>
00038 
00039 #include "contiki.h"
00040 
00041 #include "ctk/ctk.h"
00042 #include "ctk-draw.h"
00043 
00044 #ifndef NULL
00045 #define NULL (void *)0
00046 #endif /* NULL */
00047 
00048 static unsigned char sizex, sizey;
00049 
00050 unsigned char ctk_draw_windowborder_height = 1;
00051 unsigned char ctk_draw_windowborder_width = 1;
00052 unsigned char ctk_draw_windowtitle_height = 1;
00053 
00054 
00055 /*-----------------------------------------------------------------------------------*/
00056 static unsigned char
00057 cputsn(char *str, unsigned char len)
00058 {
00059   unsigned char cnt = 0;
00060   char c;
00061 
00062   while(cnt < len) {
00063     c = *str;
00064     if(c == 0) {
00065       break;
00066     }
00067     cputc(c);
00068     ++str;
00069     ++cnt;
00070   }
00071   return cnt;
00072 }
00073 /*-----------------------------------------------------------------------------------*/
00074 void
00075 ctk_draw_init(void)
00076 {
00077   (void)bgcolor(SCREENCOLOR);
00078   (void)bordercolor(BORDERCOLOR);
00079   (void)textcolor(WINDOWCOLOR_FOCUS);
00080   screensize(&sizex, &sizey);
00081   ctk_draw_clear(0, sizey);
00082   gotoxy(0, 0);
00083 }
00084 /*-----------------------------------------------------------------------------------*/
00085 static void
00086 draw_widget(struct ctk_widget *w,
00087             unsigned char x, unsigned char y,
00088             unsigned char clipx, unsigned char clipy,
00089             unsigned char clipy1, unsigned char clipy2,
00090             unsigned char focus)
00091 {
00092   unsigned char xpos, ypos, xscroll;
00093   unsigned char i, j;
00094   char c, *text;
00095   unsigned char wfocus;
00096 #if CTK_CONF_ICONS
00097   unsigned char len;
00098 #endif /* CTK_CONF_ICONS */
00099 
00100   wfocus = 0;
00101   if(focus & CTK_FOCUS_WINDOW) {    
00102     (void)textcolor(WIDGETCOLOR_FWIN);
00103     if(focus & CTK_FOCUS_WIDGET) {
00104       (void)textcolor(WIDGETCOLOR_FOCUS);
00105       wfocus = 1;
00106     }
00107 #if CTK_CONF_WINDOWS
00108   } else if(focus & CTK_FOCUS_DIALOG) {
00109     (void)textcolor(WIDGETCOLOR_DIALOG);
00110     if(focus & CTK_FOCUS_WIDGET) {
00111       (void)textcolor(WIDGETCOLOR_FOCUS);
00112       wfocus = 1;
00113     }
00114 #endif /* CTK_CONF_WINDOWS */
00115   } else {
00116     (void)textcolor(WIDGETCOLOR);
00117   }
00118   
00119   xpos = x + w->x;
00120   ypos = y + w->y;
00121     
00122   switch(w->type) {
00123   case CTK_WIDGET_SEPARATOR:
00124     if(ypos >= clipy1 && ypos < clipy2) {
00125       chlinexy(xpos, ypos, w->w);
00126     }
00127     break;
00128   case CTK_WIDGET_LABEL:
00129     text = w->widget.label.text;
00130     for(j = 0; j < w->h; ++j) {
00131       if(ypos >= clipy1 && ypos < clipy2) {
00132         gotoxy(xpos, ypos);
00133         i = cputsn(text, w->w);
00134         if(w->w - i > 0) {
00135           cclear(w->w - i);
00136         }
00137       }
00138       ++ypos;
00139       text += w->w;
00140     }
00141     break;
00142   case CTK_WIDGET_BUTTON:
00143     if(ypos >= clipy1 && ypos < clipy2) {
00144       revers(wfocus != 0);
00145       cputcxy(xpos, ypos, '[');
00146       cputsn(w->widget.button.text, w->w);
00147       cputc(']');
00148       revers(0);
00149     }
00150     break;
00151   case CTK_WIDGET_HYPERLINK:
00152     if(ypos >= clipy1 && ypos < clipy2) {
00153       revers(wfocus == 0);
00154       gotoxy(xpos, ypos);
00155       (void)textcolor(WIDGETCOLOR_HLINK);
00156       cputsn(w->widget.button.text, w->w);
00157       revers(0);
00158     }
00159     break;
00160   case CTK_WIDGET_TEXTENTRY:
00161     text = w->widget.textentry.text;
00162     xscroll = 0;
00163     if(w->widget.textentry.xpos >= w->w - 1) {
00164       xscroll = w->widget.textentry.xpos - w->w + 1;
00165     }
00166     for(j = 0; j < w->h; ++j) {
00167       if(ypos >= clipy1 && ypos < clipy2) {
00168         if(w->widget.textentry.state == CTK_TEXTENTRY_EDIT &&
00169            w->widget.textentry.ypos == j) {
00170           revers(0);
00171           cputcxy(xpos, ypos, '>');
00172           c = 1;
00173           for(i = 0; i < w->w; ++i) {
00174             if(c != 0) {
00175               c = text[i + xscroll];
00176             }
00177             revers(i == w->widget.textentry.xpos - xscroll);
00178             if(c == 0) {
00179               cputc(' ');
00180             } else {
00181               cputc(c);
00182             }
00183           }
00184           revers(0);
00185           cputc('<');
00186         } else {
00187           revers(wfocus != 0 && j == w->widget.textentry.ypos);
00188           cvlinexy(xpos, ypos, 1);
00189           gotoxy(xpos + 1, ypos);          
00190           i = cputsn(text, w->w);
00191           if(w->w - i > 0) {
00192             cclear(w->w - i);
00193           }
00194           cvline(1);
00195         }
00196       }
00197       ++ypos;
00198       text += w->widget.textentry.len + 1;
00199     }
00200     revers(0);
00201     break;
00202 #if CTK_CONF_ICONS
00203   case CTK_WIDGET_ICON:
00204     if(ypos >= clipy1 && ypos < clipy2) {
00205       revers(wfocus != 0);
00206 #if CTK_CONF_ICON_TEXTMAPS
00207       if(w->widget.icon.textmap != NULL) {
00208         for(i = 0; i < 3; ++i) {
00209           gotoxy(xpos, ypos);
00210           if(ypos >= clipy1 && ypos < clipy2) {
00211             cputc(w->widget.icon.textmap[0 + 3 * i]);
00212             cputc(w->widget.icon.textmap[1 + 3 * i]);
00213             cputc(w->widget.icon.textmap[2 + 3 * i]);
00214           }
00215           ++ypos;
00216         }
00217       }
00218 #endif /* CTK_CONF_ICON_TEXTMAPS */
00219   
00220       len = (unsigned char)strlen(w->widget.icon.title);
00221       if(xpos + len >= sizex) {
00222         xpos = sizex - len;
00223       }
00224 
00225       gotoxy(xpos, ypos);
00226       if(ypos >= clipy1 && ypos < clipy2) {
00227         cputs(w->widget.icon.title);
00228       }
00229       revers(0);
00230     }
00231     break;
00232 #endif /* CTK_CONF_ICONS */
00233 
00234   default:
00235     break;
00236   }
00237 }
00238 /*-----------------------------------------------------------------------------------*/
00239 void
00240 ctk_draw_widget(struct ctk_widget *w, unsigned char focus,
00241                 unsigned char clipy1, unsigned char clipy2)
00242 {
00243   struct ctk_window *win = w->window;
00244   unsigned char posx, posy;
00245 
00246 #if CTK_CONF_WINDOWS
00247   posx = win->x + 1;
00248   posy = win->y + 1 + CTK_CONF_MENUS;
00249 #else /* CTK_CONF_WINDOWS */
00250   posx = 0;
00251   posy = 0;
00252 #endif /* CTK_CONF_WINDOWS */
00253 
00254   if(w == win->focused) {
00255     focus |= CTK_FOCUS_WIDGET;
00256   }
00257   
00258   draw_widget(w, posx, posy, posx + win->w, posy + win->h, clipy1, clipy2, focus);
00259   
00260 #ifdef CTK_CONIO_CONF_UPDATE
00261   CTK_CONIO_CONF_UPDATE();
00262 #endif /* CTK_CONIO_CONF_UPDATE */
00263 }
00264 /*-----------------------------------------------------------------------------------*/
00265 void
00266 ctk_draw_clear_window(struct ctk_window *window, unsigned char focus,
00267                       unsigned char clipy1, unsigned char clipy2)
00268 {
00269   unsigned char i;
00270 #if CTK_CONF_WINDOWS
00271   unsigned char h;
00272 #endif /* CTK_CONF_WINDOWS */
00273 
00274   if(focus & CTK_FOCUS_WINDOW) {
00275     (void)textcolor(WINDOWCOLOR_FOCUS);
00276   } else {
00277     (void)textcolor(WINDOWCOLOR);
00278   }
00279   
00280 #if CTK_CONF_WINDOWS
00281   h = window->y + 1 + CTK_CONF_MENUS + window->h;
00282 
00283   /* Clear window contents. */
00284   for(i = window->y + 1 + CTK_CONF_MENUS; i < h; ++i) {
00285     if(i >= clipy1 && i < clipy2) {
00286       cclearxy(window->x + 1, i, window->w);
00287     }
00288   }
00289 #else /* CTK_CONF_WINDOWS */
00290   for(i = 0; i < window->h; ++i) {
00291     if(i >= clipy1 && i < clipy2) {
00292       cclearxy(0, i, window->w);
00293     }
00294   }
00295 #endif /* CTK_CONF_WINDOWS */
00296 }
00297 /*-----------------------------------------------------------------------------------*/
00298 static void
00299 draw_window_contents(struct ctk_window *window, unsigned char focus,
00300                      unsigned char clipy1, unsigned char clipy2,
00301                      unsigned char x1, unsigned char x2,
00302                      unsigned char y1, unsigned char y2)
00303 {
00304   struct ctk_widget *w;
00305   unsigned char wfocus;
00306   
00307   /* Draw inactive widgets. */
00308   for(w = window->inactive; w != NULL; w = w->next) {
00309     draw_widget(w, x1, y1, x2, y2, clipy1, clipy2, focus);
00310   }
00311   
00312   /* Draw active widgets. */
00313   for(w = window->active; w != NULL; w = w->next) {  
00314     wfocus = focus;
00315     if(w == window->focused) {
00316       wfocus |= CTK_FOCUS_WIDGET;
00317     }
00318 
00319    draw_widget(w, x1, y1, x2, y2, clipy1, clipy2, wfocus);
00320   }
00321 
00322 #ifdef CTK_CONIO_CONF_UPDATE
00323   CTK_CONIO_CONF_UPDATE();
00324 #endif /* CTK_CONIO_CONF_UPDATE */
00325 }
00326 /*-----------------------------------------------------------------------------------*/
00327 void
00328 ctk_draw_window(struct ctk_window *window, unsigned char focus,
00329                 unsigned char clipy1, unsigned char clipy2,
00330                 unsigned char draw_borders)
00331 {
00332 #if CTK_CONF_WINDOWS
00333   unsigned char x, y;
00334   unsigned char x1, y1, x2, y2;
00335   unsigned char h;
00336 
00337   if(window->y + CTK_CONF_MENUS >= clipy2) {
00338     return;
00339   }
00340     
00341   x = window->x;
00342   y = window->y + CTK_CONF_MENUS;
00343   x1 = x + 1;
00344   y1 = y + 1;
00345   x2 = x1 + window->w;
00346   y2 = y1 + window->h;
00347 
00348   if(draw_borders) {
00349 
00350     /* Draw window frame. */  
00351     if(focus & CTK_FOCUS_WINDOW) {
00352       (void)textcolor(WINDOWCOLOR_FOCUS);
00353     } else {
00354       (void)textcolor(WINDOWCOLOR);
00355     }
00356 
00357     if(y >= clipy1) {
00358       cputcxy(x, y, (char)CH_ULCORNER);
00359       gotoxy(wherex() + window->titlelen + CTK_CONF_WINDOWMOVE * 2, wherey());
00360       chline(window->w - (wherex() - x) - 2);
00361       cputcxy(x2, y, (char)CH_URCORNER);
00362     }
00363 
00364     h = window->h;
00365   
00366     if(clipy1 > y1) {
00367       if(clipy1 - y1 < h) {
00368         h = clipy1 - y1;
00369         y1 = clipy1;
00370       } else {
00371         h = 0;
00372       }
00373     }
00374 
00375     if(clipy2 < y1 + h) {
00376       if(y1 >= clipy2) {
00377         h = 0;
00378       } else {
00379         h = clipy2 - y1;
00380       }
00381     }
00382 
00383     cvlinexy(x, y1, h);
00384     cvlinexy(x2, y1, h);  
00385 
00386     if(y + window->h >= clipy1 && y + window->h < clipy2) {
00387       cputcxy(x, y2, (char)CH_LLCORNER);
00388       chlinexy(x1, y2, window->w);
00389       cputcxy(x2, y2, (char)CH_LRCORNER);
00390     }
00391   }
00392 
00393   draw_window_contents(window, focus, clipy1, clipy2, x1, x2, y + 1, y2);
00394 
00395 #else /* CTK_CONF_WINDOWS */
00396 
00397   draw_window_contents(window, focus, clipy1, clipy2, 0, window->w, 0, window->h);
00398 
00399 #endif /* CTK_CONF_WINDOWS */
00400 }
00401 /*-----------------------------------------------------------------------------------*/
00402 #if CTK_CONF_WINDOWS
00403 void
00404 ctk_draw_dialog(struct ctk_window *dialog)
00405 {
00406   unsigned char x, y;
00407   unsigned char i;
00408   unsigned char x1, y1, x2, y2;
00409   
00410   (void)textcolor(DIALOGCOLOR);
00411 
00412   x = dialog->x;
00413   y = dialog->y + CTK_CONF_MENUS;
00414 
00415   x1 = x + 1;
00416   y1 = y + 1;
00417   x2 = x1 + dialog->w;
00418   y2 = y1 + dialog->h;
00419 
00420   /* Draw dialog frame. */
00421   cvlinexy(x, y1, dialog->h);
00422   cvlinexy(x2, y1, dialog->h);
00423 
00424   chlinexy(x1, y, dialog->w);
00425   chlinexy(x1, y2, dialog->w);
00426 
00427   cputcxy(x, y, (char)CH_ULCORNER);
00428   cputcxy(x, y2, (char)CH_LLCORNER);
00429   cputcxy(x2, y, (char)CH_URCORNER);
00430   cputcxy(x2, y2, (char)CH_LRCORNER);
00431   
00432   /* Clear dialog contents. */
00433   for(i = y1; i < y2; ++i) {
00434     cclearxy(x1, i, dialog->w);
00435   }
00436 
00437   draw_window_contents(dialog, CTK_FOCUS_DIALOG, 0, sizey, x1, x2, y1, y2);
00438 }
00439 #endif /* CTK_CONF_WINDOWS */
00440 /*-----------------------------------------------------------------------------------*/
00441 void
00442 ctk_draw_clear(unsigned char y1, unsigned char y2)
00443 {
00444   unsigned char i;
00445  
00446   for(i = y1; i < y2; ++i) {
00447     cclearxy(0, i, sizex);
00448   }
00449 }
00450 /*-----------------------------------------------------------------------------------*/
00451 #if CTK_CONF_MENUS
00452 static void
00453 draw_menu(struct ctk_menu *m, unsigned char open)
00454 {
00455   unsigned char x, x2, y;
00456 
00457   if(open) {
00458     x = x2 = wherex();
00459     if(x2 + CTK_CONF_MENUWIDTH > sizex) {
00460       x2 = sizex - CTK_CONF_MENUWIDTH;
00461     }
00462 
00463     for(y = 0; y < m->nitems; ++y) {
00464       if(y == m->active) {
00465         (void)textcolor(ACTIVEMENUITEMCOLOR);
00466         revers(0);
00467       } else {
00468         (void)textcolor(MENUCOLOR);       
00469         revers(1);
00470       }
00471       gotoxy(x2, y + 1);
00472       if(m->items[y].title[0] == '-') {
00473         chline(CTK_CONF_MENUWIDTH);
00474       } else {
00475         cputs(m->items[y].title);
00476       }
00477       if(x2 + CTK_CONF_MENUWIDTH > wherex()) {
00478         cclear(x2 + CTK_CONF_MENUWIDTH - wherex());
00479       }
00480     }
00481 
00482     gotoxy(x, 0);
00483     (void)textcolor(OPENMENUCOLOR);
00484     revers(0);
00485   }
00486 
00487   cputs(m->title);
00488   cputc(' ');
00489   (void)textcolor(MENUCOLOR);
00490   revers(1);
00491 }
00492 /*-----------------------------------------------------------------------------------*/
00493 void
00494 ctk_draw_menus(struct ctk_menus *menus)
00495 {
00496   struct ctk_menu *m;
00497 
00498   /* Draw menus */
00499   (void)textcolor(MENUCOLOR);
00500   gotoxy(0, 0);
00501   revers(1);
00502   cputc(' ');
00503   for(m = menus->menus->next; m != NULL; m = m->next) {
00504     draw_menu(m, m == menus->open);
00505   }
00506 
00507   /* Draw desktopmenu */
00508   if(wherex() + strlen(menus->desktopmenu->title) + 1 >= sizex) {
00509     gotoxy(sizex - (unsigned char)strlen(menus->desktopmenu->title) - 1, 0);
00510   } else {
00511     cclear(sizex - wherex() -
00512            (unsigned char)strlen(menus->desktopmenu->title) - 1);
00513   }
00514   draw_menu(menus->desktopmenu, menus->desktopmenu == menus->open);
00515 
00516   revers(0);
00517 }
00518 #endif /* CTK_CONF_MENUS */
00519 /*-----------------------------------------------------------------------------------*/
00520 unsigned char
00521 ctk_draw_height(void)
00522 {
00523   return sizey;
00524 }
00525 /*-----------------------------------------------------------------------------------*/
00526 unsigned char
00527 ctk_draw_width(void)
00528 {
00529   return sizex;
00530 }
00531 /*-----------------------------------------------------------------------------------*/