blob: 74ba31f688a1eac4ebfd888455296eb9128ee106 [file] [log] [blame]
adamdunkelscc46c522003-09-01 22:24:24 +00001/**
2 * \file
3 * The ctk-draw implementation for the CTK VNC server.
4 * \author Adam Dunkels <adam@dunkels.com>
5 *
adamdunkelse937ded2003-10-01 07:53:57 +00006 */
7
8/**
9 * \defgroup CTKVNCServer The CTK VNC server
10 * @{
adamdunkelscc46c522003-09-01 22:24:24 +000011 */
12
adamdunkels2d015312003-07-02 21:34:00 +000013/*
adamdunkelscc46c522003-09-01 22:24:24 +000014 * Copyright (c) 2003, Adam Dunkels.
adamdunkels2d015312003-07-02 21:34:00 +000015 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
19 * are met:
20 * 1. Redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer.
22 * 2. Redistributions in binary form must reproduce the above
23 * copyright notice, this list of conditions and the following
24 * disclaimer in the documentation and/or other materials provided
25 * with the distribution.
adamdunkelscc46c522003-09-01 22:24:24 +000026 * 3. The name of the author may not be used to endorse or promote
adamdunkels2d015312003-07-02 21:34:00 +000027 * products derived from this software without specific prior
28 * written permission.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
31 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
32 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
34 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
36 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
37 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
38 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
39 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
40 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 *
42 * This file is part of the "ctk" console GUI toolkit for cc65
43 *
oliverschmidte43cb182006-05-28 20:38:19 +000044 * $Id: ctk-vncserver.c,v 1.17 2006/05/28 20:38:19 oliverschmidt Exp $
adamdunkels2d015312003-07-02 21:34:00 +000045 *
46 */
47
48#include "ctk.h"
49#include "ctk-draw.h"
50
adamdunkels0e840602004-07-04 11:40:56 +000051#include "contiki.h"
52
53#include "ek.h"
adamdunkels2d015312003-07-02 21:34:00 +000054#include "loader.h"
55#include "vnc-server.h"
56#include "vnc-out.h"
57
adamdunkels8b12b042004-08-09 20:27:07 +000058#include "ctk-vncfont.h"
adamdunkels2bd4ec42003-08-24 22:38:44 +000059#include "ctk-vncserver.h"
adamdunkelscc46c522003-09-01 22:24:24 +000060#include "ctk-vncserver-conf.h"
adamdunkels2bd4ec42003-08-24 22:38:44 +000061
adamdunkels2d015312003-07-02 21:34:00 +000062static unsigned char sizex, sizey;
63
64#define CH_ULCORNER 0x00
65#define CH_TITLEBAR 0x01
66#define CH_URCORNER 0x02
67#define CH_WINDOWRBORDER 0x03
68#define CH_LRCORNER 0x04
69#define CH_WINDOWLOWERBORDER 0x05
70#define CH_LLCORNER 0x06
71#define CH_WINDOWLBORDER 0x07
72
73#define CH_DIALOG_ULCORNER 0x12
74#define CH_DIALOGUPPERBORDER 0x09
75#define CH_DIALOG_URCORNER 0x0a
76#define CH_DIALOGRBORDER 0x0b
77#define CH_DIALOG_LRCORNER 0x0c
78#define CH_DIALOGLOWERBORDER 0x0d
79#define CH_DIALOG_LLCORNER 0x0e
80#define CH_DIALOGLBORDER 0x0f
81
82#define CH_BUTTONLEFT 0x10
83#define CH_BUTTONRIGHT 0x11
84
85#define CH_SEPARATOR 0x13
86
87#include "libconio.h"
88
89#define SCREENCOLOR 0
90#define BORDERCOLOR 1
91
92#define WIDGETCOLOR 2
93#define WIDGETCOLOR_FWIN 3
94#define WIDGETCOLOR_FOCUS 4
95#define WIDGETCOLOR_DIALOG 5
96#define WIDGETCOLOR_HLINK 6
97#define WIDGETCOLOR_HLINK_FOCUS 7
98
99#define WINDOWCOLOR 8
100#define WINDOWCOLOR_FOCUS 9
101
102#define WINDOWBORDER 10
103#define WINDOWBORDER_FOCUS 11
104
105#define DIALOGCOLOR 12
106
107#define OPENMENUCOLOR 13
108
109#define ACTIVEMENUITEMCOLOR 14
110
111#define MENUCOLOR 15
112
adamdunkels0e840602004-07-04 11:40:56 +0000113/*static DISPATCHER_UIPCALL(ctk_vncserver_appcall, state);
adamdunkels2d015312003-07-02 21:34:00 +0000114
115static struct dispatcher_proc p =
116 {DISPATCHER_PROC("CTK VNC server", NULL, NULL,
117 ctk_vncserver_appcall)};
adamdunkels0e840602004-07-04 11:40:56 +0000118 static ek_id_t id;*/
119EK_EVENTHANDLER(eventhandler, ev, data);
120EK_PROCESS(p, "CTK VNC server", EK_PRIO_NORMAL,
121 eventhandler, NULL, NULL);
122static ek_id_t id = EK_ID_NONE;
adamdunkels2d015312003-07-02 21:34:00 +0000123
adamdunkelscc46c522003-09-01 22:24:24 +0000124static struct vnc_server_state conns[CTK_VNCSERVER_CONF_NUMCONNS];
adamdunkels2d015312003-07-02 21:34:00 +0000125
126#define PRINTF(x)
127
128#define revers(x)
129
adamdunkels0e840602004-07-04 11:40:56 +0000130unsigned char ctk_draw_windowborder_height = 1;
131unsigned char ctk_draw_windowborder_width = 1;
132unsigned char ctk_draw_windowtitle_height = 1;
133
adamdunkels2d015312003-07-02 21:34:00 +0000134
135/*-----------------------------------------------------------------------------------*/
adamdunkelscc46c522003-09-01 22:24:24 +0000136/**
137 * Add an update request from a client to the list of pending updates
138 * for the connection.
139 *
140 * This function is called from the vnc-out module.
141 *
142 * \param vs The VNC connection state.
143 * \param a The area that is requested to be updated.
144 */
145/*-----------------------------------------------------------------------------------*/
adamdunkels2d015312003-07-02 21:34:00 +0000146void
147vnc_server_update_add(struct vnc_server_state *vs,
148 struct vnc_server_update *a)
149{
150 /* XXX: test both head and tail placement!*/
151 a->next = vs->updates_pending;
152 vs->updates_pending = a;
153}
adamdunkelscc46c522003-09-01 22:24:24 +0000154/*-----------------------------------------------------------------------------------*/
155/**
156 * Allocate an update request from the VNC connection state.
157 *
158 * This function is called from the vnc-out module.
159 *
160 * \param vs The VNC connection state.
161 *
162 * \return Memory for an update structure, or NULL if no update could
163 * be allocated.
164 */
165/*-----------------------------------------------------------------------------------*/
adamdunkels2d015312003-07-02 21:34:00 +0000166struct vnc_server_update *
167vnc_server_update_alloc(struct vnc_server_state *vs)
168{
169 struct vnc_server_update *a;
170
171 a = vs->updates_free;
172 if(a == NULL) {
173 return NULL;
174 }
175 vs->updates_free = a->next;
176 a->next = NULL;
177 return a;
178}
adamdunkelscc46c522003-09-01 22:24:24 +0000179/*-----------------------------------------------------------------------------------*/
180/**
181 * Deallocate an update request from the VNC connection state.
182 *
183 * This function is called from the vnc-out module.
184 *
185 * \param vs The VNC connection state.
186 *
187 * \param a The update structure to be deallocated.
188 */
189/*-----------------------------------------------------------------------------------*/
adamdunkels2d015312003-07-02 21:34:00 +0000190void
191vnc_server_update_free(struct vnc_server_state *vs,
192 struct vnc_server_update *a)
193{
194 a->next = vs->updates_free;
195 vs->updates_free = a;
196}
adamdunkelscc46c522003-09-01 22:24:24 +0000197/*-----------------------------------------------------------------------------------*/
198/**
199 * Dequeue the first update on the queue of updates.
200 *
201 * This function is called from the vnc-out module.
202 *
203 * \param vs The VNC connection state.
204 *
205 * \return The first update on the queue, or NULL if the queue is empty.
206 */
207/*-----------------------------------------------------------------------------------*/
adamdunkels2d015312003-07-02 21:34:00 +0000208struct vnc_server_update *
209vnc_server_update_dequeue(struct vnc_server_state *vs)
210{
211 struct vnc_server_update *a;
212
213 a = vs->updates_pending;
214 if(a == NULL) {
215 return a;
216 }
217 vs->updates_pending = a->next;
218 a->next = NULL;
219 return a;
220}
adamdunkelscc46c522003-09-01 22:24:24 +0000221/*-----------------------------------------------------------------------------------*/
222/**
223 * Remove a specific update on the queue of updates.
224 *
225 * \param vs The VNC connection state.
226 * \param a The update to be removed.
227 */
228/*-----------------------------------------------------------------------------------*/
adamdunkels2d015312003-07-02 21:34:00 +0000229void
230vnc_server_update_remove(struct vnc_server_state *vs,
231 struct vnc_server_update *a)
232{
233 struct vnc_server_update *b, *c;
234
235 if(a == vs->updates_pending) {
236 vs->updates_pending = a->next;
237 } else {
adamdunkelscc46c522003-09-01 22:24:24 +0000238 b = vs->updates_pending;
adamdunkels2d015312003-07-02 21:34:00 +0000239 for(c = vs->updates_pending; c != a; b = c, c = c->next);
240
241 b->next = a->next;
242 }
243}
244/*-----------------------------------------------------------------------------------*/
adamdunkelscc46c522003-09-01 22:24:24 +0000245/** \internal
246 * Flag an area to be updated for all open VNC server connections.
247 *
248 */
249/*-----------------------------------------------------------------------------------*/
adamdunkels2d015312003-07-02 21:34:00 +0000250static void
251update_area(u8_t x, u8_t y, u8_t w, u8_t h)
252{
253 u8_t i;
254
255 if(h == 0 || w == 0) {
256 return;
257 }
258
259 /* Update for all active VNC connections. */
adamdunkelscc46c522003-09-01 22:24:24 +0000260 for(i = 0; i < CTK_VNCSERVER_CONF_NUMCONNS; ++i) {
adamdunkels2d015312003-07-02 21:34:00 +0000261 if(conns[i].state != VNC_DEALLOCATED) {
262 vnc_out_update_area(&conns[i],
263 x, y, w, h);
264 }
265 }
266
267}
268/*-----------------------------------------------------------------------------------*/
adamdunkelscc46c522003-09-01 22:24:24 +0000269/** \internal
270 * Allocate a VNC server connection state from the array of available
271 * VNC connection states.
272 */
273/*-----------------------------------------------------------------------------------*/
adamdunkels2d015312003-07-02 21:34:00 +0000274static struct vnc_server_state *
275alloc_state(void)
276{
277 u8_t i;
adamdunkelscc46c522003-09-01 22:24:24 +0000278 for(i = 0; i < CTK_VNCSERVER_CONF_NUMCONNS; ++i) {
adamdunkels2d015312003-07-02 21:34:00 +0000279 if(conns[i].state == VNC_DEALLOCATED) {
280 return &conns[i];
281 }
282 }
283
284 /* We are overloaded! XXX: we'll just kick all other connections! */
adamdunkelscc46c522003-09-01 22:24:24 +0000285 for(i = 0; i < CTK_VNCSERVER_CONF_NUMCONNS; ++i) {
adamdunkels2d015312003-07-02 21:34:00 +0000286 conns[i].state = VNC_DEALLOCATED;
287 }
288
289 return NULL;
290}
291/*-----------------------------------------------------------------------------------*/
adamdunkelscc46c522003-09-01 22:24:24 +0000292/** \internal
293 * Deallocate a VNC connection state.
294 */
295/*-----------------------------------------------------------------------------------*/
adamdunkels2d015312003-07-02 21:34:00 +0000296static void
297dealloc_state(struct vnc_server_state *s)
298{
299 s->state = VNC_DEALLOCATED;
300}
301/*-----------------------------------------------------------------------------------*/
adamdunkels2d015312003-07-02 21:34:00 +0000302static void
303cputsn(char *str, unsigned char len)
304{
oliverschmidt4037b262004-06-27 20:59:05 +0000305 char c;
306
307 while(len > 0) {
308 --len;
309 c = *str;
310 if(c == 0) {
311 break;
312 }
313 cputc(c);
314 ++str;
315 }
adamdunkels2d015312003-07-02 21:34:00 +0000316}
317/*-----------------------------------------------------------------------------------*/
adamdunkelscc46c522003-09-01 22:24:24 +0000318/**
319 * Initialize the VNC ctk-draw module. Called by the CTK module.
320 *
321 */
322/*-----------------------------------------------------------------------------------*/
adamdunkels2d015312003-07-02 21:34:00 +0000323void
324ctk_draw_init(void)
325{
326 bgcolor(SCREENCOLOR);
327 bordercolor(BORDERCOLOR);
328 screensize(&sizex, &sizey);
329 ctk_draw_clear(0, sizey);
330}
331/*-----------------------------------------------------------------------------------*/
332static void
333draw_widget(struct ctk_widget *w,
334 unsigned char x, unsigned char y,
335 unsigned char clipx,
336 unsigned char clipy,
337 unsigned char clipy1, unsigned char clipy2,
338 unsigned char focus)
339{
340 unsigned char xpos, ypos, xscroll;
341 unsigned char i, j;
342 unsigned char iconnum;
343 char c, *text;
344 unsigned char len;
345
346 /*
347 if(focus & CTK_FOCUS_WINDOW) {
348 textcolor(WIDGETCOLOR_FWIN);
349 if(focus & CTK_FOCUS_WIDGET) {
350 textcolor(WIDGETCOLOR_FOCUS);
351 }
352 } else if(focus & CTK_FOCUS_DIALOG) {
353 textcolor(WIDGETCOLOR_DIALOG);
354 if(focus & CTK_FOCUS_WIDGET) {
355 textcolor(WIDGETCOLOR_FOCUS);
356 }
357 } else {
358 textcolor(WIDGETCOLOR);
359 }
360*/
361 xpos = x + w->x;
362 ypos = y + w->y;
363
364 switch(w->type) {
365 case CTK_WIDGET_SEPARATOR:
366 textcolor(VNC_OUT_SEPARATORCOLOR + focus);
367 if(ypos >= clipy1 && ypos < clipy2) {
368 /* chlinexy(xpos, ypos, w->w);*/
369 gotoxy(xpos, ypos);
370 for(i = 0; i < w->w; ++i) {
371 cputc(CH_SEPARATOR);
372 }
373 }
374 break;
375 case CTK_WIDGET_LABEL:
376 textcolor(VNC_OUT_LABELCOLOR + focus);
377 text = w->widget.label.text;
378 for(i = 0; i < w->h; ++i) {
379 if(ypos >= clipy1 && ypos < clipy2) {
380 gotoxy(xpos, ypos);
381 cputsn(text, w->w);
382 if(w->w - (wherex() - xpos) > 0) {
383 cclear(w->w - (wherex() - xpos));
384 }
385 }
386 ++ypos;
387 text += w->w;
388 }
389 break;
390 case CTK_WIDGET_BUTTON:
391 textcolor(VNC_OUT_BUTTONCOLOR + focus);
392 if(ypos >= clipy1 && ypos < clipy2) {
393 if(focus & CTK_FOCUS_WIDGET) {
394 revers(1);
395 } else {
396 revers(0);
397 }
398 cputcxy(xpos, ypos, CH_BUTTONLEFT);
399 cputsn(w->widget.button.text, w->w);
400 cputc(CH_BUTTONRIGHT);
401 revers(0);
402 }
403 break;
404 case CTK_WIDGET_HYPERLINK:
405 textcolor(VNC_OUT_HYPERLINKCOLOR + focus);
406 if(ypos >= clipy1 && ypos < clipy2) {
407 /* if(focus & CTK_FOCUS_WIDGET) {
408 textcolor(WIDGETCOLOR_HLINK_FOCUS);
409 revers(0);
410 } else {
411 textcolor(WIDGETCOLOR_HLINK);
412 revers(1);
413 }*/
414 gotoxy(xpos, ypos);
415 cputsn(w->widget.button.text, w->w);
416 revers(0);
417 }
418 break;
419 case CTK_WIDGET_TEXTENTRY:
420 textcolor(VNC_OUT_TEXTENTRYCOLOR + focus);
421 text = w->widget.textentry.text;
adamdunkels2d015312003-07-02 21:34:00 +0000422 xscroll = 0;
423 if(w->widget.textentry.xpos >= w->w - 1) {
424 xscroll = w->widget.textentry.xpos - w->w + 1;
425 }
426 for(j = 0; j < w->h; ++j) {
427 if(ypos >= clipy1 && ypos < clipy2) {
428 if(w->widget.textentry.state == CTK_TEXTENTRY_EDIT &&
429 w->widget.textentry.ypos == j) {
430 revers(0);
431 cputcxy(xpos, ypos, '>');
oliverschmidte43cb182006-05-28 20:38:19 +0000432 c = 1;
adamdunkels2d015312003-07-02 21:34:00 +0000433 for(i = 0; i < w->w; ++i) {
oliverschmidte43cb182006-05-28 20:38:19 +0000434 if(c != 0) {
435 c = text[i + xscroll];
436 }
adamdunkels2d015312003-07-02 21:34:00 +0000437 if(i == w->widget.textentry.xpos - xscroll) {
438 textcolor(VNC_OUT_TEXTENTRYCOLOR + (focus ^ 0x01));
439 revers(1);
440 } else {
441 revers(0);
442 }
443 if(c == 0) {
444 cputc(' ');
445 } else {
446 cputc(c);
447 }
448 revers(0);
449 textcolor(VNC_OUT_TEXTENTRYCOLOR + focus);
450 }
451 cputc('<');
452 } else {
oliverschmidtacdf6e92005-05-04 22:04:35 +0000453 if(focus & CTK_FOCUS_WIDGET && j == w->widget.textentry.ypos) {
454 revers(1);
455 } else {
456 revers(0);
457 }
adamdunkels2d015312003-07-02 21:34:00 +0000458 cvlinexy(xpos, ypos, 1);
459 gotoxy(xpos + 1, ypos);
460 cputsn(text, w->w);
461 i = wherex();
462 if(i - xpos - 1 < w->w) {
463 cclear(w->w - (i - xpos) + 1);
464 }
465 cvline(1);
466 }
467 }
468 ++ypos;
oliverschmidtcd6c30b2005-05-05 20:54:16 +0000469 text += w->widget.textentry.len + 1;
adamdunkels2d015312003-07-02 21:34:00 +0000470 }
471 revers(0);
472 break;
oliverschmidta98def52004-06-27 18:32:10 +0000473#if CTK_CONF_ICONS
adamdunkels2d015312003-07-02 21:34:00 +0000474 case CTK_WIDGET_ICON:
475 if(ypos >= clipy1 && ypos < clipy2) {
476 textcolor(VNC_OUT_ICONCOLOR + focus);
477 if(focus & 1) {
478 revers(1);
479 } else {
480 revers(0);
481 }
482
483 x = xpos;
484 len = strlen(w->widget.icon.title);
485 if(x + len >= sizex) {
486 x = sizex - len;
487 }
488
489 gotoxy(x, ypos + 3);
490 if(ypos >= clipy1 && ypos < clipy2) {
491 cputs(w->widget.icon.title);
492 }
493
oliverschmidta98def52004-06-27 18:32:10 +0000494#if CTK_CONF_ICON_BITMAPS
adamdunkels2d015312003-07-02 21:34:00 +0000495 if(w->widget.icon.bitmap != NULL) {
496 iconnum = vnc_out_add_icon((struct ctk_icon *)w);
adamdunkels2d015312003-07-02 21:34:00 +0000497 textcolor(iconnum | (focus << 6));
oliverschmidta98def52004-06-27 18:32:10 +0000498 gotoxy(xpos, ypos);
adamdunkels2d015312003-07-02 21:34:00 +0000499 cputc(0x80);
500 cputc(0x81);
501 cputc(0x82);
502 cputc(0x83);
503 ++ypos;
504 gotoxy(xpos, ypos);
505 cputc(0x90);
506 cputc(0x91);
507 cputc(0x92);
508 cputc(0x93);
509 ++ypos;
510 gotoxy(xpos, ypos);
511 cputc(0xa0);
512 cputc(0xa1);
513 cputc(0xa2);
514 cputc(0xa3);
515 ++ypos;
516 textcolor(0);
517 /* for(i = 0; i < 3; ++i) {
518
519 if(ypos >= clipy1 && ypos < clipy2) {
520 cputc(w->widget.icon.textmap[0 + 3 * i]);
521 cputc(w->widget.icon.textmap[1 + 3 * i]);
522 cputc(w->widget.icon.textmap[2 + 3 * i]);
523 }
524 ++ypos;
525 }*/
526 }
oliverschmidta98def52004-06-27 18:32:10 +0000527#endif /* CTK_CONF_ICON_BITMAPS */
528
adamdunkels2d015312003-07-02 21:34:00 +0000529 revers(0);
530 }
531 break;
oliverschmidta98def52004-06-27 18:32:10 +0000532#endif /* CTK_CONF_ICONS */
adamdunkels2d015312003-07-02 21:34:00 +0000533
534 default:
535 break;
536 }
537}
538/*-----------------------------------------------------------------------------------*/
adamdunkelscc46c522003-09-01 22:24:24 +0000539/**
540 * Draw a widget on the VNC screen. Called by the CTK module.
541 *
542 * \param w The widget to be drawn.
543 * \param focus The focus of the widget.
544 * \param clipy1 The lower y coordinate bound.
545 * \param clipy2 The upper y coordinate bound.
546 */
547/*-----------------------------------------------------------------------------------*/
adamdunkels2d015312003-07-02 21:34:00 +0000548void
549ctk_draw_widget(struct ctk_widget *w,
550 unsigned char focus,
551 unsigned char clipy1,
552 unsigned char clipy2)
553{
554 struct ctk_window *win = w->window;
555 struct ctk_icon *icon;
556 unsigned char posx, posy, x, len;
557
558 posx = win->x + 1;
559 posy = win->y + 2;
560
561 if(w == win->focused) {
562 focus |= CTK_FOCUS_WIDGET;
563 }
564
565 draw_widget(w, posx, posy,
566 posx + win->w,
567 posy + win->h,
568 clipy1, clipy2,
569 focus);
570
571 if(w->type != CTK_WIDGET_ICON) {
572 update_area(posx + w->x,
573 posy + w->y, w->w + 2, w->h);
574 } else {
575 icon = (struct ctk_icon *)w;
576
577 len = strlen(icon->title);
578 x = posx + w->x;
579 if(x + len >= sizex) {
580 x = sizex - len;
581 }
582
583 update_area(x, posy + w->y, len > 4? len: 4, w->h);
584 }
585
586#ifdef CTK_CONIO_CONF_UPDATE
587 CTK_CONIO_CONF_UPDATE();
588#endif /* CTK_CONIO_CONF_UPDATE */
589}
590/*-----------------------------------------------------------------------------------*/
adamdunkelscc46c522003-09-01 22:24:24 +0000591/**
592 * Clear a window on the VNC screen. Called by the CTK module.
593 *
594 * \param window The window to be cleared.
595 * \param focus The focus of the window.
596 * \param clipy1 The lower y coordinate bound.
597 * \param clipy2 The upper y coordinate bound.
598 */
599/*-----------------------------------------------------------------------------------*/
adamdunkels2d015312003-07-02 21:34:00 +0000600void
601ctk_draw_clear_window(struct ctk_window *window,
602 unsigned char focus,
603 unsigned char clipy1,
604 unsigned char clipy2)
605{
606 unsigned char i;
607 unsigned char h;
608 /*
609 if(focus & CTK_FOCUS_WINDOW){
610 textcolor(WINDOWCOLOR_FOCUS);
611 } else {
612 textcolor(WINDOWCOLOR);
613 }*/
614 textcolor(VNC_OUT_WINDOWCOLOR + focus);
615
616 h = window->y + 2 + window->h;
617 /* Clear window contents. */
618 for(i = window->y + 2; i < h; ++i) {
619 if(i >= clipy1 && i < clipy2) {
620 cclearxy(window->x + 1, i, window->w);
621 }
622 }
623
624 update_area(window->x + 1, window->y + 2, window->w, window->h);
625}
626/*-----------------------------------------------------------------------------------*/
627static void
628draw_window_contents(struct ctk_window *window, unsigned char focus,
629 unsigned char clipy1, unsigned char clipy2,
630 unsigned char x1, unsigned char x2,
631 unsigned char y1, unsigned char y2)
632{
633 struct ctk_widget *w;
634 unsigned char wfocus;
635
636 /* Draw inactive widgets. */
637 for(w = window->inactive; w != NULL; w = w->next) {
638 draw_widget(w, x1, y1, x2, y2,
639 clipy1, clipy2,
640 focus);
641 }
642
643 /* Draw active widgets. */
644 for(w = window->active; w != NULL; w = w->next) {
645 wfocus = focus;
646 if(w == window->focused) {
647 wfocus |= CTK_FOCUS_WIDGET;
648 }
649
650 draw_widget(w, x1, y1, x2, y2,
651 clipy1, clipy2,
652 wfocus);
653 }
654
655#ifdef CTK_CONIO_CONF_UPDATE
656 CTK_CONIO_CONF_UPDATE();
657#endif /* CTK_CONIO_CONF_UPDATE */
658
659}
660/*-----------------------------------------------------------------------------------*/
adamdunkelscc46c522003-09-01 22:24:24 +0000661/**
662 * Draw a window on the VNC screen. Called by the CTK module.
663 *
664 * \param window The window to be drawn.
665 * \param focus The focus of the window.
666 * \param clipy1 The lower y coordinate bound.
667 * \param clipy2 The upper y coordinate bound.
oliverschmidtd1040582005-03-15 16:07:35 +0000668 * \param draw_borders The flag for border drawing.
adamdunkelscc46c522003-09-01 22:24:24 +0000669 */
670/*-----------------------------------------------------------------------------------*/
adamdunkels2d015312003-07-02 21:34:00 +0000671void
672ctk_draw_window(struct ctk_window *window, unsigned char focus,
oliverschmidtadf27db2005-03-15 15:51:17 +0000673 unsigned char clipy1, unsigned char clipy2,
674 unsigned char draw_borders)
adamdunkels2d015312003-07-02 21:34:00 +0000675{
676 unsigned char x, y;
677 unsigned char h;
678 unsigned char x1, y1, x2, y2;
679 unsigned char i;
680
681
682 if(window->y + 1 >= clipy2) {
683 return;
684 }
685
686 x = window->x;
687 y = window->y + 1;
adamdunkels2d015312003-07-02 21:34:00 +0000688 x1 = x + 1;
689 y1 = y + 1;
690 x2 = x1 + window->w;
691 y2 = y1 + window->h;
692
oliverschmidtadf27db2005-03-15 15:51:17 +0000693 if(draw_borders) {
adamdunkels2d015312003-07-02 21:34:00 +0000694
oliverschmidtadf27db2005-03-15 15:51:17 +0000695 /* Draw window frame. */
696 textcolor(VNC_OUT_WINDOWCOLOR + focus);
697 /* if(focus & CTK_FOCUS_WINDOW) {
698 textcolor(WINDOWCOLOR_FOCUS);
adamdunkels2d015312003-07-02 21:34:00 +0000699 } else {
oliverschmidtadf27db2005-03-15 15:51:17 +0000700 textcolor(WINDOWCOLOR);
701 }*/
adamdunkels2d015312003-07-02 21:34:00 +0000702
oliverschmidtadf27db2005-03-15 15:51:17 +0000703 if(y >= clipy1) {
704 cputcxy(x, y, CH_ULCORNER);
oliverschmidt7b9025d2005-03-18 01:08:35 +0000705 for(i = wherex() + window->titlelen + CTK_CONF_WINDOWMOVE * 2; i < x2; ++i) {
oliverschmidtadf27db2005-03-15 15:51:17 +0000706 cputcxy(i, y, CH_TITLEBAR);
707 }
708 cputcxy(x2, y, CH_URCORNER);
adamdunkels2d015312003-07-02 21:34:00 +0000709 }
oliverschmidtadf27db2005-03-15 15:51:17 +0000710
711 h = window->h;
adamdunkels2d015312003-07-02 21:34:00 +0000712
oliverschmidtadf27db2005-03-15 15:51:17 +0000713 if(clipy1 > y1) {
714 if(clipy1 - y1 < h) {
715 h = clipy1 - y1;
716 y1 = clipy1;
717 } else {
718 h = 0;
719 }
adamdunkels2d015312003-07-02 21:34:00 +0000720 }
oliverschmidtadf27db2005-03-15 15:51:17 +0000721
722 if(clipy2 < y1 + h) {
723 if(y1 >= clipy2) {
724 h = 0;
725 } else {
726 h = clipy2 - y1;
727 }
728 }
729
730 for(i = y1; i < y1 + h; ++i) {
731 cputcxy(x, i, CH_WINDOWLBORDER);
732 cputcxy(x2, i, CH_WINDOWRBORDER);
733 }
734
735 /* cvlinexy(x, y1, h);
736 cvlinexy(x2, y1, h); */
737
738 if(y + window->h >= clipy1 &&
739 y + window->h < clipy2) {
740 cputcxy(x, y2, CH_LLCORNER);
741 for(i = x1; i < x2; ++i) {
742 cputcxy(i, y2, CH_WINDOWLOWERBORDER);
743 }
744 /* chlinexy(x1, y2, window->w);*/
745 cputcxy(x2, y2, CH_LRCORNER);
746 }
adamdunkels2d015312003-07-02 21:34:00 +0000747 }
748
oliverschmidte99386b2004-12-27 22:03:04 +0000749 draw_window_contents(window, focus, clipy1, clipy2,
adamdunkels2d015312003-07-02 21:34:00 +0000750 x1, x2, y + 1, y2);
751
752 update_area(window->x, window->y, window->w + 2, window->h + 2);
753}
754/*-----------------------------------------------------------------------------------*/
adamdunkelscc46c522003-09-01 22:24:24 +0000755/**
756 * Draw a dialog on the VNC screen. Called by the CTK module.
757 *
758 * \param dialog The dialog to be drawn.
759 */
760/*-----------------------------------------------------------------------------------*/
adamdunkels2d015312003-07-02 21:34:00 +0000761void
762ctk_draw_dialog(struct ctk_window *dialog)
763{
764 unsigned char x, y;
765 unsigned char i;
766 unsigned char x1, y1, x2, y2;
767
768 /* textcolor(DIALOGCOLOR);*/
769 textcolor(VNC_OUT_WINDOWCOLOR + CTK_FOCUS_DIALOG);
770
771 x = dialog->x;
772 y = dialog->y + 1;
773
774
775 x1 = x + 1;
776 y1 = y + 1;
777 x2 = x1 + dialog->w;
778 y2 = y1 + dialog->h;
779
780
781 /* Draw dialog frame. */
782
783 for(i = y1; i < y1 + dialog->h; ++i) {
784 cputcxy(x, i, CH_DIALOGLBORDER);
785 cputcxy(x2, i, CH_DIALOGRBORDER);
786 }
787 /* cvlinexy(x, y1,
788 dialog->h);
789 cvlinexy(x2, y1,
790 dialog->h);*/
791
792
793 for(i = x1; i < x2; ++i) {
794 cputcxy(i, y, CH_DIALOGUPPERBORDER);
795 cputcxy(i, y2, CH_DIALOGLOWERBORDER);
796 }
797 /* chlinexy(x1, y,
798 dialog->w);
799 chlinexy(x1, y2,
800 dialog->w);*/
801
802 cputcxy(x, y, CH_DIALOG_ULCORNER);
803 cputcxy(x, y2, CH_DIALOG_LLCORNER);
804 cputcxy(x2, y, CH_DIALOG_URCORNER);
805 cputcxy(x2, y2, CH_DIALOG_LRCORNER);
806
807
808 /* Clear dialog contents. */
809 for(i = y1; i < y2; ++i) {
810 cclearxy(x1, i, dialog->w);
811 }
812
813 draw_window_contents(dialog, CTK_FOCUS_DIALOG, 0, sizey,
814 x1, x2, y1, y2);
815
adamdunkels95bdfce2003-08-12 21:12:37 +0000816 update_area(dialog->x, dialog->y, dialog->w + 4, dialog->h + 4);
adamdunkels2d015312003-07-02 21:34:00 +0000817}
818/*-----------------------------------------------------------------------------------*/
adamdunkelscc46c522003-09-01 22:24:24 +0000819/**
820 * Clear parts of the VNC desktop. Called by the CTK module.
821 *
822 * \param y1 The lower y coordinate bound.
823 * \param y2 The upped y coordinate bound.
824 */
825/*-----------------------------------------------------------------------------------*/
adamdunkels2d015312003-07-02 21:34:00 +0000826void
827ctk_draw_clear(unsigned char y1, unsigned char y2)
828{
829 unsigned char i;
830
831 textcolor(VNC_OUT_BACKGROUNDCOLOR);
832 for(i = y1; i < y2; ++i) {
833 cclearxy(0, i, sizex);
834 }
835
836 update_area(0, y1, sizex, y2 - y1);
837}
838/*-----------------------------------------------------------------------------------*/
adamdunkelscc46c522003-09-01 22:24:24 +0000839/** \internal
840 * Draw one menu on the VNC desktop.
841 *
842 * \param m The CTK menu to be drawn.
843 */
844/*-----------------------------------------------------------------------------------*/
adamdunkels2d015312003-07-02 21:34:00 +0000845static void
846draw_menu(struct ctk_menu *m)
847{
848 unsigned char x, x2, y;
849
850 textcolor(VNC_OUT_MENUCOLOR);
851 x = wherex();
852 cputs(m->title);
853 cputc(' ');
854 x2 = wherex();
855 if(x + CTK_CONF_MENUWIDTH > sizex) {
856 x = sizex - CTK_CONF_MENUWIDTH;
857 }
858
859
860 for(y = 0; y < m->nitems; ++y) {
861 if(y == m->active) {
862 textcolor(VNC_OUT_ACTIVEMENUCOLOR);
863 revers(0);
864 } else {
865 textcolor(VNC_OUT_MENUCOLOR);
866 }
867 gotoxy(x, y + 1);
868 if(m->items[y].title[0] == '-') {
869 chline(CTK_CONF_MENUWIDTH);
870 } else {
871 cputs(m->items[y].title);
872 }
873 if(x + CTK_CONF_MENUWIDTH > wherex()) {
874 cclear(x + CTK_CONF_MENUWIDTH - wherex());
875 }
876 revers(1);
877 }
878
879 gotoxy(x2, 0);
880 textcolor(VNC_OUT_MENUCOLOR);
881
882 update_area(x, 0, CTK_CONF_MENUWIDTH, m->nitems + 1);
883}
884/*-----------------------------------------------------------------------------------*/
adamdunkelscc46c522003-09-01 22:24:24 +0000885/**
886 * Draw the menus on the virtual VNC desktop. Called by the CTK module.
887 *
888 * \param menus The CTK menubar.
889 */
890/*-----------------------------------------------------------------------------------*/
adamdunkels2d015312003-07-02 21:34:00 +0000891void
892ctk_draw_menus(struct ctk_menus *menus)
893{
894 struct ctk_menu *m;
895
896
897 /* Draw menus */
898 textcolor(VNC_OUT_MENUCOLOR);
899 gotoxy(0, 0);
900 revers(1);
901 cputc(' ');
902 for(m = menus->menus->next; m != NULL; m = m->next) {
903 if(m != menus->open) {
904 update_area(wherex(), 0, strlen(m->title) + 1, 1);
905 cputs(m->title);
906 cputc(' ');
907 } else {
908 draw_menu(m);
909 }
910 }
911
912
913 if(wherex() + strlen(menus->desktopmenu->title) + 1>= sizex) {
914 gotoxy(sizex - strlen(menus->desktopmenu->title) - 1, 0);
915 } else {
916 cclear(sizex - wherex() -
917 strlen(menus->desktopmenu->title) - 1);
918 update_area(wherex(), 0, sizex - wherex() -
919 strlen(menus->desktopmenu->title) - 1, 1);
920 }
921
922 /* Draw desktopmenu */
923 if(menus->desktopmenu != menus->open) {
924 update_area(wherex(), 0, strlen(menus->desktopmenu->title) + 1, 1);
925 cputs(menus->desktopmenu->title);
926 cputc(' ');
927 } else {
928 draw_menu(menus->desktopmenu);
929 }
930
931 revers(0);
932
933
934
935}
936/*-----------------------------------------------------------------------------------*/
adamdunkelscc46c522003-09-01 22:24:24 +0000937/**
938 * Obtain the height of the VNC desktop. Called by the CTK module.
939 *
940 * \return The height of the VNC desktop, in characters.
941 */
942/*-----------------------------------------------------------------------------------*/
adamdunkels2d015312003-07-02 21:34:00 +0000943unsigned char
944ctk_draw_height(void)
945{
946 return sizey;
947}
948/*-----------------------------------------------------------------------------------*/
adamdunkelscc46c522003-09-01 22:24:24 +0000949/**
950 * Obtain the height of the VNC desktop. Called by the CTK module.
951 *
952 * \return The height of the VNC desktop, in characters.
953 */
954/*-----------------------------------------------------------------------------------*/
adamdunkels2d015312003-07-02 21:34:00 +0000955unsigned char
956ctk_draw_width(void)
957{
958 return sizex;
959}
960/*-----------------------------------------------------------------------------------*/
adamdunkels8b12b042004-08-09 20:27:07 +0000961unsigned char
962ctk_mouse_xtoc(unsigned short x)
963{
964 return x / CTK_VNCFONT_WIDTH;
965}
966/*-----------------------------------------------------------------------------------*/
967unsigned char
968ctk_mouse_ytoc(unsigned short y)
969{
970 return y / CTK_VNCFONT_HEIGHT;
971}
972/*-----------------------------------------------------------------------------------*/
adamdunkelscc46c522003-09-01 22:24:24 +0000973/** \internal
974 * Converts between ASCII and the VNC screen character encoding.
975 */
976/*-----------------------------------------------------------------------------------*/
adamdunkels2d015312003-07-02 21:34:00 +0000977static unsigned char
978ascii2screen(unsigned char c)
979{
980 if(c == '|') {
981 return 0x68;
982 }
983 if(c < 0x20) {
984 return c + 0x60;
985 }
986 if(c > 0x20 && c < 0x40) {
987 return c;
988 }
989 if(c >= 0x40 && c < 0x60) {
990 return c;
991 }
992 if(c >= 0x60 && c < 0x80) {
993 return c - 0x60;
994 }
995 if(c >= 0x80) {
996 return c;
997 }
998
999 return 32;
1000}
adamdunkelscc46c522003-09-01 22:24:24 +00001001/*-----------------------------------------------------------------------------------*/
1002/**
1003 * Draws a character on the virtual VNC screen. Called by the libconio module.
1004 *
1005 * \param c The character to be drawn.
1006 * \param xpos The x position of the character.
1007 * \param ypos The y position of the character.
1008 * \param reversedflag Determines if the character should be reversed or not.
1009 * \param color The color of the character.
1010 */
1011/*-----------------------------------------------------------------------------------*/
adamdunkels2d015312003-07-02 21:34:00 +00001012void
1013ctk_arch_draw_char(char c,
1014 unsigned char xpos,
1015 unsigned char ypos,
1016 unsigned char reversedflag,
1017 unsigned char color)
1018{
1019
1020 vnc_out_update_screen(xpos, ypos, ascii2screen(c),
1021 color);
1022 /* vnc_out_update_screen(xpos, ypos, c |
1023 (reversedflag? 0x80: 0));*/
1024}
adamdunkelscc46c522003-09-01 22:24:24 +00001025/*-----------------------------------------------------------------------------------*/
1026/**
1027 * Checks the key press input queue to see if there are pending
1028 * keys. Called by the CTK module.
1029 *
1030 * \return Zero if no key presses are in buffer, non-zero if there are
1031 * key presses in input buffer.
1032 */
1033/*-----------------------------------------------------------------------------------*/
adamdunkels2d015312003-07-02 21:34:00 +00001034unsigned char
1035ctk_arch_keyavail(void)
1036{
1037 return vnc_out_keyavail();
1038}
adamdunkelscc46c522003-09-01 22:24:24 +00001039/*-----------------------------------------------------------------------------------*/
1040/**
1041 * Retrieves key presses from the VNC client. Called by the CTK
1042 * module.
1043 *
1044 * \return The next key in the input queue.
1045 */
1046/*-----------------------------------------------------------------------------------*/
adamdunkels2d015312003-07-02 21:34:00 +00001047ctk_arch_key_t
1048ctk_arch_getkey(void)
1049{
1050 return vnc_out_getkey() & 0x7f;
1051}
1052/*-----------------------------------------------------------------------------------*/
adamdunkelscc46c522003-09-01 22:24:24 +00001053/** \internal
1054 * The uIP event handler.
1055 */
1056/*-----------------------------------------------------------------------------------*/
adamdunkels0e840602004-07-04 11:40:56 +00001057void
1058ctk_vncserver_appcall(void *state)
adamdunkels2d015312003-07-02 21:34:00 +00001059{
1060 static struct vnc_server_state *vs;
adamdunkels2d015312003-07-02 21:34:00 +00001061
1062 vs = (struct vnc_server_state *)(state);
adamdunkels95bdfce2003-08-12 21:12:37 +00001063
adamdunkels2d015312003-07-02 21:34:00 +00001064 if(uip_connected()) {
1065
1066 /* Since we've just been connected, the state pointer should be
1067 NULL and we need to allocate a new state object. If we have run
1068 out of memory for state objects, we'll have to abort the
1069 connection and return. */
1070 if(vs == NULL) {
1071 vs = alloc_state();
1072 if(vs == NULL) {
1073 uip_close();
1074 return;
1075 }
adamdunkels0e840602004-07-04 11:40:56 +00001076 tcp_markconn(uip_conn, (void *)vs);
adamdunkels2d015312003-07-02 21:34:00 +00001077 }
1078 } else if(uip_closed() || uip_aborted()) {
1079 if(vs != NULL) {
1080 dealloc_state(vs);
1081 }
1082 return;
1083 }
1084 vnc_server_appcall(vs);
1085}
1086/*-----------------------------------------------------------------------------------*/
adamdunkels2bd4ec42003-08-24 22:38:44 +00001087LOADER_INIT_FUNC(ctk_vncserver_init, arg)
adamdunkels2d015312003-07-02 21:34:00 +00001088{
adamdunkels2bd4ec42003-08-24 22:38:44 +00001089 arg_free(arg);
adamdunkels2d015312003-07-02 21:34:00 +00001090
1091 if(id == EK_ID_NONE) {
adamdunkels0e840602004-07-04 11:40:56 +00001092 id = ek_start(&p);
1093 }
1094}
1095/*-----------------------------------------------------------------------------------*/
1096EK_EVENTHANDLER(eventhandler, ev, data)
1097{
1098 u8_t i;
1099 EK_EVENTHANDLER_ARGS(ev, data);
adamdunkels2d015312003-07-02 21:34:00 +00001100
adamdunkels0e840602004-07-04 11:40:56 +00001101 if(ev == EK_EVENT_INIT) {
1102 tcp_listen(HTONS(5900));
1103
adamdunkelscc46c522003-09-01 22:24:24 +00001104 for(i = 0; i < CTK_VNCSERVER_CONF_NUMCONNS; ++i) {
adamdunkels2d015312003-07-02 21:34:00 +00001105 conns[i].state = VNC_DEALLOCATED;
1106 }
adamdunkels0e840602004-07-04 11:40:56 +00001107 } else if(ev == tcpip_event) {
1108 ctk_vncserver_appcall(data);
adamdunkels2d015312003-07-02 21:34:00 +00001109 }
1110}
1111/*-----------------------------------------------------------------------------------*/
adamdunkelse937ded2003-10-01 07:53:57 +00001112/** @} */