Contiki 2.6
|
00001 /** 00002 * \file 00003 * The ctk-draw implementation for the CTK VNC server. 00004 * \author Adam Dunkels <adam@dunkels.com> 00005 * 00006 */ 00007 00008 /** 00009 * \defgroup CTKVNCServer The CTK VNC server 00010 * @{ 00011 */ 00012 00013 /* 00014 * Copyright (c) 2003, Adam Dunkels. 00015 * All rights reserved. 00016 * 00017 * Redistribution and use in source and binary forms, with or without 00018 * modification, are permitted provided that the following conditions 00019 * are met: 00020 * 1. Redistributions of source code must retain the above copyright 00021 * notice, this list of conditions and the following disclaimer. 00022 * 2. Redistributions in binary form must reproduce the above 00023 * copyright notice, this list of conditions and the following 00024 * disclaimer in the documentation and/or other materials provided 00025 * with the distribution. 00026 * 3. The name of the author may not be used to endorse or promote 00027 * products derived from this software without specific prior 00028 * written permission. 00029 * 00030 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 00031 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00032 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00033 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 00034 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00035 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 00036 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00037 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 00038 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00039 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00040 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00041 * 00042 * This file is part of the "ctk" console GUI toolkit for cc65 00043 * 00044 * $Id: ctk-vncserver.c,v 1.3 2010/10/19 18:29:04 adamdunkels Exp $ 00045 * 00046 */ 00047 00048 #include <string.h> /* For strlen() */ 00049 00050 #include "ctk/ctk.h" 00051 #include "ctk/ctk-draw.h" 00052 00053 #include "contiki-net.h" 00054 00055 #include "ctk/vnc-server.h" 00056 #include "ctk/vnc-out.h" 00057 00058 #include "ctk/ctk-vncfont.h" 00059 #include "ctk/ctk-vncserver.h" 00060 00061 00062 static unsigned char sizex, sizey; 00063 00064 #define CH_ULCORNER 0x00 00065 #define CH_TITLEBAR 0x01 00066 #define CH_URCORNER 0x02 00067 #define CH_WINDOWRBORDER 0x03 00068 #define CH_LRCORNER 0x04 00069 #define CH_WINDOWLOWERBORDER 0x05 00070 #define CH_LLCORNER 0x06 00071 #define CH_WINDOWLBORDER 0x07 00072 00073 #define CH_DIALOG_ULCORNER 0x12 00074 #define CH_DIALOGUPPERBORDER 0x09 00075 #define CH_DIALOG_URCORNER 0x0a 00076 #define CH_DIALOGRBORDER 0x0b 00077 #define CH_DIALOG_LRCORNER 0x0c 00078 #define CH_DIALOGLOWERBORDER 0x0d 00079 #define CH_DIALOG_LLCORNER 0x0e 00080 #define CH_DIALOGLBORDER 0x0f 00081 00082 #define CH_BUTTONLEFT 0x10 00083 #define CH_BUTTONRIGHT 0x11 00084 00085 #define CH_SEPARATOR 0x13 00086 00087 #include "lib/libconio.h" 00088 00089 #define SCREENCOLOR 0 00090 #define BORDERCOLOR 1 00091 00092 #define WIDGETCOLOR 2 00093 #define WIDGETCOLOR_FWIN 3 00094 #define WIDGETCOLOR_FOCUS 4 00095 #define WIDGETCOLOR_DIALOG 5 00096 #define WIDGETCOLOR_HLINK 6 00097 #define WIDGETCOLOR_HLINK_FOCUS 7 00098 00099 #define WINDOWCOLOR 8 00100 #define WINDOWCOLOR_FOCUS 9 00101 00102 #define WINDOWBORDER 10 00103 #define WINDOWBORDER_FOCUS 11 00104 00105 #define DIALOGCOLOR 12 00106 00107 #define OPENMENUCOLOR 13 00108 00109 #define ACTIVEMENUITEMCOLOR 14 00110 00111 #define MENUCOLOR 15 00112 00113 00114 PROCESS(ctk_vncserver_process, "CTK VNC server"); 00115 00116 static struct vnc_server_state conns[CTK_VNCSERVER_CONF_NUMCONNS]; 00117 00118 #define PRINTF(x) 00119 00120 #define revers(x) 00121 00122 unsigned char ctk_draw_windowborder_height = 1; 00123 unsigned char ctk_draw_windowborder_width = 1; 00124 unsigned char ctk_draw_windowtitle_height = 1; 00125 00126 00127 /*-----------------------------------------------------------------------------------*/ 00128 /** 00129 * Add an update request from a client to the list of pending updates 00130 * for the connection. 00131 * 00132 * This function is called from the vnc-out module. 00133 * 00134 * \param vs The VNC connection state. 00135 * \param a The area that is requested to be updated. 00136 */ 00137 /*-----------------------------------------------------------------------------------*/ 00138 void 00139 vnc_server_update_add(struct vnc_server_state *vs, 00140 struct vnc_server_update *a) 00141 { 00142 /* XXX: test both head and tail placement!*/ 00143 a->next = vs->updates_pending; 00144 vs->updates_pending = a; 00145 } 00146 /*-----------------------------------------------------------------------------------*/ 00147 /** 00148 * Allocate an update request from the VNC connection state. 00149 * 00150 * This function is called from the vnc-out module. 00151 * 00152 * \param vs The VNC connection state. 00153 * 00154 * \return Memory for an update structure, or NULL if no update could 00155 * be allocated. 00156 */ 00157 /*-----------------------------------------------------------------------------------*/ 00158 struct vnc_server_update * 00159 vnc_server_update_alloc(struct vnc_server_state *vs) 00160 { 00161 struct vnc_server_update *a; 00162 00163 a = vs->updates_free; 00164 if(a == NULL) { 00165 return NULL; 00166 } 00167 vs->updates_free = a->next; 00168 a->next = NULL; 00169 return a; 00170 } 00171 /*-----------------------------------------------------------------------------------*/ 00172 /** 00173 * Deallocate an update request from the VNC connection state. 00174 * 00175 * This function is called from the vnc-out module. 00176 * 00177 * \param vs The VNC connection state. 00178 * 00179 * \param a The update structure to be deallocated. 00180 */ 00181 /*-----------------------------------------------------------------------------------*/ 00182 void 00183 vnc_server_update_free(struct vnc_server_state *vs, 00184 struct vnc_server_update *a) 00185 { 00186 a->next = vs->updates_free; 00187 vs->updates_free = a; 00188 } 00189 /*-----------------------------------------------------------------------------------*/ 00190 /** 00191 * Dequeue the first update on the queue of updates. 00192 * 00193 * This function is called from the vnc-out module. 00194 * 00195 * \param vs The VNC connection state. 00196 * 00197 * \return The first update on the queue, or NULL if the queue is empty. 00198 */ 00199 /*-----------------------------------------------------------------------------------*/ 00200 struct vnc_server_update * 00201 vnc_server_update_dequeue(struct vnc_server_state *vs) 00202 { 00203 struct vnc_server_update *a; 00204 00205 a = vs->updates_pending; 00206 if(a == NULL) { 00207 return a; 00208 } 00209 vs->updates_pending = a->next; 00210 a->next = NULL; 00211 return a; 00212 } 00213 /*-----------------------------------------------------------------------------------*/ 00214 /** 00215 * Remove a specific update on the queue of updates. 00216 * 00217 * \param vs The VNC connection state. 00218 * \param a The update to be removed. 00219 */ 00220 /*-----------------------------------------------------------------------------------*/ 00221 void 00222 vnc_server_update_remove(struct vnc_server_state *vs, 00223 struct vnc_server_update *a) 00224 { 00225 struct vnc_server_update *b, *c; 00226 00227 if(a == vs->updates_pending) { 00228 vs->updates_pending = a->next; 00229 } else { 00230 b = vs->updates_pending; 00231 for(c = vs->updates_pending; c != a; b = c, c = c->next); 00232 00233 b->next = a->next; 00234 } 00235 } 00236 /*-----------------------------------------------------------------------------------*/ 00237 /** \internal 00238 * Flag an area to be updated for all open VNC server connections. 00239 * 00240 */ 00241 /*-----------------------------------------------------------------------------------*/ 00242 static void 00243 update_area(uint8_t x, uint8_t y, uint8_t w, uint8_t h) 00244 { 00245 uint8_t i; 00246 00247 if(h == 0 || w == 0) { 00248 return; 00249 } 00250 00251 /* Update for all active VNC connections. */ 00252 for(i = 0; i < CTK_VNCSERVER_CONF_NUMCONNS; ++i) { 00253 if(conns[i].state != VNC_DEALLOCATED) { 00254 vnc_out_update_area(&conns[i], 00255 x, y, w, h); 00256 } 00257 } 00258 00259 } 00260 /*-----------------------------------------------------------------------------------*/ 00261 /** \internal 00262 * Allocate a VNC server connection state from the array of available 00263 * VNC connection states. 00264 */ 00265 /*-----------------------------------------------------------------------------------*/ 00266 static struct vnc_server_state * 00267 alloc_state(void) 00268 { 00269 uint8_t i; 00270 for(i = 0; i < CTK_VNCSERVER_CONF_NUMCONNS; ++i) { 00271 if(conns[i].state == VNC_DEALLOCATED) { 00272 return &conns[i]; 00273 } 00274 } 00275 00276 /* We are overloaded! XXX: we'll just kick all other connections! */ 00277 for(i = 0; i < CTK_VNCSERVER_CONF_NUMCONNS; ++i) { 00278 conns[i].state = VNC_DEALLOCATED; 00279 } 00280 00281 return NULL; 00282 } 00283 /*-----------------------------------------------------------------------------------*/ 00284 /** \internal 00285 * Deallocate a VNC connection state. 00286 */ 00287 /*-----------------------------------------------------------------------------------*/ 00288 static void 00289 dealloc_state(struct vnc_server_state *s) 00290 { 00291 s->state = VNC_DEALLOCATED; 00292 } 00293 /*-----------------------------------------------------------------------------------*/ 00294 static void 00295 cputsn(char *str, unsigned char len) 00296 { 00297 char c; 00298 00299 while(len > 0) { 00300 --len; 00301 c = *str; 00302 if(c == 0) { 00303 break; 00304 } 00305 cputc(c); 00306 ++str; 00307 } 00308 } 00309 /*-----------------------------------------------------------------------------------*/ 00310 /** 00311 * Initialize the VNC ctk-draw module. Called by the CTK module. 00312 * 00313 */ 00314 /*-----------------------------------------------------------------------------------*/ 00315 void 00316 ctk_draw_init(void) 00317 { 00318 bgcolor(SCREENCOLOR); 00319 bordercolor(BORDERCOLOR); 00320 screensize(&sizex, &sizey); 00321 ctk_draw_clear(0, sizey); 00322 } 00323 /*-----------------------------------------------------------------------------------*/ 00324 static void 00325 draw_widget(struct ctk_widget *w, 00326 unsigned char x, unsigned char y, 00327 unsigned char clipx, 00328 unsigned char clipy, 00329 unsigned char clipy1, unsigned char clipy2, 00330 unsigned char focus) 00331 { 00332 unsigned char xpos, ypos, xscroll; 00333 unsigned char i, j; 00334 unsigned char iconnum; 00335 char c, *text; 00336 unsigned char len; 00337 00338 /* 00339 if(focus & CTK_FOCUS_WINDOW) { 00340 textcolor(WIDGETCOLOR_FWIN); 00341 if(focus & CTK_FOCUS_WIDGET) { 00342 textcolor(WIDGETCOLOR_FOCUS); 00343 } 00344 } else if(focus & CTK_FOCUS_DIALOG) { 00345 textcolor(WIDGETCOLOR_DIALOG); 00346 if(focus & CTK_FOCUS_WIDGET) { 00347 textcolor(WIDGETCOLOR_FOCUS); 00348 } 00349 } else { 00350 textcolor(WIDGETCOLOR); 00351 } 00352 */ 00353 xpos = x + w->x; 00354 ypos = y + w->y; 00355 00356 switch(w->type) { 00357 case CTK_WIDGET_SEPARATOR: 00358 textcolor(VNC_OUT_SEPARATORCOLOR + focus); 00359 if(ypos >= clipy1 && ypos < clipy2) { 00360 /* chlinexy(xpos, ypos, w->w);*/ 00361 gotoxy(xpos, ypos); 00362 for(i = 0; i < w->w; ++i) { 00363 cputc(CH_SEPARATOR); 00364 } 00365 } 00366 break; 00367 case CTK_WIDGET_LABEL: 00368 textcolor(VNC_OUT_LABELCOLOR + focus); 00369 text = w->widget.label.text; 00370 for(i = 0; i < w->h; ++i) { 00371 if(ypos >= clipy1 && ypos < clipy2) { 00372 gotoxy(xpos, ypos); 00373 cputsn(text, w->w); 00374 if(w->w - (wherex() - xpos) > 0) { 00375 cclear(w->w - (wherex() - xpos)); 00376 } 00377 } 00378 ++ypos; 00379 text += w->w; 00380 } 00381 break; 00382 case CTK_WIDGET_BUTTON: 00383 textcolor(VNC_OUT_BUTTONCOLOR + focus); 00384 if(ypos >= clipy1 && ypos < clipy2) { 00385 if(focus & CTK_FOCUS_WIDGET) { 00386 revers(1); 00387 } else { 00388 revers(0); 00389 } 00390 cputcxy(xpos, ypos, CH_BUTTONLEFT); 00391 cputsn(w->widget.button.text, w->w); 00392 cputc(CH_BUTTONRIGHT); 00393 revers(0); 00394 } 00395 break; 00396 case CTK_WIDGET_HYPERLINK: 00397 textcolor(VNC_OUT_HYPERLINKCOLOR + focus); 00398 if(ypos >= clipy1 && ypos < clipy2) { 00399 /* if(focus & CTK_FOCUS_WIDGET) { 00400 textcolor(WIDGETCOLOR_HLINK_FOCUS); 00401 revers(0); 00402 } else { 00403 textcolor(WIDGETCOLOR_HLINK); 00404 revers(1); 00405 }*/ 00406 gotoxy(xpos, ypos); 00407 cputsn(w->widget.button.text, w->w); 00408 revers(0); 00409 } 00410 break; 00411 case CTK_WIDGET_TEXTENTRY: 00412 textcolor(VNC_OUT_TEXTENTRYCOLOR + focus); 00413 text = w->widget.textentry.text; 00414 xscroll = 0; 00415 if(w->widget.textentry.xpos >= w->w - 1) { 00416 xscroll = w->widget.textentry.xpos - w->w + 1; 00417 } 00418 for(j = 0; j < w->h; ++j) { 00419 if(ypos >= clipy1 && ypos < clipy2) { 00420 if(w->widget.textentry.state == CTK_TEXTENTRY_EDIT && 00421 w->widget.textentry.ypos == j) { 00422 revers(0); 00423 cputcxy(xpos, ypos, '>'); 00424 c = 1; 00425 for(i = 0; i < w->w; ++i) { 00426 if(c != 0) { 00427 c = text[i + xscroll]; 00428 } 00429 if(i == w->widget.textentry.xpos - xscroll) { 00430 textcolor(VNC_OUT_TEXTENTRYCOLOR + (focus ^ 0x01)); 00431 revers(1); 00432 } else { 00433 revers(0); 00434 } 00435 if(c == 0) { 00436 cputc(' '); 00437 } else { 00438 cputc(c); 00439 } 00440 revers(0); 00441 textcolor(VNC_OUT_TEXTENTRYCOLOR + focus); 00442 } 00443 cputc('<'); 00444 } else { 00445 if(focus & CTK_FOCUS_WIDGET && j == w->widget.textentry.ypos) { 00446 revers(1); 00447 } else { 00448 revers(0); 00449 } 00450 cvlinexy(xpos, ypos, 1); 00451 gotoxy(xpos + 1, ypos); 00452 cputsn(text, w->w); 00453 i = wherex(); 00454 if(i - xpos - 1 < w->w) { 00455 cclear(w->w - (i - xpos) + 1); 00456 } 00457 cvline(1); 00458 } 00459 } 00460 ++ypos; 00461 text += w->widget.textentry.len + 1; 00462 } 00463 revers(0); 00464 break; 00465 #if CTK_CONF_ICONS 00466 case CTK_WIDGET_ICON: 00467 if(ypos >= clipy1 && ypos < clipy2) { 00468 textcolor(VNC_OUT_ICONCOLOR + focus); 00469 if(focus & 1) { 00470 revers(1); 00471 } else { 00472 revers(0); 00473 } 00474 00475 x = xpos; 00476 len = strlen(w->widget.icon.title); 00477 if(x + len >= sizex) { 00478 x = sizex - len; 00479 } 00480 00481 gotoxy(x, ypos + 3); 00482 if(ypos >= clipy1 && ypos < clipy2) { 00483 cputs(w->widget.icon.title); 00484 } 00485 00486 #if CTK_CONF_ICON_BITMAPS 00487 if(w->widget.icon.bitmap != NULL) { 00488 iconnum = vnc_out_add_icon((struct ctk_icon *)w); 00489 textcolor(iconnum | (focus << 6)); 00490 gotoxy(xpos, ypos); 00491 cputc(0x80); 00492 cputc(0x81); 00493 cputc(0x82); 00494 cputc(0x83); 00495 ++ypos; 00496 gotoxy(xpos, ypos); 00497 cputc(0x90); 00498 cputc(0x91); 00499 cputc(0x92); 00500 cputc(0x93); 00501 ++ypos; 00502 gotoxy(xpos, ypos); 00503 cputc(0xa0); 00504 cputc(0xa1); 00505 cputc(0xa2); 00506 cputc(0xa3); 00507 ++ypos; 00508 textcolor(0); 00509 /* for(i = 0; i < 3; ++i) { 00510 00511 if(ypos >= clipy1 && ypos < clipy2) { 00512 cputc(w->widget.icon.textmap[0 + 3 * i]); 00513 cputc(w->widget.icon.textmap[1 + 3 * i]); 00514 cputc(w->widget.icon.textmap[2 + 3 * i]); 00515 } 00516 ++ypos; 00517 }*/ 00518 } 00519 #endif /* CTK_CONF_ICON_BITMAPS */ 00520 00521 revers(0); 00522 } 00523 break; 00524 #endif /* CTK_CONF_ICONS */ 00525 00526 default: 00527 break; 00528 } 00529 } 00530 /*-----------------------------------------------------------------------------------*/ 00531 /** 00532 * Draw a widget on the VNC screen. Called by the CTK module. 00533 * 00534 * \param w The widget to be drawn. 00535 * \param focus The focus of the widget. 00536 * \param clipy1 The lower y coordinate bound. 00537 * \param clipy2 The upper y coordinate bound. 00538 */ 00539 /*-----------------------------------------------------------------------------------*/ 00540 void 00541 ctk_draw_widget(struct ctk_widget *w, 00542 unsigned char focus, 00543 unsigned char clipy1, 00544 unsigned char clipy2) 00545 { 00546 struct ctk_window *win = w->window; 00547 struct ctk_icon *icon; 00548 unsigned char posx, posy, x, len; 00549 00550 posx = win->x + 1; 00551 posy = win->y + 2; 00552 00553 if(w == win->focused) { 00554 focus |= CTK_FOCUS_WIDGET; 00555 } 00556 00557 draw_widget(w, posx, posy, 00558 posx + win->w, 00559 posy + win->h, 00560 clipy1, clipy2, 00561 focus); 00562 00563 if(w->type != CTK_WIDGET_ICON) { 00564 update_area(posx + w->x, 00565 posy + w->y, w->w + 2, w->h); 00566 } else { 00567 icon = (struct ctk_icon *)w; 00568 00569 len = strlen(icon->title); 00570 x = posx + w->x; 00571 if(x + len >= sizex) { 00572 x = sizex - len; 00573 } 00574 00575 update_area(x, posy + w->y, len > 4? len: 4, w->h); 00576 } 00577 00578 #ifdef CTK_CONIO_CONF_UPDATE 00579 CTK_CONIO_CONF_UPDATE(); 00580 #endif /* CTK_CONIO_CONF_UPDATE */ 00581 } 00582 /*-----------------------------------------------------------------------------------*/ 00583 /** 00584 * Clear a window on the VNC screen. Called by the CTK module. 00585 * 00586 * \param window The window to be cleared. 00587 * \param focus The focus of the window. 00588 * \param clipy1 The lower y coordinate bound. 00589 * \param clipy2 The upper y coordinate bound. 00590 */ 00591 /*-----------------------------------------------------------------------------------*/ 00592 void 00593 ctk_draw_clear_window(struct ctk_window *window, 00594 unsigned char focus, 00595 unsigned char clipy1, 00596 unsigned char clipy2) 00597 { 00598 unsigned char i; 00599 unsigned char h; 00600 /* 00601 if(focus & CTK_FOCUS_WINDOW){ 00602 textcolor(WINDOWCOLOR_FOCUS); 00603 } else { 00604 textcolor(WINDOWCOLOR); 00605 }*/ 00606 textcolor(VNC_OUT_WINDOWCOLOR + focus); 00607 00608 h = window->y + 2 + window->h; 00609 /* Clear window contents. */ 00610 for(i = window->y + 2; i < h; ++i) { 00611 if(i >= clipy1 && i < clipy2) { 00612 cclearxy(window->x + 1, i, window->w); 00613 } 00614 } 00615 00616 update_area(window->x + 1, window->y + 2, window->w, window->h); 00617 } 00618 /*-----------------------------------------------------------------------------------*/ 00619 static void 00620 draw_window_contents(struct ctk_window *window, unsigned char focus, 00621 unsigned char clipy1, unsigned char clipy2, 00622 unsigned char x1, unsigned char x2, 00623 unsigned char y1, unsigned char y2) 00624 { 00625 struct ctk_widget *w; 00626 unsigned char wfocus; 00627 00628 /* Draw inactive widgets. */ 00629 for(w = window->inactive; w != NULL; w = w->next) { 00630 draw_widget(w, x1, y1, x2, y2, 00631 clipy1, clipy2, 00632 focus); 00633 } 00634 00635 /* Draw active widgets. */ 00636 for(w = window->active; w != NULL; w = w->next) { 00637 wfocus = focus; 00638 if(w == window->focused) { 00639 wfocus |= CTK_FOCUS_WIDGET; 00640 } 00641 00642 draw_widget(w, x1, y1, x2, y2, 00643 clipy1, clipy2, 00644 wfocus); 00645 } 00646 00647 #ifdef CTK_CONIO_CONF_UPDATE 00648 CTK_CONIO_CONF_UPDATE(); 00649 #endif /* CTK_CONIO_CONF_UPDATE */ 00650 00651 } 00652 /*-----------------------------------------------------------------------------------*/ 00653 /** 00654 * Draw a window on the VNC screen. Called by the CTK module. 00655 * 00656 * \param window The window to be drawn. 00657 * \param focus The focus of the window. 00658 * \param clipy1 The lower y coordinate bound. 00659 * \param clipy2 The upper y coordinate bound. 00660 * \param draw_borders The flag for border drawing. 00661 */ 00662 /*-----------------------------------------------------------------------------------*/ 00663 void 00664 ctk_draw_window(struct ctk_window *window, unsigned char focus, 00665 unsigned char clipy1, unsigned char clipy2, 00666 unsigned char draw_borders) 00667 { 00668 unsigned char x, y; 00669 unsigned char h; 00670 unsigned char x1, y1, x2, y2; 00671 unsigned char i; 00672 00673 00674 if(window->y + 1 >= clipy2) { 00675 return; 00676 } 00677 00678 x = window->x; 00679 y = window->y + 1; 00680 x1 = x + 1; 00681 y1 = y + 1; 00682 x2 = x1 + window->w; 00683 y2 = y1 + window->h; 00684 00685 if(draw_borders) { 00686 00687 /* Draw window frame. */ 00688 textcolor(VNC_OUT_WINDOWCOLOR + focus); 00689 /* if(focus & CTK_FOCUS_WINDOW) { 00690 textcolor(WINDOWCOLOR_FOCUS); 00691 } else { 00692 textcolor(WINDOWCOLOR); 00693 }*/ 00694 00695 if(y >= clipy1) { 00696 cputcxy(x, y, CH_ULCORNER); 00697 for(i = wherex() + window->titlelen + CTK_CONF_WINDOWMOVE * 2; i < x2; ++i) { 00698 cputcxy(i, y, CH_TITLEBAR); 00699 } 00700 cputcxy(x2, y, CH_URCORNER); 00701 } 00702 00703 h = window->h; 00704 00705 if(clipy1 > y1) { 00706 if(clipy1 - y1 < h) { 00707 h = clipy1 - y1; 00708 y1 = clipy1; 00709 } else { 00710 h = 0; 00711 } 00712 } 00713 00714 if(clipy2 < y1 + h) { 00715 if(y1 >= clipy2) { 00716 h = 0; 00717 } else { 00718 h = clipy2 - y1; 00719 } 00720 } 00721 00722 for(i = y1; i < y1 + h; ++i) { 00723 cputcxy(x, i, CH_WINDOWLBORDER); 00724 cputcxy(x2, i, CH_WINDOWRBORDER); 00725 } 00726 00727 /* cvlinexy(x, y1, h); 00728 cvlinexy(x2, y1, h); */ 00729 00730 if(y + window->h >= clipy1 && 00731 y + window->h < clipy2) { 00732 cputcxy(x, y2, CH_LLCORNER); 00733 for(i = x1; i < x2; ++i) { 00734 cputcxy(i, y2, CH_WINDOWLOWERBORDER); 00735 } 00736 /* chlinexy(x1, y2, window->w);*/ 00737 cputcxy(x2, y2, CH_LRCORNER); 00738 } 00739 } 00740 00741 draw_window_contents(window, focus, clipy1, clipy2, 00742 x1, x2, y + 1, y2); 00743 00744 update_area(window->x, window->y, window->w + 2, window->h + 2); 00745 } 00746 /*-----------------------------------------------------------------------------------*/ 00747 /** 00748 * Draw a dialog on the VNC screen. Called by the CTK module. 00749 * 00750 * \param dialog The dialog to be drawn. 00751 */ 00752 /*-----------------------------------------------------------------------------------*/ 00753 void 00754 ctk_draw_dialog(struct ctk_window *dialog) 00755 { 00756 unsigned char x, y; 00757 unsigned char i; 00758 unsigned char x1, y1, x2, y2; 00759 00760 /* textcolor(DIALOGCOLOR);*/ 00761 textcolor(VNC_OUT_WINDOWCOLOR + CTK_FOCUS_DIALOG); 00762 00763 x = dialog->x; 00764 y = dialog->y + 1; 00765 00766 00767 x1 = x + 1; 00768 y1 = y + 1; 00769 x2 = x1 + dialog->w; 00770 y2 = y1 + dialog->h; 00771 00772 00773 /* Draw dialog frame. */ 00774 00775 for(i = y1; i < y1 + dialog->h; ++i) { 00776 cputcxy(x, i, CH_DIALOGLBORDER); 00777 cputcxy(x2, i, CH_DIALOGRBORDER); 00778 } 00779 /* cvlinexy(x, y1, 00780 dialog->h); 00781 cvlinexy(x2, y1, 00782 dialog->h);*/ 00783 00784 00785 for(i = x1; i < x2; ++i) { 00786 cputcxy(i, y, CH_DIALOGUPPERBORDER); 00787 cputcxy(i, y2, CH_DIALOGLOWERBORDER); 00788 } 00789 /* chlinexy(x1, y, 00790 dialog->w); 00791 chlinexy(x1, y2, 00792 dialog->w);*/ 00793 00794 cputcxy(x, y, CH_DIALOG_ULCORNER); 00795 cputcxy(x, y2, CH_DIALOG_LLCORNER); 00796 cputcxy(x2, y, CH_DIALOG_URCORNER); 00797 cputcxy(x2, y2, CH_DIALOG_LRCORNER); 00798 00799 00800 /* Clear dialog contents. */ 00801 for(i = y1; i < y2; ++i) { 00802 cclearxy(x1, i, dialog->w); 00803 } 00804 00805 draw_window_contents(dialog, CTK_FOCUS_DIALOG, 0, sizey, 00806 x1, x2, y1, y2); 00807 00808 update_area(dialog->x, dialog->y, dialog->w + 4, dialog->h + 4); 00809 } 00810 /*-----------------------------------------------------------------------------------*/ 00811 /** 00812 * Clear parts of the VNC desktop. Called by the CTK module. 00813 * 00814 * \param y1 The lower y coordinate bound. 00815 * \param y2 The upped y coordinate bound. 00816 */ 00817 /*-----------------------------------------------------------------------------------*/ 00818 void 00819 ctk_draw_clear(unsigned char y1, unsigned char y2) 00820 { 00821 unsigned char i; 00822 00823 textcolor(VNC_OUT_BACKGROUNDCOLOR); 00824 for(i = y1; i < y2; ++i) { 00825 cclearxy(0, i, sizex); 00826 } 00827 00828 update_area(0, y1, sizex, y2 - y1); 00829 } 00830 /*-----------------------------------------------------------------------------------*/ 00831 /** \internal 00832 * Draw one menu on the VNC desktop. 00833 * 00834 * \param m The CTK menu to be drawn. 00835 */ 00836 /*-----------------------------------------------------------------------------------*/ 00837 static void 00838 draw_menu(struct ctk_menu *m) 00839 { 00840 unsigned char x, x2, y; 00841 00842 textcolor(VNC_OUT_MENUCOLOR); 00843 x = wherex(); 00844 cputs(m->title); 00845 cputc(' '); 00846 x2 = wherex(); 00847 if(x + CTK_CONF_MENUWIDTH > sizex) { 00848 x = sizex - CTK_CONF_MENUWIDTH; 00849 } 00850 00851 00852 for(y = 0; y < m->nitems; ++y) { 00853 if(y == m->active) { 00854 textcolor(VNC_OUT_ACTIVEMENUCOLOR); 00855 revers(0); 00856 } else { 00857 textcolor(VNC_OUT_MENUCOLOR); 00858 } 00859 gotoxy(x, y + 1); 00860 if(m->items[y].title[0] == '-') { 00861 chline(CTK_CONF_MENUWIDTH); 00862 } else { 00863 cputs(m->items[y].title); 00864 } 00865 if(x + CTK_CONF_MENUWIDTH > wherex()) { 00866 cclear(x + CTK_CONF_MENUWIDTH - wherex()); 00867 } 00868 revers(1); 00869 } 00870 00871 gotoxy(x2, 0); 00872 textcolor(VNC_OUT_MENUCOLOR); 00873 00874 update_area(x, 0, CTK_CONF_MENUWIDTH, m->nitems + 1); 00875 } 00876 /*-----------------------------------------------------------------------------------*/ 00877 /** 00878 * Draw the menus on the virtual VNC desktop. Called by the CTK module. 00879 * 00880 * \param menus The CTK menubar. 00881 */ 00882 /*-----------------------------------------------------------------------------------*/ 00883 void 00884 ctk_draw_menus(struct ctk_menus *menus) 00885 { 00886 struct ctk_menu *m; 00887 00888 00889 /* Draw menus */ 00890 textcolor(VNC_OUT_MENUCOLOR); 00891 gotoxy(0, 0); 00892 revers(1); 00893 cputc(' '); 00894 for(m = menus->menus->next; m != NULL; m = m->next) { 00895 if(m != menus->open) { 00896 update_area(wherex(), 0, strlen(m->title) + 1, 1); 00897 cputs(m->title); 00898 cputc(' '); 00899 } else { 00900 draw_menu(m); 00901 } 00902 } 00903 00904 00905 if(wherex() + strlen(menus->desktopmenu->title) + 1>= sizex) { 00906 gotoxy(sizex - strlen(menus->desktopmenu->title) - 1, 0); 00907 } else { 00908 cclear(sizex - wherex() - 00909 strlen(menus->desktopmenu->title) - 1); 00910 update_area(wherex(), 0, sizex - wherex() - 00911 strlen(menus->desktopmenu->title) - 1, 1); 00912 } 00913 00914 /* Draw desktopmenu */ 00915 if(menus->desktopmenu != menus->open) { 00916 update_area(wherex(), 0, strlen(menus->desktopmenu->title) + 1, 1); 00917 cputs(menus->desktopmenu->title); 00918 cputc(' '); 00919 } else { 00920 draw_menu(menus->desktopmenu); 00921 } 00922 00923 revers(0); 00924 00925 00926 00927 } 00928 /*-----------------------------------------------------------------------------------*/ 00929 /** 00930 * Obtain the height of the VNC desktop. Called by the CTK module. 00931 * 00932 * \return The height of the VNC desktop, in characters. 00933 */ 00934 /*-----------------------------------------------------------------------------------*/ 00935 unsigned char 00936 ctk_draw_height(void) 00937 { 00938 return sizey; 00939 } 00940 /*-----------------------------------------------------------------------------------*/ 00941 /** 00942 * Obtain the height of the VNC desktop. Called by the CTK module. 00943 * 00944 * \return The height of the VNC desktop, in characters. 00945 */ 00946 /*-----------------------------------------------------------------------------------*/ 00947 unsigned char 00948 ctk_draw_width(void) 00949 { 00950 return sizex; 00951 } 00952 /*-----------------------------------------------------------------------------------*/ 00953 unsigned char 00954 ctk_mouse_xtoc(unsigned short x) 00955 { 00956 return x / CTK_VNCFONT_WIDTH; 00957 } 00958 /*-----------------------------------------------------------------------------------*/ 00959 unsigned char 00960 ctk_mouse_ytoc(unsigned short y) 00961 { 00962 return y / CTK_VNCFONT_HEIGHT; 00963 } 00964 /*-----------------------------------------------------------------------------------*/ 00965 /** \internal 00966 * Converts between ASCII and the VNC screen character encoding. 00967 */ 00968 /*-----------------------------------------------------------------------------------*/ 00969 static unsigned char 00970 ascii2screen(unsigned char c) 00971 { 00972 if(c == '|') { 00973 return 0x68; 00974 } 00975 if(c < 0x20) { 00976 return c + 0x60; 00977 } 00978 if(c > 0x20 && c < 0x40) { 00979 return c; 00980 } 00981 if(c >= 0x40 && c < 0x60) { 00982 return c; 00983 } 00984 if(c >= 0x60 && c < 0x80) { 00985 return c - 0x60; 00986 } 00987 if(c >= 0x80) { 00988 return c; 00989 } 00990 00991 return 32; 00992 } 00993 /*-----------------------------------------------------------------------------------*/ 00994 /** 00995 * Draws a character on the virtual VNC screen. Called by the libconio module. 00996 * 00997 * \param c The character to be drawn. 00998 * \param xpos The x position of the character. 00999 * \param ypos The y position of the character. 01000 * \param reversedflag Determines if the character should be reversed or not. 01001 * \param color The color of the character. 01002 */ 01003 /*-----------------------------------------------------------------------------------*/ 01004 void 01005 ctk_arch_draw_char(char c, 01006 unsigned char xpos, 01007 unsigned char ypos, 01008 unsigned char reversedflag, 01009 unsigned char color) 01010 { 01011 01012 vnc_out_update_screen(xpos, ypos, ascii2screen(c), 01013 color); 01014 /* vnc_out_update_screen(xpos, ypos, c | 01015 (reversedflag? 0x80: 0));*/ 01016 } 01017 /*-----------------------------------------------------------------------------------*/ 01018 /** 01019 * Checks the key press input queue to see if there are pending 01020 * keys. Called by the CTK module. 01021 * 01022 * \return Zero if no key presses are in buffer, non-zero if there are 01023 * key presses in input buffer. 01024 */ 01025 /*-----------------------------------------------------------------------------------*/ 01026 unsigned char 01027 ctk_arch_keyavail(void) 01028 { 01029 return vnc_out_keyavail(); 01030 } 01031 /*-----------------------------------------------------------------------------------*/ 01032 /** 01033 * Retrieves key presses from the VNC client. Called by the CTK 01034 * module. 01035 * 01036 * \return The next key in the input queue. 01037 */ 01038 /*-----------------------------------------------------------------------------------*/ 01039 ctk_arch_key_t 01040 ctk_arch_getkey(void) 01041 { 01042 return vnc_out_getkey() & 0x7f; 01043 } 01044 /*-----------------------------------------------------------------------------------*/ 01045 /** \internal 01046 * The uIP event handler. 01047 */ 01048 /*-----------------------------------------------------------------------------------*/ 01049 void 01050 ctk_vncserver_appcall(void *state) 01051 { 01052 static struct vnc_server_state *vs; 01053 01054 vs = (struct vnc_server_state *)(state); 01055 01056 if(uip_connected()) { 01057 01058 /* Since we've just been connected, the state pointer should be 01059 NULL and we need to allocate a new state object. If we have run 01060 out of memory for state objects, we'll have to abort the 01061 connection and return. */ 01062 if(vs == NULL) { 01063 vs = alloc_state(); 01064 if(vs == NULL) { 01065 uip_close(); 01066 return; 01067 } 01068 tcp_markconn(uip_conn, (void *)vs); 01069 } 01070 } else if(uip_closed() || uip_aborted()) { 01071 if(vs != NULL) { 01072 dealloc_state(vs); 01073 } 01074 return; 01075 } 01076 vnc_server_appcall(vs); 01077 } 01078 /*-----------------------------------------------------------------------------------*/ 01079 PROCESS_THREAD(ctk_vncserver_process, ev, data) 01080 { 01081 int i; 01082 01083 PROCESS_BEGIN(); 01084 01085 tcp_listen(UIP_HTONS(5900)); 01086 01087 for(i = 0; i < CTK_VNCSERVER_CONF_NUMCONNS; ++i) { 01088 conns[i].state = VNC_DEALLOCATED; 01089 } 01090 while(1) { 01091 PROCESS_WAIT_EVENT(); 01092 if(ev == tcpip_event) { 01093 ctk_vncserver_appcall(data); 01094 } 01095 } 01096 PROCESS_END(); 01097 } 01098 /*-----------------------------------------------------------------------------------*/ 01099 /** @} */