Contiki 2.5
ctk-conio_arch-source.c
1 /*
2  * Copyright (c) 2007, Takahide Matsutsuka.
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  * $Id: ctk-conio_arch-source.c,v 1.2 2007/09/29 04:10:00 matsutsuka Exp $
31  *
32  */
33 
34 /*
35  * \file
36  * This is an original source file for
37  * ctk-conio_arch.c and ctk-conio_arch-asm.S
38  * \author
39  * Takahide Matsutsuka <markn@markn.org>
40  */
41 
42 
43 #include "ctk/ctk.h"
44 #include "ctk/ctk-draw.h"
45 #include "contiki-conf.h"
46 #include "ctk/ctk_arch.h"
47 #include <string.h>
48 
49 #ifndef NULL
50 #define NULL (void *)0
51 #endif
52 
53 /*---------------------------------------------------------------------------*/
54 static char cursx, cursy;
55 static unsigned char reversed;
56 static char cy1, cy2;
57 
58 unsigned char ctk_draw_windowtitle_height = 1;
59 
60 /*---------------------------------------------------------------------------*/
61 #define revers(c) reversed = c
62 #define clip(y1, y2) cy1 = y1; cy2 = y2
63 #define OFFSET(x, y) y * SCREEN_WIDTH + x
64 
65 /*---------------------------------------------------------------------------*/
66 void cputc(char c) {
67  if (cursy >= cy1 && cursy <= cy2
68  && cursy >= 0 && cursy <= SCREEN_HEIGHT
69  && cursx >= 0 && cursx < SCREEN_WIDTH) {
70  unsigned int offset = OFFSET(cursx, cursy);
71  *((char *) VRAM_CHAR + offset) = c;
72  *((char *) VRAM_ATTR + offset) = reversed ? COLOR_REVERSED : COLOR_NORMAL;
73  }
74  cursx++;
75 }
76 
77 /*---------------------------------------------------------------------------*/
78 void cputs(char *str) {
79  while (*str != 0) {
80  cputc(*str);
81  str++;
82  }
83 }
84 /*---------------------------------------------------------------------------*/
85 void cputsn(char *str, unsigned char len) {
86  while ((len > 0) && (*str != 0)) {
87  cputc(*str);
88  str++;
89  len--;
90  }
91 }
92 /*---------------------------------------------------------------------------*/
93 void chline(unsigned char length) {
94  while (length > 0) {
95  cputc(CH_HOLILINE);
96  length--;
97  }
98 }
99 /*---------------------------------------------------------------------------*/
100 /* #define cvline(l) while (l > 0) { cputc(CH_VERTLINE); */
101 /* ++cursy; --cursx; l--; } */
102 
103 void cvline(unsigned char length) {
104  while (length > 0) {
105  cputc(CH_VERTLINE);
106  ++cursy;
107  --cursx;
108  length--;
109  }
110 }
111 /*---------------------------------------------------------------------------*/
112 void gotoxy(unsigned char x, unsigned char y) {
113  cursx = x;
114  cursy = y;
115 }
116 /*---------------------------------------------------------------------------*/
117 void clearTo(char x) {
118  while (cursx < x) {
119  cputc(CH_SPACE);
120  }
121  cursx = x;
122 }
123 
124 /*---------------------------------------------------------------------------*/
125 void ctk_draw_clear(unsigned char clipy1, unsigned char clipy2) {
126  while (clipy1 < clipy2) {
127  gotoxy(0, clipy1);
128  clearTo(SCREEN_WIDTH);
129  clipy1++;
130  }
131 }
132 
133 /*---------------------------------------------------------------------------*/
134 void ctk_draw_init(void) {
135  clip(0, SCREEN_HEIGHT);
136  ctk_draw_clear(0, SCREEN_HEIGHT);
137 }
138 /*---------------------------------------------------------------------------*/
139 /*
140  * w: widget
141  * x, y: screen position of client drawing area (left, top)
142  * clipx, clipy: screen position of client drawing area (right, bottom)
143  * clipy1, clipy2: min/max y position of screen
144  * focus: boolean
145  */
146 void
147 draw_widget(struct ctk_widget *w,
148  unsigned char x, unsigned char y,
149  unsigned char focus) {
150  unsigned char xpos, ypos, xscroll;
151  unsigned char i, j;
152  char c, *text;
153 #if CTK_CONF_ICONS
154  unsigned char len;
155 #endif /* CTK_CONF_ICONS */
156 
157  xpos = x + w->x;
158  ypos = y + w->y;
159 
160  revers(focus & CTK_FOCUS_WIDGET);
161  gotoxy(xpos, ypos);
162 
163  if (w->type == CTK_WIDGET_SEPARATOR) {
164  chline(w->w);
165  } else if (w->type == CTK_WIDGET_LABEL) {
166  text = w->widget.label.text;
167  for(i = 0; i < w->h; ++i) {
168  gotoxy(xpos, ypos);
169  cputsn(text, w->w);
170  clearTo(xpos + w->w);
171  ++ypos;
172  text += w->w;
173  }
174  } else if (w->type == CTK_WIDGET_BUTTON) {
175  cputc('[');
176  cputsn(w->widget.button.text, w->w);
177  cputc(']');
178  } else if (w->type == CTK_WIDGET_HYPERLINK) {
179  cputsn(w->widget.hyperlink.text, w->w);
180  } else if (w->type == CTK_WIDGET_TEXTENTRY) {
181  text = w->widget.textentry.text;
182  xscroll = 0;
183  if(w->widget.textentry.xpos >= w->w - 1) {
184  xscroll = w->widget.textentry.xpos - w->w + 1;
185  }
186  for(j = 0; j < w->h; ++j) {
187  gotoxy(xpos, ypos);
188  if(w->widget.textentry.state == CTK_TEXTENTRY_EDIT &&
189  w->widget.textentry.ypos == j) {
190  revers(0);
191  cputc('>');
192  for(i = 0; i < w->w; ++i) {
193  c = text[i + xscroll];
194  revers(i == w->widget.textentry.xpos - xscroll);
195  cputc((c == 0) ? CH_SPACE : c);
196  }
197  revers(0);
198  cputc('<');
199  } else {
200  cputc(CH_VERTLINE);
201  cputsn(text, w->w);
202  clearTo(xpos + w->w + 1);
203  cputc(CH_VERTLINE);
204  }
205  ++ypos;
206  text += w->w;
207  }
208 #if CTK_CONF_ICONS
209  } else if (w->type == CTK_WIDGET_ICON) {
210  if(w->widget.icon.textmap != NULL) {
211  for(i = 0; i < 3; ++i) {
212  gotoxy(xpos, ypos);
213  cputc(w->widget.icon.textmap[0 + 3 * i]);
214  cputc(w->widget.icon.textmap[1 + 3 * i]);
215  cputc(w->widget.icon.textmap[2 + 3 * i]);
216  ++ypos;
217  }
218  x = xpos;
219 
220  len = strlen(w->widget.icon.title);
221  if(x + len >= SCREEN_WIDTH) {
222  x = SCREEN_WIDTH - len;
223  }
224  gotoxy(x, ypos);
225  cputs(w->widget.icon.title);
226  }
227 #endif /* CTK_CONF_ICONS */
228  }
229  revers(0);
230 
231 }
232 /*---------------------------------------------------------------------------*/
233 void
235  unsigned char focus,
236  unsigned char clipy1,
237  unsigned char clipy2) {
238 
239  struct ctk_window *win = w->window;
240  unsigned char posx, posy;
241  clip(clipy1, clipy2);
242 
243  posx = win->x + 1;
244  posy = win->y + 2;
245 
246  if(w == win->focused) {
247  focus |= CTK_FOCUS_WIDGET;
248  }
249 
250  draw_widget(w, posx, posy, focus);
251 }
252 /*---------------------------------------------------------------------------*/
253 void
255  unsigned char focus,
256  unsigned char clipy1,
257  unsigned char clipy2) {
258 
259  unsigned char i;
260  unsigned char x1, x2, y1, y2;
261  x1 = window->x + 1;
262  x2 = x1 + window->w;
263  y1 = window->y + 2;
264  y2 = y1 + window->h;
265 
266  for(i = y1; i < y2; ++i) {
267  gotoxy(x1, i);
268  clearTo(x2);
269  }
270 }
271 /*---------------------------------------------------------------------------*/
272 void draw_window_sub(struct ctk_window *window, unsigned char focus) {
273 
274  unsigned char x, y;
275  unsigned char x1, y1, x2;
276  struct ctk_widget *w;
277  unsigned char wfocus;
278 
279  x = window->x;
280  y = window->y + 1;
281 
282  x1 = x + 1;
283  y1 = y + 1;
284  x2 = x1 + window->w;
285 
286  // |_
287  gotoxy(x, y1);
288  cvline(window->h);
289  cputc(CH_LLCORNER);
290  chline(window->w);
291  cputc(CH_LRCORNER);
292 
293  // -
294  gotoxy(x, y);
295  cputc(CH_ULCORNER);
296  chline(window->w);
297  cputc(CH_URCORNER);
298  // |
299  gotoxy(x2, y1);
300  cvline(window->h);
301 
302  /* Draw inactive widgets. */
303  for(w = window->inactive; w != NULL; w = w->next) {
304  draw_widget(w, x1, y1, focus);
305  }
306 
307  /* Draw active widgets. */
308  for(w = window->active; w != NULL; w = w->next) {
309  wfocus = focus;
310  if(w == window->focused) {
311  wfocus |= CTK_FOCUS_WIDGET;
312  }
313  draw_widget(w, x1, y1, wfocus);
314  }
315 }
316 /*---------------------------------------------------------------------------*/
317 void
318 ctk_draw_window(struct ctk_window *window, unsigned char focus,
319  unsigned char clipy1, unsigned char clipy2, unsigned char draw_borders) {
320  clip(clipy1, clipy2);
321 
322  focus = focus & CTK_FOCUS_WINDOW;
323  draw_window_sub(window, focus);
324 }
325 /*---------------------------------------------------------------------------*/
326 void ctk_draw_dialog(struct ctk_window *dialog) {
327  clip(0, SCREEN_HEIGHT);
328 
329  ctk_draw_clear_window(dialog, 0, 0, SCREEN_HEIGHT);
330  draw_window_sub(dialog, CTK_FOCUS_DIALOG);
331 }
332 /*---------------------------------------------------------------------------*/
333 #if CTK_CONF_MENUS
334 void draw_menu(struct ctk_menu *m, struct ctk_menu *open) {
335 #if CC_CONF_UNSIGNED_CHAR_BUGS
336  unsigned char x2;
337  unsigned int x, y;
338 #else
339  unsigned char x2;
340  unsigned char x, y;
341 #endif
342  x = cursx;
343  cputs(m->title);
344  cputc(CH_SPACE);
345 
346  if (m == open) {
347  x2 = cursx;
348  if(x + CTK_CONF_MENUWIDTH > SCREEN_WIDTH) {
349  x = SCREEN_WIDTH - CTK_CONF_MENUWIDTH;
350  }
351 
352  for(y = 0; y < m->nitems; y++) {
353  if(y == m->active) {
354  revers(0);
355  }
356  gotoxy(x, y + 1);
357  if(m->items[y].title[0] == '-') {
358  chline(CTK_CONF_MENUWIDTH);
359  } else {
360  cputs(m->items[y].title);
361  }
362  clearTo(x + CTK_CONF_MENUWIDTH);
363  revers(1);
364  }
365  gotoxy(x2, 0);
366  }
367 }
368 /*---------------------------------------------------------------------------*/
369 void ctk_draw_menus(struct ctk_menus *menus) {
370  struct ctk_menu *m;
371 
372  clip(0, SCREEN_HEIGHT);
373  /* Draw menus */
374  gotoxy(0, 0);
375  revers(1);
376  for(m = menus->menus->next; m != NULL; m = m->next) {
377  draw_menu(m, menus->open);
378  }
379 
380  clearTo(SCREEN_WIDTH - strlen(menus->desktopmenu->title) - 1);
381 
382  /* Draw desktopmenu */
383  draw_menu(menus->desktopmenu, menus->open);
384 
385  revers(0);
386 }
387 #endif /* CTK_CONF_MENUS */
388 /*---------------------------------------------------------------------------*/
389 /* Returns width and height of screen. */
390 unsigned char ctk_draw_width(void) {
391  return SCREEN_WIDTH;
392 }
393 unsigned char ctk_draw_height(void) {
394  return SCREEN_HEIGHT;
395 }
396