Contiki 3.x
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  *
33  */
34 
35 #include <string.h>
36 #include <ctype.h>
37 
38 #include "contiki.h"
39 
40 #include "ctk/ctk.h"
41 #include "ctk-draw.h"
42 
43 #ifndef NULL
44 #define NULL (void *)0
45 #endif /* NULL */
46 
47 static unsigned char sizex, sizey;
48 
49 unsigned char ctk_draw_windowborder_height = 1;
50 unsigned char ctk_draw_windowborder_width = 1;
51 unsigned char ctk_draw_windowtitle_height = 1;
52 
53 
54 /*-----------------------------------------------------------------------------------*/
55 static unsigned char
56 cputsn(char *str, unsigned char len)
57 {
58  unsigned char cnt = 0;
59  char c;
60 
61  while(cnt < len) {
62  c = *str;
63  if(c == 0) {
64  break;
65  }
66  cputc(c);
67  ++str;
68  ++cnt;
69  }
70  return cnt;
71 }
72 /*-----------------------------------------------------------------------------------*/
73 void
75 {
76  (void)bgcolor(SCREENCOLOR);
77  (void)bordercolor(BORDERCOLOR);
78  (void)textcolor(WINDOWCOLOR_FOCUS);
79  screensize(&sizex, &sizey);
80  ctk_draw_clear(0, sizey);
81  gotoxy(0, 0);
82 }
83 /*-----------------------------------------------------------------------------------*/
84 static void
85 draw_widget(struct ctk_widget *w,
86  unsigned char x, unsigned char y,
87  unsigned char clipx, unsigned char clipy,
88  unsigned char clipy1, unsigned char clipy2,
89  unsigned char focus)
90 {
91  unsigned char xpos, ypos, xscroll;
92  unsigned char i, j;
93  char c, *text;
94  unsigned char wfocus;
95 #if CTK_CONF_ICONS
96  unsigned char len;
97 #endif /* CTK_CONF_ICONS */
98 
99  wfocus = 0;
100  if(focus & CTK_FOCUS_WINDOW) {
101  (void)textcolor(WIDGETCOLOR_FWIN);
102  if(focus & CTK_FOCUS_WIDGET) {
103  (void)textcolor(WIDGETCOLOR_FOCUS);
104  wfocus = 1;
105  }
106 #if CTK_CONF_WINDOWS
107  } else if(focus & CTK_FOCUS_DIALOG) {
108  (void)textcolor(WIDGETCOLOR_DIALOG);
109  if(focus & CTK_FOCUS_WIDGET) {
110  (void)textcolor(WIDGETCOLOR_FOCUS);
111  wfocus = 1;
112  }
113 #endif /* CTK_CONF_WINDOWS */
114  } else {
115  (void)textcolor(WIDGETCOLOR);
116  }
117 
118  xpos = x + w->x;
119  ypos = y + w->y;
120 
121  switch(w->type) {
123  if(ypos >= clipy1 && ypos < clipy2) {
124  chlinexy(xpos, ypos, w->w);
125  }
126  break;
127  case CTK_WIDGET_LABEL:
128  text = w->widget.label.text;
129  for(j = 0; j < w->h; ++j) {
130  if(ypos >= clipy1 && ypos < clipy2) {
131  gotoxy(xpos, ypos);
132  i = cputsn(text, w->w);
133  if(w->w - i > 0) {
134  cclear(w->w - i);
135  }
136  }
137  ++ypos;
138  text += w->w;
139  }
140  break;
141  case CTK_WIDGET_BUTTON:
142  if(ypos >= clipy1 && ypos < clipy2) {
143  revers(wfocus != 0);
144  cputcxy(xpos, ypos, '[');
145  cputsn(w->widget.button.text, w->w);
146  cputc(']');
147  revers(0);
148  }
149  break;
151  if(ypos >= clipy1 && ypos < clipy2) {
152  revers(wfocus == 0);
153  gotoxy(xpos, ypos);
154  (void)textcolor(WIDGETCOLOR_HLINK);
155  cputsn(w->widget.button.text, w->w);
156  revers(0);
157  }
158  break;
160  text = w->widget.textentry.text;
161  xscroll = 0;
162  if(w->widget.textentry.xpos >= w->w - 1) {
163  xscroll = w->widget.textentry.xpos - w->w + 1;
164  }
165  for(j = 0; j < w->h; ++j) {
166  if(ypos >= clipy1 && ypos < clipy2) {
167  if(w->widget.textentry.state == CTK_TEXTENTRY_EDIT &&
168  w->widget.textentry.ypos == j) {
169  revers(0);
170  cputcxy(xpos, ypos, '>');
171  c = 1;
172  for(i = 0; i < w->w; ++i) {
173  if(c != 0) {
174  c = text[i + xscroll];
175  }
176  revers(i == w->widget.textentry.xpos - xscroll);
177  if(c == 0) {
178  cputc(' ');
179  } else {
180  cputc(c);
181  }
182  }
183  revers(0);
184  cputc('<');
185  } else {
186  revers(wfocus != 0 && j == w->widget.textentry.ypos);
187  cvlinexy(xpos, ypos, 1);
188  gotoxy(xpos + 1, ypos);
189  i = cputsn(text, w->w);
190  if(w->w - i > 0) {
191  cclear(w->w - i);
192  }
193  cvline(1);
194  }
195  }
196  ++ypos;
197  text += w->widget.textentry.len + 1;
198  }
199  revers(0);
200  break;
201 #if CTK_CONF_ICONS
202  case CTK_WIDGET_ICON:
203  if(ypos >= clipy1 && ypos < clipy2) {
204  revers(wfocus != 0);
205 #if CTK_CONF_ICON_TEXTMAPS
206  if(w->widget.icon.textmap != NULL) {
207  for(i = 0; i < 3; ++i) {
208  gotoxy(xpos, ypos);
209  if(ypos >= clipy1 && ypos < clipy2) {
210  cputc(w->widget.icon.textmap[0 + 3 * i]);
211  cputc(w->widget.icon.textmap[1 + 3 * i]);
212  cputc(w->widget.icon.textmap[2 + 3 * i]);
213  }
214  ++ypos;
215  }
216  }
217 #endif /* CTK_CONF_ICON_TEXTMAPS */
218 
219  len = (unsigned char)strlen(w->widget.icon.title);
220  if(xpos + len >= sizex) {
221  xpos = sizex - len;
222  }
223 
224  gotoxy(xpos, ypos);
225  if(ypos >= clipy1 && ypos < clipy2) {
226  cputs(w->widget.icon.title);
227  }
228  revers(0);
229  }
230  break;
231 #endif /* CTK_CONF_ICONS */
232 
233  default:
234  break;
235  }
236 }
237 /*-----------------------------------------------------------------------------------*/
238 void
239 ctk_draw_widget(struct ctk_widget *w, unsigned char focus,
240  unsigned char clipy1, unsigned char clipy2)
241 {
242  struct ctk_window *win = w->window;
243  unsigned char posx, posy;
244 
245 #if CTK_CONF_WINDOWS
246  posx = win->x + 1;
247  posy = win->y + 1 + CTK_CONF_MENUS;
248 #else /* CTK_CONF_WINDOWS */
249  posx = 0;
250  posy = 0;
251 #endif /* CTK_CONF_WINDOWS */
252 
253  if(w == win->focused) {
254  focus |= CTK_FOCUS_WIDGET;
255  }
256 
257  draw_widget(w, posx, posy, posx + win->w, posy + win->h, clipy1, clipy2, focus);
258 
259 #ifdef CTK_CONIO_CONF_UPDATE
260  CTK_CONIO_CONF_UPDATE();
261 #endif /* CTK_CONIO_CONF_UPDATE */
262 }
263 /*-----------------------------------------------------------------------------------*/
264 void
265 ctk_draw_clear_window(struct ctk_window *window, unsigned char focus,
266  unsigned char clipy1, unsigned char clipy2)
267 {
268  unsigned char i;
269 #if CTK_CONF_WINDOWS
270  unsigned char h;
271 #endif /* CTK_CONF_WINDOWS */
272 
273  if(focus & CTK_FOCUS_WINDOW) {
274  (void)textcolor(WINDOWCOLOR_FOCUS);
275  } else {
276  (void)textcolor(WINDOWCOLOR);
277  }
278 
279 #if CTK_CONF_WINDOWS
280  h = window->y + 1 + CTK_CONF_MENUS + window->h;
281 
282  /* Clear window contents. */
283  for(i = window->y + 1 + CTK_CONF_MENUS; i < h; ++i) {
284  if(i >= clipy1 && i < clipy2) {
285  cclearxy(window->x + 1, i, window->w);
286  }
287  }
288 #else /* CTK_CONF_WINDOWS */
289  for(i = 0; i < window->h; ++i) {
290  if(i >= clipy1 && i < clipy2) {
291  cclearxy(0, i, window->w);
292  }
293  }
294 #endif /* CTK_CONF_WINDOWS */
295 }
296 /*-----------------------------------------------------------------------------------*/
297 static void
298 draw_window_contents(struct ctk_window *window, unsigned char focus,
299  unsigned char clipy1, unsigned char clipy2,
300  unsigned char x1, unsigned char x2,
301  unsigned char y1, unsigned char y2)
302 {
303  struct ctk_widget *w;
304  unsigned char wfocus;
305 
306  /* Draw inactive widgets. */
307  for(w = window->inactive; w != NULL; w = w->next) {
308  draw_widget(w, x1, y1, x2, y2, clipy1, clipy2, focus);
309  }
310 
311  /* Draw active widgets. */
312  for(w = window->active; w != NULL; w = w->next) {
313  wfocus = focus;
314  if(w == window->focused) {
315  wfocus |= CTK_FOCUS_WIDGET;
316  }
317 
318  draw_widget(w, x1, y1, x2, y2, clipy1, clipy2, wfocus);
319  }
320 
321 #ifdef CTK_CONIO_CONF_UPDATE
322  CTK_CONIO_CONF_UPDATE();
323 #endif /* CTK_CONIO_CONF_UPDATE */
324 }
325 /*-----------------------------------------------------------------------------------*/
326 void
327 ctk_draw_window(struct ctk_window *window, unsigned char focus,
328  unsigned char clipy1, unsigned char clipy2,
329  unsigned char draw_borders)
330 {
331 #if CTK_CONF_WINDOWS
332  unsigned char x, y;
333  unsigned char x1, y1, x2, y2;
334  unsigned char h;
335 
336  if(window->y + CTK_CONF_MENUS >= clipy2) {
337  return;
338  }
339 
340  x = window->x;
341  y = window->y + CTK_CONF_MENUS;
342  x1 = x + 1;
343  y1 = y + 1;
344  x2 = x1 + window->w;
345  y2 = y1 + window->h;
346 
347  if(draw_borders) {
348 
349  /* Draw window frame. */
350  if(focus & CTK_FOCUS_WINDOW) {
351  (void)textcolor(WINDOWCOLOR_FOCUS);
352  } else {
353  (void)textcolor(WINDOWCOLOR);
354  }
355 
356  if(y >= clipy1) {
357  cputcxy(x, y, (char)CH_ULCORNER);
358  gotoxy(wherex() + window->titlelen + CTK_CONF_WINDOWMOVE * 2, wherey());
359  chline(window->w - (wherex() - x) - 2);
360  cputcxy(x2, y, (char)CH_URCORNER);
361  }
362 
363  h = window->h;
364 
365  if(clipy1 > y1) {
366  if(clipy1 - y1 < h) {
367  h = clipy1 - y1;
368  y1 = clipy1;
369  } else {
370  h = 0;
371  }
372  }
373 
374  if(clipy2 < y1 + h) {
375  if(y1 >= clipy2) {
376  h = 0;
377  } else {
378  h = clipy2 - y1;
379  }
380  }
381 
382  cvlinexy(x, y1, h);
383  cvlinexy(x2, y1, h);
384 
385  if(y + window->h >= clipy1 && y + window->h < clipy2) {
386  cputcxy(x, y2, (char)CH_LLCORNER);
387  chlinexy(x1, y2, window->w);
388  cputcxy(x2, y2, (char)CH_LRCORNER);
389  }
390  }
391 
392  draw_window_contents(window, focus, clipy1, clipy2, x1, x2, y + 1, y2);
393 
394 #else /* CTK_CONF_WINDOWS */
395 
396  draw_window_contents(window, focus, clipy1, clipy2, 0, window->w, 0, window->h);
397 
398 #endif /* CTK_CONF_WINDOWS */
399 }
400 /*-----------------------------------------------------------------------------------*/
401 #if CTK_CONF_WINDOWS
402 void
403 ctk_draw_dialog(struct ctk_window *dialog)
404 {
405  unsigned char x, y;
406  unsigned char i;
407  unsigned char x1, y1, x2, y2;
408 
409  (void)textcolor(DIALOGCOLOR);
410 
411  x = dialog->x;
412  y = dialog->y + CTK_CONF_MENUS;
413 
414  x1 = x + 1;
415  y1 = y + 1;
416  x2 = x1 + dialog->w;
417  y2 = y1 + dialog->h;
418 
419  /* Draw dialog frame. */
420  cvlinexy(x, y1, dialog->h);
421  cvlinexy(x2, y1, dialog->h);
422 
423  chlinexy(x1, y, dialog->w);
424  chlinexy(x1, y2, dialog->w);
425 
426  cputcxy(x, y, (char)CH_ULCORNER);
427  cputcxy(x, y2, (char)CH_LLCORNER);
428  cputcxy(x2, y, (char)CH_URCORNER);
429  cputcxy(x2, y2, (char)CH_LRCORNER);
430 
431  /* Clear dialog contents. */
432  for(i = y1; i < y2; ++i) {
433  cclearxy(x1, i, dialog->w);
434  }
435 
436  draw_window_contents(dialog, CTK_FOCUS_DIALOG, 0, sizey, x1, x2, y1, y2);
437 }
438 #endif /* CTK_CONF_WINDOWS */
439 /*-----------------------------------------------------------------------------------*/
440 void
441 ctk_draw_clear(unsigned char y1, unsigned char y2)
442 {
443  unsigned char i;
444 
445  for(i = y1; i < y2; ++i) {
446  cclearxy(0, i, sizex);
447  }
448 }
449 /*-----------------------------------------------------------------------------------*/
450 #if CTK_CONF_MENUS
451 static void
452 draw_menu(struct ctk_menu *m, unsigned char open)
453 {
454  unsigned char x, x2, y;
455 
456  if(open) {
457  x = x2 = wherex();
458  if(x2 + CTK_CONF_MENUWIDTH > sizex) {
459  x2 = sizex - CTK_CONF_MENUWIDTH;
460  }
461 
462  for(y = 0; y < m->nitems; ++y) {
463  if(y == m->active) {
464  (void)textcolor(ACTIVEMENUITEMCOLOR);
465  revers(0);
466  } else {
467  (void)textcolor(MENUCOLOR);
468  revers(1);
469  }
470  gotoxy(x2, y + 1);
471  if(m->items[y].title[0] == '-') {
472  chline(CTK_CONF_MENUWIDTH);
473  } else {
474  cputs(m->items[y].title);
475  }
476  if(x2 + CTK_CONF_MENUWIDTH > wherex()) {
477  cclear(x2 + CTK_CONF_MENUWIDTH - wherex());
478  }
479  }
480 
481  gotoxy(x, 0);
482  (void)textcolor(OPENMENUCOLOR);
483  revers(0);
484  }
485 
486  cputs(m->title);
487  cputc(' ');
488  (void)textcolor(MENUCOLOR);
489  revers(1);
490 }
491 /*-----------------------------------------------------------------------------------*/
492 void
493 ctk_draw_menus(struct ctk_menus *menus)
494 {
495  struct ctk_menu *m;
496 
497  /* Draw menus */
498  (void)textcolor(MENUCOLOR);
499  gotoxy(0, 0);
500  revers(1);
501  cputc(' ');
502  for(m = menus->menus->next; m != NULL; m = m->next) {
503  draw_menu(m, m == menus->open);
504  }
505 
506  /* Draw desktopmenu */
507  if(wherex() + strlen(menus->desktopmenu->title) + 1 >= sizex) {
508  gotoxy(sizex - (unsigned char)strlen(menus->desktopmenu->title) - 1, 0);
509  } else {
510  cclear(sizex - wherex() -
511  (unsigned char)strlen(menus->desktopmenu->title) - 1);
512  }
513  draw_menu(menus->desktopmenu, menus->desktopmenu == menus->open);
514 
515  revers(0);
516 }
517 #endif /* CTK_CONF_MENUS */
518 /*-----------------------------------------------------------------------------------*/
519 unsigned char
520 ctk_draw_height(void)
521 {
522  return sizey;
523 }
524 /*-----------------------------------------------------------------------------------*/
525 unsigned char
526 ctk_draw_width(void)
527 {
528  return sizex;
529 }
530 /*-----------------------------------------------------------------------------------*/
#define CTK_WIDGET_TEXTENTRY
Widget number: The CTK textentry widget.
Definition: ctk.h:72
unsigned char titlelen
The length of the title, cached for speed reasons.
Definition: ctk.h:522
struct ctk_menu * desktopmenu
A pointer to the &quot;Desktop&quot; menu that can be used for drawing the desktop menu in a special way (such ...
Definition: ctk.h:618
Representation of the menu bar.
Definition: ctk.h:611
unsigned char w
The width of the window, excluding window borders.
Definition: ctk.h:549
struct ctk_menu * menus
A pointer to a linked list of all menus, including the open menu and the desktop menu.
Definition: ctk.h:612
struct ctk_widget * next
The next widget in the linked list of widgets that is contained in the ctk_window structure...
Definition: ctk.h:445
struct ctk_widget * inactive
The list if widgets that cannot be selected by the user.
Definition: ctk.h:554
unsigned char active
The currently active menu item.
Definition: ctk.h:601
void ctk_draw_clear(unsigned char y1, unsigned char y2)
Clear the screen between the clip bounds.
Definition: ctk-conio.c:441
unsigned char x
The x position of the widget within the containing window, in character coordinates.
Definition: ctk.h:452
struct ctk_menuitem items[CTK_MAXMENUITEMS]
The array which contains all the menu items.
Definition: ctk.h:603
#define CTK_FOCUS_WINDOW
Widget focus flag: widget&#39;s window is the foremost one.
Definition: ctk.h:990
unsigned char nitems
The total number of menu items in the menu.
Definition: ctk.h:599
#define NULL
The null pointer.
void ctk_draw_widget(struct ctk_widget *w, unsigned char focus, unsigned char clipy1, unsigned char clipy2)
Draw a widget on a window.
Definition: ctk-conio.c:239
struct ctk_menu * next
Apointer to the next menu, or is NULL if this is the last menu, and should be used by the ctk-draw mo...
Definition: ctk.h:587
char * title
The menu title.
Definition: ctk.h:592
unsigned char type
The type of the widget: CTK_WIDGET_SEPARATOR, CTK_WIDGET_LABEL, CTK_WIDGET_BUTTON, CTK_WIDGET_HYPERLINK, CTK_WIDGET_TEXTENTRY, CTK_WIDGET_BITMAP or CTK_WIDGET_ICON.
Definition: ctk.h:456
void ctk_draw_window(struct ctk_window *window, unsigned char focus, unsigned char clipy1, unsigned char clipy2, unsigned char draw_borders)
Draw a window onto the screen.
Definition: ctk-conio.c:327
unsigned char y
The y position of the widget within the containing window, in character coordinates.
Definition: ctk.h:452
#define CTK_WIDGET_SEPARATOR
Widget number: The CTK separator widget.
Definition: ctk.h:64
char * text
The button text.
Definition: ctk.h:388
struct ctk_widget * focused
A pointer to the widget on the active list that is currently selected, or NULL if no widget is select...
Definition: ctk.h:562
#define CTK_FOCUS_DIALOG
Widget focus flag: widget is in a dialog.
Definition: ctk.h:992
struct ctk_menu * open
The currently open menu, if any.
Definition: ctk.h:615
#define CTK_WIDGET_BUTTON
Widget number: The CTK button widget.
Definition: ctk.h:68
union ctk_widget::@20 widget
The union which contains the actual widget structure, as determined by the type field.
CTK screen drawing module interface, ctk-draw.
Representation of an individual menu.
Definition: ctk.h:586
void ctk_draw_init(void)
The initialization function.
Definition: ctk-conio.c:74
void ctk_draw_dialog(struct ctk_window *dialog)
Draw a dialog onto the screen.
#define CTK_WIDGET_HYPERLINK
Widget number: The CTK hyperlink widget.
Definition: ctk.h:70
Representation of a CTK window.
Definition: ctk.h:506
struct ctk_window * window
The window in which the widget is contained.
Definition: ctk.h:448
#define CTK_FOCUS_WIDGET
Widget focus flag: widget has focus.
Definition: ctk.h:988
#define CTK_WIDGET_LABEL
Widget number: The CTK label widget.
Definition: ctk.h:66
void ctk_draw_clear_window(struct ctk_window *window, unsigned char focus, unsigned char clipy1, unsigned char clipy2)
Draw the window background.
Definition: ctk-conio.c:265
The generic CTK widget structure that contains all other widget structures.
Definition: ctk.h:444
unsigned char w
The width of the widget in character coordinates.
Definition: ctk.h:464
unsigned char h
The height of the window, excluding window borders.
Definition: ctk.h:549
char * title
The menu items text.
Definition: ctk.h:572
struct ctk_widget * active
The list of widgets that can be selected by the user.
Definition: ctk.h:558
CTK header file.
#define CTK_WIDGET_ICON
Widget number: The CTK icon widget.
Definition: ctk.h:76
unsigned char h
The height of the widget in character coordinates.
Definition: ctk.h:464