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