Contiki 2.5
ctk-conio.c
1 /*
2  * Copyright (c) 2002, Adam Dunkels.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following
12  * disclaimer in the documentation and/or other materials provided
13  * with the distribution.
14  * 3. The name of the author may not be used to endorse or promote
15  * products derived from this software without specific prior
16  * written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
19  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
24  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  * This file is part of the "ctk" console GUI toolkit for cc65
31  *
32  * $Id: ctk-conio.c,v 1.14 2010/07/20 22:19:23 oliverschmidt Exp $
33  *
34  */
35 
36 #include <string.h>
37 #include <ctype.h>
38 
39 #include "contiki.h"
40 
41 #include "ctk/ctk.h"
42 #include "ctk-draw.h"
43 
44 #ifndef NULL
45 #define NULL (void *)0
46 #endif /* NULL */
47 
48 static unsigned char sizex, sizey;
49 
50 unsigned char ctk_draw_windowborder_height = 1;
51 unsigned char ctk_draw_windowborder_width = 1;
52 unsigned char ctk_draw_windowtitle_height = 1;
53 
54 
55 /*-----------------------------------------------------------------------------------*/
56 static unsigned char
57 cputsn(char *str, unsigned char len)
58 {
59  unsigned char cnt = 0;
60  char c;
61 
62  while(cnt < len) {
63  c = *str;
64  if(c == 0) {
65  break;
66  }
67  cputc(c);
68  ++str;
69  ++cnt;
70  }
71  return cnt;
72 }
73 /*-----------------------------------------------------------------------------------*/
74 void
76 {
77  (void)bgcolor(SCREENCOLOR);
78  (void)bordercolor(BORDERCOLOR);
79  (void)textcolor(WINDOWCOLOR_FOCUS);
80  screensize(&sizex, &sizey);
81  ctk_draw_clear(0, sizey);
82  gotoxy(0, 0);
83 }
84 /*-----------------------------------------------------------------------------------*/
85 static void
86 draw_widget(struct ctk_widget *w,
87  unsigned char x, unsigned char y,
88  unsigned char clipx, unsigned char clipy,
89  unsigned char clipy1, unsigned char clipy2,
90  unsigned char focus)
91 {
92  unsigned char xpos, ypos, xscroll;
93  unsigned char i, j;
94  char c, *text;
95  unsigned char wfocus;
96 #if CTK_CONF_ICONS
97  unsigned char len;
98 #endif /* CTK_CONF_ICONS */
99 
100  wfocus = 0;
101  if(focus & CTK_FOCUS_WINDOW) {
102  (void)textcolor(WIDGETCOLOR_FWIN);
103  if(focus & CTK_FOCUS_WIDGET) {
104  (void)textcolor(WIDGETCOLOR_FOCUS);
105  wfocus = 1;
106  }
107 #if CTK_CONF_WINDOWS
108  } else if(focus & CTK_FOCUS_DIALOG) {
109  (void)textcolor(WIDGETCOLOR_DIALOG);
110  if(focus & CTK_FOCUS_WIDGET) {
111  (void)textcolor(WIDGETCOLOR_FOCUS);
112  wfocus = 1;
113  }
114 #endif /* CTK_CONF_WINDOWS */
115  } else {
116  (void)textcolor(WIDGETCOLOR);
117  }
118 
119  xpos = x + w->x;
120  ypos = y + w->y;
121 
122  switch(w->type) {
124  if(ypos >= clipy1 && ypos < clipy2) {
125  chlinexy(xpos, ypos, w->w);
126  }
127  break;
128  case CTK_WIDGET_LABEL:
129  text = w->widget.label.text;
130  for(j = 0; j < w->h; ++j) {
131  if(ypos >= clipy1 && ypos < clipy2) {
132  gotoxy(xpos, ypos);
133  i = cputsn(text, w->w);
134  if(w->w - i > 0) {
135  cclear(w->w - i);
136  }
137  }
138  ++ypos;
139  text += w->w;
140  }
141  break;
142  case CTK_WIDGET_BUTTON:
143  if(ypos >= clipy1 && ypos < clipy2) {
144  revers(wfocus != 0);
145  cputcxy(xpos, ypos, '[');
146  cputsn(w->widget.button.text, w->w);
147  cputc(']');
148  revers(0);
149  }
150  break;
152  if(ypos >= clipy1 && ypos < clipy2) {
153  revers(wfocus == 0);
154  gotoxy(xpos, ypos);
155  (void)textcolor(WIDGETCOLOR_HLINK);
156  cputsn(w->widget.button.text, w->w);
157  revers(0);
158  }
159  break;
161  text = w->widget.textentry.text;
162  xscroll = 0;
163  if(w->widget.textentry.xpos >= w->w - 1) {
164  xscroll = w->widget.textentry.xpos - w->w + 1;
165  }
166  for(j = 0; j < w->h; ++j) {
167  if(ypos >= clipy1 && ypos < clipy2) {
168  if(w->widget.textentry.state == CTK_TEXTENTRY_EDIT &&
169  w->widget.textentry.ypos == j) {
170  revers(0);
171  cputcxy(xpos, ypos, '>');
172  c = 1;
173  for(i = 0; i < w->w; ++i) {
174  if(c != 0) {
175  c = text[i + xscroll];
176  }
177  revers(i == w->widget.textentry.xpos - xscroll);
178  if(c == 0) {
179  cputc(' ');
180  } else {
181  cputc(c);
182  }
183  }
184  revers(0);
185  cputc('<');
186  } else {
187  revers(wfocus != 0 && j == w->widget.textentry.ypos);
188  cvlinexy(xpos, ypos, 1);
189  gotoxy(xpos + 1, ypos);
190  i = cputsn(text, w->w);
191  if(w->w - i > 0) {
192  cclear(w->w - i);
193  }
194  cvline(1);
195  }
196  }
197  ++ypos;
198  text += w->widget.textentry.len + 1;
199  }
200  revers(0);
201  break;
202 #if CTK_CONF_ICONS
203  case CTK_WIDGET_ICON:
204  if(ypos >= clipy1 && ypos < clipy2) {
205  revers(wfocus != 0);
206 #if CTK_CONF_ICON_TEXTMAPS
207  if(w->widget.icon.textmap != NULL) {
208  for(i = 0; i < 3; ++i) {
209  gotoxy(xpos, ypos);
210  if(ypos >= clipy1 && ypos < clipy2) {
211  cputc(w->widget.icon.textmap[0 + 3 * i]);
212  cputc(w->widget.icon.textmap[1 + 3 * i]);
213  cputc(w->widget.icon.textmap[2 + 3 * i]);
214  }
215  ++ypos;
216  }
217  }
218 #endif /* CTK_CONF_ICON_TEXTMAPS */
219 
220  len = (unsigned char)strlen(w->widget.icon.title);
221  if(xpos + len >= sizex) {
222  xpos = sizex - len;
223  }
224 
225  gotoxy(xpos, ypos);
226  if(ypos >= clipy1 && ypos < clipy2) {
227  cputs(w->widget.icon.title);
228  }
229  revers(0);
230  }
231  break;
232 #endif /* CTK_CONF_ICONS */
233 
234  default:
235  break;
236  }
237 }
238 /*-----------------------------------------------------------------------------------*/
239 void
240 ctk_draw_widget(struct ctk_widget *w, unsigned char focus,
241  unsigned char clipy1, unsigned char clipy2)
242 {
243  struct ctk_window *win = w->window;
244  unsigned char posx, posy;
245 
246 #if CTK_CONF_WINDOWS
247  posx = win->x + 1;
248  posy = win->y + 1 + CTK_CONF_MENUS;
249 #else /* CTK_CONF_WINDOWS */
250  posx = 0;
251  posy = 0;
252 #endif /* CTK_CONF_WINDOWS */
253 
254  if(w == win->focused) {
255  focus |= CTK_FOCUS_WIDGET;
256  }
257 
258  draw_widget(w, posx, posy, posx + win->w, posy + win->h, clipy1, clipy2, focus);
259 
260 #ifdef CTK_CONIO_CONF_UPDATE
261  CTK_CONIO_CONF_UPDATE();
262 #endif /* CTK_CONIO_CONF_UPDATE */
263 }
264 /*-----------------------------------------------------------------------------------*/
265 void
266 ctk_draw_clear_window(struct ctk_window *window, unsigned char focus,
267  unsigned char clipy1, unsigned char clipy2)
268 {
269  unsigned char i;
270 #if CTK_CONF_WINDOWS
271  unsigned char h;
272 #endif /* CTK_CONF_WINDOWS */
273 
274  if(focus & CTK_FOCUS_WINDOW) {
275  (void)textcolor(WINDOWCOLOR_FOCUS);
276  } else {
277  (void)textcolor(WINDOWCOLOR);
278  }
279 
280 #if CTK_CONF_WINDOWS
281  h = window->y + 1 + CTK_CONF_MENUS + window->h;
282 
283  /* Clear window contents. */
284  for(i = window->y + 1 + CTK_CONF_MENUS; i < h; ++i) {
285  if(i >= clipy1 && i < clipy2) {
286  cclearxy(window->x + 1, i, window->w);
287  }
288  }
289 #else /* CTK_CONF_WINDOWS */
290  for(i = 0; i < window->h; ++i) {
291  if(i >= clipy1 && i < clipy2) {
292  cclearxy(0, i, window->w);
293  }
294  }
295 #endif /* CTK_CONF_WINDOWS */
296 }
297 /*-----------------------------------------------------------------------------------*/
298 static void
299 draw_window_contents(struct ctk_window *window, unsigned char focus,
300  unsigned char clipy1, unsigned char clipy2,
301  unsigned char x1, unsigned char x2,
302  unsigned char y1, unsigned char y2)
303 {
304  struct ctk_widget *w;
305  unsigned char wfocus;
306 
307  /* Draw inactive widgets. */
308  for(w = window->inactive; w != NULL; w = w->next) {
309  draw_widget(w, x1, y1, x2, y2, clipy1, clipy2, focus);
310  }
311 
312  /* Draw active widgets. */
313  for(w = window->active; w != NULL; w = w->next) {
314  wfocus = focus;
315  if(w == window->focused) {
316  wfocus |= CTK_FOCUS_WIDGET;
317  }
318 
319  draw_widget(w, x1, y1, x2, y2, clipy1, clipy2, wfocus);
320  }
321 
322 #ifdef CTK_CONIO_CONF_UPDATE
323  CTK_CONIO_CONF_UPDATE();
324 #endif /* CTK_CONIO_CONF_UPDATE */
325 }
326 /*-----------------------------------------------------------------------------------*/
327 void
328 ctk_draw_window(struct ctk_window *window, unsigned char focus,
329  unsigned char clipy1, unsigned char clipy2,
330  unsigned char draw_borders)
331 {
332 #if CTK_CONF_WINDOWS
333  unsigned char x, y;
334  unsigned char x1, y1, x2, y2;
335  unsigned char h;
336 
337  if(window->y + CTK_CONF_MENUS >= clipy2) {
338  return;
339  }
340 
341  x = window->x;
342  y = window->y + CTK_CONF_MENUS;
343  x1 = x + 1;
344  y1 = y + 1;
345  x2 = x1 + window->w;
346  y2 = y1 + window->h;
347 
348  if(draw_borders) {
349 
350  /* Draw window frame. */
351  if(focus & CTK_FOCUS_WINDOW) {
352  (void)textcolor(WINDOWCOLOR_FOCUS);
353  } else {
354  (void)textcolor(WINDOWCOLOR);
355  }
356 
357  if(y >= clipy1) {
358  cputcxy(x, y, (char)CH_ULCORNER);
359  gotoxy(wherex() + window->titlelen + CTK_CONF_WINDOWMOVE * 2, wherey());
360  chline(window->w - (wherex() - x) - 2);
361  cputcxy(x2, y, (char)CH_URCORNER);
362  }
363 
364  h = window->h;
365 
366  if(clipy1 > y1) {
367  if(clipy1 - y1 < h) {
368  h = clipy1 - y1;
369  y1 = clipy1;
370  } else {
371  h = 0;
372  }
373  }
374 
375  if(clipy2 < y1 + h) {
376  if(y1 >= clipy2) {
377  h = 0;
378  } else {
379  h = clipy2 - y1;
380  }
381  }
382 
383  cvlinexy(x, y1, h);
384  cvlinexy(x2, y1, h);
385 
386  if(y + window->h >= clipy1 && y + window->h < clipy2) {
387  cputcxy(x, y2, (char)CH_LLCORNER);
388  chlinexy(x1, y2, window->w);
389  cputcxy(x2, y2, (char)CH_LRCORNER);
390  }
391  }
392 
393  draw_window_contents(window, focus, clipy1, clipy2, x1, x2, y + 1, y2);
394 
395 #else /* CTK_CONF_WINDOWS */
396 
397  draw_window_contents(window, focus, clipy1, clipy2, 0, window->w, 0, window->h);
398 
399 #endif /* CTK_CONF_WINDOWS */
400 }
401 /*-----------------------------------------------------------------------------------*/
402 #if CTK_CONF_WINDOWS
403 void
404 ctk_draw_dialog(struct ctk_window *dialog)
405 {
406  unsigned char x, y;
407  unsigned char i;
408  unsigned char x1, y1, x2, y2;
409 
410  (void)textcolor(DIALOGCOLOR);
411 
412  x = dialog->x;
413  y = dialog->y + CTK_CONF_MENUS;
414 
415  x1 = x + 1;
416  y1 = y + 1;
417  x2 = x1 + dialog->w;
418  y2 = y1 + dialog->h;
419 
420  /* Draw dialog frame. */
421  cvlinexy(x, y1, dialog->h);
422  cvlinexy(x2, y1, dialog->h);
423 
424  chlinexy(x1, y, dialog->w);
425  chlinexy(x1, y2, dialog->w);
426 
427  cputcxy(x, y, (char)CH_ULCORNER);
428  cputcxy(x, y2, (char)CH_LLCORNER);
429  cputcxy(x2, y, (char)CH_URCORNER);
430  cputcxy(x2, y2, (char)CH_LRCORNER);
431 
432  /* Clear dialog contents. */
433  for(i = y1; i < y2; ++i) {
434  cclearxy(x1, i, dialog->w);
435  }
436 
437  draw_window_contents(dialog, CTK_FOCUS_DIALOG, 0, sizey, x1, x2, y1, y2);
438 }
439 #endif /* CTK_CONF_WINDOWS */
440 /*-----------------------------------------------------------------------------------*/
441 void
442 ctk_draw_clear(unsigned char y1, unsigned char y2)
443 {
444  unsigned char i;
445 
446  for(i = y1; i < y2; ++i) {
447  cclearxy(0, i, sizex);
448  }
449 }
450 /*-----------------------------------------------------------------------------------*/
451 #if CTK_CONF_MENUS
452 static void
453 draw_menu(struct ctk_menu *m, unsigned char open)
454 {
455  unsigned char x, x2, y;
456 
457  if(open) {
458  x = x2 = wherex();
459  if(x2 + CTK_CONF_MENUWIDTH > sizex) {
460  x2 = sizex - CTK_CONF_MENUWIDTH;
461  }
462 
463  for(y = 0; y < m->nitems; ++y) {
464  if(y == m->active) {
465  (void)textcolor(ACTIVEMENUITEMCOLOR);
466  revers(0);
467  } else {
468  (void)textcolor(MENUCOLOR);
469  revers(1);
470  }
471  gotoxy(x2, y + 1);
472  if(m->items[y].title[0] == '-') {
473  chline(CTK_CONF_MENUWIDTH);
474  } else {
475  cputs(m->items[y].title);
476  }
477  if(x2 + CTK_CONF_MENUWIDTH > wherex()) {
478  cclear(x2 + CTK_CONF_MENUWIDTH - wherex());
479  }
480  }
481 
482  gotoxy(x, 0);
483  (void)textcolor(OPENMENUCOLOR);
484  revers(0);
485  }
486 
487  cputs(m->title);
488  cputc(' ');
489  (void)textcolor(MENUCOLOR);
490  revers(1);
491 }
492 /*-----------------------------------------------------------------------------------*/
493 void
494 ctk_draw_menus(struct ctk_menus *menus)
495 {
496  struct ctk_menu *m;
497 
498  /* Draw menus */
499  (void)textcolor(MENUCOLOR);
500  gotoxy(0, 0);
501  revers(1);
502  cputc(' ');
503  for(m = menus->menus->next; m != NULL; m = m->next) {
504  draw_menu(m, m == menus->open);
505  }
506 
507  /* Draw desktopmenu */
508  if(wherex() + strlen(menus->desktopmenu->title) + 1 >= sizex) {
509  gotoxy(sizex - (unsigned char)strlen(menus->desktopmenu->title) - 1, 0);
510  } else {
511  cclear(sizex - wherex() -
512  (unsigned char)strlen(menus->desktopmenu->title) - 1);
513  }
514  draw_menu(menus->desktopmenu, menus->desktopmenu == menus->open);
515 
516  revers(0);
517 }
518 #endif /* CTK_CONF_MENUS */
519 /*-----------------------------------------------------------------------------------*/
520 unsigned char
521 ctk_draw_height(void)
522 {
523  return sizey;
524 }
525 /*-----------------------------------------------------------------------------------*/
526 unsigned char
527 ctk_draw_width(void)
528 {
529  return sizex;
530 }
531 /*-----------------------------------------------------------------------------------*/