Contiki 2.6

ctk-vncserver.c

Go to the documentation of this file.
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 /** @} */