First version of the uVNC server port to Contiki
diff --git a/contiki/ctk/ctk-vncarch.h b/contiki/ctk/ctk-vncarch.h
new file mode 100644
index 0000000..e32b6be
--- /dev/null
+++ b/contiki/ctk/ctk-vncarch.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2002, Adam Dunkels.
+ * All rights reserved. 
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met: 
+ * 1. Redistributions of source code must retain the above copyright 
+ *    notice, this list of conditions and the following disclaimer. 
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials provided
+ *    with the distribution. 
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgement:
+ *        This product includes software developed by Adam Dunkels. 
+ * 4. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.  
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
+ *
+ * This file is part of the "ctk" console GUI toolkit for cc65
+ *
+ * $Id: ctk-vncarch.h,v 1.1 2003/07/02 21:34:47 adamdunkels Exp $
+ *
+ */
+#ifndef __CTK_VNCARCH_H__
+#define __CTK_VNCARCH_H__
+
+
+typedef char ctk_arch_key_t;
+
+unsigned char ctk_arch_keyavail(void);
+ctk_arch_key_t ctk_arch_getkey(void);
+
+#define CH_ENTER 0x0d
+#define CH_DEL 0x08
+
+#define CH_ESC 0x1b
+
+#define CH_HOME 0x50
+
+#define CH_TAB  0x09
+
+#define CH_CURS_LEFT  0x51
+#define CH_CURS_UP    0x52
+#define CH_CURS_RIGHT 0x53
+#define CH_CURS_DOWN  0x54
+
+
+
+
+
+#endif /* __CTK_VNCARCH_H__ */
diff --git a/contiki/ctk/ctk-vncfont.c b/contiki/ctk/ctk-vncfont.c
new file mode 100644
index 0000000..61d867c
--- /dev/null
+++ b/contiki/ctk/ctk-vncfont.c
@@ -0,0 +1,1203 @@
+/*
+ * Copyright (c) 2003, Adam Dunkels.
+ * All rights reserved. 
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met: 
+ * 1. Redistributions of source code must retain the above copyright 
+ *    notice, this list of conditions and the following disclaimer. 
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials provided
+ *    with the distribution. 
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgement:
+ *        This product includes software developed by Adam Dunkels. 
+ * 4. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.  
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
+ *
+ * This file is part of the Contiki VNC server
+ *
+ * $Id: ctk-vncfont.c,v 1.1 2003/07/02 21:34:00 adamdunkels Exp $
+ *
+ */
+
+#define _ 0x00
+#define o 0x01 /* 1001 0010 */
+#define X 0x02 /* 1111 0110 */
+
+#ifndef NOT_AVR
+#include <avr/pgmspace.h>
+#else
+#define prog_char unsigned char
+#endif
+
+prog_char ctk_vncfont[] = {
+/* Char 0x0 '?' */
+o,X,X,X,X,o,
+X,X,o,o,X,X,
+X,X,_,X,X,X,
+X,X,_,X,X,X,
+X,X,_,_,_,_,
+X,X,o,_,_,X,
+o,X,X,X,X,_,
+_,_,_,_,_,_,
+/* Char 0x1 '?' */
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,X,X,X,o,_,
+_,o,_,o,X,_,
+o,X,X,X,X,_,
+X,o,_,o,X,_,
+o,X,X,X,X,o,
+_,_,_,_,_,_,
+/* Char 0x2 '?' */
+_,_,_,_,_,_,
+X,o,_,_,_,_,
+X,_,_,_,_,_,
+X,X,X,X,o,_,
+X,_,_,o,X,_,
+X,_,_,o,X,_,
+X,X,X,X,o,_,
+_,_,_,_,_,_,
+/* Char 0x3 '?' */
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+o,X,X,X,o,_,
+X,o,_,_,_,_,
+X,_,_,_,_,_,
+X,o,_,_,o,_,
+o,X,X,X,o,_,
+_,_,_,_,_,_,
+/* Char 0x4 '?' */
+_,_,_,_,_,_,
+_,_,_,o,X,_,
+_,_,_,_,X,_,
+o,X,X,X,X,_,
+X,o,_,_,X,_,
+X,o,_,_,X,_,
+o,X,X,X,X,o,
+_,_,_,_,_,_,
+/* Char 0x5 '?' */
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+o,X,X,X,o,_,
+X,_,_,_,X,_,
+X,X,X,X,o,_,
+X,o,_,_,_,_,
+o,X,X,X,_,_,
+_,_,_,_,_,_,
+/* Char 0x6 '?' */
+_,_,_,_,_,_,
+_,_,o,X,X,_,
+_,_,X,o,_,_,
+_,X,X,X,X,_,
+_,o,X,_,_,_,
+_,_,X,_,_,_,
+_,_,X,o,_,_,
+_,_,_,_,_,_,
+/* Char 0x7 '?' */
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+o,X,X,X,X,_,
+X,o,_,o,X,_,
+X,o,_,o,X,_,
+o,X,X,X,X,_,
+_,_,_,o,X,_,
+_,X,X,X,o,_,
+/* Char 0x8 '?' */
+_,_,_,_,_,_,
+X,o,_,_,_,_,
+X,_,_,_,_,_,
+X,X,X,X,o,_,
+X,_,_,o,X,_,
+X,_,_,_,X,_,
+X,o,_,_,X,o,
+_,_,_,_,_,_,
+/* Char 0x9 '?' */
+_,_,_,_,_,_,
+_,_,X,_,_,_,
+_,_,_,_,_,_,
+_,X,X,_,_,_,
+_,o,X,_,_,_,
+_,o,X,o,_,_,
+_,X,X,X,_,_,
+_,_,_,_,_,_,
+/* Char 0xa '?' */
+_,_,_,_,_,_,
+_,_,_,_,X,_,
+_,_,_,_,_,_,
+_,_,_,X,X,_,
+_,_,_,o,X,_,
+_,_,_,_,X,_,
+_,_,_,o,X,_,
+_,X,X,X,o,_,
+/* Char 0xb '?' */
+_,_,_,_,_,_,
+X,o,_,_,_,_,
+X,_,_,_,_,_,
+X,_,o,X,_,_,
+X,X,X,o,_,_,
+X,_,o,X,o,_,
+X,o,_,o,X,o,
+_,_,_,_,_,_,
+/* Char 0xc '?' */
+_,_,_,_,_,_,
+_,X,X,_,_,_,
+_,o,X,_,_,_,
+_,_,X,_,_,_,
+_,_,X,_,_,_,
+_,o,X,o,_,_,
+_,X,X,X,_,_,
+_,_,_,_,_,_,
+/* Char 0xd '?' */
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+X,X,o,X,o,_,
+X,X,X,X,X,_,
+X,o,X,o,X,_,
+X,_,o,_,X,o,
+X,o,_,_,X,o,
+_,_,_,_,_,_,
+/* Char 0xe '?' */
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+X,o,X,X,o,_,
+X,X,_,o,X,_,
+X,_,_,_,X,_,
+X,_,_,_,X,_,
+X,_,_,_,X,o,
+_,_,_,_,_,_,
+/* Char 0xf '?' */
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+o,X,X,X,o,_,
+X,o,_,o,X,_,
+X,_,_,_,X,_,
+X,o,_,o,X,_,
+o,X,X,X,o,_,
+_,_,_,_,_,_,
+/* Char 0x10 '?' */
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+X,X,X,X,o,_,
+X,_,_,o,X,_,
+X,_,_,o,X,_,
+X,X,X,X,o,_,
+X,_,_,_,_,_,
+X,o,_,_,_,_,
+/* Char 0x11 '?' */
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+o,X,X,X,X,_,
+X,o,_,_,X,_,
+X,o,_,_,X,_,
+o,X,X,X,X,_,
+_,_,_,o,X,_,
+_,_,_,_,X,o,
+/* Char 0x12 '?' */
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+X,o,X,X,o,_,
+X,X,_,o,X,_,
+X,_,_,_,_,_,
+X,_,_,_,_,_,
+X,o,_,_,_,_,
+_,_,_,_,_,_,
+/* Char 0x13 '?' */
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+o,X,X,X,o,_,
+X,_,_,_,_,_,
+o,X,X,X,o,_,
+_,_,_,o,X,_,
+X,X,X,X,o,_,
+_,_,_,_,_,_,
+/* Char 0x14 '?' */
+_,_,_,_,_,_,
+_,o,X,_,_,_,
+X,X,X,X,X,_,
+_,_,X,o,_,_,
+_,_,X,_,_,_,
+_,_,X,o,_,_,
+_,_,o,X,o,_,
+_,_,_,_,_,_,
+/* Char 0x15 '?' */
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+X,o,_,_,X,_,
+X,_,_,_,X,_,
+X,_,_,_,X,_,
+X,o,_,_,X,_,
+o,X,X,X,X,o,
+_,_,_,_,_,_,
+/* Char 0x16 '?' */
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+X,o,_,_,X,o,
+X,_,_,_,X,_,
+X,o,_,o,X,_,
+o,X,o,X,o,_,
+_,o,X,o,_,_,
+_,_,_,_,_,_,
+/* Char 0x17 '?' */
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+X,o,_,_,X,o,
+X,_,_,_,X,_,
+X,_,o,_,X,_,
+X,o,X,o,X,_,
+o,X,o,X,X,o,
+_,_,_,_,_,_,
+/* Char 0x18 '?' */
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+X,o,_,o,X,o,
+o,X,o,X,o,_,
+_,o,X,o,_,_,
+o,X,o,X,o,_,
+X,o,_,o,X,o,
+_,_,_,_,_,_,
+/* Char 0x19 '?' */
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+X,o,_,_,X,o,
+X,_,_,_,X,_,
+X,o,_,_,X,_,
+o,X,X,X,X,_,
+_,_,_,o,X,_,
+_,o,X,X,o,_,
+/* Char 0x1a '?' */
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+X,X,X,X,X,_,
+o,_,o,X,o,_,
+_,o,X,o,_,_,
+o,X,o,_,X,_,
+X,X,X,X,X,_,
+_,_,_,_,_,_,
+/* Char 0x1b '?' */
+_,X,X,X,X,_,
+_,X,o,_,_,_,
+_,X,_,_,_,_,
+_,X,_,_,_,_,
+_,X,_,_,_,_,
+_,X,o,_,_,_,
+_,X,X,X,X,_,
+_,_,_,_,_,_,
+/* Char 0x1c '?' */
+_,_,_,X,X,_,
+_,o,X,_,_,X,
+o,X,X,o,_,_,
+X,X,X,X,X,_,
+o,X,X,o,_,_,
+X,X,o,_,_,X,
+X,X,X,X,X,_,
+_,_,_,_,_,_,
+/* Char 0x1d '?' */
+_,X,X,X,X,_,
+_,_,_,o,X,_,
+_,_,_,_,X,_,
+_,_,_,_,X,_,
+_,_,_,_,X,_,
+_,_,_,o,X,_,
+_,X,X,X,X,_,
+_,_,_,_,_,_,
+/* Char 0x1e '?' */
+_,_,_,_,_,_,
+o,X,o,_,_,_,
+X,o,X,o,X,_,
+_,_,o,X,o,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+/* Char 0x1f '?' */
+_,_,_,_,_,_,
+_,o,X,_,_,_,
+o,X,X,o,_,_,
+X,X,X,X,X,X,
+X,X,X,X,X,X,
+o,X,X,o,_,_,
+_,o,X,_,_,_,
+_,_,_,_,_,_,
+/* Char 0x20 ' ' */
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+/* Char 0x21 '!' */
+_,_,X,X,_,_,
+_,_,X,o,_,_,
+_,_,X,_,_,_,
+_,_,X,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,X,_,_,_,
+_,_,_,_,_,_,
+/* Char 0x22 '"' */
+X,_,_,_,X,_,
+X,_,_,_,X,_,
+X,_,_,_,X,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+/* Char 0x23 '#' */
+_,X,_,_,X,_,
+_,X,o,o,X,_,
+X,X,X,X,X,X,
+_,X,o,o,X,_,
+X,X,X,X,X,X,
+_,X,_,_,X,_,
+_,X,_,_,X,_,
+_,_,_,_,_,_,
+/* Char 0x24 '$' */
+_,o,X,X,o,_,
+o,X,X,X,X,X,
+X,X,o,_,_,_,
+o,X,X,X,X,o,
+_,_,_,o,X,X,
+X,X,X,X,X,o,
+_,o,X,X,o,_,
+_,_,_,_,_,_,
+/* Char 0x25 '%' */
+X,X,_,_,o,X,
+X,X,_,o,X,X,
+_,_,o,X,X,o,
+_,o,X,X,o,_,
+o,X,X,o,_,_,
+X,X,o,_,X,X,
+X,o,_,_,X,X,
+_,_,_,_,_,_,
+/* Char 0x26 '&' */
+o,X,X,X,o,_,
+X,o,_,o,X,_,
+o,X,X,X,o,_,
+_,o,X,o,_,_,
+X,o,_,_,X,_,
+X,o,o,X,X,_,
+o,X,X,o,X,_,
+_,_,_,_,_,_,
+/* Char 0x27 ''' */
+_,_,_,o,X,_,
+_,_,o,X,o,_,
+_,_,X,o,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+/* Char 0x28 '(' */
+_,_,o,X,_,_,
+_,o,X,o,_,_,
+_,X,o,_,_,_,
+_,X,_,_,_,_,
+_,X,o,_,_,_,
+_,o,X,o,_,_,
+_,_,o,X,_,_,
+_,_,_,_,_,_,
+/* Char 0x29 ')' */
+_,_,X,o,_,_,
+_,_,o,X,o,_,
+_,_,_,o,X,_,
+_,_,_,_,X,_,
+_,_,_,o,X,_,
+_,_,o,X,o,_,
+_,_,X,o,_,_,
+_,_,_,_,_,_,
+/* Char 0x2a '*' */
+_,_,_,_,_,_,
+X,o,_,o,X,_,
+o,X,o,X,o,_,
+X,X,X,X,X,_,
+o,X,o,X,o,_,
+X,o,_,o,X,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+/* Char 0x2b '+' */
+_,_,_,_,_,_,
+_,_,X,_,_,_,
+_,_,X,o,_,_,
+X,X,X,X,X,_,
+_,o,X,_,_,_,
+_,_,X,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+/* Char 0x2c ',' */
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,X,_,_,_,
+_,o,X,_,_,_,
+_,X,o,_,_,_,
+/* Char 0x2d '-' */
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+X,X,X,X,X,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+/* Char 0x2e '.' */
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,X,_,_,_,
+_,_,X,_,_,_,
+_,_,_,_,_,_,
+/* Char 0x2f '/' */
+_,_,_,_,_,_,
+_,_,_,o,X,_,
+_,_,o,X,o,_,
+_,o,X,o,_,_,
+_,X,o,_,_,_,
+o,X,o,_,_,_,
+o,X,o,_,_,_,
+_,_,_,_,_,_,
+/* Char 0x30 '0' */
+o,X,X,X,o,_,
+X,_,_,o,X,_,
+X,_,o,X,X,_,
+X,_,X,o,X,_,
+X,X,o,_,X,_,
+X,o,_,o,X,_,
+o,X,X,X,o,_,
+_,_,_,_,_,_,
+/* Char 0x31 '1' */
+_,o,X,_,_,_,
+_,X,X,_,_,_,
+_,o,X,_,_,_,
+_,_,X,_,_,_,
+_,_,X,_,_,_,
+_,o,X,o,_,_,
+_,X,X,X,_,_,
+_,_,_,_,_,_,
+/* Char 0x32 '2' */
+o,X,X,X,o,_,
+X,o,_,o,X,_,
+_,_,_,o,X,_,
+_,o,X,X,o,_,
+o,X,o,_,_,_,
+X,o,_,_,_,_,
+X,X,X,X,X,_,
+_,_,_,_,_,_,
+/* Char 0x33 '3' */
+o,X,X,X,o,_,
+X,o,_,o,X,_,
+_,_,_,o,X,_,
+_,_,X,X,o,_,
+_,_,_,o,X,_,
+X,o,_,o,X,_,
+o,X,X,X,o,_,
+_,_,_,_,_,_,
+/* Char 0x34 '4' */
+_,_,_,o,X,_,
+_,_,o,X,X,_,
+_,o,X,o,X,_,
+o,X,o,_,X,_,
+X,X,X,X,X,_,
+_,_,_,o,X,_,
+_,_,_,_,X,X,
+_,_,_,_,_,_,
+/* Char 0x35 '5' */
+X,X,X,X,X,_,
+X,o,_,_,o,_,
+X,X,X,X,o,_,
+_,_,_,o,X,_,
+_,_,_,_,X,_,
+X,o,_,o,X,_,
+o,X,X,X,o,_,
+_,_,_,_,_,_,
+/* Char 0x36 '6' */
+o,X,X,X,o,_,
+X,o,_,o,X,_,
+X,o,_,_,_,_,
+X,X,X,X,o,_,
+X,o,_,o,X,_,
+X,o,_,o,X,_,
+o,X,X,X,o,_,
+_,_,_,_,_,_,
+/* Char 0x37 '7' */
+X,X,X,X,X,_,
+X,_,_,o,X,_,
+_,_,_,o,X,_,
+_,_,_,X,o,_,
+_,_,o,X,_,_,
+_,_,X,o,_,_,
+_,_,X,_,_,_,
+_,_,_,_,_,_,
+/* Char 0x38 '8' */
+o,X,X,X,o,_,
+X,o,_,o,X,_,
+X,o,_,o,X,_,
+o,X,X,X,o,_,
+X,o,_,o,X,_,
+X,o,_,o,X,_,
+o,X,X,X,o,_,
+_,_,_,_,_,_,
+/* Char 0x39 '9' */
+o,X,X,X,o,_,
+X,o,_,o,X,_,
+X,o,_,_,X,_,
+o,X,X,X,X,_,
+_,_,_,o,X,_,
+X,o,_,o,X,_,
+o,X,X,X,o,_,
+_,_,_,_,_,_,
+/* Char 0x3a ':' */
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,X,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,X,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+/* Char 0x3b ';' */
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,X,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,X,_,_,_,
+_,o,X,_,_,_,
+_,X,o,o,_,_,
+/* Char 0x3c '<' */
+_,_,o,X,X,_,
+_,o,X,o,_,_,
+o,X,o,_,_,_,
+X,o,_,_,_,_,
+o,X,o,_,_,_,
+_,o,X,o,_,_,
+_,_,o,X,X,_,
+_,_,_,_,_,_,
+/* Char 0x3d '=' */
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+X,X,X,X,X,_,
+_,_,_,_,_,_,
+X,X,X,X,X,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+/* Char 0x3e '>' */
+X,X,o,_,_,_,
+_,o,X,o,_,_,
+_,_,o,X,o,_,
+_,_,_,o,X,_,
+_,_,o,X,o,_,
+_,o,X,o,_,_,
+X,X,o,_,_,_,
+_,_,_,_,_,_,
+/* Char 0x3f '?' */
+o,X,X,X,o,_,
+X,o,_,o,X,_,
+_,_,_,o,X,_,
+_,_,o,X,o,_,
+_,_,X,o,_,_,
+_,_,_,_,_,_,
+_,_,X,_,_,_,
+_,_,_,_,_,_,
+/* Char 0x40 '@' */
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+X,X,X,X,X,X,
+X,X,X,X,X,X,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+/* Char 0x41 'A' */
+_,o,X,o,_,_,
+o,X,o,X,o,_,
+X,o,_,o,X,_,
+X,o,_,o,X,_,
+X,X,X,X,X,_,
+X,_,_,o,X,_,
+X,o,_,_,X,o,
+_,_,_,_,_,_,
+/* Char 0x42 'B' */
+X,X,X,X,o,_,
+X,_,_,o,X,_,
+X,_,_,o,X,_,
+X,X,X,X,o,_,
+X,_,_,o,X,_,
+X,_,_,o,X,_,
+X,X,X,X,o,_,
+_,_,_,_,_,_,
+/* Char 0x43 'C' */
+o,X,X,X,o,_,
+X,o,_,_,X,_,
+X,_,_,_,_,_,
+X,_,_,_,_,_,
+X,_,_,_,_,_,
+X,o,_,_,X,_,
+o,X,X,X,o,_,
+_,_,_,_,_,_,
+/* Char 0x44 'D' */
+X,X,X,o,_,_,
+X,_,o,X,o,_,
+X,_,_,o,X,_,
+X,_,_,_,X,_,
+X,_,_,o,X,_,
+X,_,o,X,o,_,
+X,X,X,o,_,_,
+_,_,_,_,_,_,
+/* Char 0x45 'E' */
+X,X,X,X,X,_,
+X,_,_,_,o,_,
+X,_,_,_,_,_,
+X,X,X,X,_,_,
+X,_,_,_,_,_,
+X,_,_,_,o,_,
+X,X,X,X,X,_,
+_,_,_,_,_,_,
+/* Char 0x46 'F' */
+X,X,X,X,X,_,
+X,_,_,_,o,_,
+X,_,_,_,_,_,
+X,X,X,o,_,_,
+X,_,_,_,_,_,
+X,_,_,_,_,_,
+X,o,_,_,_,_,
+_,_,_,_,_,_,
+/* Char 0x47 'G' */
+o,X,X,X,o,_,
+X,o,_,o,X,_,
+X,_,_,_,_,_,
+X,_,_,X,X,_,
+X,_,_,o,X,_,
+X,o,_,o,X,_,
+o,X,X,X,o,_,
+_,_,_,_,_,_,
+/* Char 0x48 'H' */
+X,o,_,_,X,o,
+X,_,_,_,X,_,
+X,_,_,_,X,_,
+X,X,X,X,X,_,
+X,_,_,_,X,_,
+X,_,_,_,X,_,
+X,o,_,_,X,o,
+_,_,_,_,_,_,
+/* Char 0x49 'I' */
+_,X,X,X,_,_,
+_,o,X,o,_,_,
+_,_,X,_,_,_,
+_,_,X,_,_,_,
+_,_,X,_,_,_,
+_,o,X,o,_,_,
+_,X,X,X,_,_,
+_,_,_,_,_,_,
+/* Char 0x4a 'J' */
+_,_,X,X,X,_,
+_,_,o,X,o,_,
+_,_,_,X,_,_,
+_,_,_,X,_,_,
+_,_,_,X,_,_,
+X,o,o,X,_,_,
+o,X,X,o,_,_,
+_,_,_,_,_,_,
+/* Char 0x4b 'K' */
+X,o,_,_,X,o,
+X,_,_,o,X,_,
+X,_,_,o,_,_,
+X,X,X,o,_,_,
+X,_,_,o,_,_,
+X,_,_,o,X,_,
+X,o,_,_,X,o,
+_,_,_,_,_,_,
+/* Char 0x4c 'L' */
+X,o,_,_,_,_,
+X,_,_,_,_,_,
+X,_,_,_,_,_,
+X,_,_,_,_,_,
+X,_,_,_,_,_,
+X,_,_,_,o,_,
+X,X,X,X,X,_,
+_,_,_,_,_,_,
+/* Char 0x4d 'M' */
+X,o,_,o,X,o,
+X,X,o,X,X,_,
+X,X,X,X,X,_,
+X,o,X,o,X,_,
+X,_,o,_,X,_,
+X,_,_,_,X,_,
+X,o,_,_,X,o,
+_,_,_,_,_,_,
+/* Char 0x4e 'N' */
+X,o,_,_,X,o,
+X,X,o,_,X,_,
+X,o,X,o,X,_,
+X,_,o,X,X,_,
+X,_,_,X,X,_,
+X,_,_,o,X,_,
+X,o,_,_,X,o,
+_,_,_,_,_,_,
+/* Char 0x4f 'O' */
+o,X,X,X,o,_,
+X,o,_,o,X,_,
+X,_,_,_,X,_,
+X,_,_,_,X,_,
+X,_,_,_,X,_,
+X,o,_,o,X,_,
+o,X,X,X,o,_,
+_,_,_,_,_,_,
+/* Char 0x50 'P' */
+X,X,X,X,o,_,
+X,_,_,o,X,_,
+X,_,_,o,X,_,
+X,X,X,X,o,_,
+X,_,_,_,_,_,
+X,_,_,_,_,_,
+X,o,_,_,_,_,
+_,_,_,_,_,_,
+/* Char 0x51 'Q' */
+o,X,X,X,o,_,
+X,o,_,o,X,_,
+X,_,_,_,X,_,
+X,_,_,_,X,_,
+X,o,_,_,X,_,
+o,X,X,o,X,o,
+_,_,o,X,o,X,
+_,_,_,_,_,_,
+/* Char 0x52 'R' */
+X,X,X,X,o,_,
+X,_,_,o,X,_,
+X,_,_,o,X,_,
+X,X,X,X,o,_,
+X,_,o,X,o,_,
+X,_,_,o,X,_,
+X,o,_,_,X,o,
+_,_,_,_,_,_,
+/* Char 0x53 'S' */
+o,X,X,X,o,_,
+X,o,_,o,X,_,
+X,o,_,_,_,_,
+o,X,X,X,o,_,
+_,_,_,o,X,_,
+X,o,_,o,X,_,
+o,X,X,X,o,_,
+_,_,_,_,_,_,
+/* Char 0x54 'T' */
+X,X,X,X,X,_,
+o,_,X,_,o,_,
+_,_,X,_,_,_,
+_,_,X,_,_,_,
+_,_,X,_,_,_,
+_,_,X,_,_,_,
+_,X,X,X,_,_,
+_,_,_,_,_,_,
+/* Char 0x55 'U' */
+X,o,_,_,X,o,
+X,_,_,_,X,_,
+X,_,_,_,X,_,
+X,_,_,_,X,_,
+X,_,_,_,X,_,
+X,_,_,o,X,_,
+o,X,X,X,o,_,
+_,_,_,_,_,_,
+/* Char 0x56 'V' */
+X,o,_,_,X,o,
+X,_,_,_,X,_,
+X,_,_,_,X,_,
+X,o,_,o,X,_,
+o,X,_,X,o,_,
+o,X,o,X,o,_,
+_,o,X,o,_,_,
+_,_,_,_,_,_,
+/* Char 0x57 'W' */
+X,o,_,_,X,o,
+X,_,_,_,X,_,
+X,_,_,_,X,_,
+X,_,o,_,X,_,
+X,o,X,o,X,_,
+X,X,o,X,X,_,
+X,o,_,o,X,o,
+_,_,_,_,_,_,
+/* Char 0x58 'X' */
+X,o,_,_,X,o,
+X,o,_,o,X,_,
+o,X,o,X,o,_,
+_,o,X,o,_,_,
+o,X,o,X,o,_,
+X,o,_,o,X,_,
+X,o,_,_,X,o,
+_,_,_,_,_,_,
+/* Char 0x59 'Y' */
+X,o,_,_,X,o,
+X,_,_,_,X,_,
+X,o,_,o,X,_,
+o,X,o,X,o,_,
+_,o,X,o,_,_,
+_,o,X,o,_,_,
+_,X,X,X,_,_,
+_,_,_,_,_,_,
+/* Char 0x5a 'Z' */
+X,X,X,X,X,_,
+X,o,_,o,X,_,
+_,_,o,X,o,_,
+_,o,X,o,_,_,
+o,X,o,_,_,_,
+X,o,_,o,X,_,
+X,X,X,X,X,o,
+_,_,_,_,_,_,
+/* Char 0x5b '[' */
+_,X,X,X,X,_,
+_,X,_,_,_,_,
+_,X,_,_,_,_,
+_,X,_,_,_,_,
+_,X,_,_,_,_,
+_,X,_,_,_,_,
+_,X,_,_,_,_,
+_,X,X,X,X,_,
+/* Char 0x5c '\' */
+X,_,_,_,_,_,
+X,_,_,_,_,_,
+_,X,X,_,_,_,
+_,X,X,_,_,_,
+X,_,_,_,_,_,
+X,_,_,_,_,_,
+_,X,X,_,_,_,
+_,X,X,_,_,_,
+/* Char 0x5d ']' */
+_,X,X,X,X,_,
+_,_,_,_,X,_,
+_,_,_,_,X,_,
+_,_,_,_,X,_,
+_,_,_,_,X,_,
+_,_,_,_,X,_,
+_,_,_,_,X,_,
+_,X,X,X,X,_,
+/* Char 0x5e '^' */
+_,X,X,_,_,X,
+_,X,X,_,_,X,
+X,_,_,X,X,_,
+X,_,_,X,X,_,
+_,X,X,_,_,X,
+_,X,X,_,_,X,
+X,_,_,X,X,_,
+X,_,_,X,X,_,
+/* Char 0x5f '_' */
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+X,X,X,X,X,_,
+_,_,_,_,_,_,
+/* Char 0x60 '`' */
+X,o,_,_,_,_,
+X,_,_,_,_,_,
+X,_,_,5,5,5,
+X,_,5,4,4,4,
+X,_,5,4,3,3,
+X,_,5,4,3,_,
+X,_,5,4,3,_,
+X,_,5,4,3,_,
+/* Char 0x61 'a' */
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+5,5,5,5,5,5,
+4,4,4,4,4,4,
+3,3,3,3,3,3,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+/* Char 0x62 'b' */
+_,_,_,_,o,X,
+_,_,_,_,_,X,
+5,5,5,_,_,X,
+4,4,4,3,_,X,
+3,3,4,3,_,X,
+_,5,4,3,_,X,
+_,5,4,3,_,X,
+_,5,4,3,_,X,
+/* Char 0x63 'c' */
+_,5,4,3,_,X,
+_,5,4,3,_,X,
+_,5,4,3,_,X,
+_,5,4,3,_,X,
+_,5,4,3,_,X,
+_,5,4,3,_,X,
+_,5,4,3,_,X,
+_,5,4,3,_,X,
+/* Char 0x64 'd' */
+_,5,4,3,_,X,
+_,5,4,3,_,X,
+5,5,4,3,_,X,
+4,4,4,3,_,X,
+3,3,3,_,_,X,
+_,_,_,_,_,X,
+_,_,_,_,o,X,
+X,X,X,X,X,X,
+/* Char 0x65 'e' */
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+5,5,5,5,5,5,
+4,4,4,4,4,4,
+3,3,3,3,3,3,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+X,X,X,X,X,X,
+/* Char 0x66 'f' */
+X,_,5,4,3,_,
+X,_,5,4,3,_,
+X,_,5,4,3,5,
+X,_,5,4,4,4,
+X,_,_,3,3,3,
+X,_,_,_,_,_,
+X,o,_,_,_,_,
+X,X,X,X,X,X,
+/* Char 0x67 'g' */
+X,_,5,4,3,_,
+X,_,5,4,3,_,
+X,_,5,4,3,_,
+X,_,5,4,3,_,
+X,_,5,4,3,_,
+X,_,5,4,3,_,
+X,_,5,4,3,_,
+X,_,5,4,3,_,
+/* Char 0x68 'h' */
+_,_,X,_,_,_,
+_,_,X,_,_,_,
+_,_,X,_,_,_,
+_,_,X,_,_,_,
+_,_,X,_,_,_,
+_,_,X,_,_,_,
+_,_,X,_,_,_,
+_,_,X,_,_,_,
+/* Char 0x69 'i' */
+X,X,X,X,X,X,
+_,_,_,_,_,_,
+X,X,X,X,X,X,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+/* Char 0x6a 'j' */
+X,X,X,X,X,X,
+_,_,_,_,_,X,
+X,X,X,X,_,X,
+_,_,_,X,_,X,
+_,_,_,X,_,X,
+_,_,_,X,_,X,
+_,_,_,X,_,X,
+_,_,_,X,_,X,
+/* Char 0x6b 'k' */
+_,_,_,X,_,X,
+_,_,_,X,_,X,
+_,_,_,X,_,X,
+_,_,_,X,_,X,
+_,_,_,X,_,X,
+_,_,_,X,_,X,
+_,_,_,X,_,X,
+_,_,_,X,_,X,
+/* Char 0x6c 'l' */
+_,_,_,X,_,X,
+_,_,_,X,_,X,
+_,_,_,X,_,X,
+_,_,_,X,_,X,
+_,_,_,X,_,X,
+X,X,X,X,_,X,
+_,_,_,_,_,X,
+X,X,X,X,X,X,
+/* Char 0x6d 'm' */
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+X,X,X,X,X,X,
+_,_,_,_,_,_,
+X,X,X,X,X,X,
+/* Char 0x6e 'n' */
+X,_,X,_,_,_,
+X,_,X,_,_,_,
+X,_,X,_,_,_,
+X,_,X,_,_,_,
+X,_,X,_,_,_,
+X,_,X,X,X,X,
+X,_,_,_,_,_,
+X,X,X,X,X,X,
+/* Char 0x6f 'o' */
+X,_,X,_,_,_,
+X,_,X,_,_,_,
+X,_,X,_,_,_,
+X,_,X,_,_,_,
+X,_,X,_,_,_,
+X,_,X,_,_,_,
+X,_,X,_,_,_,
+X,_,X,_,_,_,
+/* Char 0x70 'p' */
+6,6,7,7,_,_,
+6,7,_,_,4,3,
+6,7,_,5,3,_,
+6,_,4,3,_,_,
+6,_,3,_,_,_,
+6,7,_,_,_,_,
+6,7,_,_,_,_,
+6,6,7,7,_,_,
+/* Char 0x71 'q' */
+_,_,7,7,6,6,
+_,_,_,_,7,6,
+_,_,_,_,7,6,
+_,_,_,_,_,6,
+_,_,_,_,_,6,
+_,_,_,_,7,6,
+_,_,_,_,7,6,
+_,_,7,7,6,6,
+/* Char 0x72 'r' */
+X,X,X,X,X,X,
+X,_,_,_,_,_,
+X,_,X,X,X,X,
+X,_,X,_,_,_,
+X,_,X,_,_,_,
+X,_,X,_,_,_,
+X,_,X,_,_,_,
+X,_,X,_,_,_,
+/* Char 0x73 's' */
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+X,X,X,X,X,X,
+X,X,X,X,X,X,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+/* Char 0x74 't' */
+X,_,_,_,_,_,
+X,_,_,_,_,_,
+X,_,_,_,_,_,
+X,_,_,_,_,_,
+X,_,_,_,_,_,
+X,_,_,_,_,_,
+X,_,_,_,_,_,
+X,_,_,_,_,_,
+/* Char 0x75 'u' */
+X,X,_,_,_,_,
+X,X,_,_,_,_,
+X,X,_,_,_,_,
+X,X,_,_,_,_,
+X,X,_,_,_,_,
+X,X,_,_,_,_,
+X,X,_,_,_,_,
+X,X,_,_,_,_,
+/* Char 0x76 'v' */
+_,_,_,_,X,X,
+_,_,_,_,X,X,
+_,_,_,_,X,X,
+_,_,_,_,X,X,
+_,_,_,_,X,X,
+_,_,_,_,X,X,
+_,_,_,_,X,X,
+_,_,_,_,X,X,
+/* Char 0x77 'w' */
+X,X,X,X,X,X,
+X,X,X,X,X,X,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+/* Char 0x78 'x' */
+X,X,X,X,X,X,
+X,X,X,X,X,X,
+X,X,X,X,X,X,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+/* Char 0x79 'y' */
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+X,X,X,X,X,X,
+X,X,X,X,X,X,
+X,X,X,X,X,X,
+/* Char 0x7a 'z' */
+_,_,_,_,_,_,
+_,_,_,_,o,X,
+_,_,_,o,X,X,
+X,X,o,X,X,o,
+X,X,X,X,o,_,
+X,X,X,o,_,_,
+X,X,o,_,_,_,
+_,_,_,_,_,_,
+/* Char 0x7b '{' */
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+X,X,X,_,_,_,
+X,X,X,_,_,_,
+X,X,X,_,_,_,
+X,X,X,_,_,_,
+/* Char 0x7c '|' */
+_,_,_,X,X,X,
+_,_,_,X,X,X,
+_,_,_,X,X,X,
+_,_,_,X,X,X,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+/* Char 0x7d '}' */
+_,_,X,X,_,_,
+_,_,X,X,_,_,
+_,o,X,X,_,_,
+X,X,X,X,_,_,
+X,X,X,X,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+/* Char 0x7e '~' */
+X,X,X,_,_,_,
+X,X,X,_,_,_,
+X,X,X,_,_,_,
+X,X,X,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+_,_,_,_,_,_,
+/* Char 0x7f '?' */
+X,X,X,_,_,_,
+X,X,X,_,_,_,
+X,X,X,_,_,_,
+X,X,X,_,_,_,
+_,_,_,X,X,X,
+_,_,_,X,X,X,
+_,_,_,X,X,X,
+_,_,_,X,X,X,
+
+};
diff --git a/contiki/ctk/ctk-vncfont.h b/contiki/ctk/ctk-vncfont.h
new file mode 100644
index 0000000..18a8f08
--- /dev/null
+++ b/contiki/ctk/ctk-vncfont.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2003, Adam Dunkels.
+ * All rights reserved. 
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met: 
+ * 1. Redistributions of source code must retain the above copyright 
+ *    notice, this list of conditions and the following disclaimer. 
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials provided
+ *    with the distribution. 
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgement:
+ *        This product includes software developed by Adam Dunkels. 
+ * 4. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.  
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
+ *
+ * This file is part of the Contiki VNC server
+ *
+ * $Id: ctk-vncfont.h,v 1.1 2003/07/02 21:34:00 adamdunkels Exp $
+ *
+ */
+#ifndef __CTK_VNCFONT_H__
+#define __CTK_VNCFONT_H__
+
+unsigned char ctk_vncfont[6*8*128];
+
+#endif /* __CTK_VNCFONT_H__ */
diff --git a/contiki/ctk/ctk-vncserver.c b/contiki/ctk/ctk-vncserver.c
new file mode 100644
index 0000000..66ede6f
--- /dev/null
+++ b/contiki/ctk/ctk-vncserver.c
@@ -0,0 +1,884 @@
+/*
+ * Copyright (c) 2002, Adam Dunkels.
+ * All rights reserved. 
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met: 
+ * 1. Redistributions of source code must retain the above copyright 
+ *    notice, this list of conditions and the following disclaimer. 
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials provided
+ *    with the distribution. 
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgement:
+ *        This product includes software developed by Adam Dunkels. 
+ * 4. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.  
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
+ *
+ * This file is part of the "ctk" console GUI toolkit for cc65
+ *
+ * $Id: ctk-vncserver.c,v 1.1 2003/07/02 21:34:00 adamdunkels Exp $
+ *
+ */
+
+#include "ctk.h"
+#include "ctk-draw.h"
+
+#include "dispatcher.h"
+#include "loader.h"
+#include "vnc-server.h"
+#include "vnc-out.h"
+
+static unsigned char sizex, sizey;
+
+#define CH_ULCORNER 0x00
+#define CH_TITLEBAR 0x01
+#define CH_URCORNER 0x02
+#define CH_WINDOWRBORDER 0x03
+#define CH_LRCORNER 0x04
+#define CH_WINDOWLOWERBORDER 0x05
+#define CH_LLCORNER 0x06
+#define CH_WINDOWLBORDER 0x07
+
+#define CH_DIALOG_ULCORNER 0x12
+#define CH_DIALOGUPPERBORDER 0x09
+#define CH_DIALOG_URCORNER 0x0a
+#define CH_DIALOGRBORDER 0x0b
+#define CH_DIALOG_LRCORNER 0x0c
+#define CH_DIALOGLOWERBORDER 0x0d
+#define CH_DIALOG_LLCORNER 0x0e
+#define CH_DIALOGLBORDER 0x0f
+
+#define CH_BUTTONLEFT  0x10
+#define CH_BUTTONRIGHT 0x11
+
+#define CH_SEPARATOR   0x13
+
+#include "libconio.h"
+
+#define SCREENCOLOR         0
+#define BORDERCOLOR         1
+
+#define WIDGETCOLOR         2
+#define WIDGETCOLOR_FWIN    3
+#define WIDGETCOLOR_FOCUS   4
+#define WIDGETCOLOR_DIALOG  5
+#define WIDGETCOLOR_HLINK   6
+#define WIDGETCOLOR_HLINK_FOCUS   7
+
+#define WINDOWCOLOR         8
+#define WINDOWCOLOR_FOCUS   9
+
+#define WINDOWBORDER        10
+#define WINDOWBORDER_FOCUS  11
+
+#define DIALOGCOLOR         12
+
+#define OPENMENUCOLOR       13
+
+#define ACTIVEMENUITEMCOLOR 14
+
+#define MENUCOLOR           15
+
+static DISPATCHER_UIPCALL(ctk_vncserver_appcall, state);
+
+static struct dispatcher_proc p =
+  {DISPATCHER_PROC("CTK VNC server", NULL, NULL,
+		   ctk_vncserver_appcall)};
+static ek_id_t id;
+
+
+#define VNCSERVER_CONF_NUMCONNS 8
+static struct vnc_server_state conns[VNCSERVER_CONF_NUMCONNS];
+
+#define PRINTF(x) 
+
+#define revers(x)
+
+
+/*-----------------------------------------------------------------------------------*/
+void
+vnc_server_update_add(struct vnc_server_state *vs,
+		      struct vnc_server_update *a)
+{
+  /* XXX: test both head and tail placement!*/
+  a->next = vs->updates_pending;
+  vs->updates_pending = a;
+}
+struct vnc_server_update *
+vnc_server_update_alloc(struct vnc_server_state *vs)
+{
+  struct vnc_server_update *a;
+
+  a = vs->updates_free;
+  if(a == NULL) {
+    return NULL;
+  }
+  vs->updates_free = a->next;
+  a->next = NULL;
+  return a;
+}
+void
+vnc_server_update_free(struct vnc_server_state *vs,
+		       struct vnc_server_update *a)
+{
+  a->next = vs->updates_free;
+  vs->updates_free = a;
+}
+struct vnc_server_update *
+vnc_server_update_dequeue(struct vnc_server_state *vs)
+{
+  struct vnc_server_update *a;
+
+  a = vs->updates_pending;
+  if(a == NULL) {
+    return a;
+  }
+  vs->updates_pending = a->next;
+  a->next = NULL;
+  return a;
+}
+void
+vnc_server_update_remove(struct vnc_server_state *vs,
+			 struct vnc_server_update *a)
+{
+  struct vnc_server_update *b, *c;
+
+  if(a == vs->updates_pending) {
+    vs->updates_pending = a->next;
+  } else {
+    
+    for(c = vs->updates_pending; c != a; b = c, c = c->next);
+
+    b->next = a->next;
+  }
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+update_area(u8_t x, u8_t y, u8_t w, u8_t h)
+{
+  u8_t i;
+  
+  if(h == 0 || w == 0) {
+    return;
+  }
+  
+  /* Update for all active VNC connections. */
+  for(i = 0; i < VNCSERVER_CONF_NUMCONNS; ++i) {
+    if(conns[i].state != VNC_DEALLOCATED) {
+      vnc_out_update_area(&conns[i],
+			  x, y, w, h);
+    }
+  }
+
+}
+/*-----------------------------------------------------------------------------------*/
+static struct vnc_server_state *
+alloc_state(void)
+{
+  u8_t i;
+  for(i = 0; i < VNCSERVER_CONF_NUMCONNS; ++i) {
+    if(conns[i].state == VNC_DEALLOCATED) {
+      return &conns[i];
+    }
+  }
+
+  /* We are overloaded! XXX: we'll just kick all other connections! */
+  for(i = 0; i < VNCSERVER_CONF_NUMCONNS; ++i) {
+    conns[i].state = VNC_DEALLOCATED;
+  }
+  
+  return NULL;
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+dealloc_state(struct vnc_server_state *s)
+{
+  s->state = VNC_DEALLOCATED;
+}
+/*-----------------------------------------------------------------------------------*/
+static char tmp[40];
+static void
+cputsn(char *str, unsigned char len)
+{
+  strncpy(tmp, str, len);
+  tmp[len] = 0;
+  cputs(tmp);
+}
+/*-----------------------------------------------------------------------------------*/
+void
+ctk_draw_init(void)
+{
+  bgcolor(SCREENCOLOR);
+  bordercolor(BORDERCOLOR);
+  screensize(&sizex, &sizey);
+  ctk_draw_clear(0, sizey);
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+draw_widget(struct ctk_widget *w,
+	    unsigned char x, unsigned char y,
+	    unsigned char clipx,
+	    unsigned char clipy,
+	    unsigned char clipy1, unsigned char clipy2,
+	    unsigned char focus)
+{
+  unsigned char xpos, ypos, xscroll;
+  unsigned char i, j;
+  unsigned char iconnum;
+  char c, *text;
+  unsigned char len;
+
+  /*
+  if(focus & CTK_FOCUS_WINDOW) {    
+    textcolor(WIDGETCOLOR_FWIN);
+    if(focus & CTK_FOCUS_WIDGET) {
+      textcolor(WIDGETCOLOR_FOCUS);
+    }
+  } else if(focus & CTK_FOCUS_DIALOG) {
+    textcolor(WIDGETCOLOR_DIALOG);
+    if(focus & CTK_FOCUS_WIDGET) {
+      textcolor(WIDGETCOLOR_FOCUS);
+    }
+  } else {
+    textcolor(WIDGETCOLOR);
+  }
+*/  
+  xpos = x + w->x;
+  ypos = y + w->y;
+    
+  switch(w->type) {
+  case CTK_WIDGET_SEPARATOR:
+    textcolor(VNC_OUT_SEPARATORCOLOR + focus);
+    if(ypos >= clipy1 && ypos < clipy2) {
+      /*      chlinexy(xpos, ypos, w->w);*/
+      gotoxy(xpos, ypos);
+      for(i = 0; i < w->w; ++i) {
+	cputc(CH_SEPARATOR);
+      }
+    }
+    break;
+  case CTK_WIDGET_LABEL:
+    textcolor(VNC_OUT_LABELCOLOR + focus);
+    text = w->widget.label.text;
+    for(i = 0; i < w->h; ++i) {
+      if(ypos >= clipy1 && ypos < clipy2) {
+	gotoxy(xpos, ypos);
+	cputsn(text, w->w);
+	if(w->w - (wherex() - xpos) > 0) {
+	  cclear(w->w - (wherex() - xpos));
+	}
+      }
+      ++ypos;
+      text += w->w;
+    }
+    break;
+  case CTK_WIDGET_BUTTON:
+    textcolor(VNC_OUT_BUTTONCOLOR + focus);
+    if(ypos >= clipy1 && ypos < clipy2) {
+      if(focus & CTK_FOCUS_WIDGET) {
+	revers(1);
+      } else {
+	revers(0);
+      }
+      cputcxy(xpos, ypos, CH_BUTTONLEFT);
+      cputsn(w->widget.button.text, w->w);
+      cputc(CH_BUTTONRIGHT);
+      revers(0);
+    }
+    break;
+  case CTK_WIDGET_HYPERLINK:
+    textcolor(VNC_OUT_HYPERLINKCOLOR + focus);
+    if(ypos >= clipy1 && ypos < clipy2) {
+      /*      if(focus & CTK_FOCUS_WIDGET) {
+	textcolor(WIDGETCOLOR_HLINK_FOCUS);
+	revers(0);	
+      } else {
+	textcolor(WIDGETCOLOR_HLINK);
+	revers(1);
+	}*/
+      gotoxy(xpos, ypos);
+      cputsn(w->widget.button.text, w->w);
+      revers(0);
+    }
+    break;
+  case CTK_WIDGET_TEXTENTRY:
+    textcolor(VNC_OUT_TEXTENTRYCOLOR + focus);
+    text = w->widget.textentry.text;
+    if(focus & CTK_FOCUS_WIDGET) {
+      revers(1);
+    } else {
+      revers(0);
+    }
+    xscroll = 0;
+    if(w->widget.textentry.xpos >= w->w - 1) {
+      xscroll = w->widget.textentry.xpos - w->w + 1;
+    }
+    for(j = 0; j < w->h; ++j) {
+      if(ypos >= clipy1 && ypos < clipy2) {
+	if(w->widget.textentry.state == CTK_TEXTENTRY_EDIT &&
+	   w->widget.textentry.ypos == j) {
+	  revers(0);
+	  cputcxy(xpos, ypos, '>');
+	  for(i = 0; i < w->w; ++i) {
+	    c = text[i + xscroll];
+	    if(i == w->widget.textentry.xpos - xscroll) {
+	      textcolor(VNC_OUT_TEXTENTRYCOLOR + (focus ^ 0x01));
+	      revers(1);
+	    } else {
+	      revers(0);
+	    }
+	    if(c == 0) {
+	      cputc(' ');
+	    } else {
+	      cputc(c);
+	    }
+	    revers(0);
+	    textcolor(VNC_OUT_TEXTENTRYCOLOR + focus);
+	  }
+	  cputc('<');
+	} else {
+	  cvlinexy(xpos, ypos, 1);
+	  gotoxy(xpos + 1, ypos);          
+	  cputsn(text, w->w);
+	  i = wherex();
+	  if(i - xpos - 1 < w->w) {
+	    cclear(w->w - (i - xpos) + 1);
+	  }
+	  cvline(1);
+	}
+      }
+      ++ypos;
+      text += w->w;
+    }
+    revers(0);
+    break;
+  case CTK_WIDGET_ICON:
+    if(ypos >= clipy1 && ypos < clipy2) {
+      textcolor(VNC_OUT_ICONCOLOR + focus);
+      if(focus & 1) {
+	revers(1);
+      } else {
+	revers(0);
+      }
+
+      x = xpos;
+      len = strlen(w->widget.icon.title);
+      if(x + len >= sizex) {
+	x = sizex - len;
+      }
+
+      gotoxy(x, ypos + 3);
+      if(ypos >= clipy1 && ypos < clipy2) {
+	cputs(w->widget.icon.title);
+      }
+
+      gotoxy(xpos, ypos);
+      if(w->widget.icon.bitmap != NULL) {
+	iconnum = vnc_out_add_icon((struct ctk_icon *)w);
+	gotoxy(xpos, ypos);
+	textcolor(iconnum | (focus << 6));
+	cputc(0x80);
+	cputc(0x81);
+	cputc(0x82);
+	cputc(0x83);
+	++ypos;
+	gotoxy(xpos, ypos);
+	cputc(0x90);
+	cputc(0x91);
+	cputc(0x92);
+	cputc(0x93);
+	++ypos;
+	gotoxy(xpos, ypos);
+	cputc(0xa0);
+	cputc(0xa1);
+	cputc(0xa2);
+	cputc(0xa3);
+	++ypos;
+	textcolor(0);
+	/*	for(i = 0; i < 3; ++i) {
+
+	  if(ypos >= clipy1 && ypos < clipy2) {
+	    cputc(w->widget.icon.textmap[0 + 3 * i]);
+	    cputc(w->widget.icon.textmap[1 + 3 * i]);
+	    cputc(w->widget.icon.textmap[2 + 3 * i]);
+	  }
+	  ++ypos;
+	  }*/
+      }
+      x = xpos;
+  
+      revers(0);
+    }
+    break;
+
+  default:
+    break;
+  }
+}
+/*-----------------------------------------------------------------------------------*/
+void
+ctk_draw_widget(struct ctk_widget *w,
+		unsigned char focus,
+		unsigned char clipy1,
+		unsigned char clipy2)
+{
+  struct ctk_window *win = w->window;
+  struct ctk_icon *icon;
+  unsigned char posx, posy, x, len;
+
+  posx = win->x + 1;
+  posy = win->y + 2;
+
+  if(w == win->focused) {
+    focus |= CTK_FOCUS_WIDGET;
+  }
+  
+  draw_widget(w, posx, posy,
+	      posx + win->w,
+	      posy + win->h,
+	      clipy1, clipy2,
+	      focus);
+
+  if(w->type != CTK_WIDGET_ICON) {
+    update_area(posx + w->x,
+		posy + w->y, w->w + 2, w->h);
+  } else {
+    icon = (struct ctk_icon *)w;
+
+    len = strlen(icon->title);
+    x = posx + w->x;
+    if(x + len >= sizex) {
+      x = sizex - len;
+    }
+
+    update_area(x, posy + w->y, len > 4? len: 4, w->h);    
+  }
+  
+#ifdef CTK_CONIO_CONF_UPDATE
+  CTK_CONIO_CONF_UPDATE();
+#endif /* CTK_CONIO_CONF_UPDATE */
+}
+/*-----------------------------------------------------------------------------------*/
+void
+ctk_draw_clear_window(struct ctk_window *window,
+		      unsigned char focus,
+		      unsigned char clipy1,
+		      unsigned char clipy2)
+{
+  unsigned char i;
+  unsigned char h;
+  /*
+  if(focus & CTK_FOCUS_WINDOW){
+    textcolor(WINDOWCOLOR_FOCUS);
+  } else {
+    textcolor(WINDOWCOLOR);
+    }*/
+  textcolor(VNC_OUT_WINDOWCOLOR + focus);
+  
+  h = window->y + 2 + window->h;
+  /* Clear window contents. */
+  for(i = window->y + 2; i < h; ++i) {
+    if(i >= clipy1 && i < clipy2) {
+      cclearxy(window->x + 1, i, window->w);
+    }
+  }
+
+  update_area(window->x + 1, window->y + 2, window->w, window->h);
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+draw_window_contents(struct ctk_window *window, unsigned char focus,
+		     unsigned char clipy1, unsigned char clipy2,
+		     unsigned char x1, unsigned char x2,
+		     unsigned char y1, unsigned char y2)
+{
+  struct ctk_widget *w;
+  unsigned char wfocus;
+  
+  /* Draw inactive widgets. */
+  for(w = window->inactive; w != NULL; w = w->next) {
+    draw_widget(w, x1, y1, x2, y2,
+		clipy1, clipy2,
+		focus);
+  }
+  
+  /* Draw active widgets. */
+  for(w = window->active; w != NULL; w = w->next) {  
+    wfocus = focus;
+    if(w == window->focused) {
+      wfocus |= CTK_FOCUS_WIDGET;
+    }
+
+   draw_widget(w, x1, y1, x2, y2, 
+	       clipy1, clipy2,
+	       wfocus);
+  }
+
+#ifdef CTK_CONIO_CONF_UPDATE
+  CTK_CONIO_CONF_UPDATE();
+#endif /* CTK_CONIO_CONF_UPDATE */
+
+}
+/*-----------------------------------------------------------------------------------*/
+void
+ctk_draw_window(struct ctk_window *window, unsigned char focus,
+		unsigned char clipy1, unsigned char clipy2)
+{
+  unsigned char x, y;
+  unsigned char h;
+  unsigned char x1, y1, x2, y2;
+  unsigned char i;
+  
+
+  if(window->y + 1 >= clipy2) {
+    return;
+  }
+    
+  x = window->x;
+  y = window->y + 1;
+
+  textcolor(VNC_OUT_WINDOWCOLOR + focus);
+  /*  if(focus & CTK_FOCUS_WINDOW) {
+    textcolor(WINDOWCOLOR_FOCUS);
+  } else {
+    textcolor(WINDOWCOLOR);
+    }*/
+
+  x1 = x + 1;
+  y1 = y + 1;
+  x2 = x1 + window->w;
+  y2 = y1 + window->h;
+
+  /* Draw window frame. */  
+  if(y >= clipy1) {
+    cputcxy(x, y, CH_ULCORNER);
+    for(i = wherex() + window->titlelen + 2; i < x2; ++i) {
+      cputcxy(i, y, CH_TITLEBAR);
+    }
+    cputcxy(x2, y, CH_URCORNER);
+  }
+
+  h = window->h;
+  
+  if(clipy1 > y1) {
+    if(clipy1 - y1 < h) {
+      h = clipy1 - y1;
+            y1 = clipy1;
+    } else {
+      h = 0;
+    }
+  }
+
+  if(clipy2 < y1 + h) {
+    if(y1 >= clipy2) {
+      h = 0;
+    } else {
+      h = clipy2 - y1;
+    }
+  }
+  
+  for(i = y1; i < y1 + h; ++i) {
+    cputcxy(x, i, CH_WINDOWLBORDER);
+    cputcxy(x2, i, CH_WINDOWRBORDER);
+  }
+
+  /*  cvlinexy(x, y1, h);
+      cvlinexy(x2, y1, h);  */
+
+  if(y + window->h >= clipy1 &&
+     y + window->h < clipy2) {
+    cputcxy(x, y2, CH_LLCORNER);
+    for(i = x1; i < x2; ++i) {
+      cputcxy(i, y2, CH_WINDOWLOWERBORDER);
+    }
+    /*    chlinexy(x1, y2, window->w);*/
+    cputcxy(x2, y2, CH_LRCORNER);
+  }
+
+  draw_window_contents(window, focus & CTK_FOCUS_WINDOW, clipy1, clipy2,
+		       x1, x2, y + 1, y2);
+
+  update_area(window->x, window->y, window->w + 2, window->h + 2);
+}
+/*-----------------------------------------------------------------------------------*/
+void
+ctk_draw_dialog(struct ctk_window *dialog)
+{
+  unsigned char x, y;
+  unsigned char i;
+  unsigned char x1, y1, x2, y2;
+
+  /*  textcolor(DIALOGCOLOR);*/
+  textcolor(VNC_OUT_WINDOWCOLOR + CTK_FOCUS_DIALOG);
+
+  x = dialog->x;
+  y = dialog->y + 1;
+
+
+  x1 = x + 1;
+  y1 = y + 1;
+  x2 = x1 + dialog->w;
+  y2 = y1 + dialog->h;
+
+
+  /* Draw dialog frame. */
+  
+  for(i = y1; i < y1 + dialog->h; ++i) {
+    cputcxy(x, i, CH_DIALOGLBORDER);
+    cputcxy(x2, i, CH_DIALOGRBORDER);
+  }
+  /*  cvlinexy(x, y1,
+	   dialog->h);
+  cvlinexy(x2, y1,
+  dialog->h);*/
+
+  
+  for(i = x1; i < x2; ++i) {
+    cputcxy(i, y, CH_DIALOGUPPERBORDER);
+    cputcxy(i, y2, CH_DIALOGLOWERBORDER);
+  }
+    /*  chlinexy(x1, y,
+	   dialog->w);
+  chlinexy(x1, y2,
+  dialog->w);*/
+
+  cputcxy(x, y, CH_DIALOG_ULCORNER);
+  cputcxy(x, y2, CH_DIALOG_LLCORNER);
+  cputcxy(x2, y, CH_DIALOG_URCORNER);
+  cputcxy(x2, y2, CH_DIALOG_LRCORNER);
+  
+  
+  /* Clear dialog contents. */
+  for(i = y1; i < y2; ++i) {
+    cclearxy(x1, i, dialog->w);
+  }
+
+  draw_window_contents(dialog, CTK_FOCUS_DIALOG, 0, sizey,
+		       x1, x2, y1, y2);
+
+  update_area(dialog->x, dialog->y, dialog->w, dialog->h);
+}
+/*-----------------------------------------------------------------------------------*/
+void
+ctk_draw_clear(unsigned char y1, unsigned char y2)
+{
+  unsigned char i;
+
+  textcolor(VNC_OUT_BACKGROUNDCOLOR);
+  for(i = y1; i < y2; ++i) {
+    cclearxy(0, i, sizex);
+  }
+
+  update_area(0, y1, sizex, y2 - y1);
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+draw_menu(struct ctk_menu *m)
+{
+  unsigned char x, x2, y;
+
+  textcolor(VNC_OUT_MENUCOLOR);
+  x = wherex();
+  cputs(m->title);
+  cputc(' ');
+  x2 = wherex();
+  if(x + CTK_CONF_MENUWIDTH > sizex) {
+    x = sizex - CTK_CONF_MENUWIDTH;
+  }
+  
+  
+  for(y = 0; y < m->nitems; ++y) {
+    if(y == m->active) {
+      textcolor(VNC_OUT_ACTIVEMENUCOLOR);
+      revers(0);
+    } else {
+      textcolor(VNC_OUT_MENUCOLOR);	  
+    }
+    gotoxy(x, y + 1);
+    if(m->items[y].title[0] == '-') {
+      chline(CTK_CONF_MENUWIDTH);
+    } else {
+      cputs(m->items[y].title);
+    }
+    if(x + CTK_CONF_MENUWIDTH > wherex()) {
+      cclear(x + CTK_CONF_MENUWIDTH - wherex());
+    }
+    revers(1);
+  }
+  
+  gotoxy(x2, 0);
+  textcolor(VNC_OUT_MENUCOLOR);  
+
+  update_area(x, 0, CTK_CONF_MENUWIDTH, m->nitems + 1);
+}
+/*-----------------------------------------------------------------------------------*/
+void
+ctk_draw_menus(struct ctk_menus *menus)
+{
+  struct ctk_menu *m;  
+
+  
+  /* Draw menus */
+  textcolor(VNC_OUT_MENUCOLOR);
+  gotoxy(0, 0);
+  revers(1);
+  cputc(' ');
+  for(m = menus->menus->next; m != NULL; m = m->next) {
+    if(m != menus->open) {
+      update_area(wherex(), 0, strlen(m->title) + 1, 1);
+      cputs(m->title);
+      cputc(' ');
+    } else {
+      draw_menu(m);
+    }
+  }
+
+
+  if(wherex() + strlen(menus->desktopmenu->title) + 1>= sizex) {
+    gotoxy(sizex - strlen(menus->desktopmenu->title) - 1, 0);
+  } else {
+    cclear(sizex - wherex() -
+	   strlen(menus->desktopmenu->title) - 1);
+    update_area(wherex(), 0, sizex - wherex() -
+		strlen(menus->desktopmenu->title) - 1, 1);
+  }
+  
+  /* Draw desktopmenu */
+  if(menus->desktopmenu != menus->open) {
+    update_area(wherex(), 0, strlen(menus->desktopmenu->title) + 1, 1);
+    cputs(menus->desktopmenu->title);
+    cputc(' ');
+  } else {
+    draw_menu(menus->desktopmenu);
+  }
+
+  revers(0);
+
+
+
+}
+/*-----------------------------------------------------------------------------------*/
+unsigned char
+ctk_draw_height(void)
+{
+  return sizey;
+}
+/*-----------------------------------------------------------------------------------*/
+unsigned char
+ctk_draw_width(void)
+{
+  return sizex;
+}
+/*-----------------------------------------------------------------------------------*/
+static unsigned char
+ascii2screen(unsigned char c)
+{
+  if(c == '|') {
+    return 0x68;
+  }
+  if(c < 0x20) {
+    return c + 0x60;
+  }
+  if(c > 0x20 && c < 0x40) {
+    return c;
+  }
+  if(c >= 0x40 && c < 0x60) {
+    return c;
+  }
+  if(c >= 0x60 && c < 0x80) {
+    return c - 0x60;
+  }
+  if(c >= 0x80) {
+    return c;
+  }
+
+  return 32;
+}
+
+void
+ctk_arch_draw_char(char c,
+		   unsigned char xpos,
+		   unsigned char ypos,
+		   unsigned char reversedflag,
+		   unsigned char color)
+{
+
+  vnc_out_update_screen(xpos, ypos, ascii2screen(c),
+			color);
+  /*  vnc_out_update_screen(xpos, ypos, c |
+      (reversedflag? 0x80: 0));*/
+}
+
+unsigned char
+ctk_arch_keyavail(void)
+{
+  return vnc_out_keyavail();
+}
+
+ctk_arch_key_t
+ctk_arch_getkey(void)
+{
+  return vnc_out_getkey() & 0x7f;
+}
+/*-----------------------------------------------------------------------------------*/
+static
+DISPATCHER_UIPCALL(ctk_vncserver_appcall, state)
+{
+  static struct vnc_server_state *vs;
+  DISPATCHER_UIPCALL_ARG(state);
+
+  vs = (struct vnc_server_state *)(state);
+  
+  if(uip_connected()) {
+
+    /* Since we've just been connected, the state pointer should be
+       NULL and we need to allocate a new state object. If we have run
+       out of memory for state objects, we'll have to abort the
+       connection and return. */
+    if(vs == NULL) {
+      vs = alloc_state();
+      if(vs == NULL) {
+	uip_close();
+	return;
+      }
+      dispatcher_markconn(uip_conn, (void *)vs);
+    }
+  } else if(uip_closed() || uip_aborted()) {
+    if(vs != NULL) {
+      dealloc_state(vs);
+    }
+    return;
+  }
+  vnc_server_appcall(vs);
+}
+/*-----------------------------------------------------------------------------------*/
+LOADER_INIT_FUNC(ctk_vncserver_init)
+{
+  u8_t i;
+  
+  if(id == EK_ID_NONE) {
+    id = dispatcher_start(&p);
+    dispatcher_uiplisten(5900);
+
+    for(i = 0; i < VNCSERVER_CONF_NUMCONNS; ++i) {
+      conns[i].state = VNC_DEALLOCATED;
+    }
+  }
+}
+/*-----------------------------------------------------------------------------------*/
diff --git a/contiki/ctk/ctk-vncserver.h b/contiki/ctk/ctk-vncserver.h
new file mode 100644
index 0000000..aed42d9
--- /dev/null
+++ b/contiki/ctk/ctk-vncserver.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2002, Adam Dunkels.
+ * All rights reserved. 
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met: 
+ * 1. Redistributions of source code must retain the above copyright 
+ *    notice, this list of conditions and the following disclaimer. 
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials provided
+ *    with the distribution. 
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgement:
+ *        This product includes software developed by Adam Dunkels. 
+ * 4. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.  
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
+ *
+ * This file is part of the "ctk" console GUI toolkit for cc65
+ *
+ * $Id: ctk-vncserver.h,v 1.1 2003/07/02 21:34:00 adamdunkels Exp $
+ *
+ */
+#ifndef __CTK_VNCSERVER_H__
+#define __CTK_VNCSERVER_H__
+
+void ctk_vncserver_init(void);
+
+
+
+#endif /* __CTK_VNCSERVER_H__ */
diff --git a/contiki/ctk/vnc-out.c b/contiki/ctk/vnc-out.c
new file mode 100644
index 0000000..9e14d2f
--- /dev/null
+++ b/contiki/ctk/vnc-out.c
@@ -0,0 +1,964 @@
+/*
+ * Copyright (c) 2001, Adam Dunkels
+ * All rights reserved. 
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met: 
+ * 1. Redistributions of source code must retain the above copyright 
+ *    notice, this list of conditions and the following disclaimer. 
+ * 2. Redistributions in binary form must reproduce the above copyright 
+ *    notice, this list of conditions and the following disclaimer in the 
+ *    documentation and/or other materials provided with the distribution. 
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Adam Dunkels.
+ * 4. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.  
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
+ *
+ * This file is part of the uIP TCP/IP stack.
+ *
+ * $Id: vnc-out.c,v 1.1 2003/07/02 21:34:00 adamdunkels Exp $
+ *
+ */
+
+#include "uip.h"
+#include "vnc-server.h"
+#include "vnc-out.h"
+
+#include "libconio.h"
+
+#include "ctk-vncfont.h"
+
+#include "ctk-arch.h"
+
+#include "ctk-mouse.h"
+
+#ifndef NOT_AVR
+#include <avr/pgmspace.h>
+#else
+#define memcpy_P memcpy
+#endif /* NOT_AVR */
+
+#define CHARS_WIDTH    LIBCONIO_CONF_SCREEN_WIDTH
+#define CHARS_HEIGHT   LIBCONIO_CONF_SCREEN_HEIGHT
+
+#define SCREEN_X       10
+#define SCREEN_Y       8
+
+#define FONT_WIDTH 6
+#define FONT_HEIGHT 8
+
+#define SCREEN_WIDTH  (CHARS_WIDTH * FONT_WIDTH + 2 * SCREEN_X) /*420*/
+#define SCREEN_HEIGHT (CHARS_HEIGHT * FONT_HEIGHT + 2 * SCREEN_Y) /*300*/
+#define BORDER_COLOR 0x00
+#define TEXT_COLOR   0x38 /*0xe0*/
+#define SCREEN_COLOR 0x00 /*0xc0*/
+
+#define BGR(b,g,r) (((b) << 6) | (g) << 3 | (r))
+
+#define BGCOLOR BGR(1,0,1)
+
+static u8_t menucolor[] = {
+  BGR(0,7,7), /* Background. */           
+  BGR(0,5,5), /* Anti-alias font color. */ 
+  BGR(0,0,0), /* Font color. */            
+};
+
+
+static u8_t activemenucolor[] = {
+  BGR(3,7,7), /* Background. */           
+  BGR(3,6,6), /* Anti-alias font color. */ 
+  BGR(0,0,0), /* Font color. */            
+};
+
+
+static unsigned char backgroundcolor[] = {BGR(1,0,1)};
+
+static unsigned char wincol[] =
+ {BGR(2,5,5),BGR(2,2,2),BGR(0,1,1),BGR(1,0,0),BGR(2,0,0),BGR(2,1,1)};
+static unsigned char wincol_f[] =
+ {BGR(3,6,6),BGR(1,2,2),BGR(0,1,1),BGR(2,0,0),BGR(3,2,2),BGR(3,4,4)};
+static unsigned char wincol_d[] =
+ {BGR(3,7,7),BGR(1,5,5),BGR(0,0,0),BGR(2,0,0),BGR(3,2,2),BGR(3,4,4)};
+
+static unsigned char sepcol[] =
+ {BGR(2,5,5),BGR(2,6,6),BGR(3,6,6)};
+static unsigned char sepcol_f[] =
+ {BGR(3,6,6),BGR(3,5,5),BGR(2,5,5)};
+static unsigned char sepcol_d[] =
+ {BGR(3,7,7),BGR(1,5,7),BGR(0,0,0)};
+
+static unsigned char labcol[] =
+ {BGR(2,5,5),BGR(1,3,3),BGR(0,1,1)};
+static unsigned char labcol_f[] =
+ {BGR(3,6,6),BGR(3,5,5),BGR(0,0,0)};
+static unsigned char labcol_d[] =
+ {BGR(3,7,7),BGR(1,5,5),BGR(0,0,0)};
+
+
+static unsigned char butcol[] =
+ {BGR(2,4,4),BGR(1,3,3),BGR(0,1,1),BGR(2,4,4),BGR(2,4,4),BGR(2,4,4),
+  BGR(2,5,5),BGR(2,5,5)};
+static unsigned char butcol_w[] =
+ {BGR(2,4,4),BGR(1,3,3),BGR(0,1,1),BGR(2,4,4),BGR(2,4,4),BGR(2,4,4),
+  BGR(2,5,5),BGR(2,5,5)};
+static unsigned char butcol_f[] =
+ {BGR(2,3,3),BGR(3,5,5),BGR(3,6,6),BGR(3,5,5),BGR(3,6,6),BGR(3,7,7),
+  BGR(3,6,6),BGR(2,5,5)};
+static unsigned char butcol_fw[] =
+ {BGR(3,7,7),BGR(3,6,6),BGR(0,0,0),BGR(1,7,7),BGR(2,7,7),BGR(3,7,7),
+  BGR(3,6,6),BGR(3,7,6)};
+static unsigned char butcol_d[] =
+ {BGR(2,3,3),BGR(2,5,5),BGR(3,6,6),BGR(1,3,4),BGR(1,5,6),BGR(2,6,7),
+  BGR(3,7,7),BGR(2,5,5)};
+static unsigned char butcol_dw[] =
+ {BGR(0,0,0),BGR(2,5,5),BGR(3,7,7),BGR(1,3,4),BGR(1,5,6),BGR(2,6,7),
+  BGR(3,7,7),BGR(2,5,5)};
+
+
+static unsigned char hlcol[] =
+ {BGR(2,5,5),BGR(1,3,3),BGR(1,0,0)};
+static unsigned char hlcol_w[] =
+ {BGR(2,5,5),BGR(1,3,3),BGR(1,0,0)};
+static unsigned char hlcol_f[] =
+ {BGR(3,6,6),BGR(3,5,5),BGR(3,0,0)};
+static unsigned char hlcol_fw[] =
+ {BGR(3,6,6),BGR(3,6,7),BGR(3,7,7)};
+static unsigned char hlcol_d[] =
+ {BGR(3,7,7),BGR(3,5,5),BGR(2,0,0)};
+static unsigned char hlcol_dw[] =
+ {BGR(3,7,7),BGR(1,5,5),BGR(0,0,0)};
+
+static unsigned char iconcol[] =
+ {BGR(0,1,1),BGR(2,3,3),BGR(2,5,5)};
+static unsigned char iconcol_w[] =
+ {BGR(0,1,1),BGR(2,5,5),BGR(3,7,7)};
+
+
+
+static u8_t *colortheme[] =
+  {
+    backgroundcolor,
+    
+    /* Window colors */
+    wincol, wincol, wincol_f, wincol_f, wincol_d, wincol_d,
+
+    /* Separator colors. */
+    sepcol, sepcol, sepcol_f, sepcol_f, sepcol_d, sepcol_d,    
+
+    /* Label colors. */
+    labcol, labcol, labcol_f, labcol_f, labcol_d, labcol_d,    
+
+    /* Button colors. */
+    butcol, butcol_w, butcol_f, butcol_fw, butcol_d, butcol_dw,    
+
+    /* Hyperlink colors. */
+    hlcol, hlcol_w, hlcol_f, hlcol_fw, hlcol_d, hlcol_dw,
+
+    /* Textentry colors. */
+    butcol, butcol_w, butcol_f, butcol_fw, butcol_d, butcol_dw,
+
+    /* Icon colors */
+    iconcol, iconcol_w, iconcol, iconcol_w, iconcol, iconcol_w,
+    
+    /* Menu colors. */
+    menucolor, activemenucolor, activemenucolor
+  };
+
+
+static int mouse_x, mouse_y, mouse_button;
+
+static u8_t screen[CHARS_WIDTH * CHARS_HEIGHT],
+  colorscreen[CHARS_WIDTH * CHARS_HEIGHT];
+
+
+#define PRINTF(x)
+
+/*-----------------------------------------------------------------------------------*/
+#define MAX_ICONS 16
+struct ctk_icon *icons[MAX_ICONS];
+
+unsigned char
+vnc_out_add_icon(struct ctk_icon *icon)
+{
+  u8_t i;
+  signed int empty;
+
+  empty = -1;
+  for(i = 0; i < MAX_ICONS; ++i) {
+    if(icon == icons[i]) {
+      return i;
+    }
+    if(icons[i] == NULL && empty < 0){
+      empty = i;
+    }
+  }
+
+  if(empty == -1) {
+    empty = 0;
+  }
+  icons[empty] = icon;
+  return empty;
+}
+
+/*-----------------------------------------------------------------------------------*/
+void
+vnc_out_init(void)
+{
+  u16_t i;
+  for(i = 0; i < CHARS_WIDTH * CHARS_HEIGHT; ++i) {
+    screen[i] = 0x20;
+  }
+}
+
+void
+vnc_out_update_screen(u8_t xpos, u8_t ypos, u8_t c, u8_t color)
+{
+  screen[xpos + ypos * CHARS_WIDTH] = c;
+  colorscreen[xpos + ypos * CHARS_WIDTH] = color;
+}
+/*-----------------------------------------------------------------------------------*/
+void
+vnc_out_update_area(struct vnc_server_state *vs,
+		    u8_t x, u8_t y, u8_t w, u8_t h)
+{
+  u8_t x2, y2, ax2, ay2;
+  struct vnc_server_update *a, *b;
+
+  PRINTF(("update_area_connection: should update (%d:%d) (%d:%d)\n",
+	 x, y, w, h));
+  
+  /* First check if we already have a full update queued. If so, there
+     is no need to put this update on the list. If there is a full
+     update, it is always the first one on the list, so there is no
+     need to go step the list in search for it. */
+
+  if(vs->updates_pending != NULL &&
+     vs->updates_pending->type == VNC_SERVER_UPDATE_FULL) {
+    PRINTF(("Update_area_connecion: full update already queued...\n"));
+    return;
+  }
+
+ again:
+  
+  /* Check that we don't update the same area twice by going through
+     the list and search for an update with the same coordinates. */
+  for(a = vs->updates_pending; a != NULL; a = a->next) {
+    if(a->x == x && a->y == y &&
+       a->w == w && a->h == h) {
+      PRINTF(("Update_area_connecion: found equal area\n"));
+      return;
+    }    
+  }
+
+  /* Next we check if this update covers an existing update. If so, we
+     remove the old update, expand this update so that it covers both
+     areas to be updated and run through the process again. */
+  b = NULL;
+  for(a = vs->updates_pending; a != NULL; a = a->next) {      
+    x2 = x + w;
+    y2 = y + h;
+    
+    ax2 = a->x + a->w;
+    ay2 = a->y + a->h;
+
+    /* Test the corners of both updates to see if they are inside the
+       other area. */
+#define INSIDE(x,y,x1,y1,x2,y2) ((x1) <= (x) && \
+                                 (x2) >= (x) && \
+                                 (y1) <= (y) && \
+                                 (y2) >= (y))
+    if(INSIDE(x, y, a->x, a->y, ax2, ay2) ||
+       INSIDE(x, y2, a->x, a->y, ax2, ay2) ||
+       INSIDE(x2, y2, a->x, a->y, ax2, ay2) ||
+       INSIDE(x2, y, a->x, a->y, ax2, ay2) ||
+       INSIDE(a->x, a->y, x, y, x2, y2) ||
+       INSIDE(a->x, ay2, x, y, x2, y2) ||
+       INSIDE(ax2, ay2, x, y, x2, y2) ||
+       INSIDE(ax2, a->y, x, y, x2, y2)) {
+
+      /* Remove the old update from the list. */
+      vnc_server_update_remove(vs, a);
+
+      /* Put it on the free list. */
+      vnc_server_update_free(vs, a);
+
+      PRINTF(("update_area_connection: inside (%d:%d, %d:%d)\n",
+	     a->x, a->y, ax2, ay2));
+      
+      /* Find the area that covers both updates. */
+#define MIN(a,b) ((a) < (b)? (a): (b))
+#define MAX(a,b) ((a) > (b)? (a): (b))
+      x = MIN(a->x, x);
+      y = MIN(a->y, y);
+      ax2 = MAX(ax2, x2);
+      ay2 = MAX(ay2, y2);
+      w = ax2 - x;
+      h = ay2 - y;
+
+      /* This should really be done by a recursive call to this
+	 function: update_area_connection(vs, x, y, w, h); but because
+	 some compilers might not be able to optimize away the
+	 recursive call, we do it using a goto instead. */
+      PRINTF(("Update_area_connecion: trying larger area (%d:%d) (%d:%d)\n", x, y, w, h));
+      goto again;
+    }
+    if(b != NULL) {
+      b = b->next;
+    }
+  }
+  
+  /* Allocate an update object by pulling it off the free list. If
+     there are no free objects, we go for a full update instead. */
+
+  /*  a = vs->updates_free;*/
+  a = vnc_server_update_alloc(vs);
+  if(a == NULL) {
+    PRINTF(("Update_area_connecion: no free updates, doing full\n"));
+    /* Put all pending updates, except for one, on the free list. Use
+       the remaining update as a full update. */
+    while(vs->updates_pending != NULL) {
+      a = vs->updates_pending;
+      vnc_server_update_remove(vs, a);
+      vnc_server_update_free(vs, a);
+    }
+
+    a = vnc_server_update_alloc(vs);
+    a->type = VNC_SERVER_UPDATE_FULL;
+    vnc_server_update_add(vs, a);
+					
+
+  } else {
+    
+    PRINTF(("Update_area_connecion: allocated update for (%d:%d) (%d:%d)\n", x, y, w, h));
+  /* Else, we put the update object at the end of the pending
+     list. */
+    a->type = VNC_SERVER_UPDATE_PARTS;
+    a->x = x;
+    a->y = y;
+    a->w = w;
+    a->h = h;
+    vnc_server_update_add(vs, a);
+  }
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+init_send_screen(struct vnc_server_state *vs)
+{
+  vs->sendmsg = SEND_SCREEN;
+  vs->x = vs->y = 0;
+  vs->x1 = vs->y1 = 0;
+  vs->x2 = vs->y2 = 0;
+  vs->w = CHARS_WIDTH;
+  vs->h = CHARS_HEIGHT;
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+check_updates(struct vnc_server_state *vs)
+{
+  
+  if(vs->state == VNC_RUNNING &&
+     vs->sendmsg == SEND_NONE &&
+     vs->updates_current == NULL) {
+    if(vs->updates_pending != NULL &&
+       vs->update_requested != 0) {
+      vs->update_requested = 0;
+      /*      vs->updates_current = vs->updates_pending;
+      vs->updates_pending = vs->updates_pending->next;
+      vs->updates_current->next = NULL;*/
+
+      vs->updates_current = vnc_server_update_dequeue(vs);
+      
+      if(vs->updates_current->type == VNC_SERVER_UPDATE_PARTS) {
+	vs->x = vs->x1 = vs->x2 = vs->updates_current->x;
+	vs->y = vs->y1 = vs->y2 = vs->updates_current->y;
+	vs->w = vs->updates_current->w;
+	vs->h = vs->updates_current->h;
+	vs->sendmsg = SEND_UPDATE;
+	
+	PRINTF(("New update from (%d:%d) (%d:%d) to (%d:%d)\n",
+	       vs->x, vs->y, vs->x1, vs->y1, vs->x + vs->w,
+	       vs->y + vs->h));
+      } else if(vs->updates_current->type == VNC_SERVER_UPDATE_FULL) {
+	init_send_screen(vs);
+	PRINTF(("New full update\n"));
+      }
+    }
+  }
+}
+/*-----------------------------------------------------------------------------------*/
+static u8_t tmp[FONT_WIDTH * FONT_HEIGHT];
+static void
+makechar(char *ptr, u8_t x, u8_t y)
+{
+  u8_t i, *tmpptr;
+  u8_t *colorscheme;
+  unsigned char *bitmap;
+  u8_t b, b2;
+  u8_t xmove, ymove;
+  unsigned char c, color;
+
+  color = colorscreen[x + y * CHARS_WIDTH];
+  c = screen[x + y * CHARS_WIDTH];
+
+  colorscheme = colortheme[color];
+      
+  /* First check if the character is a special icon character. These
+     are to be interpreted in a special manner: the first character of
+     the icon (the top left corner) has the highest bit set, but not
+     but 6. All other characters have bit 6 set, and also count the
+     number of positions away from the top left corner. Only the top
+     left corner contains enough information to identify the icon, all
+     other chars only contain the number of steps to reach the
+     identifying icon. */
+  if((c & 0x80) != 0) {
+    xmove = c & 0x0f;
+    ymove = (c & 0x30) >> 4;
+    
+    c = colorscreen[x + y * CHARS_WIDTH];
+    bitmap = icons[c & 0x3f]->bitmap + ymove * 8*3;
+
+    colorscheme = colortheme[VNC_OUT_ICONCOLOR + (c >> 6)];
+    switch(xmove) {
+    case 0:
+      for(i = 0; i < FONT_HEIGHT; ++i) {
+	b = bitmap[i];
+	*ptr++ = colorscheme[(b >> 7) & 0x01];
+	*ptr++ = colorscheme[(b >> 6) & 0x01];
+	*ptr++ = colorscheme[(b >> 5) & 0x01];
+	*ptr++ = colorscheme[(b >> 4) & 0x01];
+	*ptr++ = colorscheme[(b >> 3) & 0x01];
+	*ptr++ = colorscheme[(b >> 2) & 0x01];		
+      }
+      break;
+    case 1:
+      for(i = 0; i < FONT_HEIGHT; ++i) {
+	b = bitmap[i];
+	b2 = bitmap[i + 8];
+	*ptr++ = colorscheme[(b >> 1) & 0x01];
+	*ptr++ = colorscheme[(b >> 0) & 0x01];
+	*ptr++ = colorscheme[(b2 >> 7) & 0x01];
+	*ptr++ = colorscheme[(b2 >> 6) & 0x01];
+	*ptr++ = colorscheme[(b2 >> 5) & 0x01];
+	*ptr++ = colorscheme[(b2 >> 4) & 0x01];		
+      }
+      break;
+    case 2:
+      for(i = 0; i < FONT_HEIGHT; ++i) {
+	b = bitmap[i+8];
+	b2 = bitmap[i+16];
+	*ptr++ = colorscheme[(b >> 3) & 0x01];
+	*ptr++ = colorscheme[(b >> 2) & 0x01];
+	*ptr++ = colorscheme[(b >> 1) & 0x01];
+	*ptr++ = colorscheme[(b >> 0) & 0x01];
+	*ptr++ = colorscheme[(b2 >> 7) & 0x01];
+	*ptr++ = colorscheme[(b2 >> 6) & 0x01];		
+      }
+      break;
+    case 3:
+      for(i = 0; i < FONT_HEIGHT; ++i) {
+	b = bitmap[i+16];
+	*ptr++ = colorscheme[(b >> 5) & 0x01];
+	*ptr++ = colorscheme[(b >> 4) & 0x01];
+	*ptr++ = colorscheme[(b >> 3) & 0x01];
+	*ptr++ = colorscheme[(b >> 2) & 0x01];
+	*ptr++ = colorscheme[(b >> 1) & 0x01];
+	*ptr++ = colorscheme[(b >> 0) & 0x01];		
+      }
+      break;
+    }
+  } else {
+    memcpy_P(tmp, &ctk_vncfont[c * (FONT_WIDTH * FONT_HEIGHT)],
+	     FONT_WIDTH * FONT_HEIGHT);
+    
+    tmpptr = tmp;
+
+    
+    for(i = 0; i < FONT_HEIGHT * FONT_WIDTH; ++i) {
+      *ptr++ = colorscheme[*tmpptr++];
+    }
+  }
+}
+/*-----------------------------------------------------------------------------------*/
+void
+vnc_out_new(struct vnc_server_state *vs)
+{
+  u8_t i;
+  
+  vs->width = SCREEN_WIDTH;
+  vs->height = SCREEN_HEIGHT;
+  vs->x = vs->y = vs->x1 = vs->y1 = vs->x2 = vs->y2 = 0;
+  vs->w = CHARS_WIDTH;
+  vs->h = CHARS_HEIGHT;
+
+  /* Initialize the linked list of updates. */
+  for(i = 0; i < VNC_SERVER_MAX_UPDATES - 1; ++i) {
+    vs->updates_pool[i].next = &vs->updates_pool[i + 1];    
+  }
+  vs->updates_pool[VNC_SERVER_MAX_UPDATES].next = NULL;
+
+  vs->updates_free = &vs->updates_pool[0];
+  vs->updates_pending = vs->updates_current = NULL;
+}
+/*-----------------------------------------------------------------------------------*/
+void
+vnc_out_send_blank(struct vnc_server_state *vs)
+{
+  struct rfb_fb_update *umsg;
+  u8_t *ptr;
+  u16_t len;
+  u8_t msglen;
+      
+  vs->x = vs->y = 0;
+  vs->x2 = vs->y2 = 0;
+	  
+  umsg = (struct rfb_fb_update *)uip_appdata;
+  
+  umsg->type = RFB_FB_UPDATE;
+  umsg->rects = HTONS(2);
+
+  ptr = (u8_t *)umsg + sizeof(struct rfb_fb_update);
+  len = sizeof(struct rfb_fb_update);
+  
+  msglen = vnc_server_draw_rect(ptr, 0, 0,
+				HTONS(SCREEN_WIDTH),
+				HTONS(SCREEN_HEIGHT),
+				BORDER_COLOR);
+
+  
+  ptr += msglen;
+  len += msglen;
+
+  msglen = vnc_server_draw_rect(ptr,
+				HTONS(SCREEN_X), HTONS(SCREEN_Y),
+				HTONS(SCREEN_WIDTH - SCREEN_X * 2),
+				HTONS(SCREEN_HEIGHT - SCREEN_Y * 2),
+				SCREEN_COLOR);
+
+  uip_send(uip_appdata, len + msglen);
+
+  vs->sendmsg = SENT_BLANK;
+}
+/*-----------------------------------------------------------------------------------*/
+void
+vnc_out_send_screen(struct vnc_server_state *vs)
+{
+  vnc_out_send_update(vs);
+}
+/*-----------------------------------------------------------------------------------*/
+
+void
+vnc_out_send_update(struct vnc_server_state *vs)
+{
+  u8_t x, y, x0;
+  u8_t msglen;
+  u16_t len, n;
+  u8_t *ptr;
+  struct rfb_fb_update *umsg;
+  struct rfb_fb_update_rect_hdr *recthdr;
+  struct rfb_rre_hdr *rrehdr;
+  u8_t c, color, lastcolor;
+  u8_t numblanks;
+
+  /* First, check if we need to feed the update function with a new
+     pending update. */
+  check_updates(vs);
+
+  /*  PRINTF(("Sending Update from (%d:%d) (%d:%d) to (%d:%d)\n",
+	 vs->x, vs->y, vs->x1, vs->y1, vs->x + vs->w,
+	 vs->y + vs->h));*/
+  
+  umsg = (struct rfb_fb_update *)uip_appdata;
+
+  umsg->type = RFB_FB_UPDATE;
+
+  x0 = vs->x1;
+  n = 0;
+  msglen = 0;
+  ptr = (u8_t *)umsg + sizeof(struct rfb_fb_update);
+  len = sizeof(struct rfb_fb_update);
+  
+  /* Loop over all characters that are covered by this update. */
+  for(y = vs->y1; y < vs->y + vs->h; ++y) {
+    for(x = x0; x < vs->x + vs->w; ++x) {
+
+
+      /* First check if there are any blank space characters, and if
+	 so, find out how many of them there are in a row. Instead of
+	 sending the individual space characters as raw bitmaps, we
+	 can send the entire string of blanks as a single color
+	 rectangle instead. */
+      
+      c = screen[x + y * CHARS_WIDTH];
+      numblanks = 0;
+      lastcolor = color = colorscreen[x + y * CHARS_WIDTH];
+
+      /* If the character is a blank, we continue reading characters
+	 until we find one that has a different color, or one that is
+	 not a blank. We must keep within the update rectangle, so we
+	 make sure that the "x" variable does not increase beyond the
+	 edge. The "numblanks" variable is used to keep track of how
+	 many blank characters we have found. */
+      while(lastcolor == color &&
+	    c == 0x20 &&
+	    x < vs->x + vs->w) {
+	++numblanks;
+
+	
+	++x;
+	lastcolor = color;
+	color = colorscreen[x + y * CHARS_WIDTH];
+	c = screen[x + y * CHARS_WIDTH];
+      }
+
+      if(numblanks > 0) {
+	
+	/*	PRINTF(("Found %d blanks (%d:%d -> %d:%d)\n",
+		numblanks, x - numblanks, y, x, y));*/
+	
+	/* There were one or more blank characters, so we send out a
+	   single color rectangle with the right width. But first we
+	   make sure that there is enough space in the current TCP
+	   segment to put the rectangle. If there isn't we have to
+	   backtrack the "x" variable to where we found the first
+	   blank character so that the next TCP segment will be able
+	   to update this area instead. */	
+
+	msglen = sizeof(struct rfb_fb_update_rect_hdr) +
+	  sizeof(struct rfb_rre_hdr);
+
+	if(msglen >= uip_mss() - len) {
+	  /*	  PRINTF(("Not enouch space for blanks (%d, left %d)\n",
+		  msglen, uip_mss() - len));*/
+	  /* There is not enough space in the segment, so we remember
+	     where we were ... */
+	  vs->x2 = x - numblanks;
+	  vs->y2 = y;
+
+	  /* ... and we break out of the loop. */
+	  goto loopend;	  
+	}
+
+	/* We construct a rectangle with the right width and color. */
+	recthdr = (struct rfb_fb_update_rect_hdr *)ptr;
+	rrehdr = (struct rfb_rre_hdr *)(ptr +
+		 sizeof(struct rfb_fb_update_rect_hdr));
+
+	/*	PRINTF(("Blankign (%d:%d) to (%d:%d)\n",
+	       (x - numblanks) * FONT_WIDTH,
+	       y * FONT_HEIGHT,
+	       FONT_WIDTH * numblanks,
+	       FONT_HEIGHT));*/
+	recthdr->rect.x = htons(SCREEN_X + (x - numblanks) *
+				FONT_WIDTH);
+	recthdr->rect.y = htons(SCREEN_Y + y * FONT_HEIGHT);
+	recthdr->rect.w = htons(FONT_WIDTH * numblanks);
+	recthdr->rect.h = HTONS(FONT_HEIGHT);
+	recthdr->encoding[0] =
+	  recthdr->encoding[1] =
+	  recthdr->encoding[2] = 0;
+	recthdr->encoding[3] = RFB_ENC_RRE;
+	
+	rrehdr->subrects[0] =
+	  rrehdr->subrects[1] = 0;
+	rrehdr->bgpixel = colortheme[lastcolor][0];
+
+	--x;
+      } else {
+
+	/* So there were no blank characters. */
+
+	/*	PRINTF(("An char at (%d:%d)\n", x, y));*/
+	/* First we must make sure that there is enough space in the
+	   outgoing TCP segment. */
+
+	msglen = sizeof(struct rfb_fb_update_rect_hdr) +
+	  FONT_HEIGHT * FONT_WIDTH;
+	if(msglen >= uip_mss() - len) {
+	  /*	  PRINTF(("Not enouch space for char (%d, left %d)\n",
+		  msglen, uip_mss() - len));*/
+	  
+	  /* There is not enough space in the segment, so we remember
+	     where we were ... */
+	  vs->x2 = x;
+	  vs->y2 = y;
+
+	  /* ... and we break out of the loop. */
+	  goto loopend;	  
+	}
+
+	/*	PRINTF(("ptr %p\n",ptr);*/
+	recthdr = (struct rfb_fb_update_rect_hdr *)ptr;
+
+	recthdr->rect.x = htons(SCREEN_X + x * FONT_WIDTH);
+	recthdr->rect.y = htons(SCREEN_Y + y * FONT_HEIGHT);
+	recthdr->rect.w = HTONS(FONT_WIDTH);
+	recthdr->rect.h = HTONS(FONT_HEIGHT);
+	recthdr->encoding[0] =
+	  recthdr->encoding[1] =
+	  recthdr->encoding[2] = 0;
+	recthdr->encoding[3] = RFB_ENC_RAW;
+	
+	makechar((u8_t *)recthdr +
+		 sizeof(struct rfb_fb_update_rect_hdr),
+		 x, y);
+#if 0
+		 c,
+		 /*		 &ctk_vncfont[c * (FONT_WIDTH * FONT_HEIGHT)]*/
+		 color);
+#endif /* 0 */
+	/*	PRINTF(("Msglen %d (%d:%d)\n", msglen, x, y);*/
+      }
+      len += msglen;
+      ptr += msglen;
+      ++n;
+    }
+    x0 = vs->x;
+  }
+  
+ loopend:
+
+  umsg->rects = htons(n);
+	
+  if(y == vs->y + vs->h && x == vs->x + vs->w) {
+    vs->x2 = vs->y2 = 0;
+  }
+
+  if(n > 0) {
+    /*    printf("Sending %d rects, %d bytes (%p, %p, %p)\n", n, len,
+	  uip_appdata, umsg, ptr);*/
+    uip_send(uip_appdata, len);
+  }
+
+}
+/*-----------------------------------------------------------------------------------*/
+#define NUMKEYS 100
+static char keys[NUMKEYS];
+static int firstkey, lastkey;
+
+
+char
+vnc_out_keyavail(void)
+{
+  return firstkey != lastkey;
+}
+
+char
+vnc_out_getkey(void)
+{
+  char key;
+  key = keys[firstkey];
+  
+  if(firstkey != lastkey) {
+    ++firstkey;
+    if(firstkey >= NUMKEYS) {
+      firstkey = 0;
+    }
+  }
+  
+  return key;  
+}
+
+void
+vnc_out_key_event(struct vnc_server_state *vs)
+{
+  struct rfb_key_event *ev;
+  
+  ev = (struct rfb_key_event *)uip_appdata;
+
+  if(ev->down != 0) {
+    if(vs->sendmsg == SEND_NONE) {
+      vs->sendmsg = SEND_UPDATE;
+    }
+
+
+    if(ev->key[2] == 0 ||
+       (ev->key[2] == 0xff &&	
+	(ev->key[3] == CH_HOME ||
+	 ev->key[3] == CH_TAB ||
+	 ev->key[3] == CH_ESC ||
+	 ev->key[3] == CH_DEL ||
+	 ev->key[3] == CH_ENTER ||
+	 ev->key[3] == CH_CURS_LEFT ||
+	 ev->key[3] == CH_CURS_UP ||
+	 ev->key[3] == CH_CURS_RIGHT ||
+	 ev->key[3] == CH_CURS_DOWN))) {
+      
+      keys[lastkey] = ev->key[3];
+      ++lastkey;
+      if(lastkey >= NUMKEYS) {
+	lastkey = 0;
+      }
+    }
+  }
+
+  check_updates(vs);
+}
+/*-----------------------------------------------------------------------------------*/
+void
+vnc_out_pointer_event(struct vnc_server_state *vs)
+{
+  struct rfb_pointer_event *ev;
+  u16_t evx, evy;
+  
+  ev = (struct rfb_pointer_event *)uip_appdata;
+
+  evx = htons(ev->x);
+  evy = htons(ev->y);
+  
+  if(evx > SCREEN_X && evx < SCREEN_WIDTH - 2 * SCREEN_X &&
+     evy > SCREEN_Y && evy < SCREEN_HEIGHT - 2 * SCREEN_Y) {
+
+    mouse_button = ev->buttonmask & RFB_BUTTON_MASK1;
+    
+    mouse_x = evx - SCREEN_X;
+    mouse_y = evy - SCREEN_Y;
+
+    check_updates(vs);    
+  }    
+}
+/*-----------------------------------------------------------------------------------*/
+void
+vnc_out_acked(struct vnc_server_state *vs)
+{
+  if(vs->state != VNC_RUNNING) {
+    return;
+  }
+  if(vs->sendmsg == SENT_BLANK) {
+    init_send_screen(vs);
+  } else if(vs->sendmsg == SEND_BLANK) {
+    /* Do nothing until sendmsg == SENT_BLANK. */
+  } else if(vs->sendmsg == SEND_SCREEN) {
+    /* When the screen has been fully drawn, ->x2 and ->y2 are both
+       set to 0 to indicate this.*/
+    if(vs->x2 == 0 && vs->y2 == 0) {
+      vs->sendmsg = SEND_NONE;
+      
+      /* If there was an updaterequest for the entire screen, we can
+	 clear that flag now. */
+      if(vs->updates_current != NULL) {	
+	vnc_server_update_free(vs, vs->updates_current);
+	vs->updates_current = NULL;
+      }
+      check_updates(vs);
+    } else {
+      vs->x1 = vs->x2;
+      vs->y1 = vs->y2;
+    }
+	      
+  } else if(vs->sendmsg == SEND_UPDATE) {
+    if(vs->x2 == 0 && vs->y2 == 0) {
+      /* So, we have updated the area that we needed. We now check if
+	 there have been any recent full screen update requests. If
+	 so, we need to go to the SEND_SCREEN state. Else, we see if
+	 there were more areas that needed to be updated and if so,
+	 we'll continue with those. */
+
+      vs->sendmsg = SEND_NONE;
+
+      if(vs->updates_current != NULL) {
+	vnc_server_update_free(vs, vs->updates_current);
+	vs->updates_current = NULL;
+
+      }
+      check_updates(vs);
+#if 0
+      if(vs->updaterequest == VNC_SERVER_UPDATE_FULL) {
+	check_updates(vs);
+      } else {
+	vs->updatesptr2 = (vs->updatesptr2 + 1) %
+	  VNC_SERVER_MAX_UPDATES;
+
+	/* If there are no more updates to do, we'll go back to the
+	   SEND_NONE state. */	
+	if(vs->updatesptr2 == vs->updatesptr) {
+	  vs->updatetype = VNC_SERVER_UPDATE_NONE;
+	} else {	 
+	  /* Otherwise, we continue to update the next area. */
+	  vs->updaterequest = VNC_SERVER_UPDATE_PARTS;
+	  check_updates(vs);
+	}
+      }
+#endif /* 0 */
+    } else {	     
+      vs->x1 = vs->x2;
+      vs->y1 = vs->y2;
+    }    
+  } else {
+    vs->sendmsg = SEND_NONE;
+  }
+}
+/*-----------------------------------------------------------------------------------*/
+void
+vnc_out_poll(struct vnc_server_state *vs)
+{
+  /*  PRINTF(("vs->state %d, sendmsg %d, updatetype %d, updatereq %d\n",
+      vs->state, vs->sendmsg, vs->updatetype, vs->updaterequest);*/
+  
+  if(vs->state == VNC_RUNNING &&
+     vs->sendmsg == SEND_NONE) {
+    check_updates(vs);
+    vnc_server_send_data(vs);
+  }
+}
+/*-----------------------------------------------------------------------------------*/
+void
+ctk_mouse_init(void)
+{
+
+}
+/*-----------------------------------------------------------------------------------*/
+unsigned short
+ctk_mouse_x(void)
+{
+  return mouse_x;
+}
+/*-----------------------------------------------------------------------------------*/
+unsigned short
+ctk_mouse_y(void)
+{
+  return mouse_y;
+}
+/*-----------------------------------------------------------------------------------*/
+unsigned char
+ctk_mouse_xtoc(unsigned short x)
+{
+  return x / FONT_WIDTH;
+}
+/*-----------------------------------------------------------------------------------*/
+unsigned char
+ctk_mouse_ytoc(unsigned short y)
+{
+  return y / FONT_HEIGHT;
+}
+/*-----------------------------------------------------------------------------------*/
+unsigned char
+ctk_mouse_button(void)
+{
+  return mouse_button;
+}
+/*-----------------------------------------------------------------------------------*/
+void
+ctk_mouse_hide(void)
+{
+}
+/*-----------------------------------------------------------------------------------*/
+void
+ctk_mouse_show(void)
+{
+}
+/*-----------------------------------------------------------------------------------*/
diff --git a/contiki/ctk/vnc-out.h b/contiki/ctk/vnc-out.h
new file mode 100644
index 0000000..3e43d6f
--- /dev/null
+++ b/contiki/ctk/vnc-out.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2001, Adam Dunkels.
+ * All rights reserved. 
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met: 
+ * 1. Redistributions of source code must retain the above copyright 
+ *    notice, this list of conditions and the following disclaimer. 
+ * 2. Redistributions in binary form must reproduce the above copyright 
+ *    notice, this list of conditions and the following disclaimer in the 
+ *    documentation and/or other materials provided with the distribution. 
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Adam Dunkels.
+ * 4. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.  
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
+ *
+ * This file is part of the uIP TCP/IP stack.
+ *
+ * $Id: vnc-out.h,v 1.1 2003/07/02 21:34:00 adamdunkels Exp $
+ *
+ */
+
+#ifndef __VNC_OUT_H__
+#define __VNC_OUT_H__
+
+
+void vnc_out_init(void);
+void vnc_out_new(struct vnc_server_state *vs);
+
+void vnc_out_send_blank(struct vnc_server_state *vs);
+void vnc_out_send_screen(struct vnc_server_state *vs);
+void vnc_out_send_update(struct vnc_server_state *vs);
+
+void vnc_out_key_event(struct vnc_server_state *vs);
+void vnc_out_pointer_event(struct vnc_server_state *vs);
+
+void vnc_out_acked(struct vnc_server_state *vs);
+
+void vnc_out_poll(struct vnc_server_state *vs);
+
+
+void vnc_out_update_screen(u8_t x, u8_t y, u8_t c, u8_t color);
+char vnc_out_getkey(void);
+char vnc_out_keyavail(void);
+
+void vnc_out_update_area(struct vnc_server_state *vs,
+			 u8_t x, u8_t y, u8_t w, u8_t h);
+
+#include "ctk.h"
+
+unsigned char vnc_out_add_icon(struct ctk_icon *icon);
+
+#define VNC_OUT_BACKGROUNDCOLOR 0
+#define VNC_OUT_WINDOWCOLOR    1
+#define VNC_OUT_SEPARATORCOLOR (VNC_OUT_WINDOWCOLOR + 6)
+#define VNC_OUT_LABELCOLOR     (VNC_OUT_SEPARATORCOLOR + 6)
+#define VNC_OUT_BUTTONCOLOR    (VNC_OUT_LABELCOLOR + 6)
+#define VNC_OUT_HYPERLINKCOLOR (VNC_OUT_BUTTONCOLOR + 6)
+#define VNC_OUT_TEXTENTRYCOLOR (VNC_OUT_HYPERLINKCOLOR + 6)
+#define VNC_OUT_ICONCOLOR      (VNC_OUT_TEXTENTRYCOLOR + 6)
+#define VNC_OUT_MENUCOLOR      (VNC_OUT_ICONCOLOR + 6)
+#define VNC_OUT_OPENMENUCOLOR  (VNC_OUT_MENUCOLOR + 1)
+#define VNC_OUT_ACTIVEMENUCOLOR (VNC_OUT_OPENMENUCOLOR + 1)
+
+#endif /* __VNC_OUT_H__ */
diff --git a/contiki/ctk/vnc-server.c b/contiki/ctk/vnc-server.c
new file mode 100644
index 0000000..4f5bf49
--- /dev/null
+++ b/contiki/ctk/vnc-server.c
@@ -0,0 +1,489 @@
+/*
+ * Copyright (c) 2001, Adam Dunkels.
+ * All rights reserved. 
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met: 
+ * 1. Redistributions of source code must retain the above copyright 
+ *    notice, this list of conditions and the following disclaimer. 
+ * 2. Redistributions in binary form must reproduce the above copyright 
+ *    notice, this list of conditions and the following disclaimer in the 
+ *    documentation and/or other materials provided with the distribution. 
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Adam Dunkels.
+ * 4. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.  
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
+ *
+ * This file is part of the uIP TCP/IP stack.
+ *
+ * $Id: vnc-server.c,v 1.1 2003/07/02 21:34:00 adamdunkels Exp $
+ *
+ */
+
+/* A micro implementation of a VNC server. VNC is a protocol for
+   remote network displays. See http://www.uk.research.att.com/vnc/
+   for information about VNC.
+
+   Initialization states:
+
+   VNC_VERSION (send version string)
+   VNC_AUTH    (send auth message)
+   VNC_INIT    (send init message)
+
+   Steady state:
+   
+   VNC_RUNNING (send RFB updates, parse incoming messages)
+
+   What kind of message should be sent:
+
+   SEND_NONE   (No message)
+   SEND_BLANK  (Blank screen initially)
+   SEND_SCREEN (Send entire screen, initially)
+   SEND_UPDATE (Send incremental update)
+
+*/
+
+#include "uip.h"
+#include "vnc-server.h"
+#include "vnc-out.h"
+
+
+/* RFB server initial handshaking string. */
+#define RFB_SERVER_VERSION_STRING rfb_server_version_string
+
+/* "RFB 003.003" */
+static u8_t rfb_server_version_string[12] = {82,70,66,32,48,48,51,46,48,48,51,10};
+
+/* uVNC */
+static u8_t uvnc_name[4] = {117,86,78,67};
+#if 1
+#define PRINTF(x)
+#else
+#define PRINTF(x) printf x
+#endif
+
+/*-----------------------------------------------------------------------------------*/
+u8_t
+vnc_server_draw_rect(u8_t *ptr, u16_t x, u16_t y, u16_t w, u16_t h, u8_t c)
+{
+  struct rfb_fb_update_rect_hdr *recthdr;
+  struct rfb_rre_hdr *rrehdr;
+
+  recthdr = (struct rfb_fb_update_rect_hdr *)ptr;
+  rrehdr = (struct rfb_rre_hdr *)(ptr + sizeof(struct rfb_fb_update_rect_hdr));
+  
+  recthdr->rect.x = x;
+  recthdr->rect.y = y;
+  recthdr->rect.w = w;
+  recthdr->rect.h = h; 
+  recthdr->encoding[0] =
+    recthdr->encoding[1] =
+    recthdr->encoding[2] = 0;
+  recthdr->encoding[3] = RFB_ENC_RRE;
+      
+  rrehdr->subrects[0] =
+    rrehdr->subrects[1] = 0;
+  rrehdr->bgpixel = c;
+      
+  return sizeof(struct rfb_fb_update_rect_hdr) + sizeof(struct rfb_rre_hdr);
+}
+/*-----------------------------------------------------------------------------------*/
+void
+vnc_server_init(void)
+{
+  vnc_out_init();
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+vnc_send_blank(struct vnc_server_state *vs)
+{
+  switch(vs->type) {
+  case 0:	
+    vnc_out_send_blank(vs);
+    break;
+    /*  case 1:
+    vnc_stats_send_blank(vs);
+    break;   */
+  }
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+vnc_send_screen(struct vnc_server_state *vs)
+{
+  switch(vs->type) {
+  case 0:	
+    vnc_out_send_screen(vs);
+    break;
+    /*  case 1:
+    vnc_stats_send_screen(vs);
+    break;*/
+  }
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+vnc_send_update(struct vnc_server_state *vs)
+{
+  switch(vs->type) {
+  case 0:	
+    vnc_out_send_update(vs);
+    break;
+    /*  case 1:
+    vnc_stats_send_update(vs);
+    break;*/
+  }
+}
+/*-----------------------------------------------------------------------------------*/
+void
+vnc_server_send_data(struct vnc_server_state *vs)
+{
+  struct rfb_server_init *initmsg;
+  
+  switch(vs->state) {
+  case VNC_VERSION:
+    uip_send(RFB_SERVER_VERSION_STRING, sizeof(RFB_SERVER_VERSION_STRING));
+    break;
+  case VNC_AUTH:
+    uip_appdata[0] = 0;
+    uip_appdata[1] = 0;
+    uip_appdata[2] = 0;
+    uip_appdata[3] = RFB_AUTH_NONE;
+    uip_send(uip_appdata, 4);
+    break;
+  case VNC_INIT:
+    initmsg = (struct rfb_server_init *)uip_appdata;
+    initmsg->width = htons(vs->width);
+    initmsg->height = htons(vs->height);
+    /* BGR233 pixel format. */
+    initmsg->format.bps = 8;
+    initmsg->format.depth = 8;
+    initmsg->format.endian = 1;
+    initmsg->format.truecolor = 1;
+    initmsg->format.red_max = htons(7);
+    initmsg->format.green_max = htons(7);
+    initmsg->format.blue_max = htons(3);
+    initmsg->format.red_shift = 0;
+    initmsg->format.green_shift = 3;
+    initmsg->format.blue_shift = 6;
+    initmsg->namelength[0] = 0;
+    initmsg->namelength[1] = 0;
+    initmsg->namelength[2] = 0;	    
+    initmsg->namelength[3] = 4;
+    /*    bcopy(uvnc_name, &uip_appdata[sizeof(struct rfb_server_init)], 4);*/
+    uip_appdata[sizeof(struct rfb_server_init)+0] = 'u';
+    uip_appdata[sizeof(struct rfb_server_init)+1] = 'V';
+    uip_appdata[sizeof(struct rfb_server_init)+2] = 'N';
+    uip_appdata[sizeof(struct rfb_server_init)+3] = 'C';
+    uip_send(uip_appdata, sizeof(struct rfb_server_init) + 4);
+    break;
+  case VNC_RUNNING:
+    switch(vs->sendmsg) {
+    case SEND_NONE:
+      PRINTF(("Sending none\n"));
+      break;
+      
+    case SEND_BLANK:
+    case SENT_BLANK:
+      PRINTF(("Sending blank\n"));
+      vnc_send_blank(vs);
+      break;
+      
+    case SEND_SCREEN:
+      PRINTF(("Sending screen\n"));
+      vnc_send_screen(vs);
+      break;
+
+    case SEND_UPDATE:
+      PRINTF(("Sending update\n"));
+      vnc_send_update(vs);
+      break;
+    }
+    break;
+    
+  default:
+    break;
+  }
+
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+vnc_key_event(struct vnc_server_state *vs)
+{
+  switch(vs->type) {
+  case 0:	
+    vnc_out_key_event(vs);
+    break;
+    /*  case 1:
+    vnc_stats_key_event(vs);
+    break;*/
+  }
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+vnc_pointer_event(struct vnc_server_state *vs)
+{
+  switch(vs->type) {
+  case 0:	
+    vnc_out_pointer_event(vs);
+    break;
+    /*  case 1:
+    vnc_stats_pointer_event(vs);
+    break;*/
+  }
+}
+/*-----------------------------------------------------------------------------------*/
+static u8_t
+vnc_read_data(struct vnc_server_state *vs)
+{
+  u8_t *appdata;
+  u16_t len;
+  struct rfb_fb_update_request *req;
+  /*  u8_t niter;*/
+  
+  len = uip_datalen();
+  appdata = (u8_t *)uip_appdata;
+  
+  /* First, check if there is data left to discard since last read. */
+  if(vs->readlen > 0) {
+    appdata += vs->readlen;
+    if(len > vs->readlen) {
+      len -= vs->readlen;
+      vs->readlen = 0;
+    } else {
+      vs->readlen -= len;
+      len = 0;
+    }
+  }
+
+  if(vs->readlen != 0) {
+    return 1;
+  }
+
+  /* All data read and ignored, parse next message. */
+  /*  for(niter = 32; niter > 0 && len > 0; --niter) {*/
+  while(len > 0) {
+    switch(vs->state) {
+    case VNC_VERSION:
+    case VNC_VERSION2:
+      PRINTF(("Read in version\n"));
+      /* Receive and ignore client version string (12 bytes). */
+      vs->state = VNC_AUTH;
+      vs->readlen = 12;
+      break;
+      
+    case VNC_AUTH:
+    case VNC_AUTH2:
+      PRINTF(("Read in auth \n"));
+      /* Read and discard initialization from client (1 byte). */
+      vs->readlen = 1;
+      vs->state = VNC_INIT;
+      break;
+      
+    case VNC_INIT:
+    case VNC_INIT2:
+      PRINTF(("Read in init \n"));
+      vs->readlen = 0;
+      vs->state = VNC_RUNNING;
+      
+    case VNC_RUNNING:
+      /* Handle all client events. */
+      switch(*appdata) {
+      case RFB_SET_PIXEL_FORMAT:
+	PRINTF(("Set pixel format\n"));
+	vs->readlen = sizeof(struct rfb_set_pixel_format);
+	/* Check if client runs with BGR233 format. If not, abort the
+	   connection. */
+	/* XXX: not implemented yet. */
+	break;
+	
+      case RFB_FIX_COLORMAP_ENTRIES:
+	PRINTF(("Fix colormap entries\n"));
+	return 0;
+	
+      case RFB_SET_ENCODINGS:
+	PRINTF(("Set encodings\n"));
+	vs->readlen = sizeof(struct rfb_set_encoding);
+	vs->readlen += htons(((struct rfb_set_encoding *)appdata)->encodings) * 4;
+	/* Make sure that client supports the encodings we use. */
+	/* XXX: not implemented yet. */
+	break;
+	
+      case RFB_FB_UPDATE_REQ:
+	PRINTF(("Update request\n"));
+	vs->update_requested = 1;
+	vs->readlen = sizeof(struct rfb_fb_update_request);
+	/* blank the screen initially */
+	req = (struct rfb_fb_update_request *)appdata;
+	if(req->incremental == 0) {
+	  /*	  vs->sendmsg = SEND_BLANK;*/
+	  vnc_out_update_area(vs, 0, 0, vs->w, vs->h);
+	}
+	break;
+	
+      case RFB_KEY_EVENT:
+	vs->readlen = sizeof(struct rfb_key_event);
+	vnc_key_event(vs);
+	break;
+	
+      case RFB_POINTER_EVENT:
+	vs->readlen = sizeof(struct rfb_pointer_event);
+	vnc_pointer_event(vs);
+	break;
+	
+      case RFB_CLIENT_CUT_TEXT:
+	PRINTF(("Client cut text\n"));
+
+	if(((struct rfb_client_cut_text *)appdata)->len[0] != 0 ||
+	   ((struct rfb_client_cut_text *)appdata)->len[1] != 0) {
+	  return 0;
+	  
+	}
+	vs->readlen = sizeof(struct rfb_client_cut_text) +
+	  (((struct rfb_client_cut_text *)appdata)->len[2] << 8) +
+	  ((struct rfb_client_cut_text *)appdata)->len[3];
+	/*	return 0;*/
+	break;
+	
+      default:
+	PRINTF(("Unknown message %d\n", *appdata));
+	return 0;
+      }
+      break;
+      
+    default:
+      return 0;
+    }
+
+    if(vs->readlen > 0) {
+      if(len > vs->readlen) {
+	len -= vs->readlen;
+	appdata += vs->readlen;
+	vs->readlen = 0;
+      } else {
+	vs->readlen -= len;
+	len = 0;
+      }
+    } else {
+      /* Lost data. */
+      break;
+    }
+    
+  }
+
+  /*  if(vs->readlen > 0) {
+    printf("More data %d\n", vs->readlen);
+    }*/
+  
+  /*  uip_appdata = appdata;*/
+
+  return 1;
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+vnc_new(struct vnc_server_state *vs)
+{
+  vs->counter = 0;
+  vs->readlen = 0;
+  vs->sendmsg = SEND_NONE;
+  vs->update_requested = 1;
+  switch(vs->type) {
+  case 0:	
+    vnc_out_new(vs);
+    break;
+    /*  case 1:
+    vnc_stats_new(vs);
+    break;*/
+  }
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+vnc_acked(struct vnc_server_state *vs)
+{
+  switch(vs->state) {
+  case VNC_VERSION:
+    vs->state = VNC_VERSION2;
+    break;
+    
+  case VNC_AUTH:
+    vs->state = VNC_AUTH2;
+    break;
+    
+  case VNC_INIT:
+    vs->state = VNC_INIT2;
+    break;
+
+  case VNC_RUNNING:
+    switch(vs->type) {
+    case 0:	
+      vnc_out_acked(vs);
+      break;
+      /*    case 1:
+      vnc_stats_acked(vs);
+      break;*/
+    }
+    break;
+  }
+}
+/*-----------------------------------------------------------------------------------*/
+void
+vnc_server_appcall(struct vnc_server_state *vs)
+{
+  
+  vs->type = htons(uip_conn->lport) - 5900;
+  
+  if(uip_connected()) {      
+    vnc_new(vs);
+    vs->state = VNC_VERSION;
+    vnc_server_send_data(vs);
+    return;
+  }
+  if(uip_acked()) {
+    PRINTF(("Acked\n"));
+    vnc_acked(vs);
+  }
+  
+  if(uip_newdata()) {
+    PRINTF(("Newdata\n"));
+    vs->counter = 0;
+    if(vnc_read_data(vs) == 0) {
+      uip_abort();
+      return;
+    }
+  }
+  
+  if(uip_rexmit()) {
+    PRINTF(("Rexmit\n"));
+  }
+  
+  
+  if(uip_newdata() ||
+     uip_rexmit() ||
+     uip_acked()) {
+    vnc_server_send_data(vs);
+  } else if(uip_poll()) {
+    ++vs->counter;
+    /* Abort connection after about 20 seconds of inactivity. */
+    if(vs->counter >= 40) {
+      uip_abort();
+      return;
+    }
+    
+    vnc_out_poll(vs);
+  }
+  
+}
+/*-----------------------------------------------------------------------------------*/
diff --git a/contiki/ctk/vnc-server.h b/contiki/ctk/vnc-server.h
new file mode 100644
index 0000000..eeb3f5d
--- /dev/null
+++ b/contiki/ctk/vnc-server.h
@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 2001, Adam Dunkels.
+ * All rights reserved. 
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met: 
+ * 1. Redistributions of source code must retain the above copyright 
+ *    notice, this list of conditions and the following disclaimer. 
+ * 2. Redistributions in binary form must reproduce the above copyright 
+ *    notice, this list of conditions and the following disclaimer in the 
+ *    documentation and/or other materials provided with the distribution. 
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Adam Dunkels.
+ * 4. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.  
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
+ *
+ * This file is part of the uIP TCP/IP stack.
+ *
+ * $Id: vnc-server.h,v 1.1 2003/07/02 21:34:00 adamdunkels Exp $
+ *
+ */
+
+#ifndef __VNC_SERVER_H__
+#define __VNC_SERVER_H__
+
+
+/*struct vnc_server_updatearea {
+  u8_t active;
+  u8_t x, y;
+  u8_t w, h;
+  };*/
+
+struct vnc_server_update {
+  struct vnc_server_update *next;
+
+#define VNC_SERVER_UPDATE_NONE  0
+#define VNC_SERVER_UPDATE_PARTS 1
+#define VNC_SERVER_UPDATE_FULL  2
+
+  u8_t type;
+
+  u8_t x, y;
+  u8_t w, h;  
+};
+
+struct vnc_server_state {
+  u16_t counter;
+  u8_t type;
+  u8_t state;
+  u16_t height, width;
+
+  u8_t update_requested;
+  
+  /* Variables used when sending screen updates. */
+  u8_t x, y, x1, y1, x2, y2;
+  u8_t w, h;
+
+  
+
+  u16_t readlen;
+  u8_t sendmsg;
+  u8_t button;
+
+  
+  struct vnc_server_update *updates_current;
+  struct vnc_server_update *updates_pending;
+  struct vnc_server_update *updates_free;
+
+#define VNC_SERVER_MAX_UPDATES 8  
+  struct vnc_server_update updates_pool[VNC_SERVER_MAX_UPDATES];
+
+#if 0
+  /* The current update type. */
+  u8_t updatetype;
+ 
+  struct vnc_server_updatearea updates[VNC_SERVER_MAX_UPDATES];
+  u8_t updatesptr, updatesptr2;
+
+  u8_t updaterequest;
+#endif /* 0 */
+};
+
+struct vnc_server_update *
+     vnc_server_update_alloc(struct vnc_server_state *vs);
+void vnc_server_update_free(struct vnc_server_state *vs,
+			    struct vnc_server_update *a);
+void vnc_server_update_remove(struct vnc_server_state *vs,
+			      struct vnc_server_update *a);
+
+void vnc_server_update_add(struct vnc_server_state *vs,
+			   struct vnc_server_update *a);
+struct vnc_server_update *
+     vnc_server_update_dequeue(struct vnc_server_state *vs);
+
+
+
+
+void vnc_server_init(void);
+void vnc_server_appcall(struct vnc_server_state *state);
+
+
+extern struct vnc_server_state *vs;
+
+enum {
+  VNC_DEALLOCATED,
+  VNC_VERSION,
+  VNC_VERSION2,
+  VNC_AUTH,
+  VNC_AUTH2,
+  VNC_INIT,
+  VNC_INIT2,
+  VNC_RUNNING
+};
+
+/* Sendmsg */
+enum {
+  SEND_NONE,
+  SEND_BLANK,
+  SENT_BLANK,
+  SEND_SCREEN,
+  SEND_UPDATE
+};
+
+
+/* Definitions of the RFB (Remote Frame Buffer) protocol
+   structures and constants. */
+
+#include "uipopt.h"
+
+void vnc_server_send_data(struct vnc_server_state *vs);
+u8_t vnc_server_draw_rect(u8_t *ptr, u16_t x, u16_t y, u16_t w, u16_t h, u8_t c);
+
+
+/* Generic rectangle - x, y coordinates, width and height. */
+struct rfb_rect {
+  u16_t x;
+  u16_t y;
+  u16_t w;
+  u16_t h;
+};
+
+/* Pixel format definition. */
+struct rfb_pixel_format {
+  u8_t bps;       /* Bits per pixel: 8, 16 or 32. */
+  u8_t depth;     /* Color depth: 8-32 */
+  u8_t endian;    /* 1 - big endian (motorola), 0 - little endian
+		     (x86) */
+  u8_t truecolor; /* 1 - true color is used, 0 - true color is not used. */
+
+  /* The following fields are only used if true color is used. */
+  u16_t red_max, green_max, blue_max;
+  u8_t red_shift, green_shift, blue_shift;
+  u8_t pad1;
+  u16_t pad2;
+};
+
+
+/* RFB authentication constants. */
+
+#define RFB_AUTH_FAILED      0
+#define RFB_AUTH_NONE        1
+#define RFB_AUTH_VNC         2
+
+#define RFB_VNC_AUTH_OK      0
+#define RFB_VNC_AUTH_FAILED  1
+#define RFB_VNC_AUTH_TOOMANY 2
+
+/* RFB message types. */
+
+/* From server to client: */
+#define RFB_FB_UPDATE            0
+#define RFB_SET_COLORMAP_ENTRIES 1
+#define RFB_BELL                 2
+#define RFB_SERVER_CUT_TEXT      3
+
+/* From client to server. */
+#define RFB_SET_PIXEL_FORMAT     0
+#define RFB_FIX_COLORMAP_ENTRIES 1
+#define RFB_SET_ENCODINGS        2
+#define RFB_FB_UPDATE_REQ        3
+#define RFB_KEY_EVENT            4
+#define RFB_POINTER_EVENT        5
+#define RFB_CLIENT_CUT_TEXT      6
+
+/* Encoding types. */
+#define RFB_ENC_RAW      0
+#define RFB_ENC_COPYRECT 1
+#define RFB_ENC_RRE      2
+#define RFB_ENC_CORRE    3
+#define RFB_ENC_HEXTILE  4
+
+/* Message definitions. */
+
+/* Server to client messages. */
+
+struct rfb_server_init {
+  u16_t width;
+  u16_t height;
+  struct rfb_pixel_format format;
+  u8_t namelength[4];
+  /* Followed by name. */
+};
+
+struct rfb_fb_update {
+  u8_t type;
+  u8_t pad;
+  u16_t rects; /* Number of rectanges (struct rfb_fb_update_rect_hdr +
+		  data) that follows. */
+};
+
+struct rfb_fb_update_rect_hdr {
+  struct rfb_rect rect;
+  u8_t encoding[4];
+};
+
+struct rfb_copy_rect {
+  u16_t srcx;
+  u16_t srcy;
+};
+
+struct rfb_rre_hdr {
+  u16_t subrects[2];  /* Number of subrectangles (struct
+			 rfb_rre_subrect) to follow. */
+  u8_t bgpixel;
+};
+
+struct rfb_rre_subrect {
+  u8_t pixel;
+  struct rfb_rect rect;
+};
+
+struct rfb_corre_rect {
+  u8_t x;
+  u8_t y;
+  u8_t w;
+  u8_t h;
+};
+
+/* Client to server messages. */
+
+struct rfb_set_pixel_format {
+  u8_t type;
+  u8_t pad;
+  u16_t pad2;
+  struct rfb_pixel_format format;
+};
+
+struct rfb_fix_colormap_entries {
+  u8_t type;
+  u8_t pad;
+  u16_t firstcolor;
+  u16_t colors;
+};
+
+struct rfb_set_encoding {
+  u8_t type;
+  u8_t pad;
+  u16_t encodings;
+};
+
+struct rfb_fb_update_request {
+  u8_t type;
+  u8_t incremental;
+  u16_t x;
+  u16_t y;
+  u16_t w;
+  u16_t h;
+};
+
+struct rfb_key_event {
+  u8_t type;
+  u8_t down;
+  u16_t pad;
+  u8_t key[4];
+};
+
+#define RFB_BUTTON_MASK1 1
+#define RFB_BUTTON_MASK2 2
+#define RFB_BUTTON_MASK3 4
+struct rfb_pointer_event {
+  u8_t type;
+  u8_t buttonmask;
+  u16_t x;
+  u16_t y;
+};
+
+struct rfb_client_cut_text {
+  u8_t type;
+  u8_t pad[3];
+  u8_t len[4];
+};
+
+#endif /* __VNC_SERVER_H__ */