blob: 45b4f1eb6521613d1236fb1eb6b4b1c12d1e78e3 [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 *
adamdunkelsa45d8a12003-04-08 07:22:13 +000035 * $Id: ctk-conio.c,v 1.2 2003/04/08 07:22:13 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) {
198 if(focus) {
199 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);
256}
257/*-----------------------------------------------------------------------------------*/
258void
259ctk_draw_clear_window(struct ctk_window *window,
260 unsigned char focus,
261 unsigned char clipy1,
262 unsigned char clipy2)
263{
264 unsigned char i;
265 unsigned char h;
266
267
268 h = window->y + 2 + window->h;
269 /* Clear window contents. */
270 for(i = window->y + 2; i < h; ++i) {
271 if(i >= clipy1 && i < clipy2) {
272 cclearxy(window->x + 1, i, window->w);
273 }
274 }
275}
276/*-----------------------------------------------------------------------------------*/
adamdunkelsa45d8a12003-04-08 07:22:13 +0000277static void
278draw_window_contents(struct ctk_window *window, unsigned char focus,
279 unsigned char clipy1, unsigned char clipy2,
280 unsigned char x1, unsigned char x2,
281 unsigned char y1, unsigned char y2)
282{
283 struct ctk_widget *w;
284 unsigned char wfocus;
285
286 /* Draw inactive widgets. */
287 for(w = window->inactive; w != NULL; w = w->next) {
288 draw_widget(w, x1, y1, x2, y2,
289 clipy1, clipy2,
290 focus);
291 }
292
293 /* Draw active widgets. */
294 for(w = window->active; w != NULL; w = w->next) {
295 wfocus = focus;
296 if(w == window->focused) {
297 wfocus |= CTK_FOCUS_WIDGET;
298 }
299
300 draw_widget(w, x1, y1, x2, y2,
301 clipy1, clipy2,
302 wfocus);
303 }
304
305}
306/*-----------------------------------------------------------------------------------*/
adamdunkels09c28b62003-04-02 10:17:52 +0000307void
308ctk_draw_window(struct ctk_window *window, unsigned char focus,
309 unsigned char clipy1, unsigned char clipy2)
310{
311 unsigned char x, y;
312 unsigned char h;
adamdunkels09c28b62003-04-02 10:17:52 +0000313 unsigned char x1, y1, x2, y2;
314
315 if(window->y + 1 >= clipy2) {
316 return;
317 }
318
319 x = window->x;
320 y = window->y + 1;
321
322 if(focus & CTK_FOCUS_WINDOW) {
323 textcolor(WINDOWCOLOR_FOCUS);
324 } else {
325 textcolor(WINDOWCOLOR);
326 }
327
328 x1 = x + 1;
329 y1 = y + 1;
330 x2 = x1 + window->w;
331 y2 = y1 + window->h;
332
333 /* Draw window frame. */
334 if(y >= clipy1) {
335 cputcxy(x, y, CH_ULCORNER);
336 /* cputc(' ');
337 cputs(window->title);
338 cputc(' ');*/
339 gotoxy(wherex() + window->titlelen + 2, wherey());
340 chline(window->w - (wherex() - x) - 2);
341 cputcxy(x2, y, CH_URCORNER);
342 }
343
344 h = window->h;
345
346 if(clipy1 > y1) {
347 if(clipy1 - y1 < h) {
348 h = clipy1 - y1;
349 y1 = clipy1;
350 } else {
351 h = 0;
352 }
353 }
354
355 if(y1 + h >= clipy2) {
356 if(y1 >= clipy2) {
357 h = 0;
358 } else {
359 h = clipy2 - y1;
360 }
361 }
362
363 cvlinexy(x, y1, h);
364 cvlinexy(x2, y1, h);
365
366 if(y + window->h >= clipy1 &&
367 y + window->h < clipy2) {
368 cputcxy(x, y2, CH_LLCORNER);
369 chlinexy(x1, y2, window->w);
370 cputcxy(x2, y2, CH_LRCORNER);
371 }
372
adamdunkelsa45d8a12003-04-08 07:22:13 +0000373 draw_window_contents(window, focus & CTK_FOCUS_WINDOW, clipy1, clipy2,
374 x1, x2, y1, y2);
adamdunkels09c28b62003-04-02 10:17:52 +0000375}
376/*-----------------------------------------------------------------------------------*/
377void
378ctk_draw_dialog(struct ctk_window *dialog)
379{
380 unsigned char x, y;
381 unsigned char i;
adamdunkels09c28b62003-04-02 10:17:52 +0000382 unsigned char x1, y1, x2, y2;
383
384 textcolor(DIALOGCOLOR);
385
386 x = dialog->x;
387 y = dialog->y + 1;
388
389
390 x1 = x + 1;
391 y1 = y + 1;
392 x2 = x1 + dialog->w;
393 y2 = y1 + dialog->h;
394
395
396 /* Draw dialog frame. */
397
398 cvlinexy(x, y1,
399 dialog->h);
400 cvlinexy(x2, y1,
401 dialog->h);
402
403 chlinexy(x1, y,
404 dialog->w);
405 chlinexy(x1, y2,
406 dialog->w);
407
408 cputcxy(x, y, CH_ULCORNER);
409 cputcxy(x, y2, CH_LLCORNER);
410 cputcxy(x2, y, CH_URCORNER);
411 cputcxy(x2, y2, CH_LRCORNER);
412
413
adamdunkels09c28b62003-04-02 10:17:52 +0000414 /* Clear dialog contents. */
415 for(i = y1; i < y2; ++i) {
416 cclearxy(x1, i, dialog->w);
417 }
adamdunkels09c28b62003-04-02 10:17:52 +0000418
adamdunkelsa45d8a12003-04-08 07:22:13 +0000419 draw_window_contents(dialog, CTK_FOCUS_DIALOG, 0, sizey,
420 x1, x2, y1, y2);
adamdunkels09c28b62003-04-02 10:17:52 +0000421}
422/*-----------------------------------------------------------------------------------*/
423void
424ctk_draw_clear(unsigned char y1, unsigned char y2)
425{
426 unsigned char i;
427
428 for(i = y1; i < y2; ++i) {
429 cclearxy(0, i, sizex);
430 }
431}
432/*-----------------------------------------------------------------------------------*/
433static void
434draw_menu(struct ctk_menu *m)
435{
436 unsigned char x, x2, y;
437 textcolor(OPENMENUCOLOR);
438 x = wherex();
439 cputs(m->title);
440 cputc(' ');
441 x2 = wherex();
442 if(x + CTK_CONF_MENUWIDTH > sizex) {
443 x = sizex - CTK_CONF_MENUWIDTH;
444 }
445
446
447 for(y = 0; y < m->nitems; ++y) {
448 if(y == m->active) {
449 textcolor(ACTIVEMENUITEMCOLOR);
450 revers(0);
451 } else {
452 textcolor(MENUCOLOR);
453 }
454 gotoxy(x, y + 1);
455 if(m->items[y].title[0] == '-') {
456 chline(CTK_CONF_MENUWIDTH);
457 } else {
458 cputs(m->items[y].title);
459 }
460 if(x + CTK_CONF_MENUWIDTH > wherex()) {
461 cclear(x + CTK_CONF_MENUWIDTH - wherex());
462 }
463 revers(1);
464 }
465 gotoxy(x2, 0);
466 textcolor(MENUCOLOR);
467}
468/*-----------------------------------------------------------------------------------*/
469void
470ctk_draw_menus(struct ctk_menus *menus)
471{
472 struct ctk_menu *m;
473
474
475 /* Draw menus */
476 textcolor(MENUCOLOR);
477 gotoxy(0, 0);
478 revers(1);
479 for(m = menus->menus->next; m != NULL; m = m->next) {
480 if(m != menus->open) {
481 cputs(m->title);
482 cputc(' ');
483 } else {
484 draw_menu(m);
485 }
486 }
487
488
489 if(wherex() + strlen(menus->desktopmenu->title) + 1>= sizex) {
490 gotoxy(sizex - strlen(menus->desktopmenu->title) - 1, 0);
491 } else {
492 cclear(sizex - wherex() -
493 strlen(menus->desktopmenu->title) - 1);
494 }
495
496 /* Draw desktopmenu */
497 if(menus->desktopmenu != menus->open) {
498 cputs(menus->desktopmenu->title);
499 cputc(' ');
500 } else {
501 draw_menu(menus->desktopmenu);
502 }
503
504 revers(0);
505}
506/*-----------------------------------------------------------------------------------*/
507unsigned char
508ctk_draw_height(void)
509{
510 return sizey;
511}
512/*-----------------------------------------------------------------------------------*/
513unsigned char
514ctk_draw_width(void)
515{
516 return sizex;
517}
518/*-----------------------------------------------------------------------------------*/