Contiki 2.6
|
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 /*-----------------------------------------------------------------------------------*/