summaryrefslogtreecommitdiffstats
path: root/krfb/libvncserver
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commitbcb704366cb5e333a626c18c308c7e0448a8e69f (patch)
treef0d6ab7d78ecdd9207cf46536376b44b91a1ca71 /krfb/libvncserver
downloadtdenetwork-bcb704366cb5e333a626c18c308c7e0448a8e69f.tar.gz
tdenetwork-bcb704366cb5e333a626c18c308c7e0448a8e69f.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdenetwork@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'krfb/libvncserver')
-rw-r--r--krfb/libvncserver/1instance.c141
-rw-r--r--krfb/libvncserver/CHANGES75
-rw-r--r--krfb/libvncserver/COPYING340
-rw-r--r--krfb/libvncserver/Makefile.am14
-rw-r--r--krfb/libvncserver/README417
-rw-r--r--krfb/libvncserver/TODO80
-rw-r--r--krfb/libvncserver/auth.c109
-rw-r--r--krfb/libvncserver/bdf2c.pl60
-rw-r--r--krfb/libvncserver/cargs.c135
-rw-r--r--krfb/libvncserver/corre.c355
-rw-r--r--krfb/libvncserver/cursor.c678
-rw-r--r--krfb/libvncserver/cutpaste.c39
-rw-r--r--krfb/libvncserver/d3des.c442
-rw-r--r--krfb/libvncserver/d3des.h56
-rw-r--r--krfb/libvncserver/default8x16.h261
-rw-r--r--krfb/libvncserver/draw.c61
-rw-r--r--krfb/libvncserver/example.c279
-rw-r--r--krfb/libvncserver/font.c192
-rw-r--r--krfb/libvncserver/fontsel.c71
-rw-r--r--krfb/libvncserver/hextile.c347
-rw-r--r--krfb/libvncserver/httpd.c423
-rw-r--r--krfb/libvncserver/keysym.h1639
-rw-r--r--krfb/libvncserver/mac.c604
-rw-r--r--krfb/libvncserver/main.c729
-rw-r--r--krfb/libvncserver/pnmshow.c81
-rw-r--r--krfb/libvncserver/pnmshow24.c90
-rw-r--r--krfb/libvncserver/radon.h195
-rw-r--r--krfb/libvncserver/rfb.h865
-rw-r--r--krfb/libvncserver/rfbproto.h848
-rw-r--r--krfb/libvncserver/rfbserver.c1590
-rw-r--r--krfb/libvncserver/rre.c322
-rw-r--r--krfb/libvncserver/selbox.c301
-rw-r--r--krfb/libvncserver/sockets.c592
-rw-r--r--krfb/libvncserver/sraRegion.c889
-rw-r--r--krfb/libvncserver/sraRegion.h65
-rw-r--r--krfb/libvncserver/stats.c103
-rw-r--r--krfb/libvncserver/storepasswd.c46
-rw-r--r--krfb/libvncserver/tableinit24.c157
-rw-r--r--krfb/libvncserver/tableinitcmtemplate.c84
-rw-r--r--krfb/libvncserver/tableinittctemplate.c142
-rw-r--r--krfb/libvncserver/tabletrans24template.c281
-rw-r--r--krfb/libvncserver/tabletranstemplate.c117
-rw-r--r--krfb/libvncserver/tight.c1809
-rw-r--r--krfb/libvncserver/translate.c484
-rw-r--r--krfb/libvncserver/vncauth.c171
-rw-r--r--krfb/libvncserver/vncev.c119
-rw-r--r--krfb/libvncserver/x11vnc.c578
-rw-r--r--krfb/libvncserver/zippy.c182
-rw-r--r--krfb/libvncserver/zlib.c304
49 files changed, 17962 insertions, 0 deletions
diff --git a/krfb/libvncserver/1instance.c b/krfb/libvncserver/1instance.c
new file mode 100644
index 00000000..8feadb53
--- /dev/null
+++ b/krfb/libvncserver/1instance.c
@@ -0,0 +1,141 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+
+typedef struct {
+ char* filename; /* this file is the pipe (set by user) */
+ char is_server; /* this is set by open_control_file */
+ int fd; /* this is set by open_control_file */
+} single_instance_struct;
+
+/* returns fd, is_server is set to -1 if server, 0 if client */
+int open_control_file(single_instance_struct* str)
+{
+ struct stat buf;
+
+ if(stat(str->filename,&buf)) {
+ mkfifo(str->filename,128|256);
+ str->is_server=-1;
+ str->fd=open(str->filename,O_NONBLOCK|O_RDONLY);
+ } else {
+ str->fd=open(str->filename,O_NONBLOCK|O_WRONLY);
+ if(errno==ENXIO) {
+ str->is_server=-1;
+ str->fd=open(str->filename,O_NONBLOCK|O_RDONLY);
+ } else
+ str->is_server=0;
+ }
+
+ return(str->fd);
+}
+
+void delete_control_file(single_instance_struct* str)
+{
+ remove(str->filename);
+}
+
+void close_control_file(single_instance_struct* str)
+{
+ close(str->fd);
+}
+
+typedef void (*event_dispatcher)(char* message);
+
+int get_next_message(char* buffer,int len,single_instance_struct* str,int usecs)
+{
+ struct timeval tv;
+ fd_set fdset;
+ int num_fds;
+
+ FD_ZERO(&fdset);
+ FD_SET(str->fd,&fdset);
+ tv.tv_sec=0;
+ tv.tv_usec=usecs;
+
+ num_fds=select(str->fd+1,&fdset,NULL,NULL,&tv);
+ if(num_fds) {
+ int reallen;
+
+ reallen=read(str->fd,buffer,len);
+ if(reallen==0) {
+ close(str->fd);
+ str->fd=open(str->filename,O_NONBLOCK|O_RDONLY);
+ num_fds--;
+ }
+ buffer[reallen]=0;
+#ifdef DEBUG_1INSTANCE
+ if(reallen!=0) fprintf(stderr,"message received: %s.\n",buffer);
+#endif
+ }
+
+ return(num_fds);
+}
+
+int dispatch_event(single_instance_struct* str,event_dispatcher dispatcher,int usecs)
+{
+ char buffer[1024];
+ int num_fds;
+
+ if((num_fds=get_next_message(buffer,1024,str,usecs)) && buffer[0])
+ dispatcher(buffer);
+
+ return(num_fds);
+}
+
+int loop_if_server(single_instance_struct* str,event_dispatcher dispatcher)
+{
+ open_control_file(str);
+ if(str->is_server) {
+ while(1)
+ dispatch_event(str,dispatcher,50);
+ }
+
+ return(str->fd);
+}
+
+void send_message(single_instance_struct* str,char* message)
+{
+#ifdef DEBUG_1INSTANCE
+ int i=
+#endif
+ write(str->fd,message,strlen(message));
+#ifdef DEBUG_1INSTANCE
+ fprintf(stderr,"send: %s => %d(%d)\n",message,i,strlen(message));
+#endif
+}
+
+#ifdef DEBUG_MAIN
+
+#include <stdio.h>
+#include <stdlib.h>
+
+single_instance_struct str1 = { "/tmp/1instance" };
+
+void my_dispatcher(char* message)
+{
+#ifdef DEBUG_1INSTANCE
+ fprintf(stderr,"Message arrived: %s.\n",message);
+#endif
+ if(!strcmp(message,"quit")) {
+ delete_control_file(str1);
+ exit(0);
+ }
+}
+
+int main(int argc,char** argv)
+{
+ int i;
+
+ loop_if_server(str1,my_dispatcher);
+
+ for(i=1;i<argc;i++)
+ send_event(str1,argv[i]);
+
+ return(0);
+}
+
+#endif
diff --git a/krfb/libvncserver/CHANGES b/krfb/libvncserver/CHANGES
new file mode 100644
index 00000000..8767a12a
--- /dev/null
+++ b/krfb/libvncserver/CHANGES
@@ -0,0 +1,75 @@
+ memory leaks squashed (localtime pseudo leak is still there :-)
+ small improvements for OSXvnc (still not working correctly)
+ synced with TightVNC 1.2.3
+ solaris compile cleanups
+ many x11vnc improvements
+ added backchannel, an encoding which needs special clients to pass
+ arbitrary data to the client
+ changes from Tim Jansen regarding multi threading and client blocking
+ as well as C++ compliancy
+ x11vnc can be controlled by starting again with special options if compiling
+ with LOCAL_CONTROL defined
+0.3
+ added x11vnc, a x0rfbserver clone
+ regard deferUpdateTime in processEvents, if usec<0
+ initialize deferUpdateTime (memory "leak"!)
+ changed command line handling (arguments are parsed and then removed)
+ added very simple example: zippy
+ added rfbDrawLine, rfbDrawPixel
+0.2
+ inserted a deferUpdate mechanism (X11 independent).
+ removed deletion of requestedRegion
+ added rfbLoadConsoleFont
+ fixed font colour handling.
+ added rfbSelectBox
+ added rfbDrawCharWithClip to allow for clipping and a background colour.
+ fixed font colours
+ added rfbFillRect
+ added IO function to check password.
+ rfbNewClient now sets the socket in the fd_set (for the select() call)
+ when compiling the library with HAVE_PTHREADS and an application
+ which includes "rfb.h" without, the structures got mixed up.
+ So, the pthreads section is now always at the end, and also
+ you get a linker error for rfbInitServer when using two different
+ pthread setups.
+ fixed two deadlocks: when setting a cursor and when using CopyRect
+ fixed CopyRect when copying modified regions (they lost the modified
+ property)
+ WIN32 target compiles and works for example :-)
+ fixed CopyRect (was using the wrong order of rectangles...)
+ should also work with pthreads, because copyrects are
+ always sent immediately (so that two consecutive copy rects
+ cannot conflict).
+ changed rfbUndrawCursor(rfbClientPtr) to (rfbScreenInfoPtr), because
+ this makes more sense!
+ flag backgroundLoop in rfbScreenInfo (if having pthreads)
+ CopyRect & CopyRegion were implemented.
+ if you use a rfbDoCopyR* function, it copies the data in the
+ framebuffer. If you prefer to do that yourself, use rfbScheduleCopyR*
+ instead; this doesn't modify the frameBuffer.
+ added flag to optionally not send XCursor updates, but only RichCursor,
+ or if that is not possible, fall back to server side cursor.
+ This is useful if your cursor has many nice colours.
+ fixed java viewer on server side:
+ SendCursorUpdate would send data even before the client pixel format
+ was set, but the java applet doesn't like the server's format.
+ fixed two pthread issues:
+ rfbSendFramebuffer was sent by a ProcessClientMessage function
+ (unprotected by updateMutex).
+ cursor coordinates were set without protection by cursorMutex
+ source is now equivalent to TridiaVNC 1.2.1
+ pthreads now work (use iterators!)
+ cursors are supported (rfbSetCursor automatically undraws cursor)
+ support for 3 bytes/pixel (slow!)
+ server side colourmap support
+ fixed rfbCloseClient not to close the connection (pthreads!)
+ this is done lazily (and with proper signalling).
+ cleaned up mac.c (from original OSXvnc); now compiles (untested!)
+ compiles cleanly on Linux, IRIX, BSD, Apple (Darwin)
+ fixed prototypes
+0.1
+ rewrote API to use pseudo-methods instead of required functions.
+ lots of clean up.
+ Example can show symbols now.
+ All encodings
+ HTTP
diff --git a/krfb/libvncserver/COPYING b/krfb/libvncserver/COPYING
new file mode 100644
index 00000000..a3f6b12e
--- /dev/null
+++ b/krfb/libvncserver/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/krfb/libvncserver/Makefile.am b/krfb/libvncserver/Makefile.am
new file mode 100644
index 00000000..ed8e22d2
--- /dev/null
+++ b/krfb/libvncserver/Makefile.am
@@ -0,0 +1,14 @@
+INCLUDES = $(all_includes)
+
+noinst_LTLIBRARIES = libvncserver.la
+
+libvncserver_la_SOURCES = main.c rfbserver.c sraRegion.c auth.c sockets.c \
+ stats.c corre.c hextile.c rre.c translate.c cutpaste.c \
+ zlib.c tight.c httpd.c cursor.c font.c \
+ draw.c selbox.c d3des.c vncauth.c cargs.c
+
+EXTRA_DIST = CHANGES COPYING README TODO
+
+AM_CPPFLAGS = -DHAVE_PTHREADS -DALLOW24BPP
+AM_CFLAGS = -Wno-unused
+
diff --git a/krfb/libvncserver/README b/krfb/libvncserver/README
new file mode 100644
index 00000000..fe6d0c01
--- /dev/null
+++ b/krfb/libvncserver/README
@@ -0,0 +1,417 @@
+LibVNCServer: a library for easy implementation of a RDP/VNC server.
+Copyright (C) 2001 Johannes E. Schindelin
+
+What is it?
+-----------
+
+VNC is a set of programs using the RFB (Remote Frame Buffer) protocol. They
+are designed to "export" a frame buffer via net (if you don't know VNC, I
+suggest you read "Basics" below). It is already in wide use for
+administration, but it is not that easy to program a server yourself.
+
+This has been changed by LibVNCServer.
+
+There are two examples included:
+ - example, a shared scribble sheet
+ - pnmshow, a program to show PNMs (pictures) over the net.
+
+The examples are not too well documented, but easy straight forward and a
+good starting point.
+
+Try example: it outputs on which port it listens (default: 5900), so it is
+display 0. To view, call
+ vncviewer :0
+You should see a sheet with a gradient and "Hello World!" written on it. Try
+to paint something. Note that everytime you click, there is some bigger blot.
+The size depends on the mouse button you click. Open a second vncviewer with
+the same parameters and watch it as you paint in the other window. This also
+works over internet. You just have to know either the name or the IP of your
+machine. Then it is
+ vncviewer machine.where.example.runs.com:0
+or similar for the remote client. Now you are ready to type something. Be sure
+that your mouse sits still, because everytime the mouse moves, the cursor is
+reset! If you are done with that demo, just press Escape in the viewer. Note
+that the server still runs, even if you closed both windows. When you
+reconnect now, everything you painted and wrote is still there. So you press
+"Page Up" for a blank page.
+
+The demo pnmshow is much simpler: you either provide a filename as argument
+or pipe a file through stdin. Note that the file has to be a raw pnm/ppm file,
+i.e. a truecolour graphics. Only the Escape key is implemented. This may be
+the best starting point if you want to learn how to use LibVNCServer. You
+are confronted with the fact that the bytes per pixel can only be 8, 16 or 32.
+
+How to use
+----------
+
+To make a server, you just have to initialise a server structure using the
+function rfbDefaultScreenInit, like
+ rfbScreenInfoPtr rfbScreen =
+ rfbGetScreen(argc,argv,width,height,8,3,bpp);
+where byte per pixel should be 1, 2 or 4. If performance doesn't matter,
+you may try bpp=3 (internally one cannot use native data types in this
+case; if you want to use this, look at pnmshow24).
+
+
+You then can set hooks and io functions (see below) or other
+options (see below).
+
+And you allocate the frame buffer like this:
+ rfbScreen->frameBuffer = (char*)malloc(width*height*bpp);
+
+After that, you initialize the server, like
+ rfbInitServer(rfbScreen);
+
+You can use a blocking event loop, a background (pthread based) event loop,
+or implement your own using the rfbProcessEvents function.
+
+Making it interactive
+---------------------
+
+Input is handled by IO functions (see below).
+
+Whenever you change something in the frame buffer, call rfbMarkRectAsModified.
+You should make sure that the cursor is not drawn before drawing yourself
+by calling rfbUndrawCursor. You can also draw the cursor using rfbDrawCursor,
+but it hardly seems necessary. For cursor details, see below.
+
+Utility functions
+-----------------
+
+Whenever you draw something, you have to call
+ rfbMarkRectAsModified(screen,x1,y1,x2,y2).
+This tells LibVNCServer to send updates to all connected clients.
+
+Before you draw something, be sure to call
+ rfbUndrawCursor(screen).
+This tells LibVNCServer to hide the cursor.
+Remark: There are vncviewers out there, which know a cursor encoding, so
+that network traffic is low, and also the cursor doesn't need to be
+drawn the cursor everytime an update is sent. LibVNCServer handles
+all the details. Just set the cursor and don't bother any more.
+
+To set the mouse coordinates (or emulate mouse clicks), call
+ defaultPtrAddEvent(buttonMask,x,y,cl);
+However, this works only if your client doesn't do local cursor drawing. There
+is no way (to my knowledge) to set the pointer of a client via RFB protocol.
+IMPORTANT: do this at the end of your function, because this actually draws
+the cursor if no cursor encoding is active.
+
+What is the difference between rfbScreenInfoPtr and rfbClientPtr?
+-----------------------------------------------------------------
+
+The rfbScreenInfoPtr is a pointer to a rfbScreenInfo structure, which
+holds information about the server, like pixel format, io functions,
+frame buffer etc.
+
+The rfbClientPtr is a pointer to an rfbClientRec structure, which holds
+information about a client, like pixel format, socket of the
+connection, etc.
+
+A server can have several clients, but needn't have any. So, if you
+have a server and three clients are connected, you have one instance
+of a rfbScreenInfo and three instances of rfbClientRec's.
+
+The rfbClientRec structure holds a member
+ rfbScreenInfoPtr screen
+which points to the server and a member
+ rfbClientPtr next
+to the next client.
+
+The rfbScreenInfo structure holds a member
+ rfbClientPtr rfbClientHead
+which points to the first client.
+
+So, to access the server from the client structure, you use client->screen.
+To access all clients from a server, get screen->rfbClientHead and
+iterate using client->next.
+
+If you change client settings, be sure to use the provided iterator
+ rfbGetClientIterator(rfbScreen)
+with
+ rfbClientIteratorNext(iterator)
+and
+ rfbReleaseClientIterator
+to prevent thread clashes.
+
+Other options
+-------------
+
+These options have to be set between rfbGetScreen and rfbInitServer.
+
+If you already have a socket to talk to, just set rfbScreen->inetdSock
+(originally this is for inetd handling, but why not use it for your purpose?).
+
+To also start an HTTP server (running on port 5800+display_number), you have
+to set rfbScreen->httpdDir to a directory containing vncviewer.jar and
+index.vnc (like the included "classes" directory).
+
+Hooks and IO functions
+----------------------
+
+There exist the following IO functions as members of rfbScreen:
+kbdAddEvent, kbdReleaseAllKeys, ptrAddEvent and setXCutText
+
+kbdAddEvent(Bool down,KeySym key,rfbClientPtr cl)
+ is called when a key is pressed.
+kbdReleaseAllKeys(rfbClientPtr cl)
+ is not called at all (maybe in the future).
+ptrAddEvent(int buttonMask,int x,int y,rfbClientPtr cl)
+ is called when the mouse moves or a button is pressed.
+ WARNING: if you want to have proper cursor handling, call
+ defaultPtrAddEvent(buttonMask,x,y,cl)
+ in your own function. This sets the coordinates of the cursor.
+setXCutText(char* str,int len,rfbClientPtr cl)
+ is called when the selection changes.
+
+There are only two hooks:
+newClientHook(rfbClientPtr cl)
+ is called when a new client has connected.
+displayHook
+ is called just before a frame buffer update is sent.
+
+You can also override the following methods:
+getCursorPtr(rfbClientPtr cl)
+ This could be used to make an animated cursor (if you really want ...)
+setTranslateFunction(rfbClientPtr cl)
+ If you insist on colour maps or something more obscure, you have to
+ implement this. Default is a trueColour mapping.
+
+Cursor handling
+---------------
+
+The screen holds a pointer
+ rfbCursorPtr cursor
+to the current cursor. Whenever you set it, remember that any dynamically
+created cursor (like return value from rfbMakeXCursor) is not free'd!
+
+The rfbCursor structure consists mainly of a mask and a source. The mask
+describes, which pixels are drawn for the cursor (a cursor needn't be
+rectangular). The source describes, which colour those pixels should have.
+
+The standard is an XCursor: a cursor with a foreground and a background
+colour (stored in backRed,backGreen,backBlue and the same for foreground
+in a range from 0-0xffff). Therefore, the arrays "mask" and "source"
+contain pixels as single bits stored in bytes in MSB order. The rows are
+padded, such that each row begins with a new byte (i.e. a 10x4
+cursor's mask has 2x4 bytes, because 2 bytes are needed to hold 10 bits).
+
+It is however very easy to make a cursor like this:
+
+char* cur=" "
+ " xx "
+ " x "
+ " ";
+char* mask="xxxx"
+ "xxxx"
+ "xxxx"
+ "xxx ";
+rfbCursorPtr c=rfbMakeXCursor(4,4,cur,mask);
+
+You can even set "mask" to NULL in this call and LibVNCServer will calculate
+a mask for you (dynamically, so you have to free it yourself).
+
+There is also an array named "richSource" for colourful cursors. They have
+the same format as the frameBuffer (i.e. if the server is 32 bit,
+a 10x4 cursor has 4x10x4 bytes).
+
+History
+-------
+
+LibVNCServer is based on Tridia VNC and OSXvnc, which in turn are based on
+the original code from ORL/AT&T.
+
+When I began hacking with computers, my first interest was speed. So, when I
+got around assembler, I programmed the floppy to do much of the work, because
+it's clock rate was higher than that of my C64. This was my first experience
+with client/server techniques.
+
+When I came around Xwindows (much later), I was at once intrigued by the
+elegance of such connectedness between the different computers. I used it
+a lot - not the least priority lay on games. However, when I tried it over
+modem from home, it was no longer that much fun.
+
+When I started working with ASP (Application Service Provider) programs, I
+tumbled across Tarantella and Citrix. Being a security fanatic, the idea of
+running a server on windows didn't appeal to me, so Citrix went down the
+basket. However, Tarantella has it's own problems (security as well as the
+high price). But at the same time somebody told me about this "great little
+administrator's tool" named VNC. Being used to windows programs' sizes, the
+surprise was reciprocal inverse to the size of VNC!
+
+At the same time, the program "rdesktop" (a native Linux client for the
+Terminal Services of Windows servers) came to my attention. There where even
+works under way to make a protocol converter "rdp2vnc" out of this. However,
+my primary goal was a slow connection and rdp2vnc could only speak RRE
+encoding, which is not that funny with just 5kB/s. Tim Edmonds, the original
+author of rdp2vnc, suggested that I adapt it to Hextile Encoding, which is
+better. I first tried that, but had no success at all (crunchy pictures).
+
+Also, I liked the idea of an HTTP server included and possibly other
+encodings like the Tight Encodings from Const Kaplinsky. So I started looking
+for libraries implementing a VNC server where I could steal what I can't make.
+I found some programs based on the demo server from AT&T, which was also the
+basis for rdp2vnc (can only speak Raw and RRE encoding). There were some
+rumors that GGI has a VNC backend, but I didn't find any code, so probably
+there wasn't a working version anyway.
+
+All of a sudden, everything changed: I read on freshmeat that "OSXvnc" was
+released. I looked at the code and it was not much of a problem to work out
+a simple server - using every functionality there is in Xvnc. It became clear
+to me that I *had* to build a library out of it, so everybody can use it.
+Every change, every new feature can propagate to every user of it.
+
+It also makes everything easier:
+ You don't care about the cursor, once set (or use the standard cursor).
+You don't care about those sockets. You don't care about encodings.
+You just change your frame buffer and inform the library about it. Every once
+in a while you call rfbProcessEvents and that's it.
+
+Basics
+------
+
+VNC (Virtual network computing) works like this: You set up a server and can
+connect to it via vncviewers. The communication uses a protocol named RFB
+(Remote Frame Buffer). If the server supports HTTP, you can also connect
+using a java enabled browser. In this case, the server sends back a
+vncviewer applet with the correct settings.
+
+There exist several encodings for VNC, which are used to compress the regions
+which have changed before they are sent to the client. A client need not be
+able to understand every encoding, but at least Raw encoding. Which encoding
+it understands is negotiated by the RFB protocol.
+
+The following encodings are known to me:
+Raw, RRE, CoRRE, Hextile, CopyRect from the original AT&T code and
+Tight, ZLib, LastRect, XCursor, RichCursor from Const Kaplinsky et al.
+
+If you are using a modem, you want to try the "new" encodings. Especially
+with my 56k modem I like ZLib or Tight with Quality 0. In my tests, it even
+beats Tarantella.
+
+There is the possibility to set a password, which is also negotiated by the
+RFB protocol, but IT IS NOT SECURE. Anybody sniffing your net can get the
+password. You really should tunnel through SSH.
+
+Windows or: why do you do that to me?
+--------------------------------------------
+
+If you love products from Redmod, you better skip this paragraph.
+I am always amazed how people react whenever Microsoft(tm) puts in some
+features into their products which were around for a long time. Especially
+reporters seem to not know dick about what they are reporting about! But
+what is everytime annoying again, is that they don't do it right. Every
+concept has it's new name (remember what enumerators used to be until
+Mickeysoft(tm) claimed that enumerators are what we thought were iterators.
+Yeah right, enumerators are also containers. They are not separate. Muddy.)
+
+There are three packages you want to get hold of: zlib, jpeg and pthreads.
+The latter is not strictly necessary, but when you put something like this
+into your source:
+
+#define MUTEX(s)
+ struct {
+ int something;
+ MUTEX(latex);
+ }
+
+Microsoft's C++ compiler doesn't do it. It complains that this is an error.
+
+You can find the packages at
+http://www.gimp.org/win32/extralibs-dev-20001007.zip
+
+Thanks go to all the GIMP team!
+
+What are those other targets in the Makefile?
+---------------------------------------------
+
+OSXvnc-server is the original OSXvnc adapted to use the library, which was in
+turn adapted from OSXvnc. As you easily can see, the OSX dependend part is
+minimal.
+
+storepasswd is the original program to save a vnc style password in a file.
+Unfortunately, authentication as every vncviewer speaks it means the server
+has to know the plain password. You really should tunnel via ssh or use
+your own PasswordCheck to build a PIN/TAN system.
+
+sratest is a test unit. Run it to assert correct behaviour of sraRegion. I
+wrote this to test my iterator implementation.
+
+blooptest is a test of pthreads. It is just the example, but with a background
+loop to hunt down thread lockups.
+
+pnmshow24 is like pnmshow, but it uses 3 bytes/pixel internally, which is not
+as efficient as 4 bytes/pixel for translation, because there is no native data
+type of that size, so you have to memcpy pixels and be real cautious with
+endianness. Anyway, it works.
+
+fontsel is a test for rfbSelectBox and rfbLoadConsoleFont. If you have Linux
+console fonts, you can browse them via VNC. Directory browsing not implemented
+yet :-(
+
+Why I don't feel bad about GPL
+------------------------------
+
+At the beginning of this projects I would have liked to make it a BSD
+license. However, it is based on plenty of GPL'ed code, so it has to be
+a GPL. I hear BeeGee complaining: "but that's invasive, every derivative
+work, even just linking, makes my software GPL!"
+
+Yeah. That's right. It is because there are nasty jarheads out there who
+would take anybody's work and claim it their own, selling it for much too
+much money, stealing freedom and innovation from others, saying they were
+the maintainers of innovation, lying, making money with that.
+
+The people at AT&T worked really well to produce something as clean and lean
+as VNC. The managers decided that for their fame, they would release the
+program for free. But not only that! They realized that by releasing also
+the code for free, VNC would become an evolving little child, conquering
+new worlds, making it's parents very proud. As well they can be! To protect
+this innovation, they decided to make it GPL, not BSD. The principal
+difference is: You can make closed source programs deriving from BSD, not
+from GPL. You have to give proper credit with both.
+
+Now, why not BSD? Well, imagine your child being some famous actor. Along
+comes a manager who exploits your child exclusively, that is: nobody else
+can profit from the child, it itself included. Got it?
+
+What reason do you have now to use this library commercially?
+
+Several: You don't have to give away your product. Then you have effectively
+circumvented the GPL, because you have the benefits of other's work and you
+don't give back anything and you will be in hell for that. In fact, this
+library, as my other projects, is a payback for all the free software I can
+use (and sometimes, make better). For example, just now, I am using XEmacs
+on top X11, all running under Linux.
+
+Better: Use a concept like MySQL. This is free software, however, they make
+money with it. If you want something implemented, you have the choice:
+Ask them to do it (and pay a fair price), or do it yourself, normally giving
+back your enhancements to the free world of computing.
+
+Learn from it: If you like the style this is written, learn how to imitate
+it. If you don't like the style, learn how to avoid those things you don't
+like. I learnt so much, just from looking at code like Linux, XEmacs,
+LilyPond, STL, etc.
+
+License
+-------
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.dfdf
+
+Contact
+-------
+
+To contact me, mail me: Johannes dot Schindelin at gmx dot de
diff --git a/krfb/libvncserver/TODO b/krfb/libvncserver/TODO
new file mode 100644
index 00000000..70dae90d
--- /dev/null
+++ b/krfb/libvncserver/TODO
@@ -0,0 +1,80 @@
+immediate:
+----------
+
+x11vnc: clipboard, cursor, updates interruptible by input (doesn't work yet)
+extra_bytes in rfbDrawCharWithClip.
+tested mouse buttons make copy rect, but text is not marked as mod.
+cursor drawing: set optional grain to mark bigger rectangles as drawn (else
+ you end up with thousands of one-pixel-rectangles to encode).
+selectbox: scroll bars
+documentation
+ hint that to mark very tiny regions as
+ modified is possibly inefficient for the encodings.
+ (a trail of points could better be a small rectangle).
+
+later:
+------
+
+authentification schemes (secure vnc)
+ IO function ptr exists; now explain how to tunnel and implement a
+ client address restriction scheme.
+autoconf? at least Sun Solaris and Windows compilation
+ (maybe Michael makes a small autconf)
+using Hermes library for fast colour translations.
+CORBA
+internal HTTP tunnelling feature (needs a special GET target and a few
+ changes to java applet).
+
+done:
+-----
+
+.x11vnc: sometimes XTest fails (but doesn't with x0rfbserver)
+.DeferUpdateTime (timing problems!)
+.empty cursor sending doesn't work.
+.udp (need an rfbClientPtr udpClient in rfbScreen)
+ input only; nearly untested (don't have the clients).
+.font handling: bpp>1
+.test copyRect and pthreads.
+.optionally dont draw rich cursors as xcursors
+.cursor smears on IRIX with pthreads, then has bus error. has to be a mutex
+ problem in cursor routines.
+.fix bug in http (java) client with big endian server: byte swapping is broken
+ (was a cursorshape which was sent too soon; java vncviewer assumes
+ a rich cursor shape to be always 1 byte per pixel, however, framebuffer
+ updates before setting the pixel format can be server format)
+.rfbConnect, ConnectToTcpAddr
+.update to newest TridiaVNC version (1.2.1).
+.adapt rdp2vnc (rdesktop)
+.pthreads concept: How to iterate over rfbClientPtr's? So that it can be
+ either called from rfbProcessEvents (which locks the list mutex)
+ or from the main thread (where the background loop sometimes
+ locks the list mutex).
+ - cursor drawing!
+ - cursor setting!
+ - rfbMarkRectAsModified
+ (did that by adding a refcount to clients secured by refCountMutex;
+ it also was necessary to check for cl->sock<0 in SendUpdateBuf)
+.translate.c: warning about non 8-bit colourmaps
+ 16-bit colourmaps are 192k -> no use without fast net.
+.rfbCloseClient
+.set colourmap
+.support 3 bytes per pixel
+.cursors
+.cutpaste
+.httpd
+.other encodings
+.test drawing of cursors when not using xcursor or rich cursor encoding
+fix bug with odd width (depends on client depth: width has to be multiple of server.bytesPerPixel/client.bytesPerPixel). only raw!! -> bug of vncviewer!
+.use sraRegion from Wez instead of miregion, because it is much smaller
+. - connection gone and then reconnect is a problem
+ the reason: there are in fact three threads accessing
+ the clientPtr: input, output and the application thread.
+ if you kill the viewer or do rfbCloseClient, all of those
+ three have to be warned that this is happening.
+ -> rfbClientConnectionGone can only be called by the outer loop
+ (with background loop, it is input, else it is processEvents).
+. fixed pthreads issues:
+ cursor deadlock,
+ CopyRect deadlock.
+. when copying a region with modified parts, they were not marked
+ as modified
diff --git a/krfb/libvncserver/auth.c b/krfb/libvncserver/auth.c
new file mode 100644
index 00000000..35657b8f
--- /dev/null
+++ b/krfb/libvncserver/auth.c
@@ -0,0 +1,109 @@
+/*
+ * auth.c - deal with authentication.
+ *
+ * This file implements the VNC authentication protocol when setting up an RFB
+ * connection.
+ */
+
+/*
+ * OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
+ * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
+ * All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "rfb.h"
+
+static int rfbMaxPasswordWait = 120000; /* password timeout (ms) */
+
+/*
+ * rfbAuthNewClient is called when we reach the point of authenticating
+ * a new client. If authentication isn't being used then we simply send
+ * rfbNoAuth. Otherwise we send rfbVncAuth plus the challenge.
+ */
+
+void
+rfbAuthNewClient(cl)
+ rfbClientPtr cl;
+{
+ char buf[4 + CHALLENGESIZE];
+ int len;
+
+ cl->state = RFB_AUTHENTICATION;
+
+ if (cl->screen->rfbAuthPasswdData && !cl->reverseConnection) {
+ *(CARD32 *)buf = Swap32IfLE(rfbVncAuth);
+ vncRandomBytes(cl->authChallenge);
+ memcpy(&buf[4], (char *)cl->authChallenge, CHALLENGESIZE);
+ len = 4 + CHALLENGESIZE;
+ } else {
+ *(CARD32 *)buf = Swap32IfLE(rfbNoAuth);
+ len = 4;
+ cl->state = RFB_INITIALISATION;
+ }
+
+ if (WriteExact(cl, buf, len) < 0) {
+ rfbLogPerror("rfbAuthNewClient: write");
+ rfbCloseClient(cl);
+ return;
+ }
+}
+
+
+/*
+ * rfbAuthProcessClientMessage is called when the client sends its
+ * authentication response.
+ */
+
+void
+rfbAuthProcessClientMessage(cl)
+ rfbClientPtr cl;
+{
+ int n;
+ CARD8 response[CHALLENGESIZE];
+ CARD32 authResult;
+
+ if ((n = ReadExactTimeout(cl, (char *)response, CHALLENGESIZE,
+ rfbMaxPasswordWait)) <= 0) {
+ if (n != 0)
+ rfbLogPerror("rfbAuthProcessClientMessage: read");
+ rfbCloseClient(cl);
+ return;
+ }
+
+ if(!cl->screen->passwordCheck(cl,response,CHALLENGESIZE)) {
+ rfbLog("rfbAuthProcessClientMessage: password check failed\n");
+ authResult = Swap32IfLE(rfbVncAuthFailed);
+ if (WriteExact(cl, (char *)&authResult, 4) < 0) {
+ rfbLogPerror("rfbAuthProcessClientMessage: write");
+ }
+ rfbCloseClient(cl);
+ return;
+ }
+
+ authResult = Swap32IfLE(rfbVncAuthOK);
+
+ if (WriteExact(cl, (char *)&authResult, 4) < 0) {
+ rfbLogPerror("rfbAuthProcessClientMessage: write");
+ rfbCloseClient(cl);
+ return;
+ }
+
+ cl->state = RFB_INITIALISATION;
+}
diff --git a/krfb/libvncserver/bdf2c.pl b/krfb/libvncserver/bdf2c.pl
new file mode 100644
index 00000000..fc437127
--- /dev/null
+++ b/krfb/libvncserver/bdf2c.pl
@@ -0,0 +1,60 @@
+#!/usr/bin/perl
+
+@encodings=();
+for($i=0;$i<256*5;$i++) {
+ $encodings[$i]="0";
+}
+
+$out="";
+$counter=0;
+$fontname="default";
+
+$i=0;
+$searchfor="";
+$nullx="0x";
+
+while(<>) {
+ if(/^FONT (.*)$/) {
+ $fontname=$1;
+ $fontname=~y/\"//d;
+ } elsif(/^ENCODING (.*)$/) {
+ $glyphindex=$1;
+ $searchfor="BBX";
+ $dwidth=0;
+ } elsif(/^DWIDTH (.*) (.*)/) {
+ $dwidth=$1;
+ } elsif(/^BBX (.*) (.*) (.*) (.*)$/) {
+ ($width,$height,$x,$y)=($1,$2,$3,$4);
+ @encodings[$glyphindex*5..($glyphindex*5+4)]=($counter,$width,$height,$x,$y);
+ if($dwidth != 0) {
+ $encodings[$glyphindex*5+1]=$dwidth;
+ } else {
+ $dwidth=$width;
+ }
+ $searchfor="BITMAP";
+ } elsif(/^BITMAP/) {
+ $i=1;
+ } elsif($i>0) {
+ if($i>$height) {
+ $i=0;
+ $out.=" /* $glyphindex */\n";
+ } else {
+ if(int(($dwidth+7)/8) > int(($width+7)/8)) {
+ $_ .= "00"x(int(($dwidth+7)/8)-int(($width+7)/8));
+ }
+ $_=substr($_,0,(int(($dwidth+7)/8)*2));
+ $counter+=(int(($dwidth+7)/8));
+ s/(..)/$nullx$1,/g;
+ $out.=$_;
+ $i++;
+ }
+ }
+}
+
+print "unsigned char " . $fontname . "FontData[$counter]={\n" . $out;
+print "};\nint " . $fontname . "FontMetaData[256*5]={\n";
+for($i=0;$i<256*5;$i++) {
+ print $encodings[$i] . ",";
+}
+print "};\nrfbFontData " . $fontname . "Font={" .
+ $fontname . "FontData, " . $fontname . "FontMetaData};\n";
diff --git a/krfb/libvncserver/cargs.c b/krfb/libvncserver/cargs.c
new file mode 100644
index 00000000..03696a31
--- /dev/null
+++ b/krfb/libvncserver/cargs.c
@@ -0,0 +1,135 @@
+/*
+ * This parses the command line arguments. It was seperated from main.c by
+ * Justin Dearing <jdeari01@longisland.poly.edu>.
+ */
+
+/*
+ * LibVNCServer (C) 2001 Johannes E. Schindelin <Johannes.Schindelin@gmx.de>
+ * Original OSXvnc (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
+ * Original Xvnc (C) 1999 AT&T Laboratories Cambridge.
+ * All Rights Reserved.
+ *
+ * see GPL (latest version) for full details
+ */
+
+#include "rfb.h"
+
+void
+rfbUsage(void)
+{
+ fprintf(stderr, "-rfbport port TCP port for RFB protocol\n");
+ fprintf(stderr, "-rfbwait time max time in ms to wait for RFB client\n");
+ fprintf(stderr, "-rfbauth passwd-file use authentication on RFB protocol\n"
+ " (use 'storepasswd' to create a password file)\n");
+ fprintf(stderr, "-passwd plain-password use authentication \n"
+ " (use plain-password as password, USE AT YOUR RISK)\n");
+ fprintf(stderr, "-deferupdate time time in ms to defer updates "
+ "(default 40)\n");
+ fprintf(stderr, "-desktop name VNC desktop name (default \"LibVNCServer\")\n");
+ fprintf(stderr, "-alwaysshared always treat new clients as shared\n");
+ fprintf(stderr, "-nevershared never treat new clients as shared\n");
+ fprintf(stderr, "-dontdisconnect don't disconnect existing clients when a "
+ "new non-shared\n"
+ " connection comes in (refuse new connection "
+ "instead)\n");
+ exit(1);
+}
+
+/* purges COUNT arguments from ARGV at POSITION and decrements ARGC.
+ POSITION points to the first non purged argument afterwards. */
+void rfbPurgeArguments(int* argc,int* position,int count,char *argv[])
+{
+ int amount=(*argc)-(*position)-count;
+ if(amount)
+ memmove(argv+(*position),argv+(*position)+count,sizeof(char*)*amount);
+ (*argc)-=count;
+ (*position)--;
+}
+
+void
+rfbProcessArguments(rfbScreenInfoPtr rfbScreen,int* argc, char *argv[])
+{
+ int i,i1;
+
+ if(!argc) return;
+
+ for (i = i1 = 1; i < *argc; i++) {
+ if (strcmp(argv[i], "-help") == 0) {
+ rfbUsage();
+ exit(1);
+ } else if (strcmp(argv[i], "-rfbport") == 0) { /* -rfbport port */
+ if (i + 1 >= *argc) rfbUsage();
+ rfbScreen->rfbPort = atoi(argv[++i]);
+ } else if (strcmp(argv[i], "-rfbwait") == 0) { /* -rfbwait ms */
+ if (i + 1 >= *argc) rfbUsage();
+ rfbScreen->rfbMaxClientWait = atoi(argv[++i]);
+ } else if (strcmp(argv[i], "-rfbauth") == 0) { /* -rfbauth passwd-file */
+ if (i + 1 >= *argc) rfbUsage();
+ rfbScreen->rfbAuthPasswdData = argv[++i];
+ } else if (strcmp(argv[i], "-passwd") == 0) { /* -passwd password */
+ char **passwds = malloc(sizeof(char**)*2);
+ if (i + 1 >= *argc) rfbUsage();
+ passwds[0] = argv[++i];
+ passwds[1] = 0;
+ rfbScreen->rfbAuthPasswdData = (void*)passwds;
+ rfbScreen->passwordCheck = rfbCheckPasswordByList;
+ } else if (strcmp(argv[i], "-deferupdate") == 0) { /* -desktop desktop-name */
+ if (i + 1 >= *argc) rfbUsage();
+ rfbScreen->rfbDeferUpdateTime = atoi(argv[++i]);
+ } else if (strcmp(argv[i], "-desktop") == 0) { /* -desktop desktop-name */
+ if (i + 1 >= *argc) rfbUsage();
+ rfbScreen->desktopName = argv[++i];
+ } else if (strcmp(argv[i], "-alwaysshared") == 0) {
+ rfbScreen->rfbAlwaysShared = TRUE;
+ } else if (strcmp(argv[i], "-nevershared") == 0) {
+ rfbScreen->rfbNeverShared = TRUE;
+ } else if (strcmp(argv[i], "-dontdisconnect") == 0) {
+ rfbScreen->rfbDontDisconnect = TRUE;
+ } else if (strcmp(argv[i], "-width") == 0) {
+ rfbScreen->width = atoi(argv[++i]);
+ } else if (strcmp(argv[i], "-height") == 0) {
+ rfbScreen->height = atoi(argv[++i]);
+ } else {
+ /* we just remove the processed arguments from the list */
+ if(i != i1)
+ rfbPurgeArguments(argc,&i,i1-i,argv);
+ i1++;
+ i++;
+ }
+ }
+ *argc -= i-i1;
+}
+
+void rfbSizeUsage()
+{
+ fprintf(stderr, "-width sets the width of the framebuffer\n");
+ fprintf(stderr, "-height sets the height of the framebuffer\n");
+ exit(1);
+}
+
+void
+rfbProcessSizeArguments(int* width,int* height,int* bpp,int* argc, char *argv[])
+{
+ int i,i1;
+
+ if(!argc) return;
+ for (i = i1 = 1; i < *argc-1; i++) {
+ if (strcmp(argv[i], "-bpp") == 0) {
+ *bpp = atoi(argv[++i]);
+ } else if (strcmp(argv[i], "-width") == 0) {
+ *width = atoi(argv[++i]);
+ } else if (strcmp(argv[i], "-height") == 0) {
+ *height = atoi(argv[++i]);
+ } else {
+ /* we just remove the processed arguments from the list */
+ if(i != i1) {
+ memmove(argv+i1,argv+i,sizeof(char*)*(*argc-i));
+ *argc -= i-i1;
+ }
+ i1++;
+ i = i1-1;
+ }
+ }
+ *argc -= i-i1;
+}
+
diff --git a/krfb/libvncserver/corre.c b/krfb/libvncserver/corre.c
new file mode 100644
index 00000000..d6329a10
--- /dev/null
+++ b/krfb/libvncserver/corre.c
@@ -0,0 +1,355 @@
+/*
+ * corre.c
+ *
+ * Routines to implement Compact Rise-and-Run-length Encoding (CoRRE). This
+ * code is based on krw's original javatel rfbserver.
+ */
+
+/*
+ * OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
+ * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
+ * All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "rfb.h"
+
+/*
+ * rreBeforeBuf contains pixel data in the client's format.
+ * rreAfterBuf contains the RRE encoded version. If the RRE encoded version is
+ * larger than the raw data or if it exceeds rreAfterBufSize then
+ * raw encoding is used instead.
+ */
+
+static int rreBeforeBufSize = 0;
+static char *rreBeforeBuf = NULL;
+
+static int rreAfterBufSize = 0;
+static char *rreAfterBuf = NULL;
+static int rreAfterBufLen;
+
+static int subrectEncode8(CARD8 *data, int w, int h);
+static int subrectEncode16(CARD16 *data, int w, int h);
+static int subrectEncode32(CARD32 *data, int w, int h);
+static CARD32 getBgColour(char *data, int size, int bpp);
+static Bool rfbSendSmallRectEncodingCoRRE(rfbClientPtr cl, int x, int y,
+ int w, int h);
+
+
+/*
+ * rfbSendRectEncodingCoRRE - send an arbitrary size rectangle using CoRRE
+ * encoding.
+ */
+
+Bool
+rfbSendRectEncodingCoRRE(cl, x, y, w, h)
+ rfbClientPtr cl;
+ int x, y, w, h;
+{
+ if (h > cl->correMaxHeight) {
+ rfbSendRectEncodingCoRRE(cl, x, y, w, cl->correMaxHeight );
+ rfbSendRectEncodingCoRRE(cl, x, y + cl->correMaxHeight, w,
+ h - cl->correMaxHeight);
+ return FALSE;
+ }
+
+ if (w > cl->correMaxWidth) {
+ rfbSendRectEncodingCoRRE(cl, x, y, cl->correMaxWidth, h);
+ rfbSendRectEncodingCoRRE(cl, x + cl->correMaxWidth, y,
+ w - cl->correMaxWidth, h);
+ return FALSE;
+ }
+
+ rfbSendSmallRectEncodingCoRRE(cl, x, y, w, h);
+ return TRUE;
+}
+
+
+
+/*
+ * rfbSendSmallRectEncodingCoRRE - send a small (guaranteed < 256x256)
+ * rectangle using CoRRE encoding.
+ */
+
+static Bool
+rfbSendSmallRectEncodingCoRRE(cl, x, y, w, h)
+ rfbClientPtr cl;
+ int x, y, w, h;
+{
+ rfbFramebufferUpdateRectHeader rect;
+ rfbRREHeader hdr;
+ int nSubrects;
+ int i;
+ char *fbptr = (cl->screen->frameBuffer + (cl->screen->paddedWidthInBytes * y)
+ + (x * (cl->screen->bitsPerPixel / 8)));
+
+ int maxRawSize = (cl->screen->width * cl->screen->height
+ * (cl->format.bitsPerPixel / 8));
+
+ if (rreBeforeBufSize < maxRawSize) {
+ rreBeforeBufSize = maxRawSize;
+ if (rreBeforeBuf == NULL)
+ rreBeforeBuf = (char *)malloc(rreBeforeBufSize);
+ else
+ rreBeforeBuf = (char *)realloc(rreBeforeBuf, rreBeforeBufSize);
+ }
+
+ if (rreAfterBufSize < maxRawSize) {
+ rreAfterBufSize = maxRawSize;
+ if (rreAfterBuf == NULL)
+ rreAfterBuf = (char *)malloc(rreAfterBufSize);
+ else
+ rreAfterBuf = (char *)realloc(rreAfterBuf, rreAfterBufSize);
+ }
+
+ (*cl->translateFn)(cl->translateLookupTable,&(cl->screen->rfbServerFormat),
+ &cl->format, fbptr, rreBeforeBuf,
+ cl->screen->paddedWidthInBytes, w, h);
+
+ switch (cl->format.bitsPerPixel) {
+ case 8:
+ nSubrects = subrectEncode8((CARD8 *)rreBeforeBuf, w, h);
+ break;
+ case 16:
+ nSubrects = subrectEncode16((CARD16 *)rreBeforeBuf, w, h);
+ break;
+ case 32:
+ nSubrects = subrectEncode32((CARD32 *)rreBeforeBuf, w, h);
+ break;
+ default:
+ rfbLog("getBgColour: bpp %d?\n",cl->format.bitsPerPixel);
+ exit(1);
+ }
+
+ if (nSubrects < 0) {
+
+ /* RRE encoding was too large, use raw */
+
+ return rfbSendRectEncodingRaw(cl, x, y, w, h);
+ }
+
+ cl->rfbRectanglesSent[rfbEncodingCoRRE]++;
+ cl->rfbBytesSent[rfbEncodingCoRRE] += (sz_rfbFramebufferUpdateRectHeader
+ + sz_rfbRREHeader + rreAfterBufLen);
+
+ if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader
+ > UPDATE_BUF_SIZE)
+ {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ rect.r.x = Swap16IfLE(x);
+ rect.r.y = Swap16IfLE(y);
+ rect.r.w = Swap16IfLE(w);
+ rect.r.h = Swap16IfLE(h);
+ rect.encoding = Swap32IfLE(rfbEncodingCoRRE);
+
+ memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
+ sz_rfbFramebufferUpdateRectHeader);
+ cl->ublen += sz_rfbFramebufferUpdateRectHeader;
+
+ hdr.nSubrects = Swap32IfLE(nSubrects);
+
+ memcpy(&cl->updateBuf[cl->ublen], (char *)&hdr, sz_rfbRREHeader);
+ cl->ublen += sz_rfbRREHeader;
+
+ for (i = 0; i < rreAfterBufLen;) {
+
+ int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen;
+
+ if (i + bytesToCopy > rreAfterBufLen) {
+ bytesToCopy = rreAfterBufLen - i;
+ }
+
+ memcpy(&cl->updateBuf[cl->ublen], &rreAfterBuf[i], bytesToCopy);
+
+ cl->ublen += bytesToCopy;
+ i += bytesToCopy;
+
+ if (cl->ublen == UPDATE_BUF_SIZE) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+
+/*
+ * subrectEncode() encodes the given multicoloured rectangle as a background
+ * colour overwritten by single-coloured rectangles. It returns the number
+ * of subrectangles in the encoded buffer, or -1 if subrect encoding won't
+ * fit in the buffer. It puts the encoded rectangles in rreAfterBuf. The
+ * single-colour rectangle partition is not optimal, but does find the biggest
+ * horizontal or vertical rectangle top-left anchored to each consecutive
+ * coordinate position.
+ *
+ * The coding scheme is simply [<bgcolour><subrect><subrect>...] where each
+ * <subrect> is [<colour><x><y><w><h>].
+ */
+
+#define DEFINE_SUBRECT_ENCODE(bpp) \
+static int \
+subrectEncode##bpp(data,w,h) \
+ CARD##bpp *data; \
+ int w; \
+ int h; \
+{ \
+ CARD##bpp cl; \
+ rfbCoRRERectangle subrect; \
+ int x,y; \
+ int i,j; \
+ int hx=0,hy,vx=0,vy; \
+ int hyflag; \
+ CARD##bpp *seg; \
+ CARD##bpp *line; \
+ int hw,hh,vw,vh; \
+ int thex,they,thew,theh; \
+ int numsubs = 0; \
+ int newLen; \
+ CARD##bpp bg = (CARD##bpp)getBgColour((char*)data,w*h,bpp); \
+ \
+ *((CARD##bpp*)rreAfterBuf) = bg; \
+ \
+ rreAfterBufLen = (bpp/8); \
+ \
+ for (y=0; y<h; y++) { \
+ line = data+(y*w); \
+ for (x=0; x<w; x++) { \
+ if (line[x] != bg) { \
+ cl = line[x]; \
+ hy = y-1; \
+ hyflag = 1; \
+ for (j=y; j<h; j++) { \
+ seg = data+(j*w); \
+ if (seg[x] != cl) {break;} \
+ i = x; \
+ while ((seg[i] == cl) && (i < w)) i += 1; \
+ i -= 1; \
+ if (j == y) vx = hx = i; \
+ if (i < vx) vx = i; \
+ if ((hyflag > 0) && (i >= hx)) {hy += 1;} else {hyflag = 0;} \
+ } \
+ vy = j-1; \
+ \
+ /* We now have two possible subrects: (x,y,hx,hy) and (x,y,vx,vy) \
+ * We'll choose the bigger of the two. \
+ */ \
+ hw = hx-x+1; \
+ hh = hy-y+1; \
+ vw = vx-x+1; \
+ vh = vy-y+1; \
+ \
+ thex = x; \
+ they = y; \
+ \
+ if ((hw*hh) > (vw*vh)) { \
+ thew = hw; \
+ theh = hh; \
+ } else { \
+ thew = vw; \
+ theh = vh; \
+ } \
+ \
+ subrect.x = thex; \
+ subrect.y = they; \
+ subrect.w = thew; \
+ subrect.h = theh; \
+ \
+ newLen = rreAfterBufLen + (bpp/8) + sz_rfbCoRRERectangle; \
+ if ((newLen > (w * h * (bpp/8))) || (newLen > rreAfterBufSize)) \
+ return -1; \
+ \
+ numsubs += 1; \
+ *((CARD##bpp*)(rreAfterBuf + rreAfterBufLen)) = cl; \
+ rreAfterBufLen += (bpp/8); \
+ memcpy(&rreAfterBuf[rreAfterBufLen],&subrect,sz_rfbCoRRERectangle); \
+ rreAfterBufLen += sz_rfbCoRRERectangle; \
+ \
+ /* \
+ * Now mark the subrect as done. \
+ */ \
+ for (j=they; j < (they+theh); j++) { \
+ for (i=thex; i < (thex+thew); i++) { \
+ data[j*w+i] = bg; \
+ } \
+ } \
+ } \
+ } \
+ } \
+ \
+ return numsubs; \
+}
+
+DEFINE_SUBRECT_ENCODE(8)
+DEFINE_SUBRECT_ENCODE(16)
+DEFINE_SUBRECT_ENCODE(32)
+
+
+/*
+ * getBgColour() gets the most prevalent colour in a byte array.
+ */
+static CARD32
+getBgColour(data,size,bpp)
+ char *data;
+ int size;
+ int bpp;
+{
+
+#define NUMCLRS 256
+
+ static int counts[NUMCLRS];
+ int i,j,k;
+
+ int maxcount = 0;
+ CARD8 maxclr = 0;
+
+ if (bpp != 8) {
+ if (bpp == 16) {
+ return ((CARD16 *)data)[0];
+ } else if (bpp == 32) {
+ return ((CARD32 *)data)[0];
+ } else {
+ rfbLog("getBgColour: bpp %d?\n",bpp);
+ exit(1);
+ }
+ }
+
+ for (i=0; i<NUMCLRS; i++) {
+ counts[i] = 0;
+ }
+
+ for (j=0; j<size; j++) {
+ k = (int)(((CARD8 *)data)[j]);
+ if (k >= NUMCLRS) {
+ rfbLog("getBgColour: unusual colour = %d\n", k);
+ exit(1);
+ }
+ counts[k] += 1;
+ if (counts[k] > maxcount) {
+ maxcount = counts[k];
+ maxclr = ((CARD8 *)data)[j];
+ }
+ }
+
+ return maxclr;
+}
diff --git a/krfb/libvncserver/cursor.c b/krfb/libvncserver/cursor.c
new file mode 100644
index 00000000..13175118
--- /dev/null
+++ b/krfb/libvncserver/cursor.c
@@ -0,0 +1,678 @@
+/*
+ * cursor.c - support for cursor shape updates.
+ */
+
+/*
+ * Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved.
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include "rfb.h"
+
+/*
+ * Send cursor shape either in X-style format or in client pixel format.
+ */
+
+Bool
+rfbSendCursorShape(cl)
+ rfbClientPtr cl;
+{
+ rfbCursorPtr pCursor;
+ rfbFramebufferUpdateRectHeader rect;
+ rfbXCursorColors colors;
+ int saved_ublen;
+ int bitmapRowBytes, maskBytes, dataBytes;
+ int i, j;
+ CARD8 *bitmapData;
+ CARD8 bitmapByte;
+
+ pCursor = cl->screen->getCursorPtr(cl);
+ /*if(!pCursor) return TRUE;*/
+
+ if (cl->useRichCursorEncoding) {
+ if(pCursor && !pCursor->richSource)
+ MakeRichCursorFromXCursor(cl->screen,pCursor);
+ rect.encoding = Swap32IfLE(rfbEncodingRichCursor);
+ } else {
+ if(pCursor && !pCursor->source)
+ MakeXCursorFromRichCursor(cl->screen,pCursor);
+ rect.encoding = Swap32IfLE(rfbEncodingXCursor);
+ }
+
+ /* If there is no cursor, send update with empty cursor data. */
+
+ if ( pCursor && pCursor->width == 1 &&
+ pCursor->height == 1 &&
+ pCursor->mask[0] == 0 ) {
+ pCursor = NULL;
+ }
+
+ if (pCursor == NULL) {
+ if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE ) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+ rect.r.x = rect.r.y = 0;
+ rect.r.w = rect.r.h = 0;
+ memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
+ sz_rfbFramebufferUpdateRectHeader);
+ cl->ublen += sz_rfbFramebufferUpdateRectHeader;
+
+ cl->rfbCursorBytesSent += sz_rfbFramebufferUpdateRectHeader;
+ cl->rfbCursorUpdatesSent++;
+
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+
+ return TRUE;
+ }
+
+ /* Calculate data sizes. */
+
+ bitmapRowBytes = (pCursor->width + 7) / 8;
+ maskBytes = bitmapRowBytes * pCursor->height;
+ dataBytes = (cl->useRichCursorEncoding) ?
+ (pCursor->width * pCursor->height *
+ (cl->format.bitsPerPixel / 8)) : maskBytes;
+
+ /* Send buffer contents if needed. */
+
+ if ( cl->ublen + sz_rfbFramebufferUpdateRectHeader +
+ sz_rfbXCursorColors + maskBytes + dataBytes > UPDATE_BUF_SIZE ) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ if ( cl->ublen + sz_rfbFramebufferUpdateRectHeader +
+ sz_rfbXCursorColors + maskBytes + dataBytes > UPDATE_BUF_SIZE ) {
+ return FALSE; /* FIXME. */
+ }
+
+ saved_ublen = cl->ublen;
+
+ /* Prepare rectangle header. */
+
+ rect.r.x = Swap16IfLE(pCursor->xhot);
+ rect.r.y = Swap16IfLE(pCursor->yhot);
+ rect.r.w = Swap16IfLE(pCursor->width);
+ rect.r.h = Swap16IfLE(pCursor->height);
+
+ memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader);
+ cl->ublen += sz_rfbFramebufferUpdateRectHeader;
+
+ /* Prepare actual cursor data (depends on encoding used). */
+
+ if (!cl->useRichCursorEncoding) {
+ /* XCursor encoding. */
+ colors.foreRed = (char)(pCursor->foreRed >> 8);
+ colors.foreGreen = (char)(pCursor->foreGreen >> 8);
+ colors.foreBlue = (char)(pCursor->foreBlue >> 8);
+ colors.backRed = (char)(pCursor->backRed >> 8);
+ colors.backGreen = (char)(pCursor->backGreen >> 8);
+ colors.backBlue = (char)(pCursor->backBlue >> 8);
+
+ memcpy(&cl->updateBuf[cl->ublen], (char *)&colors, sz_rfbXCursorColors);
+ cl->ublen += sz_rfbXCursorColors;
+
+ bitmapData = (CARD8 *)pCursor->source;
+
+ for (i = 0; i < pCursor->height; i++) {
+ for (j = 0; j < bitmapRowBytes; j++) {
+ bitmapByte = bitmapData[i * bitmapRowBytes + j];
+ cl->updateBuf[cl->ublen++] = (char)bitmapByte;
+ }
+ }
+ } else {
+ /* RichCursor encoding. */
+ int bpp1=cl->screen->rfbServerFormat.bitsPerPixel/8,
+ bpp2=cl->format.bitsPerPixel/8;
+ (*cl->translateFn)(cl->translateLookupTable,
+ &(cl->screen->rfbServerFormat),
+ &cl->format, pCursor->richSource,
+ &cl->updateBuf[cl->ublen],
+ pCursor->width*bpp1, pCursor->width, pCursor->height);
+
+ cl->ublen += pCursor->width*bpp2*pCursor->height;
+ }
+
+ /* Prepare transparency mask. */
+
+ bitmapData = (CARD8 *)pCursor->mask;
+
+ for (i = 0; i < pCursor->height; i++) {
+ for (j = 0; j < bitmapRowBytes; j++) {
+ bitmapByte = bitmapData[i * bitmapRowBytes + j];
+ cl->updateBuf[cl->ublen++] = (char)bitmapByte;
+ }
+ }
+
+ /* Send everything we have prepared in the cl->updateBuf[]. */
+
+ cl->rfbCursorBytesSent += (cl->ublen - saved_ublen);
+ cl->rfbCursorUpdatesSent++;
+
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+
+ return TRUE;
+}
+
+/*
+ * Send soft cursor state and possibly image
+ */
+
+Bool
+rfbSendSoftCursor(rfbClientPtr cl, Bool cursorWasChanged)
+{
+ rfbCursorPtr pCursor;
+ rfbSoftCursorSetImage setImage;
+ rfbSoftCursorMove moveMsg;
+ rfbFramebufferUpdateRectHeader rect;
+ int saved_ublen, i, scOindex, scNindex, nlen, imgLen;
+
+ pCursor = cl->screen->getCursorPtr(cl);
+ if (cursorWasChanged && cl->softSource) {
+ free(cl->softSource);
+ cl->softSource = 0;
+ }
+ if (!cl->softSource)
+ MakeSoftCursor(cl, pCursor);
+
+ imgLen = cl->softSourceLen;
+
+ /* If there is no cursor, send update with empty cursor data. */
+
+ if ( pCursor && pCursor->width <= 1 &&
+ pCursor->height <= 1 &&
+ pCursor->mask[0] == 0 ) {
+ pCursor = NULL;
+ }
+
+ setImage.imageLength = Swap16IfLE(imgLen);
+
+ scOindex = -1;
+ scNindex = -1;
+ for (i = 0; i < rfbSoftCursorMaxImages; i++) {
+ rfbSoftCursorSetImage *scsi = cl->softCursorImages[i];
+ if (!scsi) {
+ scNindex = i;
+ break;
+ }
+
+ setImage.imageIndex = scsi->imageIndex;
+ if (!memcmp((char*)scsi, (char*)&setImage, sizeof(setImage))) {
+ if (imgLen && !memcmp(((char*)scsi)+sizeof(rfbSoftCursorSetImage),
+ cl->softSource,
+ imgLen)) {
+ scOindex = i;
+ break;
+ }
+ }
+ }
+
+ nlen = 0;
+ if (scOindex < 0) {
+ if (scNindex < 0) {
+ scNindex = cl->nextUnusedSoftCursorImage;
+ cl->nextUnusedSoftCursorImage = (cl->nextUnusedSoftCursorImage+1)
+ % rfbSoftCursorMaxImages;
+ free(cl->softCursorImages[scNindex]);
+ }
+
+ scOindex = scNindex;
+ setImage.imageIndex = scNindex + rfbSoftCursorSetIconOffset;
+ nlen = sizeof(setImage) + imgLen;
+ cl->softCursorImages[scNindex] = calloc(1, nlen);
+ memcpy((char*)cl->softCursorImages[scNindex], (char*)&setImage,
+ sizeof(setImage));
+ if (imgLen)
+ memcpy(((char*)cl->softCursorImages[scNindex])+sizeof(setImage),
+ (char*)cl->softSource, imgLen);
+ }
+
+ /* Send buffer contents if needed. */
+
+ if ( cl->ublen + sizeof(rfbSoftCursorMove) +
+ ((scNindex >= 0 && cursorWasChanged) ?
+ (sizeof(rfbSoftCursorSetImage) + imgLen) : 0) > UPDATE_BUF_SIZE) {
+
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ saved_ublen = cl->ublen;
+
+ if (scNindex >= 0 && cursorWasChanged) {
+ rect.encoding = Swap32IfLE(rfbEncodingSoftCursor);
+ if (pCursor) {
+ rect.r.x = Swap16IfLE(pCursor->xhot);
+ rect.r.y = Swap16IfLE(pCursor->yhot);
+ rect.r.w = Swap16IfLE(pCursor->width);
+ rect.r.h = Swap16IfLE(pCursor->height);
+ }
+ else {
+ rect.r.x = 0;
+ rect.r.y = 0;
+ rect.r.w = 0;
+ rect.r.h = 0;
+ }
+
+ memcpy(&cl->updateBuf[cl->ublen],
+ (char *)&rect,sz_rfbFramebufferUpdateRectHeader);
+ cl->ublen += sz_rfbFramebufferUpdateRectHeader;
+ memcpy(&cl->updateBuf[cl->ublen], (char*)cl->softCursorImages[scNindex], nlen);
+ cl->ublen += nlen;
+ cl->rfbCursorUpdatesSent++;
+ }
+
+ rect.encoding = Swap32IfLE(rfbEncodingSoftCursor);
+ rect.r.x = 0;
+ rect.r.y = 0;
+ rect.r.w = Swap16IfLE(cl->screen->cursorX);
+ rect.r.h = Swap16IfLE(cl->screen->cursorY);
+ moveMsg.imageIndex = scOindex;
+ moveMsg.buttonMask = 0; /* todo */
+ memcpy(&cl->updateBuf[cl->ublen],
+ (char *)&rect,sz_rfbFramebufferUpdateRectHeader);
+ cl->ublen += sz_rfbFramebufferUpdateRectHeader;
+ memcpy(&cl->updateBuf[cl->ublen], (char*)&moveMsg, sizeof(moveMsg));
+ cl->ublen += sizeof(moveMsg);
+
+ /* Send everything we have prepared in the cl->updateBuf[]. */
+
+ cl->rfbCursorBytesSent += (cl->ublen - saved_ublen);
+ cl->rfbCursorUpdatesSent++;
+
+ return rfbSendUpdateBuf(cl);
+}
+
+/* conversion routine for predefined cursors in LSB order */
+unsigned char rfbReverseByte[0x100] = {
+ /* copied from Xvnc/lib/font/util/utilbitmap.c */
+ 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
+ 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+ 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
+ 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
+ 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
+ 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
+ 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
+ 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
+ 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
+ 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
+ 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
+ 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
+ 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
+ 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
+ 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
+ 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
+ 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
+ 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
+ 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
+ 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
+ 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
+ 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+ 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
+ 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
+ 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
+ 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
+ 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
+ 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
+ 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
+ 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
+ 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
+ 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
+};
+
+void rfbConvertLSBCursorBitmapOrMask(int width,int height,unsigned char* bitmap)
+{
+ int i,t=(width+7)/8*height;
+ for(i=0;i<t;i++)
+ bitmap[i]=rfbReverseByte[(int)bitmap[i]];
+}
+
+/* Cursor creation. You "paint" a cursor and let these routines do the work */
+
+rfbCursorPtr rfbMakeXCursor(int width,int height,char* cursorString,char* maskString)
+{
+ int i,j,w=(width+7)/8;
+ rfbCursorPtr cursor = (rfbCursorPtr)calloc(1,sizeof(rfbCursor));
+ char* cp;
+ unsigned char bit;
+
+ cursor->width=width;
+ cursor->height=height;
+ /*cursor->backRed=cursor->backGreen=cursor->backBlue=0xffff;*/
+ cursor->foreRed=cursor->foreGreen=cursor->foreBlue=0xffff;
+
+ cursor->source = (unsigned char*)calloc(w,height);
+ for(j=0,cp=cursorString;j<height;j++)
+ for(i=0,bit=0x80;i<width;i++,bit=(bit&1)?0x80:bit>>1,cp++)
+ if(*cp!=' ') cursor->source[j*w+i/8]|=bit;
+
+ if(maskString) {
+ cursor->mask = (unsigned char*)calloc(w,height);
+ for(j=0,cp=maskString;j<height;j++)
+ for(i=0,bit=0x80;i<width;i++,bit=(bit&1)?0x80:bit>>1,cp++)
+ if(*cp!=' ') cursor->mask[j*w+i/8]|=bit;
+ } else
+ cursor->mask = (unsigned char*)rfbMakeMaskForXCursor(width,height,cursor->source);
+
+ return(cursor);
+}
+
+char* rfbMakeMaskForXCursor(int width,int height,char* source)
+{
+ int i,j,w=(width+7)/8;
+ char* mask=(char*)calloc(w,height);
+ unsigned char c;
+
+ for(j=0;j<height;j++)
+ for(i=w-1;i>=0;i--) {
+ c=source[j*w+i];
+ if(j>0) c|=source[(j-1)*w+i];
+ if(j<height-1) c|=source[(j+1)*w+i];
+
+ if(i>0 && (c&0x80))
+ mask[j*w+i-1]|=0x01;
+ if(i<w-1 && (c&0x01))
+ mask[j*w+i+1]|=0x80;
+
+ mask[j*w+i]|=(c<<1)|c|(c>>1);
+ }
+
+ return(mask);
+}
+
+void rfbFreeCursor(rfbCursorPtr cursor)
+{
+ if(cursor) {
+ if(cursor->richSource)
+ free(cursor->richSource);
+ free(cursor->source);
+ free(cursor->mask);
+ free(cursor);
+ }
+
+}
+
+/* background and foregroud colour have to be set beforehand */
+void MakeXCursorFromRichCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr cursor)
+{
+ rfbPixelFormat* format=&rfbScreen->rfbServerFormat;
+ int i,j,w=(cursor->width+7)/8,bpp=format->bitsPerPixel/8,
+ width=cursor->width*bpp;
+ CARD32 background;
+ char *back=(char*)&background;
+ unsigned char bit;
+
+ cursor->source=(unsigned char*)calloc(w,cursor->height);
+
+ if(format->bigEndian)
+ back+=4-bpp;
+
+ background=cursor->backRed<<format->redShift|
+ cursor->backGreen<<format->greenShift|cursor->backBlue<<format->blueShift;
+
+ for(j=0;j<cursor->height;j++)
+ for(i=0,bit=0x80;i<cursor->width;i++,bit=(bit&1)?0x80:bit>>1)
+ if(memcmp(cursor->richSource+j*width+i*bpp,back,bpp))
+ cursor->source[j*w+i/8]|=bit;
+}
+
+void MakeRichCursorFromXCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr cursor)
+{
+ rfbPixelFormat* format=&rfbScreen->rfbServerFormat;
+ int i,j,w=(cursor->width+7)/8,bpp=format->bitsPerPixel/8;
+ CARD32 background,foreground;
+ char *back=(char*)&background,*fore=(char*)&foreground;
+ unsigned char *cp;
+ unsigned char bit;
+
+ cp=cursor->richSource=(unsigned char*)calloc(cursor->width*bpp,cursor->height);
+
+ if(format->bigEndian) {
+ back+=4-bpp;
+ fore+=4-bpp;
+ }
+
+ background=cursor->backRed<<format->redShift|
+ cursor->backGreen<<format->greenShift|cursor->backBlue<<format->blueShift;
+ foreground=cursor->foreRed<<format->redShift|
+ cursor->foreGreen<<format->greenShift|cursor->foreBlue<<format->blueShift;
+
+ for(j=0;j<cursor->height;j++)
+ for(i=0,bit=0x80;i<cursor->height;i++,bit=(bit&1)?0x80:bit>>1,cp+=bpp)
+ if(cursor->source[j*w+i/8]&bit) memcpy(cp,fore,bpp);
+ else memcpy(cp,back,bpp);
+}
+
+void MakeSoftCursor(rfbClientPtr cl, rfbCursorPtr cursor)
+{
+ int w = (cursor->width+7)/8;
+ int bpp = cl->format.bitsPerPixel/8;
+ int sbpp= cl->screen->rfbServerFormat.bitsPerPixel/8;
+ unsigned char *cp, *sp, *translatedCursor;
+ int state; /* 0 = transparent, 1 otherwise */
+ CARD8 *counter;
+ unsigned char bit;
+ int i,j;
+
+ if ((!cursor) || (cl->softSource)) {
+ cl->softSourceLen = 0;
+ return;
+ }
+
+ if (!cursor->richSource)
+ MakeRichCursorFromXCursor(cl->screen, cursor);
+
+ sp = malloc(cursor->width*bpp*cursor->height);
+
+ (*cl->translateFn)(cl->translateLookupTable,
+ &(cl->screen->rfbServerFormat),
+ &cl->format, cursor->richSource,
+ sp, cursor->width*sbpp,
+ cursor->width, cursor->height);
+
+ translatedCursor = sp;
+ cp=cl->softSource=(unsigned char*)calloc(cursor->width*(bpp+2),cursor->height);
+
+ state = 0;
+ counter = cp++;
+ *counter = 0;
+
+ for(j=0;j<cursor->height;j++)
+ for(i=0,bit=0x80;i<cursor->width;i++,bit=(bit&1)?0x80:bit>>1)
+ if(cursor->mask[j*w+i/8]&bit) {
+ if (state) {
+ memcpy(cp,sp,bpp);
+ cp += bpp;
+ sp += bpp;
+ (*counter)++;
+ if (*counter == 255) {
+ state = 0;
+ counter = cp++;
+ *counter = 0;
+ }
+ }
+ else {
+ state = 1;
+ counter = cp++;
+ *counter = 1;
+ memcpy(cp,sp,bpp);
+ cp += bpp;
+ sp += bpp;
+ }
+ }
+ else {
+ if (!state) {
+ (*counter)++;
+ if (*counter == 255) {
+ state = 1;
+ counter = cp++;
+ *counter = 0;
+ }
+ }
+ else {
+ state = 0;
+ counter = cp++;
+ *counter = 1;
+ }
+ sp += bpp;
+ }
+
+ free(translatedCursor);
+ cl->softSourceLen = cp - cl->softSource;
+}
+
+
+/* functions to draw/hide cursor directly in the frame buffer */
+
+void rfbUndrawCursor(rfbScreenInfoPtr s)
+{
+ rfbCursorPtr c=s->cursor;
+ int j,x1,x2,y1,y2,bpp=s->rfbServerFormat.bitsPerPixel/8,
+ rowstride=s->paddedWidthInBytes;
+ LOCK(s->cursorMutex);
+ if(!s->cursorIsDrawn) {
+ UNLOCK(s->cursorMutex);
+ return;
+ }
+
+ /* restore what is under the cursor */
+ x1=s->cursorX-c->xhot;
+ x2=x1+c->width;
+ if(x1<0) x1=0;
+ if(x2>=s->width) x2=s->width-1;
+ x2-=x1; if(x2<=0) {
+ UNLOCK(s->cursorMutex);
+ return;
+ }
+ y1=s->cursorY-c->yhot;
+ y2=y1+c->height;
+ if(y1<0) y1=0;
+ if(y2>=s->height) y2=s->height-1;
+ y2-=y1; if(y2<=0) {
+ UNLOCK(s->cursorMutex);
+ return;
+ }
+
+ /* get saved data */
+ for(j=0;j<y2;j++)
+ memcpy(s->frameBuffer+(y1+j)*rowstride+x1*bpp,
+ s->underCursorBuffer+j*x2*bpp,
+ x2*bpp);
+
+ rfbMarkRectAsModified(s,x1,y1,x1+x2,y1+y2);
+ s->cursorIsDrawn = FALSE;
+ UNLOCK(s->cursorMutex);
+}
+
+void rfbDrawCursor(rfbScreenInfoPtr s)
+{
+ rfbCursorPtr c=s->cursor;
+ int i,j,x1,x2,y1,y2,i1,j1,bpp=s->rfbServerFormat.bitsPerPixel/8,
+ rowstride=s->paddedWidthInBytes,
+ bufSize,w;
+ if(!c) return;
+ LOCK(s->cursorMutex);
+ if(s->cursorIsDrawn) {
+ /* is already drawn */
+ UNLOCK(s->cursorMutex);
+ return;
+ }
+ bufSize=c->width*c->height*bpp;
+ w=(c->width+7)/8;
+ if(s->underCursorBufferLen<bufSize) {
+ if(s->underCursorBuffer!=NULL)
+ free(s->underCursorBuffer);
+ s->underCursorBuffer=malloc(bufSize);
+ s->underCursorBufferLen=bufSize;
+ }
+ /* save what is under the cursor */
+ i1=j1=0; /* offset in cursor */
+ x1=s->cursorX-c->xhot;
+ x2=x1+c->width;
+ if(x1<0) { i1=-x1; x1=0; }
+ if(x2>=s->width) x2=s->width-1;
+ x2-=x1; if(x2<=0) {
+ UNLOCK(s->cursorMutex);
+ return; /* nothing to do */
+ }
+ y1=s->cursorY-c->yhot;
+ y2=y1+c->height;
+ if(y1<0) { j1=-y1; y1=0; }
+ if(y2>=s->height) y2=s->height-1;
+ y2-=y1; if(y2<=0) {
+ UNLOCK(s->cursorMutex);
+ return; /* nothing to do */
+ }
+
+ /* save data */
+ for(j=0;j<y2;j++)
+ memcpy(s->underCursorBuffer+j*x2*bpp,
+ s->frameBuffer+(y1+j)*rowstride+x1*bpp,
+ x2*bpp);
+
+ if(!c->richSource)
+ MakeRichCursorFromXCursor(s,c);
+
+ /* now the cursor has to be drawn */
+ for(j=0;j<y2;j++)
+ for(i=0;i<x2;i++)
+ if((c->mask[(j+j1)*w+(i+i1)/8]<<((i+i1)&7))&0x80)
+ memcpy(s->frameBuffer+(j+y1)*rowstride+(i+x1)*bpp,
+ c->richSource+(j+j1)*c->width*bpp+(i+i1)*bpp,bpp);
+
+
+ rfbMarkRectAsModified(s,x1,y1,x1+x2,y1+y2);
+ s->cursorIsDrawn = TRUE;
+ UNLOCK(s->cursorMutex);
+}
+
+/* for debugging */
+
+void rfbPrintXCursor(rfbCursorPtr cursor)
+{
+ int i,i1,j,w=(cursor->width+7)/8;
+ unsigned char bit;
+ for(j=0;j<cursor->height;j++) {
+ for(i=0,i1=0,bit=0x80;i1<cursor->width;i1++,i+=(bit&1)?1:0,bit=(bit&1)?0x80:bit>>1)
+ if(cursor->source[j*w+i]&bit) putchar('#'); else putchar(' ');
+ putchar(':');
+ for(i=0,i1=0,bit=0x80;i1<cursor->width;i1++,i+=(bit&1)?1:0,bit=(bit&1)?0x80:bit>>1)
+ if(cursor->mask[j*w+i]&bit) putchar('#'); else putchar(' ');
+ putchar('\n');
+ }
+}
+
+extern void rfbSetCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr c,Bool freeOld)
+{
+ LOCK(rfbScreen->cursorMutex);
+ while(rfbScreen->cursorIsDrawn) {
+ UNLOCK(rfbScreen->cursorMutex);
+ rfbUndrawCursor(rfbScreen);
+ LOCK(rfbScreen->cursorMutex);
+ }
+
+ if(freeOld && rfbScreen->cursor)
+ rfbFreeCursor(rfbScreen->cursor);
+
+ rfbScreen->cursor = c;
+
+ UNLOCK(rfbScreen->cursorMutex);
+}
diff --git a/krfb/libvncserver/cutpaste.c b/krfb/libvncserver/cutpaste.c
new file mode 100644
index 00000000..7dcefe7f
--- /dev/null
+++ b/krfb/libvncserver/cutpaste.c
@@ -0,0 +1,39 @@
+/*
+ * cutpaste.c - routines to deal with cut & paste buffers / selection.
+ */
+
+/*
+ * OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
+ * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
+ * All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include <stdio.h>
+#include "rfb.h"
+
+
+/*
+ * rfbSetXCutText sets the cut buffer to be the given string. We also clear
+ * the primary selection. Ideally we'd like to set it to the same thing, but I
+ * can't work out how to do that without some kind of helper X client.
+ */
+
+void rfbGotXCutText(rfbScreenInfoPtr rfbScreen, char *str, int len)
+{
+ rfbSendServerCutText(rfbScreen, str, len);
+}
diff --git a/krfb/libvncserver/d3des.c b/krfb/libvncserver/d3des.c
new file mode 100644
index 00000000..4994afb1
--- /dev/null
+++ b/krfb/libvncserver/d3des.c
@@ -0,0 +1,442 @@
+/*
+ * This is D3DES (V5.09) by Richard Outerbridge with the double and
+ * triple-length support removed for use in VNC. Also the bytebit[] array
+ * has been reversed so that the most significant bit in each byte of the
+ * key is ignored, not the least significant.
+ *
+ * These changes are:
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/* D3DES (V5.09) -
+ *
+ * A portable, public domain, version of the Data Encryption Standard.
+ *
+ * Written with Symantec's THINK (Lightspeed) C by Richard Outerbridge.
+ * Thanks to: Dan Hoey for his excellent Initial and Inverse permutation
+ * code; Jim Gillogly & Phil Karn for the DES key schedule code; Dennis
+ * Ferguson, Eric Young and Dana How for comparing notes; and Ray Lau,
+ * for humouring me on.
+ *
+ * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge.
+ * (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992.
+ */
+
+#include "d3des.h"
+
+static void scrunch(unsigned char *, unsigned long *);
+static void unscrun(unsigned long *, unsigned char *);
+static void desfunc(unsigned long *, unsigned long *);
+static void cookey(unsigned long *);
+
+static unsigned long KnL[32] = { 0L };
+/*
+static unsigned long KnR[32] = { 0L };
+static unsigned long Kn3[32] = { 0L };
+static unsigned char Df_Key[24] = {
+ 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,
+ 0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10,
+ 0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 };
+*/
+
+static unsigned short bytebit[8] = {
+ 01, 02, 04, 010, 020, 040, 0100, 0200 };
+
+static unsigned long bigbyte[24] = {
+ 0x800000L, 0x400000L, 0x200000L, 0x100000L,
+ 0x80000L, 0x40000L, 0x20000L, 0x10000L,
+ 0x8000L, 0x4000L, 0x2000L, 0x1000L,
+ 0x800L, 0x400L, 0x200L, 0x100L,
+ 0x80L, 0x40L, 0x20L, 0x10L,
+ 0x8L, 0x4L, 0x2L, 0x1L };
+
+/* Use the key schedule specified in the Standard (ANSI X3.92-1981). */
+
+static unsigned char pc1[56] = {
+ 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
+ 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
+ 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
+ 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 };
+
+static unsigned char totrot[16] = {
+ 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 };
+
+static unsigned char pc2[48] = {
+ 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
+ 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
+ 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
+ 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 };
+
+void deskey(key, edf) /* Thanks to James Gillogly & Phil Karn! */
+unsigned char *key;
+int edf;
+{
+ register int i, j, l, m, n;
+ unsigned char pc1m[56], pcr[56];
+ unsigned long kn[32];
+
+ for ( j = 0; j < 56; j++ ) {
+ l = pc1[j];
+ m = l & 07;
+ pc1m[j] = (key[l >> 3] & bytebit[m]) ? 1 : 0;
+ }
+ for( i = 0; i < 16; i++ ) {
+ if( edf == DE1 ) m = (15 - i) << 1;
+ else m = i << 1;
+ n = m + 1;
+ kn[m] = kn[n] = 0L;
+ for( j = 0; j < 28; j++ ) {
+ l = j + totrot[i];
+ if( l < 28 ) pcr[j] = pc1m[l];
+ else pcr[j] = pc1m[l - 28];
+ }
+ for( j = 28; j < 56; j++ ) {
+ l = j + totrot[i];
+ if( l < 56 ) pcr[j] = pc1m[l];
+ else pcr[j] = pc1m[l - 28];
+ }
+ for( j = 0; j < 24; j++ ) {
+ if( pcr[pc2[j]] ) kn[m] |= bigbyte[j];
+ if( pcr[pc2[j+24]] ) kn[n] |= bigbyte[j];
+ }
+ }
+ cookey(kn);
+ return;
+ }
+
+static void cookey(raw1)
+register unsigned long *raw1;
+{
+ register unsigned long *cook, *raw0;
+ unsigned long dough[32];
+ register int i;
+
+ cook = dough;
+ for( i = 0; i < 16; i++, raw1++ ) {
+ raw0 = raw1++;
+ *cook = (*raw0 & 0x00fc0000L) << 6;
+ *cook |= (*raw0 & 0x00000fc0L) << 10;
+ *cook |= (*raw1 & 0x00fc0000L) >> 10;
+ *cook++ |= (*raw1 & 0x00000fc0L) >> 6;
+ *cook = (*raw0 & 0x0003f000L) << 12;
+ *cook |= (*raw0 & 0x0000003fL) << 16;
+ *cook |= (*raw1 & 0x0003f000L) >> 4;
+ *cook++ |= (*raw1 & 0x0000003fL);
+ }
+ usekey(dough);
+ return;
+ }
+
+void cpkey(into)
+register unsigned long *into;
+{
+ register unsigned long *from, *endp;
+
+ from = KnL, endp = &KnL[32];
+ while( from < endp ) *into++ = *from++;
+ return;
+ }
+
+void usekey(from)
+register unsigned long *from;
+{
+ register unsigned long *to, *endp;
+
+ to = KnL, endp = &KnL[32];
+ while( to < endp ) *to++ = *from++;
+ return;
+ }
+
+void des(inblock, outblock)
+unsigned char *inblock, *outblock;
+{
+ unsigned long work[2];
+
+ scrunch(inblock, work);
+ desfunc(work, KnL);
+ unscrun(work, outblock);
+ return;
+ }
+
+static void scrunch(outof, into)
+register unsigned char *outof;
+register unsigned long *into;
+{
+ *into = (*outof++ & 0xffL) << 24;
+ *into |= (*outof++ & 0xffL) << 16;
+ *into |= (*outof++ & 0xffL) << 8;
+ *into++ |= (*outof++ & 0xffL);
+ *into = (*outof++ & 0xffL) << 24;
+ *into |= (*outof++ & 0xffL) << 16;
+ *into |= (*outof++ & 0xffL) << 8;
+ *into |= (*outof & 0xffL);
+ return;
+ }
+
+static void unscrun(outof, into)
+register unsigned long *outof;
+register unsigned char *into;
+{
+ *into++ = (unsigned char)((*outof >> 24) & 0xffL);
+ *into++ = (unsigned char)((*outof >> 16) & 0xffL);
+ *into++ = (unsigned char)((*outof >> 8) & 0xffL);
+ *into++ = (unsigned char)( *outof++ & 0xffL);
+ *into++ = (unsigned char)((*outof >> 24) & 0xffL);
+ *into++ = (unsigned char)((*outof >> 16) & 0xffL);
+ *into++ = (unsigned char)((*outof >> 8) & 0xffL);
+ *into = (unsigned char)( *outof & 0xffL);
+ return;
+ }
+
+static unsigned long SP1[64] = {
+ 0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L,
+ 0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L,
+ 0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L,
+ 0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L,
+ 0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L,
+ 0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L,
+ 0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L,
+ 0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L,
+ 0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L,
+ 0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L,
+ 0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L,
+ 0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L,
+ 0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L,
+ 0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L,
+ 0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L,
+ 0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L };
+
+static unsigned long SP2[64] = {
+ 0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L,
+ 0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L,
+ 0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L,
+ 0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L,
+ 0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L,
+ 0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L,
+ 0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L,
+ 0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L,
+ 0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L,
+ 0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L,
+ 0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L,
+ 0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L,
+ 0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L,
+ 0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L,
+ 0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L,
+ 0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L };
+
+static unsigned long SP3[64] = {
+ 0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L,
+ 0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L,
+ 0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L,
+ 0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L,
+ 0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L,
+ 0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L,
+ 0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L,
+ 0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L,
+ 0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L,
+ 0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L,
+ 0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L,
+ 0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L,
+ 0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L,
+ 0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L,
+ 0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L,
+ 0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L };
+
+static unsigned long SP4[64] = {
+ 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
+ 0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L,
+ 0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L,
+ 0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L,
+ 0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L,
+ 0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L,
+ 0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L,
+ 0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L,
+ 0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L,
+ 0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L,
+ 0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L,
+ 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
+ 0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L,
+ 0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L,
+ 0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L,
+ 0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L };
+
+static unsigned long SP5[64] = {
+ 0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L,
+ 0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L,
+ 0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L,
+ 0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L,
+ 0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L,
+ 0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L,
+ 0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L,
+ 0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L,
+ 0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L,
+ 0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L,
+ 0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L,
+ 0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L,
+ 0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L,
+ 0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L,
+ 0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L,
+ 0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L };
+
+static unsigned long SP6[64] = {
+ 0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L,
+ 0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L,
+ 0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L,
+ 0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L,
+ 0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L,
+ 0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L,
+ 0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L,
+ 0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L,
+ 0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L,
+ 0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L,
+ 0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L,
+ 0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L,
+ 0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L,
+ 0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L,
+ 0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L,
+ 0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L };
+
+static unsigned long SP7[64] = {
+ 0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L,
+ 0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L,
+ 0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L,
+ 0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L,
+ 0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L,
+ 0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L,
+ 0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L,
+ 0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L,
+ 0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L,
+ 0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L,
+ 0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L,
+ 0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L,
+ 0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L,
+ 0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L,
+ 0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L,
+ 0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L };
+
+static unsigned long SP8[64] = {
+ 0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L,
+ 0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L,
+ 0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L,
+ 0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L,
+ 0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L,
+ 0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L,
+ 0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L,
+ 0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L,
+ 0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L,
+ 0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L,
+ 0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L,
+ 0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L,
+ 0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L,
+ 0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L,
+ 0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L,
+ 0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L };
+
+static void desfunc(block, keys)
+register unsigned long *block, *keys;
+{
+ register unsigned long fval, work, right, leftt;
+ register int round;
+
+ leftt = block[0];
+ right = block[1];
+ work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL;
+ right ^= work;
+ leftt ^= (work << 4);
+ work = ((leftt >> 16) ^ right) & 0x0000ffffL;
+ right ^= work;
+ leftt ^= (work << 16);
+ work = ((right >> 2) ^ leftt) & 0x33333333L;
+ leftt ^= work;
+ right ^= (work << 2);
+ work = ((right >> 8) ^ leftt) & 0x00ff00ffL;
+ leftt ^= work;
+ right ^= (work << 8);
+ right = ((right << 1) | ((right >> 31) & 1L)) & 0xffffffffL;
+ work = (leftt ^ right) & 0xaaaaaaaaL;
+ leftt ^= work;
+ right ^= work;
+ leftt = ((leftt << 1) | ((leftt >> 31) & 1L)) & 0xffffffffL;
+
+ for( round = 0; round < 8; round++ ) {
+ work = (right << 28) | (right >> 4);
+ work ^= *keys++;
+ fval = SP7[ work & 0x3fL];
+ fval |= SP5[(work >> 8) & 0x3fL];
+ fval |= SP3[(work >> 16) & 0x3fL];
+ fval |= SP1[(work >> 24) & 0x3fL];
+ work = right ^ *keys++;
+ fval |= SP8[ work & 0x3fL];
+ fval |= SP6[(work >> 8) & 0x3fL];
+ fval |= SP4[(work >> 16) & 0x3fL];
+ fval |= SP2[(work >> 24) & 0x3fL];
+ leftt ^= fval;
+ work = (leftt << 28) | (leftt >> 4);
+ work ^= *keys++;
+ fval = SP7[ work & 0x3fL];
+ fval |= SP5[(work >> 8) & 0x3fL];
+ fval |= SP3[(work >> 16) & 0x3fL];
+ fval |= SP1[(work >> 24) & 0x3fL];
+ work = leftt ^ *keys++;
+ fval |= SP8[ work & 0x3fL];
+ fval |= SP6[(work >> 8) & 0x3fL];
+ fval |= SP4[(work >> 16) & 0x3fL];
+ fval |= SP2[(work >> 24) & 0x3fL];
+ right ^= fval;
+ }
+
+ right = (right << 31) | (right >> 1);
+ work = (leftt ^ right) & 0xaaaaaaaaL;
+ leftt ^= work;
+ right ^= work;
+ leftt = (leftt << 31) | (leftt >> 1);
+ work = ((leftt >> 8) ^ right) & 0x00ff00ffL;
+ right ^= work;
+ leftt ^= (work << 8);
+ work = ((leftt >> 2) ^ right) & 0x33333333L;
+ right ^= work;
+ leftt ^= (work << 2);
+ work = ((right >> 16) ^ leftt) & 0x0000ffffL;
+ leftt ^= work;
+ right ^= (work << 16);
+ work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL;
+ leftt ^= work;
+ right ^= (work << 4);
+ *block++ = right;
+ *block = leftt;
+ return;
+ }
+
+/* Validation sets:
+ *
+ * Single-length key, single-length plaintext -
+ * Key : 0123 4567 89ab cdef
+ * Plain : 0123 4567 89ab cde7
+ * Cipher : c957 4425 6a5e d31d
+ *
+ * Double-length key, single-length plaintext -
+ * Key : 0123 4567 89ab cdef fedc ba98 7654 3210
+ * Plain : 0123 4567 89ab cde7
+ * Cipher : 7f1d 0a77 826b 8aff
+ *
+ * Double-length key, double-length plaintext -
+ * Key : 0123 4567 89ab cdef fedc ba98 7654 3210
+ * Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff
+ * Cipher : 27a0 8440 406a df60 278f 47cf 42d6 15d7
+ *
+ * Triple-length key, single-length plaintext -
+ * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567
+ * Plain : 0123 4567 89ab cde7
+ * Cipher : de0b 7c06 ae5e 0ed5
+ *
+ * Triple-length key, double-length plaintext -
+ * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567
+ * Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff
+ * Cipher : ad0d 1b30 ac17 cf07 0ed1 1c63 81e4 4de5
+ *
+ * d3des V5.0a rwo 9208.07 18:44 Graven Imagery
+ **********************************************************************/
diff --git a/krfb/libvncserver/d3des.h b/krfb/libvncserver/d3des.h
new file mode 100644
index 00000000..b2f97247
--- /dev/null
+++ b/krfb/libvncserver/d3des.h
@@ -0,0 +1,56 @@
+#ifndef D3DES_H
+#define D3DES_H
+
+/*
+ * This is D3DES (V5.09) by Richard Outerbridge with the double and
+ * triple-length support removed for use in VNC.
+ *
+ * These changes are:
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/* d3des.h -
+ *
+ * Headers and defines for d3des.c
+ * Graven Imagery, 1992.
+ *
+ * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge
+ * (GEnie : OUTER; CIS : [71755,204])
+ */
+
+#define EN0 0 /* MODE == encrypt */
+#define DE1 1 /* MODE == decrypt */
+
+extern void deskey(unsigned char *, int);
+/* hexkey[8] MODE
+ * Sets the internal key register according to the hexadecimal
+ * key contained in the 8 bytes of hexkey, according to the DES,
+ * for encryption or decryption according to MODE.
+ */
+
+extern void usekey(unsigned long *);
+/* cookedkey[32]
+ * Loads the internal key register with the data in cookedkey.
+ */
+
+extern void cpkey(unsigned long *);
+/* cookedkey[32]
+ * Copies the contents of the internal key register into the storage
+ * located at &cookedkey[0].
+ */
+
+extern void des(unsigned char *, unsigned char *);
+/* from[8] to[8]
+ * Encrypts/Decrypts (according to the key currently loaded in the
+ * internal key register) one block of eight bytes at address 'from'
+ * into the block at address 'to'. They can be the same.
+ */
+
+/* d3des.h V5.09 rwo 9208.04 15:06 Graven Imagery
+ ********************************************************************/
+
+#endif
diff --git a/krfb/libvncserver/default8x16.h b/krfb/libvncserver/default8x16.h
new file mode 100644
index 00000000..d557d478
--- /dev/null
+++ b/krfb/libvncserver/default8x16.h
@@ -0,0 +1,261 @@
+unsigned char default8x16FontData[4096+1]={
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x7e,0x81,0xa5,0x81,0x81,0xbd,0x99,0x81,0x81,0x7e,0x00,0x00,0x00,0x00,
+0x00,0x00,0x7e,0xff,0xdb,0xff,0xff,0xc3,0xe7,0xff,0xff,0x7e,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x6c,0xfe,0xfe,0xfe,0xfe,0x7c,0x38,0x10,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x10,0x38,0x7c,0xfe,0x7c,0x38,0x10,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x18,0x3c,0x3c,0xe7,0xe7,0xe7,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x18,0x3c,0x7e,0xff,0xff,0x7e,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x3c,0x3c,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
+0xff,0xff,0xff,0xff,0xff,0xff,0xe7,0xc3,0xc3,0xe7,0xff,0xff,0xff,0xff,0xff,0xff,
+0x00,0x00,0x00,0x00,0x00,0x3c,0x66,0x42,0x42,0x66,0x3c,0x00,0x00,0x00,0x00,0x00,
+0xff,0xff,0xff,0xff,0xff,0xc3,0x99,0xbd,0xbd,0x99,0xc3,0xff,0xff,0xff,0xff,0xff,
+0x00,0x00,0x1e,0x0e,0x1a,0x32,0x78,0xcc,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00,0x00,
+0x00,0x00,0x3c,0x66,0x66,0x66,0x66,0x3c,0x18,0x7e,0x18,0x18,0x00,0x00,0x00,0x00,
+0x00,0x00,0x3f,0x33,0x3f,0x30,0x30,0x30,0x30,0x70,0xf0,0xe0,0x00,0x00,0x00,0x00,
+0x00,0x00,0x7f,0x63,0x7f,0x63,0x63,0x63,0x63,0x67,0xe7,0xe6,0xc0,0x00,0x00,0x00,
+0x00,0x00,0x00,0x18,0x18,0xdb,0x3c,0xe7,0x3c,0xdb,0x18,0x18,0x00,0x00,0x00,0x00,
+0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfe,0xf8,0xf0,0xe0,0xc0,0x80,0x00,0x00,0x00,0x00,
+0x00,0x02,0x06,0x0e,0x1e,0x3e,0xfe,0x3e,0x1e,0x0e,0x06,0x02,0x00,0x00,0x00,0x00,
+0x00,0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x7e,0x3c,0x18,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x66,0x66,0x00,0x00,0x00,0x00,
+0x00,0x00,0x7f,0xdb,0xdb,0xdb,0x7b,0x1b,0x1b,0x1b,0x1b,0x1b,0x00,0x00,0x00,0x00,
+0x00,0x7c,0xc6,0x60,0x38,0x6c,0xc6,0xc6,0x6c,0x38,0x0c,0xc6,0x7c,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xfe,0xfe,0xfe,0x00,0x00,0x00,0x00,
+0x00,0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x7e,0x3c,0x18,0x7e,0x00,0x00,0x00,0x00,
+0x00,0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
+0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7e,0x3c,0x18,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x18,0x0c,0xfe,0x0c,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x30,0x60,0xfe,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xc0,0xc0,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x24,0x66,0xff,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x10,0x38,0x38,0x7c,0x7c,0xfe,0xfe,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0xfe,0xfe,0x7c,0x7c,0x38,0x38,0x10,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x18,0x3c,0x3c,0x3c,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00,
+0x00,0x66,0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x6c,0x6c,0xfe,0x6c,0x6c,0x6c,0xfe,0x6c,0x6c,0x00,0x00,0x00,0x00,
+0x18,0x18,0x7c,0xc6,0xc2,0xc0,0x7c,0x06,0x06,0x86,0xc6,0x7c,0x18,0x18,0x00,0x00,
+0x00,0x00,0x00,0x00,0xc2,0xc6,0x0c,0x18,0x30,0x60,0xc6,0x86,0x00,0x00,0x00,0x00,
+0x00,0x00,0x38,0x6c,0x6c,0x38,0x76,0xdc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
+0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x0c,0x18,0x30,0x30,0x30,0x30,0x30,0x30,0x18,0x0c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x30,0x18,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x18,0x30,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x66,0x3c,0xff,0x3c,0x66,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x02,0x06,0x0c,0x18,0x30,0x60,0xc0,0x80,0x00,0x00,0x00,0x00,
+0x00,0x00,0x7c,0xc6,0xc6,0xce,0xde,0xf6,0xe6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x7e,0x00,0x00,0x00,0x00,
+0x00,0x00,0x7c,0xc6,0x06,0x0c,0x18,0x30,0x60,0xc0,0xc6,0xfe,0x00,0x00,0x00,0x00,
+0x00,0x00,0x7c,0xc6,0x06,0x06,0x3c,0x06,0x06,0x06,0xc6,0x7c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x0c,0x1c,0x3c,0x6c,0xcc,0xfe,0x0c,0x0c,0x0c,0x1e,0x00,0x00,0x00,0x00,
+0x00,0x00,0xfe,0xc0,0xc0,0xc0,0xfc,0x06,0x06,0x06,0xc6,0x7c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x38,0x60,0xc0,0xc0,0xfc,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
+0x00,0x00,0xfe,0xc6,0x06,0x06,0x0c,0x18,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00,
+0x00,0x00,0x7c,0xc6,0xc6,0xc6,0x7c,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x7c,0xc6,0xc6,0xc6,0x7e,0x06,0x06,0x06,0x0c,0x78,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x30,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x06,0x0c,0x18,0x30,0x60,0x30,0x18,0x0c,0x06,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x7e,0x00,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x60,0x30,0x18,0x0c,0x06,0x0c,0x18,0x30,0x60,0x00,0x00,0x00,0x00,
+0x00,0x00,0x7c,0xc6,0xc6,0x0c,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00,
+0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xde,0xde,0xde,0xdc,0xc0,0x7c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00,
+0x00,0x00,0xfc,0x66,0x66,0x66,0x7c,0x66,0x66,0x66,0x66,0xfc,0x00,0x00,0x00,0x00,
+0x00,0x00,0x3c,0x66,0xc2,0xc0,0xc0,0xc0,0xc0,0xc2,0x66,0x3c,0x00,0x00,0x00,0x00,
+0x00,0x00,0xf8,0x6c,0x66,0x66,0x66,0x66,0x66,0x66,0x6c,0xf8,0x00,0x00,0x00,0x00,
+0x00,0x00,0xfe,0x66,0x62,0x68,0x78,0x68,0x60,0x62,0x66,0xfe,0x00,0x00,0x00,0x00,
+0x00,0x00,0xfe,0x66,0x62,0x68,0x78,0x68,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00,
+0x00,0x00,0x3c,0x66,0xc2,0xc0,0xc0,0xde,0xc6,0xc6,0x66,0x3a,0x00,0x00,0x00,0x00,
+0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00,
+0x00,0x00,0x3c,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x1e,0x0c,0x0c,0x0c,0x0c,0x0c,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00,0x00,
+0x00,0x00,0xe6,0x66,0x66,0x6c,0x78,0x78,0x6c,0x66,0x66,0xe6,0x00,0x00,0x00,0x00,
+0x00,0x00,0xf0,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xfe,0x00,0x00,0x00,0x00,
+0x00,0x00,0xc3,0xe7,0xff,0xff,0xdb,0xc3,0xc3,0xc3,0xc3,0xc3,0x00,0x00,0x00,0x00,
+0x00,0x00,0xc6,0xe6,0xf6,0xfe,0xde,0xce,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00,
+0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
+0x00,0x00,0xfc,0x66,0x66,0x66,0x7c,0x60,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00,
+0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xd6,0xde,0x7c,0x0c,0x0e,0x00,0x00,
+0x00,0x00,0xfc,0x66,0x66,0x66,0x7c,0x6c,0x66,0x66,0x66,0xe6,0x00,0x00,0x00,0x00,
+0x00,0x00,0x7c,0xc6,0xc6,0x60,0x38,0x0c,0x06,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
+0x00,0x00,0xff,0xdb,0x99,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
+0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
+0x00,0x00,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0x66,0x3c,0x18,0x00,0x00,0x00,0x00,
+0x00,0x00,0xc3,0xc3,0xc3,0xc3,0xc3,0xdb,0xdb,0xff,0x66,0x66,0x00,0x00,0x00,0x00,
+0x00,0x00,0xc3,0xc3,0x66,0x3c,0x18,0x18,0x3c,0x66,0xc3,0xc3,0x00,0x00,0x00,0x00,
+0x00,0x00,0xc3,0xc3,0xc3,0x66,0x3c,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
+0x00,0x00,0xff,0xc3,0x86,0x0c,0x18,0x30,0x60,0xc1,0xc3,0xff,0x00,0x00,0x00,0x00,
+0x00,0x00,0x3c,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x80,0xc0,0xe0,0x70,0x38,0x1c,0x0e,0x06,0x02,0x00,0x00,0x00,0x00,
+0x00,0x00,0x3c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x3c,0x00,0x00,0x00,0x00,
+0x10,0x38,0x6c,0xc6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,
+0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
+0x00,0x00,0xe0,0x60,0x60,0x78,0x6c,0x66,0x66,0x66,0x66,0x7c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0xc0,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x1c,0x0c,0x0c,0x3c,0x6c,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x38,0x6c,0x64,0x60,0xf0,0x60,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x76,0xcc,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0xcc,0x78,0x00,
+0x00,0x00,0xe0,0x60,0x60,0x6c,0x76,0x66,0x66,0x66,0x66,0xe6,0x00,0x00,0x00,0x00,
+0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x06,0x06,0x00,0x0e,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3c,0x00,
+0x00,0x00,0xe0,0x60,0x60,0x66,0x6c,0x78,0x78,0x6c,0x66,0xe6,0x00,0x00,0x00,0x00,
+0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xe6,0xff,0xdb,0xdb,0xdb,0xdb,0xdb,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x7c,0x60,0x60,0xf0,0x00,
+0x00,0x00,0x00,0x00,0x00,0x76,0xcc,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0x0c,0x1e,0x00,
+0x00,0x00,0x00,0x00,0x00,0xdc,0x76,0x66,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0x60,0x38,0x0c,0xc6,0x7c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x10,0x30,0x30,0xfc,0x30,0x30,0x30,0x30,0x36,0x1c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xc3,0xc3,0xc3,0xc3,0x66,0x3c,0x18,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xc3,0xc3,0xc3,0xdb,0xdb,0xff,0x66,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xc3,0x66,0x3c,0x18,0x3c,0x66,0xc3,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7e,0x06,0x0c,0xf8,0x00,
+0x00,0x00,0x00,0x00,0x00,0xfe,0xcc,0x18,0x30,0x60,0xc6,0xfe,0x00,0x00,0x00,0x00,
+0x00,0x00,0x0e,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0e,0x00,0x00,0x00,0x00,
+0x00,0x00,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
+0x00,0x00,0x70,0x18,0x18,0x18,0x0e,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00,
+0x00,0x00,0x76,0xdc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xc6,0xfe,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x3c,0x66,0xc2,0xc0,0xc0,0xc0,0xc2,0x66,0x3c,0x0c,0x06,0x7c,0x00,0x00,
+0x00,0x00,0xcc,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
+0x00,0x0c,0x18,0x30,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00,
+0x00,0x10,0x38,0x6c,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
+0x00,0x00,0xcc,0x00,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
+0x00,0x60,0x30,0x18,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
+0x00,0x38,0x6c,0x38,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x3c,0x66,0x60,0x60,0x66,0x3c,0x0c,0x06,0x3c,0x00,0x00,0x00,
+0x00,0x10,0x38,0x6c,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00,
+0x00,0x00,0xc6,0x00,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00,
+0x00,0x60,0x30,0x18,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x66,0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
+0x00,0x18,0x3c,0x66,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
+0x00,0x60,0x30,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
+0x00,0xc6,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00,
+0x38,0x6c,0x38,0x00,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00,
+0x18,0x30,0x60,0x00,0xfe,0x66,0x60,0x7c,0x60,0x60,0x66,0xfe,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x6e,0x3b,0x1b,0x7e,0xd8,0xdc,0x77,0x00,0x00,0x00,0x00,
+0x00,0x00,0x3e,0x6c,0xcc,0xcc,0xfe,0xcc,0xcc,0xcc,0xcc,0xce,0x00,0x00,0x00,0x00,
+0x00,0x10,0x38,0x6c,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
+0x00,0x00,0xc6,0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
+0x00,0x60,0x30,0x18,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
+0x00,0x30,0x78,0xcc,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
+0x00,0x60,0x30,0x18,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
+0x00,0x00,0xc6,0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7e,0x06,0x0c,0x78,0x00,
+0x00,0xc6,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
+0x00,0xc6,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
+0x00,0x18,0x18,0x7e,0xc3,0xc0,0xc0,0xc0,0xc3,0x7e,0x18,0x18,0x00,0x00,0x00,0x00,
+0x00,0x38,0x6c,0x64,0x60,0xf0,0x60,0x60,0x60,0x60,0xe6,0xfc,0x00,0x00,0x00,0x00,
+0x00,0x00,0xc3,0x66,0x3c,0x18,0xff,0x18,0xff,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
+0x00,0xfc,0x66,0x66,0x7c,0x62,0x66,0x6f,0x66,0x66,0x66,0xf3,0x00,0x00,0x00,0x00,
+0x00,0x0e,0x1b,0x18,0x18,0x18,0x7e,0x18,0x18,0x18,0x18,0x18,0xd8,0x70,0x00,0x00,
+0x00,0x18,0x30,0x60,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
+0x00,0x0c,0x18,0x30,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
+0x00,0x18,0x30,0x60,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
+0x00,0x18,0x30,0x60,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
+0x00,0x00,0x76,0xdc,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,
+0x76,0xdc,0x00,0xc6,0xe6,0xf6,0xfe,0xde,0xce,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00,
+0x00,0x3c,0x6c,0x6c,0x3e,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x38,0x6c,0x6c,0x38,0x00,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x30,0x30,0x00,0x30,0x30,0x60,0xc0,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00,
+0x00,0xc0,0xc0,0xc2,0xc6,0xcc,0x18,0x30,0x60,0xce,0x9b,0x06,0x0c,0x1f,0x00,0x00,
+0x00,0xc0,0xc0,0xc2,0xc6,0xcc,0x18,0x30,0x66,0xce,0x96,0x3e,0x06,0x06,0x00,0x00,
+0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x18,0x3c,0x3c,0x3c,0x18,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x36,0x6c,0xd8,0x6c,0x36,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xd8,0x6c,0x36,0x6c,0xd8,0x00,0x00,0x00,0x00,0x00,0x00,
+0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,
+0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,
+0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+0x00,0x00,0x00,0x00,0x00,0xf8,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+0x36,0x36,0x36,0x36,0x36,0xf6,0x06,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+0x00,0x00,0x00,0x00,0x00,0xfe,0x06,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+0x36,0x36,0x36,0x36,0x36,0xf6,0x06,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x3f,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+0x36,0x36,0x36,0x36,0x36,0xf7,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xf7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x36,0x36,0x36,0x36,0x36,0xf7,0x00,0xf7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+0x18,0x18,0x18,0x18,0x18,0xff,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x1f,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xff,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+0x18,0x18,0x18,0x18,0x18,0xff,0x18,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,
+0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x76,0xdc,0xd8,0xd8,0xd8,0xdc,0x76,0x00,0x00,0x00,0x00,
+0x00,0x00,0x78,0xcc,0xcc,0xcc,0xd8,0xcc,0xc6,0xc6,0xc6,0xcc,0x00,0x00,0x00,0x00,
+0x00,0x00,0xfe,0xc6,0xc6,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0xfe,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0xfe,0xc6,0x60,0x30,0x18,0x30,0x60,0xc6,0xfe,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x7e,0xd8,0xd8,0xd8,0xd8,0xd8,0x70,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x7c,0x60,0x60,0xc0,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x76,0xdc,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x7e,0x18,0x3c,0x66,0x66,0x66,0x3c,0x18,0x7e,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0x6c,0x38,0x00,0x00,0x00,0x00,
+0x00,0x00,0x38,0x6c,0xc6,0xc6,0xc6,0x6c,0x6c,0x6c,0x6c,0xee,0x00,0x00,0x00,0x00,
+0x00,0x00,0x1e,0x30,0x18,0x0c,0x3e,0x66,0x66,0x66,0x66,0x3c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x7e,0xdb,0xdb,0xdb,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x03,0x06,0x7e,0xdb,0xdb,0xf3,0x7e,0x60,0xc0,0x00,0x00,0x00,0x00,
+0x00,0x00,0x1c,0x30,0x60,0x60,0x7c,0x60,0x60,0x60,0x30,0x1c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0xfe,0x00,0x00,0xfe,0x00,0x00,0xfe,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00,0xff,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x30,0x18,0x0c,0x06,0x0c,0x18,0x30,0x00,0x7e,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x0c,0x18,0x30,0x60,0x30,0x18,0x0c,0x00,0x7e,0x00,0x00,0x00,0x00,
+0x00,0x00,0x0e,0x1b,0x1b,0x1b,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xd8,0xd8,0xd8,0x70,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x7e,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x76,0xdc,0x00,0x76,0xdc,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x38,0x6c,0x6c,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x0f,0x0c,0x0c,0x0c,0x0c,0x0c,0xec,0x6c,0x6c,0x3c,0x1c,0x00,0x00,0x00,0x00,
+0x00,0xd8,0x6c,0x6c,0x6c,0x6c,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x70,0xd8,0x30,0x60,0xc8,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+};
+int default8x16FontMetaData[256*5+1]={
+0,8,16,0,0,16,8,16,0,0,32,8,16,0,0,48,8,16,0,0,64,8,16,0,0,80,8,16,0,0,96,8,16,0,0,112,8,16,0,0,128,8,16,0,0,144,8,16,0,0,160,8,16,0,0,176,8,16,0,0,192,8,16,0,0,208,8,16,0,0,224,8,16,0,0,240,8,16,0,0,256,8,16,0,0,272,8,16,0,0,288,8,16,0,0,304,8,16,0,0,320,8,16,0,0,336,8,16,0,0,352,8,16,0,0,368,8,16,0,0,384,8,16,0,0,400,8,16,0,0,416,8,16,0,0,432,8,16,0,0,448,8,16,0,0,464,8,16,0,0,480,8,16,0,0,496,8,16,0,0,512,8,16,0,0,528,8,16,0,0,544,8,16,0,0,560,8,16,0,0,576,8,16,0,0,592,8,16,0,0,608,8,16,0,0,624,8,16,0,0,640,8,16,0,0,656,8,16,0,0,672,8,16,0,0,688,8,16,0,0,704,8,16,0,0,720,8,16,0,0,736,8,16,0,0,752,8,16,0,0,768,8,16,0,0,784,8,16,0,0,800,8,16,0,0,816,8,16,0,0,832,8,16,0,0,848,8,16,0,0,864,8,16,0,0,880,8,16,0,0,896,8,16,0,0,912,8,16,0,0,928,8,16,0,0,944,8,16,0,0,960,8,16,0,0,976,8,16,0,0,992,8,16,0,0,1008,8,16,0,0,1024,8,16,0,0,1040,8,16,0,0,1056,8,16,0,0,1072,8,16,0,0,1088,8,16,0,0,1104,8,16,0,0,1120,8,16,0,0,1136,8,16,0,0,1152,8,16,0,0,1168,8,16,0,0,1184,8,16,0,0,1200,8,16,0,0,1216,8,16,0,0,1232,8,16,0,0,1248,8,16,0,0,1264,8,16,0,0,1280,8,16,0,0,1296,8,16,0,0,1312,8,16,0,0,1328,8,16,0,0,1344,8,16,0,0,1360,8,16,0,0,1376,8,16,0,0,1392,8,16,0,0,1408,8,16,0,0,1424,8,16,0,0,1440,8,16,0,0,1456,8,16,0,0,1472,8,16,0,0,1488,8,16,0,0,1504,8,16,0,0,1520,8,16,0,0,1536,8,16,0,0,1552,8,16,0,0,1568,8,16,0,0,1584,8,16,0,0,1600,8,16,0,0,1616,8,16,0,0,1632,8,16,0,0,1648,8,16,0,0,1664,8,16,0,0,1680,8,16,0,0,1696,8,16,0,0,1712,8,16,0,0,1728,8,16,0,0,1744,8,16,0,0,1760,8,16,0,0,1776,8,16,0,0,1792,8,16,0,0,1808,8,16,0,0,1824,8,16,0,0,1840,8,16,0,0,1856,8,16,0,0,1872,8,16,0,0,1888,8,16,0,0,1904,8,16,0,0,1920,8,16,0,0,1936,8,16,0,0,1952,8,16,0,0,1968,8,16,0,0,1984,8,16,0,0,2000,8,16,0,0,2016,8,16,0,0,2032,8,16,0,0,2048,8,16,0,0,2064,8,16,0,0,2080,8,16,0,0,2096,8,16,0,0,2112,8,16,0,0,2128,8,16,0,0,2144,8,16,0,0,2160,8,16,0,0,2176,8,16,0,0,2192,8,16,0,0,2208,8,16,0,0,2224,8,16,0,0,2240,8,16,0,0,2256,8,16,0,0,2272,8,16,0,0,2288,8,16,0,0,2304,8,16,0,0,2320,8,16,0,0,2336,8,16,0,0,2352,8,16,0,0,2368,8,16,0,0,2384,8,16,0,0,2400,8,16,0,0,2416,8,16,0,0,2432,8,16,0,0,2448,8,16,0,0,2464,8,16,0,0,2480,8,16,0,0,2496,8,16,0,0,2512,8,16,0,0,2528,8,16,0,0,2544,8,16,0,0,2560,8,16,0,0,2576,8,16,0,0,2592,8,16,0,0,2608,8,16,0,0,2624,8,16,0,0,2640,8,16,0,0,2656,8,16,0,0,2672,8,16,0,0,2688,8,16,0,0,2704,8,16,0,0,2720,8,16,0,0,2736,8,16,0,0,2752,8,16,0,0,2768,8,16,0,0,2784,8,16,0,0,2800,8,16,0,0,2816,8,16,0,0,2832,8,16,0,0,2848,8,16,0,0,2864,8,16,0,0,2880,8,16,0,0,2896,8,16,0,0,2912,8,16,0,0,2928,8,16,0,0,2944,8,16,0,0,2960,8,16,0,0,2976,8,16,0,0,2992,8,16,0,0,3008,8,16,0,0,3024,8,16,0,0,3040,8,16,0,0,3056,8,16,0,0,3072,8,16,0,0,3088,8,16,0,0,3104,8,16,0,0,3120,8,16,0,0,3136,8,16,0,0,3152,8,16,0,0,3168,8,16,0,0,3184,8,16,0,0,3200,8,16,0,0,3216,8,16,0,0,3232,8,16,0,0,3248,8,16,0,0,3264,8,16,0,0,3280,8,16,0,0,3296,8,16,0,0,3312,8,16,0,0,3328,8,16,0,0,3344,8,16,0,0,3360,8,16,0,0,3376,8,16,0,0,3392,8,16,0,0,3408,8,16,0,0,3424,8,16,0,0,3440,8,16,0,0,3456,8,16,0,0,3472,8,16,0,0,3488,8,16,0,0,3504,8,16,0,0,3520,8,16,0,0,3536,8,16,0,0,3552,8,16,0,0,3568,8,16,0,0,3584,8,16,0,0,3600,8,16,0,0,3616,8,16,0,0,3632,8,16,0,0,3648,8,16,0,0,3664,8,16,0,0,3680,8,16,0,0,3696,8,16,0,0,3712,8,16,0,0,3728,8,16,0,0,3744,8,16,0,0,3760,8,16,0,0,3776,8,16,0,0,3792,8,16,0,0,3808,8,16,0,0,3824,8,16,0,0,3840,8,16,0,0,3856,8,16,0,0,3872,8,16,0,0,3888,8,16,0,0,3904,8,16,0,0,3920,8,16,0,0,3936,8,16,0,0,3952,8,16,0,0,3968,8,16,0,0,3984,8,16,0,0,4000,8,16,0,0,4016,8,16,0,0,4032,8,16,0,0,4048,8,16,0,0,4064,8,16,0,0,4080,8,16,0,0,};
+rfbFontData default8x16Font = { default8x16FontData, default8x16FontMetaData };
diff --git a/krfb/libvncserver/draw.c b/krfb/libvncserver/draw.c
new file mode 100644
index 00000000..24c41bd4
--- /dev/null
+++ b/krfb/libvncserver/draw.c
@@ -0,0 +1,61 @@
+#include "rfb.h"
+
+void rfbFillRect(rfbScreenInfoPtr s,int x1,int y1,int x2,int y2,Pixel col)
+{
+ int rowstride = s->paddedWidthInBytes, bpp = s->bitsPerPixel>>3;
+ int i,j;
+ char* colour=(char*)&col;
+
+ if(!rfbEndianTest)
+ colour += 4-bpp;
+ for(j=y1;j<y2;j++)
+ for(i=x1;i<x2;i++)
+ memcpy(s->frameBuffer+j*rowstride+i*bpp,colour,bpp);
+ rfbMarkRectAsModified(s,x1,y1,x2,y2);
+}
+
+#define SETPIXEL(x,y) \
+ memcpy(s->frameBuffer+(y)*rowstride+(x)*bpp,colour,bpp)
+
+void rfbDrawPixel(rfbScreenInfoPtr s,int x,int y,Pixel col)
+{
+ int rowstride = s->paddedWidthInBytes, bpp = s->bitsPerPixel>>3;
+ char* colour=(char*)&col;
+
+ if(!rfbEndianTest)
+ colour += 4-bpp;
+ SETPIXEL(x,y);
+ rfbMarkRectAsModified(s,x,y,x+1,y+1);
+}
+
+void rfbDrawLine(rfbScreenInfoPtr s,int x1,int y1,int x2,int y2,Pixel col)
+{
+ int rowstride = s->paddedWidthInBytes, bpp = s->bitsPerPixel>>3;
+ int i;
+ char* colour=(char*)&col;
+
+ if(!rfbEndianTest)
+ colour += 4-bpp;
+
+#define SWAPPOINTS { i=x1; x1=x2; x2=i; i=y1; y1=y2; y2=i; }
+ if(abs(x1-x2)<abs(y1-y2)) {
+ if(y1>y2)
+ SWAPPOINTS
+ for(i=y1;i<=y2;i++)
+ SETPIXEL(x1+(i-y1)*(x2-x1)/(y2-y1),i);
+ /* TODO: Maybe make this more intelligently? */
+ if(x2<x1) { i=x1; x1=x2; x2=i; }
+ rfbMarkRectAsModified(s,x1,y1,x2+1,y2+1);
+ } else {
+ if(x1>x2)
+ SWAPPOINTS
+ else if(x1==x2) {
+ rfbDrawPixel(s,x1,y1,col);
+ return;
+ }
+ for(i=x1;i<=x2;i++)
+ SETPIXEL(i,y1+(i-x1)*(y2-y1)/(x2-x1));
+ if(y2<y1) { i=y1; y1=y2; y2=i; }
+ rfbMarkRectAsModified(s,x1,y1,x2+1,y2+1);
+ }
+}
diff --git a/krfb/libvncserver/example.c b/krfb/libvncserver/example.c
new file mode 100644
index 00000000..41165c7b
--- /dev/null
+++ b/krfb/libvncserver/example.c
@@ -0,0 +1,279 @@
+/*
+ *
+ * This is an example of how to use libvncserver.
+ *
+ * libvncserver example
+ * Copyright (C) 2001 Johannes E. Schindelin <Johannes.Schindelin@gmx.de>
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#ifdef WIN32
+#define sleep Sleep
+#else
+#include <unistd.h>
+#endif
+
+#ifdef __IRIX__
+#include <netdb.h>
+#endif
+
+#include "rfb.h"
+#include "keysym.h"
+
+const int maxx=640, maxy=480, bpp=4;
+/* TODO: odd maxx doesn't work (vncviewer bug) */
+
+/* This initializes a nice (?) background */
+
+void initBuffer(unsigned char* buffer)
+{
+ int i,j;
+ for(j=0;j<maxy;++j) {
+ for(i=0;i<maxx;++i) {
+ buffer[(j*maxx+i)*bpp+0]=(i+j)*128/(maxx+maxy); /* red */
+ buffer[(j*maxx+i)*bpp+1]=i*128/maxx; /* green */
+ buffer[(j*maxx+i)*bpp+2]=j*256/maxy; /* blue */
+ }
+ buffer[j*maxx*bpp+0]=0xff;
+ buffer[j*maxx*bpp+1]=0xff;
+ buffer[j*maxx*bpp+2]=0xff;
+ buffer[j*maxx*bpp+3]=0xff;
+ }
+}
+
+/* Here we create a structure so that every client has it's own pointer */
+
+typedef struct ClientData {
+ Bool oldButton;
+ int oldx,oldy;
+} ClientData;
+
+void clientgone(rfbClientPtr cl)
+{
+ free(cl->clientData);
+}
+
+enum rfbNewClientAction newclient(rfbClientPtr cl)
+{
+ cl->clientData = (void*)calloc(sizeof(ClientData),1);
+ cl->clientGoneHook = clientgone;
+ return RFB_CLIENT_ACCEPT;
+}
+
+/* aux function to draw a line */
+
+void drawline(unsigned char* buffer,int rowstride,int bpp,int x1,int y1,int x2,int y2)
+{
+ int i,j;
+ i=x1-x2; j=y1-y2;
+ if(i==0 && j==0) {
+ for(i=0;i<bpp;i++)
+ buffer[y1*rowstride+x1*bpp+i]=0xff;
+ return;
+ }
+ if(i<0) i=-i;
+ if(j<0) j=-j;
+ if(i<j) {
+ if(y1>y2) { i=y2; y2=y1; y1=i; i=x2; x2=x1; x1=i; }
+ if(y2==y1) { if(y2>0) y1--; else y2++; }
+ for(j=y1;j<=y2;j++)
+ for(i=0;i<bpp;i++)
+ buffer[j*rowstride+(x1+(j-y1)*(x2-x1)/(y2-y1))*bpp+i]=0xff;
+ } else {
+ if(x1>x2) { i=y2; y2=y1; y1=i; i=x2; x2=x1; x1=i; }
+ for(i=x1;i<=x2;i++)
+ for(j=0;j<bpp;j++)
+ buffer[(y1+(i-x1)*(y2-y1)/(x2-x1))*rowstride+i*bpp+j]=0xff;
+ }
+}
+
+/* Here the pointer events are handled */
+
+void doptr(int buttonMask,int x,int y,rfbClientPtr cl)
+{
+ ClientData* cd=cl->clientData;
+
+ if(cl->screen->cursorIsDrawn)
+ rfbUndrawCursor(cl->screen);
+
+ if(x>=0 && y>=0 && x<maxx && y<maxy) {
+ if(buttonMask) {
+ int i,j,x1,x2,y1,y2;
+
+ if(cd->oldButton==buttonMask) { /* draw a line */
+ drawline(cl->screen->frameBuffer,cl->screen->paddedWidthInBytes,bpp,
+ x,y,cd->oldx,cd->oldy);
+ rfbMarkRectAsModified(cl->screen,x,y,cd->oldx,cd->oldy);
+ } else { /* draw a point (diameter depends on button) */
+ int w=cl->screen->paddedWidthInBytes;
+ x1=x-buttonMask; if(x1<0) x1=0;
+ x2=x+buttonMask; if(x2>maxx) x2=maxx;
+ y1=y-buttonMask; if(y1<0) y1=0;
+ y2=y+buttonMask; if(y2>maxy) y2=maxy;
+
+ for(i=x1*bpp;i<x2*bpp;i++)
+ for(j=y1;j<y2;j++)
+ cl->screen->frameBuffer[j*w+i]=(char)0xff;
+ rfbMarkRectAsModified(cl->screen,x1,y1,x2-1,y2-1);
+ }
+
+ /* we could get a selection like that:
+ rfbGotXCutText(cl->screen,"Hallo",5);
+ */
+ } else
+ cd->oldButton=0;
+
+ cd->oldx=x; cd->oldy=y; cd->oldButton=buttonMask;
+ }
+ defaultPtrAddEvent(buttonMask,x,y,cl);
+}
+
+/* aux function to draw a character to x, y */
+
+#include "radon.h"
+
+/* Here the key events are handled */
+
+void dokey(Bool down,KeySym key,rfbClientPtr cl)
+{
+ if(down) {
+ if(key==XK_Escape)
+ rfbCloseClient(cl);
+ else if(key==XK_Page_Up) {
+ if(cl->screen->cursorIsDrawn)
+ rfbUndrawCursor(cl->screen);
+ initBuffer(cl->screen->frameBuffer);
+ rfbMarkRectAsModified(cl->screen,0,0,maxx,maxy);
+ } else if(key>=' ' && key<0x100) {
+ ClientData* cd=cl->clientData;
+ int x1=cd->oldx,y1=cd->oldy,x2,y2;
+ if(cl->screen->cursorIsDrawn)
+ rfbUndrawCursor(cl->screen);
+ cd->oldx+=rfbDrawChar(cl->screen,&radonFont,cd->oldx,cd->oldy,(char)key,0x00ffffff);
+ rfbFontBBox(&radonFont,(char)key,&x1,&y1,&x2,&y2);
+ rfbMarkRectAsModified(cl->screen,x1,y1,x2-1,y2-1);
+ }
+ }
+}
+
+/* Example for an XCursor (foreground/background only) */
+
+int exampleXCursorWidth=9,exampleXCursorHeight=7;
+char exampleXCursor[]=
+ " "
+ " xx xx "
+ " xx xx "
+ " xxx "
+ " xx xx "
+ " xx xx "
+ " ";
+
+/* Example for a rich cursor (full-colour) */
+
+void MakeRichCursor(rfbScreenInfoPtr rfbScreen)
+{
+ int i,j,w=32,h=32;
+ rfbCursorPtr c = rfbScreen->cursor;
+ char bitmap[]=
+ " "
+ " xxxxxx "
+ " xxxxxxxxxxxxxxxxx "
+ " xxxxxxxxxxxxxxxxxxxxxx "
+ " xxxxx xxxxxxxx xxxxxxxx "
+ " xxxxxxxxxxxxxxxxxxxxxxxxxxx "
+ " xxxxxxxxxxxxxxxxxxxxxxxxxxxxx "
+ " xxxxx xxxxxxxxxxx xxxxxxx "
+ " xxxx xxxxxxxxx xxxxxx "
+ " xxxxx xxxxxxxxxxx xxxxxxx "
+ " xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx "
+ " xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx "
+ " xxxxxxxxxxxx xxxxxxxxxxxxxxx "
+ " xxxxxxxxxxxxxxxxxxxxxxxxxxxx "
+ " xxxxxxxxxxxxxxxxxxxxxxxxxxxx "
+ " xxxxxxxxxxx xxxxxxxxxxxxxx "
+ " xxxxxxxxxx xxxxxxxxxxxx "
+ " xxxxxxxxx xxxxxxxxx "
+ " xxxxxxxxxx xxxxxxxxx "
+ " xxxxxxxxxxxxxxxxxxx "
+ " xxxxxxxxxxxxxxxxxxx "
+ " xxxxxxxxxxxxxxxxxxx "
+ " xxxxxxxxxxxxxxxxx "
+ " xxxxxxxxxxxxxxx "
+ " xxxx xxxxxxxxxxxxx "
+ " xx x xxxxxxxxxxx "
+ " xxx xxxxxxxxxxx "
+ " xxxx xxxxxxxxxxx "
+ " xxxxxx xxxxxxxxxxxx "
+ " xxxxxxxxxxxxxxxxxxxxxx "
+ " xxxxxxxxxxxxxxxx "
+ " ";
+ c=rfbScreen->cursor = rfbMakeXCursor(w,h,bitmap,bitmap);
+ c->xhot = 16; c->yhot = 24;
+
+ c->richSource = malloc(w*h*bpp);
+ for(j=0;j<h;j++) {
+ for(i=0;i<w;i++) {
+ c->richSource[j*w*bpp+i*bpp+0]=i*0xff/w;
+ c->richSource[j*w*bpp+i*bpp+1]=(i+j)*0xff/(w+h);
+ c->richSource[j*w*bpp+i*bpp+2]=j*0xff/h;
+ c->richSource[j*w*bpp+i*bpp+3]=0;
+ }
+ }
+}
+
+/* Initialization */
+
+int main(int argc,char** argv)
+{
+ rfbScreenInfoPtr rfbScreen =
+ rfbGetScreen(&argc,argv,maxx,maxy,8,3,bpp);
+ rfbScreen->desktopName = "LibVNCServer Example";
+ rfbScreen->frameBuffer = (char*)malloc(maxx*maxy*bpp);
+ rfbScreen->rfbAlwaysShared = TRUE;
+ rfbScreen->ptrAddEvent = doptr;
+ rfbScreen->kbdAddEvent = dokey;
+ rfbScreen->newClientHook = newclient;
+ rfbScreen->httpDir = "./classes";
+
+ initBuffer(rfbScreen->frameBuffer);
+ rfbDrawString(rfbScreen,&radonFont,20,100,"Hello, World!",0xffffff);
+
+ /* This call creates a mask and then a cursor: */
+ /* rfbScreen->defaultCursor =
+ rfbMakeXCursor(exampleCursorWidth,exampleCursorHeight,exampleCursor,0);
+ */
+
+ MakeRichCursor(rfbScreen);
+
+ /* initialize the server */
+ rfbInitServer(rfbScreen);
+
+#ifndef BACKGROUND_LOOP_TEST
+ /* this is the blocking event loop, i.e. it never returns */
+ /* 40000 are the microseconds, i.e. 0.04 seconds */
+ rfbRunEventLoop(rfbScreen,40000,FALSE);
+#elif !defined(HAVE_PTHREADS)
+#error "I need pthreads for that."
+#endif
+
+ /* this is the non-blocking event loop; a background thread is started */
+ rfbRunEventLoop(rfbScreen,-1,TRUE);
+ /* now we could do some cool things like rendering */
+ while(1) sleep(5); /* render(); */
+
+ return(0);
+}
diff --git a/krfb/libvncserver/font.c b/krfb/libvncserver/font.c
new file mode 100644
index 00000000..b9d68d0f
--- /dev/null
+++ b/krfb/libvncserver/font.c
@@ -0,0 +1,192 @@
+#include "rfb.h"
+
+int rfbDrawChar(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,
+ int x,int y,unsigned char c,Pixel col)
+{
+ int i,j,width,height;
+ unsigned char* data=font->data+font->metaData[c*5];
+ unsigned char d=*data;
+ int rowstride=rfbScreen->paddedWidthInBytes;
+ int bpp=rfbScreen->rfbServerFormat.bitsPerPixel/8;
+ char *colour=(char*)&col;
+
+ if(!rfbEndianTest)
+ colour += 4-bpp;
+
+ width=font->metaData[c*5+1];
+ height=font->metaData[c*5+2];
+ x+=font->metaData[c*5+3];
+ y+=-font->metaData[c*5+4]-height+1;
+
+ for(j=0;j<height;j++) {
+ for(i=0;i<width;i++) {
+ if((i&7)==0) {
+ d=*data;
+ data++;
+ }
+ if(d&0x80)
+ memcpy(rfbScreen->frameBuffer+(y+j)*rowstride+(x+i)*bpp,colour,bpp);
+ d<<=1;
+ }
+ /* if((i&7)!=0) data++; */
+ }
+ return(width);
+}
+
+void rfbDrawString(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,
+ int x,int y,const char* string,Pixel colour)
+{
+ while(*string) {
+ x+=rfbDrawChar(rfbScreen,font,x,y,*string,colour);
+ string++;
+ }
+}
+
+/* TODO: these two functions need to be more efficient */
+int rfbDrawCharWithClip(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,
+ int x,int y,unsigned char c,
+ int x1,int y1,int x2,int y2,
+ Pixel col,Pixel bcol)
+{
+ int i,j,width,height;
+ unsigned char* data=font->data+font->metaData[c*5];
+ unsigned char d;
+ int rowstride=rfbScreen->paddedWidthInBytes;
+ int bpp=rfbScreen->rfbServerFormat.bitsPerPixel/8,extra_bytes=0;
+ char* colour=(char*)&col;
+ char* bcolour=(char*)&bcol;
+
+ if(!rfbEndianTest) {
+ colour+=4-bpp;
+ bcolour+=4-bpp;
+ }
+
+ width=font->metaData[c*5+1];
+ height=font->metaData[c*5+2];
+ x+=font->metaData[c*5+3];
+ y+=-font->metaData[c*5+4]-height+1;
+
+ /* after clipping, x2 will be count of bytes between rows,
+ * x1 start of i, y1 start of j, width and height will be adjusted. */
+ if(y1>y) { y1-=y; data+=(width+7)/8; height-=y1; y+=y1; } else y1=0;
+ if(x1>x) { x1-=x; data+=x1; width-=x1; x+=x1; extra_bytes+=x1/8; } else x1=0;
+ if(y2<y+height) height-=y+height-y2;
+ if(x2<x+width) { extra_bytes+=(x1+width)/8-(x+width-x2+7)/8; width-=x+width-x2; }
+
+ d=*data;
+ for(j=y1;j<height;j++) {
+ if((x1&7)!=0)
+ d=data[-1]; /* TODO: check if in this case extra_bytes is correct! */
+ for(i=x1;i<width;i++) {
+ if((i&7)==0) {
+ d=*data;
+ data++;
+ }
+ /* if(x+i>=x1 && x+i<x2 && y+j>=y1 && y+j<y2) */ {
+ if(d&0x80) {
+ memcpy(rfbScreen->frameBuffer+(y+j)*rowstride+(x+i)*bpp,
+ colour,bpp);
+ } else if(bcol!=col) {
+ memcpy(rfbScreen->frameBuffer+(y+j)*rowstride+(x+i)*bpp,
+ bcolour,bpp);
+ }
+ }
+ d<<=1;
+ }
+ /* if((i&7)==0) data++; */
+ data += extra_bytes;
+ }
+ return(width);
+}
+
+void rfbDrawStringWithClip(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,
+ int x,int y,const char* string,
+ int x1,int y1,int x2,int y2,
+ Pixel colour,Pixel backColour)
+{
+ while(*string) {
+ x+=rfbDrawCharWithClip(rfbScreen,font,x,y,*string,x1,y1,x2,y2,
+ colour,backColour);
+ string++;
+ }
+}
+
+int rfbWidthOfString(rfbFontDataPtr font,const char* string)
+{
+ int i=0;
+ while(*string) {
+ i+=font->metaData[*string*5+1];
+ string++;
+ }
+ return(i);
+}
+
+int rfbWidthOfChar(rfbFontDataPtr font,unsigned char c)
+{
+ return(font->metaData[c*5+1]+font->metaData[c*5+3]);
+}
+
+void rfbFontBBox(rfbFontDataPtr font,unsigned char c,int* x1,int* y1,int* x2,int* y2)
+{
+ *x1+=font->metaData[c*5+3];
+ *y1+=-font->metaData[c*5+4]-font->metaData[c*5+2]+1;
+ *x2=*x1+font->metaData[c*5+1];
+ *y2=*y1+font->metaData[c*5+2];
+}
+
+#ifndef INT_MAX
+#define INT_MAX 0x7fffffff
+#endif
+
+void rfbWholeFontBBox(rfbFontDataPtr font,
+ int *x1, int *y1, int *x2, int *y2)
+{
+ int i;
+ int* m=font->metaData;
+
+ (*x1)=(*y1)=INT_MAX; (*x2)=(*y2)=-INT_MAX+1;
+ for(i=0;i<256;i++) {
+ if(m[i*5+1]-m[i*5+3]>(*x2))
+ (*x2)=m[i*5+1]-m[i*5+3];
+ if(-m[i*5+2]+m[i*5+4]<(*y1))
+ (*y1)=-m[i*5+2]+m[i*5+4];
+ if(m[i*5+3]<(*x1))
+ (*x1)=m[i*5+3];
+ if(-m[i*5+4]>(*y2))
+ (*y2)=-m[i*5+4];
+ }
+}
+
+rfbFontDataPtr rfbLoadConsoleFont(char *filename)
+{
+ FILE *f=fopen(filename,"rb");
+ rfbFontDataPtr p;
+ int i;
+
+ if(!f) return(0);
+
+ p=(rfbFontDataPtr)malloc(sizeof(rfbFontData));
+ p->data=(unsigned char*)malloc(4096);
+ if(1!=fread(p->data,4096,1,f)) {
+ free(p->data);
+ free(p);
+ return(0);
+ }
+ fclose(f);
+ p->metaData=(int*)malloc(256*5*sizeof(int));
+ for(i=0;i<256;i++) {
+ p->metaData[i*5+0]=i*16; /* offset */
+ p->metaData[i*5+1]=8; /* width */
+ p->metaData[i*5+2]=16; /* height */
+ p->metaData[i*5+3]=0; /* xhot */
+ p->metaData[i*5+4]=0; /* yhot */
+ }
+ return(p);
+}
+
+void rfbFreeFont(rfbFontDataPtr f)
+{
+ free(f->data);
+ free(f->metaData);
+ free(f);
+}
diff --git a/krfb/libvncserver/fontsel.c b/krfb/libvncserver/fontsel.c
new file mode 100644
index 00000000..100db817
--- /dev/null
+++ b/krfb/libvncserver/fontsel.c
@@ -0,0 +1,71 @@
+#include "rfb.h"
+
+#define FONTDIR "/usr/lib/kbd/consolefonts/"
+#define DEFAULTFONT FONTDIR "default8x16"
+
+char *fontlist[50]={
+"8x16alt", "b.fnt", "c.fnt", "default8x16", "m.fnt", "ml.fnt", "mod_d.fnt",
+"mod_s.fnt", "mr.fnt", "mu.fnt", "r.fnt", "rl.fnt", "ro.fnt", "s.fnt",
+"sc.fnt", "scrawl_s.fnt", "scrawl_w.fnt", "sd.fnt", "t.fnt",
+ 0
+};
+
+rfbScreenInfoPtr rfbScreen = 0;
+rfbFontDataPtr curFont = 0;
+void showFont(int index)
+{
+ char buffer[1024];
+
+ if(!rfbScreen) return;
+
+ if(curFont)
+ rfbFreeFont(curFont);
+
+ strcpy(buffer,FONTDIR);
+ strcat(buffer,fontlist[index]);
+ curFont = rfbLoadConsoleFont(buffer);
+
+ rfbFillRect(rfbScreen,210,30-20,210+10*16,30-20+256*20/16,0xb77797);
+ if(curFont) {
+ int i,j;
+ for(j=0;j<256;j+=16)
+ for(i=0;i<16;i++)
+ rfbDrawCharWithClip(rfbScreen,curFont,210+10*i,30+j*20/16,j+i,
+ 0,0,640,480,0xffffff,0x000000);
+ }
+}
+
+int main(int argc,char** argv)
+{
+ rfbFontDataPtr font;
+ rfbScreenInfoPtr s=rfbGetScreen(&argc,argv,640,480,8,3,3);
+ int i,j;
+
+ s->frameBuffer=(char*)malloc(640*480*3);
+ rfbInitServer(s);
+
+ for(j=0;j<480;j++)
+ for(i=0;i<640;i++) {
+ s->frameBuffer[(j*640+i)*3+0]=j*256/480;
+ s->frameBuffer[(j*640+i)*3+1]=i*256/640;
+ s->frameBuffer[(j*640+i)*3+2]=(i+j)*256/(480+640);
+ }
+
+ rfbScreen = s;
+ font=rfbLoadConsoleFont(DEFAULTFONT);
+ if(!font) {
+ fprintf(stderr,"Couldn't find %s\n",DEFAULTFONT);
+ exit(1);
+ }
+
+ for(j=0;j<0;j++)
+ rfbProcessEvents(s,900000);
+
+ i = rfbSelectBox(s,font,fontlist,10,20,200,300,0xffdfdf,0x602040,2,showFont);
+ fprintf(stderr,"Selection: %d: %s\n",i,(i>=0)?fontlist[i]:"cancelled");
+
+ rfbFreeFont(font);
+
+ return(0);
+}
+
diff --git a/krfb/libvncserver/hextile.c b/krfb/libvncserver/hextile.c
new file mode 100644
index 00000000..6166844e
--- /dev/null
+++ b/krfb/libvncserver/hextile.c
@@ -0,0 +1,347 @@
+/*
+ * hextile.c
+ *
+ * Routines to implement Hextile Encoding
+ */
+
+/*
+ * OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
+ * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
+ * All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include <stdio.h>
+#include "rfb.h"
+
+static Bool sendHextiles8(rfbClientPtr cl, int x, int y, int w, int h);
+static Bool sendHextiles16(rfbClientPtr cl, int x, int y, int w, int h);
+static Bool sendHextiles32(rfbClientPtr cl, int x, int y, int w, int h);
+
+
+/*
+ * rfbSendRectEncodingHextile - send a rectangle using hextile encoding.
+ */
+
+Bool
+rfbSendRectEncodingHextile(cl, x, y, w, h)
+ rfbClientPtr cl;
+ int x, y, w, h;
+{
+ rfbFramebufferUpdateRectHeader rect;
+
+ if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ rect.r.x = Swap16IfLE(x);
+ rect.r.y = Swap16IfLE(y);
+ rect.r.w = Swap16IfLE(w);
+ rect.r.h = Swap16IfLE(h);
+ rect.encoding = Swap32IfLE(rfbEncodingHextile);
+
+ memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
+ sz_rfbFramebufferUpdateRectHeader);
+ cl->ublen += sz_rfbFramebufferUpdateRectHeader;
+
+ cl->rfbRectanglesSent[rfbEncodingHextile]++;
+ cl->rfbBytesSent[rfbEncodingHextile] += sz_rfbFramebufferUpdateRectHeader;
+
+ switch (cl->format.bitsPerPixel) {
+ case 8:
+ return sendHextiles8(cl, x, y, w, h);
+ case 16:
+ return sendHextiles16(cl, x, y, w, h);
+ case 32:
+ return sendHextiles32(cl, x, y, w, h);
+ }
+
+ rfbLog("rfbSendRectEncodingHextile: bpp %d?\n", cl->format.bitsPerPixel);
+ return FALSE;
+}
+
+
+#define PUT_PIXEL8(pix) (cl->updateBuf[cl->ublen++] = (pix))
+
+#define PUT_PIXEL16(pix) (cl->updateBuf[cl->ublen++] = ((char*)&(pix))[0], \
+ cl->updateBuf[cl->ublen++] = ((char*)&(pix))[1])
+
+#define PUT_PIXEL32(pix) (cl->updateBuf[cl->ublen++] = ((char*)&(pix))[0], \
+ cl->updateBuf[cl->ublen++] = ((char*)&(pix))[1], \
+ cl->updateBuf[cl->ublen++] = ((char*)&(pix))[2], \
+ cl->updateBuf[cl->ublen++] = ((char*)&(pix))[3])
+
+
+#define DEFINE_SEND_HEXTILES(bpp) \
+ \
+ \
+static Bool subrectEncode##bpp(rfbClientPtr cli, CARD##bpp *data, int w, int h, \
+ CARD##bpp bg, CARD##bpp fg, Bool mono); \
+static void testColours##bpp(CARD##bpp *data, int size, Bool *mono, \
+ Bool *solid, CARD##bpp *bg, CARD##bpp *fg); \
+ \
+ \
+/* \
+ * rfbSendHextiles \
+ */ \
+ \
+static Bool \
+sendHextiles##bpp(cl, rx, ry, rw, rh) \
+ rfbClientPtr cl; \
+ int rx, ry, rw, rh; \
+{ \
+ int x, y, w, h; \
+ int startUblen; \
+ char *fbptr; \
+ CARD##bpp bg = 0, fg = 0, newBg, newFg; \
+ Bool mono, solid; \
+ Bool validBg = FALSE; \
+ Bool validFg = FALSE; \
+ CARD##bpp clientPixelData[16*16*(bpp/8)]; \
+ \
+ for (y = ry; y < ry+rh; y += 16) { \
+ for (x = rx; x < rx+rw; x += 16) { \
+ w = h = 16; \
+ if (rx+rw - x < 16) \
+ w = rx+rw - x; \
+ if (ry+rh - y < 16) \
+ h = ry+rh - y; \
+ \
+ if ((cl->ublen + 1 + (2 + 16 * 16) * (bpp/8)) > \
+ UPDATE_BUF_SIZE) { \
+ if (!rfbSendUpdateBuf(cl)) \
+ return FALSE; \
+ } \
+ \
+ fbptr = (cl->screen->frameBuffer + (cl->screen->paddedWidthInBytes * y) \
+ + (x * (cl->screen->bitsPerPixel / 8))); \
+ \
+ (*cl->translateFn)(cl->translateLookupTable, &(cl->screen->rfbServerFormat), \
+ &cl->format, fbptr, (char *)clientPixelData, \
+ cl->screen->paddedWidthInBytes, w, h); \
+ \
+ startUblen = cl->ublen; \
+ cl->updateBuf[startUblen] = 0; \
+ cl->ublen++; \
+ \
+ testColours##bpp(clientPixelData, w * h, \
+ &mono, &solid, &newBg, &newFg); \
+ \
+ if (!validBg || (newBg != bg)) { \
+ validBg = TRUE; \
+ bg = newBg; \
+ cl->updateBuf[startUblen] |= rfbHextileBackgroundSpecified; \
+ PUT_PIXEL##bpp(bg); \
+ } \
+ \
+ if (solid) { \
+ cl->rfbBytesSent[rfbEncodingHextile] += cl->ublen - startUblen; \
+ continue; \
+ } \
+ \
+ cl->updateBuf[startUblen] |= rfbHextileAnySubrects; \
+ \
+ if (mono) { \
+ if (!validFg || (newFg != fg)) { \
+ validFg = TRUE; \
+ fg = newFg; \
+ cl->updateBuf[startUblen] |= rfbHextileForegroundSpecified; \
+ PUT_PIXEL##bpp(fg); \
+ } \
+ } else { \
+ validFg = FALSE; \
+ cl->updateBuf[startUblen] |= rfbHextileSubrectsColoured; \
+ } \
+ \
+ if (!subrectEncode##bpp(cl, clientPixelData, w, h, bg, fg, mono)) { \
+ /* encoding was too large, use raw */ \
+ validBg = FALSE; \
+ validFg = FALSE; \
+ cl->ublen = startUblen; \
+ cl->updateBuf[cl->ublen++] = rfbHextileRaw; \
+ (*cl->translateFn)(cl->translateLookupTable, \
+ &(cl->screen->rfbServerFormat), &cl->format, fbptr, \
+ (char *)clientPixelData, \
+ cl->screen->paddedWidthInBytes, w, h); \
+ \
+ memcpy(&cl->updateBuf[cl->ublen], (char *)clientPixelData, \
+ w * h * (bpp/8)); \
+ \
+ cl->ublen += w * h * (bpp/8); \
+ } \
+ \
+ cl->rfbBytesSent[rfbEncodingHextile] += cl->ublen - startUblen; \
+ } \
+ } \
+ \
+ return TRUE; \
+} \
+ \
+ \
+static Bool \
+subrectEncode##bpp(rfbClientPtr cl, CARD##bpp *data, int w, int h, \
+ CARD##bpp bg, CARD##bpp fg, Bool mono) \
+{ \
+ CARD##bpp cl2; \
+ int x,y; \
+ int i,j; \
+ int hx=0,hy,vx=0,vy; \
+ int hyflag; \
+ CARD##bpp *seg; \
+ CARD##bpp *line; \
+ int hw,hh,vw,vh; \
+ int thex,they,thew,theh; \
+ int numsubs = 0; \
+ int newLen; \
+ int nSubrectsUblen; \
+ \
+ nSubrectsUblen = cl->ublen; \
+ cl->ublen++; \
+ \
+ for (y=0; y<h; y++) { \
+ line = data+(y*w); \
+ for (x=0; x<w; x++) { \
+ if (line[x] != bg) { \
+ cl2 = line[x]; \
+ hy = y-1; \
+ hyflag = 1; \
+ for (j=y; j<h; j++) { \
+ seg = data+(j*w); \
+ if (seg[x] != cl2) {break;} \
+ i = x; \
+ while ((seg[i] == cl2) && (i < w)) i += 1; \
+ i -= 1; \
+ if (j == y) vx = hx = i; \
+ if (i < vx) vx = i; \
+ if ((hyflag > 0) && (i >= hx)) { \
+ hy += 1; \
+ } else { \
+ hyflag = 0; \
+ } \
+ } \
+ vy = j-1; \
+ \
+ /* We now have two possible subrects: (x,y,hx,hy) and \
+ * (x,y,vx,vy). We'll choose the bigger of the two. \
+ */ \
+ hw = hx-x+1; \
+ hh = hy-y+1; \
+ vw = vx-x+1; \
+ vh = vy-y+1; \
+ \
+ thex = x; \
+ they = y; \
+ \
+ if ((hw*hh) > (vw*vh)) { \
+ thew = hw; \
+ theh = hh; \
+ } else { \
+ thew = vw; \
+ theh = vh; \
+ } \
+ \
+ if (mono) { \
+ newLen = cl->ublen - nSubrectsUblen + 2; \
+ } else { \
+ newLen = cl->ublen - nSubrectsUblen + bpp/8 + 2; \
+ } \
+ \
+ if (newLen > (w * h * (bpp/8))) \
+ return FALSE; \
+ \
+ numsubs += 1; \
+ \
+ if (!mono) PUT_PIXEL##bpp(cl2); \
+ \
+ cl->updateBuf[cl->ublen++] = rfbHextilePackXY(thex,they); \
+ cl->updateBuf[cl->ublen++] = rfbHextilePackWH(thew,theh); \
+ \
+ /* \
+ * Now mark the subrect as done. \
+ */ \
+ for (j=they; j < (they+theh); j++) { \
+ for (i=thex; i < (thex+thew); i++) { \
+ data[j*w+i] = bg; \
+ } \
+ } \
+ } \
+ } \
+ } \
+ \
+ cl->updateBuf[nSubrectsUblen] = numsubs; \
+ \
+ return TRUE; \
+} \
+ \
+ \
+/* \
+ * testColours() tests if there are one (solid), two (mono) or more \
+ * colours in a tile and gets a reasonable guess at the best background \
+ * pixel, and the foreground pixel for mono. \
+ */ \
+ \
+static void \
+testColours##bpp(data,size,mono,solid,bg,fg) \
+ CARD##bpp *data; \
+ int size; \
+ Bool *mono; \
+ Bool *solid; \
+ CARD##bpp *bg; \
+ CARD##bpp *fg; \
+{ \
+ CARD##bpp colour1 = 0, colour2 = 0; \
+ int n1 = 0, n2 = 0; \
+ *mono = TRUE; \
+ *solid = TRUE; \
+ \
+ for (; size > 0; size--, data++) { \
+ \
+ if (n1 == 0) \
+ colour1 = *data; \
+ \
+ if (*data == colour1) { \
+ n1++; \
+ continue; \
+ } \
+ \
+ if (n2 == 0) { \
+ *solid = FALSE; \
+ colour2 = *data; \
+ } \
+ \
+ if (*data == colour2) { \
+ n2++; \
+ continue; \
+ } \
+ \
+ *mono = FALSE; \
+ break; \
+ } \
+ \
+ if (n1 > n2) { \
+ *bg = colour1; \
+ *fg = colour2; \
+ } else { \
+ *bg = colour2; \
+ *fg = colour1; \
+ } \
+}
+
+DEFINE_SEND_HEXTILES(8)
+DEFINE_SEND_HEXTILES(16)
+DEFINE_SEND_HEXTILES(32)
diff --git a/krfb/libvncserver/httpd.c b/krfb/libvncserver/httpd.c
new file mode 100644
index 00000000..72019b64
--- /dev/null
+++ b/krfb/libvncserver/httpd.c
@@ -0,0 +1,423 @@
+/*
+ * httpd.c - a simple HTTP server
+ */
+
+/*
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#ifdef WIN32
+#include <winsock.h>
+#define close closesocket
+#else
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <errno.h>
+#ifdef __osf__
+typedef int socklen_t;
+#endif
+
+#ifdef USE_LIBWRAP
+#include <tcpd.h>
+#endif
+
+#include "rfb.h"
+
+#define NOT_FOUND_STR "HTTP/1.0 404 Not found\n\n" \
+ "<HEAD><TITLE>File Not Found</TITLE></HEAD>\n" \
+ "<BODY><H1>File Not Found</H1></BODY>\n"
+
+#define OK_STR "HTTP/1.0 200 OK\nContent-Type: text/html\n\n"
+
+static void httpProcessInput();
+static Bool compareAndSkip(char **ptr, const char *str);
+
+/*
+int httpPort = 0;
+char *httpDir = NULL;
+
+int httpListenSock = -1;
+int httpSock = -1;
+FILE* httpFP = NULL;
+*/
+
+#define BUF_SIZE 32768
+
+static char buf[BUF_SIZE];
+static size_t buf_filled=0;
+
+
+/*
+ * httpInitSockets sets up the TCP socket to listen for HTTP connections.
+ */
+
+void
+httpInitSockets(rfbScreenInfoPtr rfbScreen)
+{
+ if (rfbScreen->httpInitDone)
+ return;
+
+ rfbScreen->httpInitDone = TRUE;
+
+ if (!rfbScreen->httpDir)
+ return;
+
+ if (rfbScreen->httpPort == 0) {
+ rfbScreen->httpPort = rfbScreen->rfbPort-100;
+ }
+
+ rfbLog("Listening for HTTP connections on TCP port %d\n", rfbScreen->httpPort);
+
+ rfbLog(" URL http://%s:%d\n",rfbScreen->rfbThisHost,rfbScreen->httpPort);
+
+ if ((rfbScreen->httpListenSock = ListenOnTCPPort(rfbScreen->httpPort)) < 0) {
+ rfbLogPerror("ListenOnTCPPort");
+ exit(1);
+ }
+
+ /*AddEnabledDevice(httpListenSock);*/
+}
+
+
+/*
+ * httpCheckFds is called from ProcessInputEvents to check for input on the
+ * HTTP socket(s). If there is input to process, httpProcessInput is called.
+ */
+
+void
+httpCheckFds(rfbScreenInfoPtr rfbScreen)
+{
+ int nfds;
+ fd_set fds;
+ struct timeval tv;
+ struct sockaddr_in addr;
+ size_t addrlen = sizeof(addr);
+
+ if (!rfbScreen->httpDir)
+ return;
+
+ FD_ZERO(&fds);
+ FD_SET(rfbScreen->httpListenSock, &fds);
+ if (rfbScreen->httpSock >= 0) {
+ FD_SET(rfbScreen->httpSock, &fds);
+ }
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ nfds = select(max(rfbScreen->httpSock,rfbScreen->httpListenSock) + 1, &fds, NULL, NULL, &tv);
+ if (nfds == 0) {
+ return;
+ }
+ if (nfds < 0) {
+#ifdef WIN32
+ errno = WSAGetLastError();
+#endif
+ rfbLogPerror("httpCheckFds: select");
+ return;
+ }
+
+ if ((rfbScreen->httpSock >= 0) && FD_ISSET(rfbScreen->httpSock, &fds)) {
+ httpProcessInput(rfbScreen);
+ }
+
+ if (FD_ISSET(rfbScreen->httpListenSock, &fds)) {
+ int flags;
+ if (rfbScreen->httpSock >= 0) close(rfbScreen->httpSock);
+
+ if ((rfbScreen->httpSock = accept(rfbScreen->httpListenSock,
+ (struct sockaddr *)&addr, &addrlen)) < 0) {
+ rfbLogPerror("httpCheckFds: accept");
+ return;
+ }
+#ifdef USE_LIBWRAP
+ if(!hosts_ctl("vnc",STRING_UNKNOWN,inet_ntoa(addr.sin_addr),
+ STRING_UNKNOWN)) {
+ rfbLog("Rejected connection from client %s\n",
+ inet_ntoa(addr.sin_addr));
+#else
+ if ((rfbScreen->httpFP = fdopen(rfbScreen->httpSock, "r+")) == NULL) {
+ rfbLogPerror("httpCheckFds: fdopen");
+#endif
+ close(rfbScreen->httpSock);
+ rfbScreen->httpSock = -1;
+ return;
+ }
+ flags=fcntl(rfbScreen->httpSock,F_GETFL);
+ if(flags==-1 ||
+ fcntl(rfbScreen->httpSock,F_SETFL,flags|O_NONBLOCK)==-1) {
+ rfbLogPerror("httpCheckFds: fcntl");
+ close(rfbScreen->httpSock);
+ rfbScreen->httpSock=-1;
+ return;
+ }
+
+ /*AddEnabledDevice(httpSock);*/
+ }
+}
+
+
+static void
+httpCloseSock(rfbScreenInfoPtr rfbScreen)
+{
+ fclose(rfbScreen->httpFP);
+ rfbScreen->httpFP = NULL;
+ /*RemoveEnabledDevice(httpSock);*/
+ rfbScreen->httpSock = -1;
+}
+
+static rfbClientRec cl;
+
+/*
+ * httpProcessInput is called when input is received on the HTTP socket.
+ */
+
+static void
+httpProcessInput(rfbScreenInfoPtr rfbScreen)
+{
+ struct sockaddr_in addr;
+ size_t addrlen = sizeof(addr);
+ char fullFname[256];
+ char *fname;
+ unsigned int maxFnameLen;
+ FILE* fd;
+ Bool performSubstitutions = FALSE;
+ char str[256];
+#ifndef WIN32
+ struct passwd *user = getpwuid(getuid());
+#endif
+
+ cl.sock=rfbScreen->httpSock;
+
+ if (strlen(rfbScreen->httpDir) > 200) {
+ rfbLog("-httpd directory too long\n");
+ httpCloseSock(rfbScreen);
+ return;
+ }
+ strcpy(fullFname, rfbScreen->httpDir);
+ fname = &fullFname[strlen(fullFname)];
+ maxFnameLen = 255 - strlen(fullFname);
+
+ /* Read data from the HTTP client until we get a complete request. */
+ while (1) {
+ ssize_t got = read (rfbScreen->httpSock, buf + buf_filled,
+ sizeof (buf) - buf_filled - 1);
+
+ if (got <= 0) {
+ if (got == 0) {
+ rfbLog("httpd: premature connection close\n");
+ } else {
+ if (errno == EAGAIN) {
+ return;
+ }
+ rfbLogPerror("httpProcessInput: read");
+ }
+ httpCloseSock(rfbScreen);
+ return;
+ }
+
+ buf_filled += got;
+ buf[buf_filled] = '\0';
+
+ /* Is it complete yet (is there a blank line)? */
+ if (strstr (buf, "\r\r") || strstr (buf, "\n\n") ||
+ strstr (buf, "\r\n\r\n") || strstr (buf, "\n\r\n\r"))
+ break;
+ }
+
+
+ /* Process the request. */
+ if (strncmp(buf, "GET ", 4)) {
+ rfbLog("no GET line\n");
+ httpCloseSock(rfbScreen);
+ return;
+ } else {
+ /* Only use the first line. */
+ buf[strcspn(buf, "\n\r")] = '\0';
+ }
+
+ if (strlen(buf) > maxFnameLen) {
+ rfbLog("GET line too long\n");
+ httpCloseSock(rfbScreen);
+ return;
+ }
+
+ if (sscanf(buf, "GET %s HTTP/1.0", fname) != 1) {
+ rfbLog("couldn't parse GET line\n");
+ httpCloseSock(rfbScreen);
+ return;
+ }
+
+ if (fname[0] != '/') {
+ rfbLog("filename didn't begin with '/'\n");
+ WriteExact(&cl, NOT_FOUND_STR, strlen(NOT_FOUND_STR));
+ httpCloseSock(rfbScreen);
+ return;
+ }
+
+ if (strchr(fname+1, '/') != NULL) {
+ rfbLog("asking for file in other directory\n");
+ WriteExact(&cl, NOT_FOUND_STR, strlen(NOT_FOUND_STR));
+ httpCloseSock(rfbScreen);
+ return;
+ }
+
+ getpeername(rfbScreen->httpSock, (struct sockaddr *)&addr, &addrlen);
+ rfbLog("httpd: get '%s' for %s\n", fname+1,
+ inet_ntoa(addr.sin_addr));
+
+ /* If we were asked for '/', actually read the file index.vnc */
+
+ if (strcmp(fname, "/") == 0) {
+ strcpy(fname, "/index.vnc");
+ rfbLog("httpd: defaulting to '%s'\n", fname+1);
+ }
+
+ /* Substitutions are performed on files ending .vnc */
+
+ if (strlen(fname) >= 4 && strcmp(&fname[strlen(fname)-4], ".vnc") == 0) {
+ performSubstitutions = TRUE;
+ }
+
+ /* Open the file */
+
+ if ((fd = fopen(fullFname, "r")) <= 0) {
+ rfbLogPerror("httpProcessInput: open");
+ WriteExact(&cl, NOT_FOUND_STR, strlen(NOT_FOUND_STR));
+ httpCloseSock(rfbScreen);
+ return;
+ }
+
+ WriteExact(&cl, OK_STR, strlen(OK_STR));
+
+ while (1) {
+ int n = fread(buf, 1, BUF_SIZE-1, fd);
+ if (n < 0) {
+ rfbLogPerror("httpProcessInput: read");
+ fclose(fd);
+ httpCloseSock(rfbScreen);
+ return;
+ }
+
+ if (n == 0)
+ break;
+
+ if (performSubstitutions) {
+
+ /* Substitute $WIDTH, $HEIGHT, etc with the appropriate values.
+ This won't quite work properly if the .vnc file is longer than
+ BUF_SIZE, but it's reasonable to assume that .vnc files will
+ always be short. */
+
+ char *ptr = buf;
+ char *dollar;
+ buf[n] = 0; /* make sure it's null-terminated */
+
+ while ((dollar = strchr(ptr, '$'))!=NULL) {
+ WriteExact(&cl, ptr, (dollar - ptr));
+
+ ptr = dollar;
+
+ if (compareAndSkip(&ptr, "$WIDTH")) {
+
+ sprintf(str, "%d", rfbScreen->width);
+ WriteExact(&cl, str, strlen(str));
+
+ } else if (compareAndSkip(&ptr, "$HEIGHT")) {
+
+ sprintf(str, "%d", rfbScreen->height);
+ WriteExact(&cl, str, strlen(str));
+
+ } else if (compareAndSkip(&ptr, "$APPLETWIDTH")) {
+
+ sprintf(str, "%d", rfbScreen->width);
+ WriteExact(&cl, str, strlen(str));
+
+ } else if (compareAndSkip(&ptr, "$APPLETHEIGHT")) {
+
+ sprintf(str, "%d", rfbScreen->height + 32);
+ WriteExact(&cl, str, strlen(str));
+
+ } else if (compareAndSkip(&ptr, "$PORT")) {
+
+ sprintf(str, "%d", rfbScreen->rfbPort);
+ WriteExact(&cl, str, strlen(str));
+
+ } else if (compareAndSkip(&ptr, "$DESKTOP")) {
+
+ WriteExact(&cl, rfbScreen->desktopName, strlen(rfbScreen->desktopName));
+
+ } else if (compareAndSkip(&ptr, "$DISPLAY")) {
+
+ sprintf(str, "%s:%d", rfbScreen->rfbThisHost, rfbScreen->rfbPort-5900);
+ WriteExact(&cl, str, strlen(str));
+
+ } else if (compareAndSkip(&ptr, "$USER")) {
+#ifndef WIN32
+ if (user) {
+ WriteExact(&cl, user->pw_name,
+ strlen(user->pw_name));
+ } else
+#endif
+ WriteExact(&cl, "?", 1);
+ } else {
+ if (!compareAndSkip(&ptr, "$$"))
+ ptr++;
+
+ if (WriteExact(&cl, "$", 1) < 0) {
+ fclose(fd);
+ httpCloseSock(rfbScreen);
+ return;
+ }
+ }
+ }
+ if (WriteExact(&cl, ptr, (&buf[n] - ptr)) < 0)
+ break;
+
+ } else {
+
+ /* For files not ending .vnc, just write out the buffer */
+
+ if (WriteExact(&cl, buf, n) < 0)
+ break;
+ }
+ }
+
+ fclose(fd);
+ httpCloseSock(rfbScreen);
+}
+
+
+static Bool
+compareAndSkip(char **ptr, const char *str)
+{
+ if (strncmp(*ptr, str, strlen(str)) == 0) {
+ *ptr += strlen(str);
+ return TRUE;
+ }
+
+ return FALSE;
+}
diff --git a/krfb/libvncserver/keysym.h b/krfb/libvncserver/keysym.h
new file mode 100644
index 00000000..dc165b3b
--- /dev/null
+++ b/krfb/libvncserver/keysym.h
@@ -0,0 +1,1639 @@
+#ifndef KEYSYM_H
+#define KEYSYM_H
+
+/* $XConsortium: keysym.h,v 1.15 94/04/17 20:10:55 rws Exp $ */
+
+/***********************************************************
+
+Copyright (c) 1987 X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+
+/* default keysyms */
+#define XK_MISCELLANY
+#define XK_XKB_KEYS
+#define XK_LATIN1
+#define XK_LATIN2
+#define XK_LATIN3
+#define XK_LATIN4
+#define XK_GREEK
+
+/* $TOG: keysymdef.h /main/25 1997/06/21 10:54:51 kaleb $ */
+
+/***********************************************************
+Copyright (c) 1987, 1994 X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from the X Consortium.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+
+#define XK_VoidSymbol 0xFFFFFF /* void symbol */
+
+#ifdef XK_MISCELLANY
+/*
+ * TTY Functions, cleverly chosen to map to ascii, for convenience of
+ * programming, but could have been arbitrary (at the cost of lookup
+ * tables in client code.
+ */
+
+#define XK_BackSpace 0xFF08 /* back space, back char */
+#define XK_Tab 0xFF09
+#define XK_Linefeed 0xFF0A /* Linefeed, LF */
+#define XK_Clear 0xFF0B
+#define XK_Return 0xFF0D /* Return, enter */
+#define XK_Pause 0xFF13 /* Pause, hold */
+#define XK_Scroll_Lock 0xFF14
+#define XK_Sys_Req 0xFF15
+#define XK_Escape 0xFF1B
+#define XK_Delete 0xFFFF /* Delete, rubout */
+
+
+
+/* International & multi-key character composition */
+
+#define XK_Multi_key 0xFF20 /* Multi-key character compose */
+#define XK_SingleCandidate 0xFF3C
+#define XK_MultipleCandidate 0xFF3D
+#define XK_PreviousCandidate 0xFF3E
+
+/* Japanese keyboard support */
+
+#define XK_Kanji 0xFF21 /* Kanji, Kanji convert */
+#define XK_Muhenkan 0xFF22 /* Cancel Conversion */
+#define XK_Henkan_Mode 0xFF23 /* Start/Stop Conversion */
+#define XK_Henkan 0xFF23 /* Alias for Henkan_Mode */
+#define XK_Romaji 0xFF24 /* to Romaji */
+#define XK_Hiragana 0xFF25 /* to Hiragana */
+#define XK_Katakana 0xFF26 /* to Katakana */
+#define XK_Hiragana_Katakana 0xFF27 /* Hiragana/Katakana toggle */
+#define XK_Zenkaku 0xFF28 /* to Zenkaku */
+#define XK_Hankaku 0xFF29 /* to Hankaku */
+#define XK_Zenkaku_Hankaku 0xFF2A /* Zenkaku/Hankaku toggle */
+#define XK_Touroku 0xFF2B /* Add to Dictionary */
+#define XK_Massyo 0xFF2C /* Delete from Dictionary */
+#define XK_Kana_Lock 0xFF2D /* Kana Lock */
+#define XK_Kana_Shift 0xFF2E /* Kana Shift */
+#define XK_Eisu_Shift 0xFF2F /* Alphanumeric Shift */
+#define XK_Eisu_toggle 0xFF30 /* Alphanumeric toggle */
+#define XK_Zen_Koho 0xFF3D /* Multiple/All Candidate(s) */
+#define XK_Mae_Koho 0xFF3E /* Previous Candidate */
+
+/* 0xFF31 thru 0xFF3F are under XK_KOREAN */
+
+/* Cursor control & motion */
+
+#define XK_Home 0xFF50
+#define XK_Left 0xFF51 /* Move left, left arrow */
+#define XK_Up 0xFF52 /* Move up, up arrow */
+#define XK_Right 0xFF53 /* Move right, right arrow */
+#define XK_Down 0xFF54 /* Move down, down arrow */
+#define XK_Prior 0xFF55 /* Prior, previous */
+#define XK_Page_Up 0xFF55
+#define XK_Next 0xFF56 /* Next */
+#define XK_Page_Down 0xFF56
+#define XK_End 0xFF57 /* EOL */
+#define XK_Begin 0xFF58 /* BOL */
+
+
+/* Misc Functions */
+
+#define XK_Select 0xFF60 /* Select, mark */
+#define XK_Print 0xFF61
+#define XK_Execute 0xFF62 /* Execute, run, do */
+#define XK_Insert 0xFF63 /* Insert, insert here */
+#define XK_Undo 0xFF65 /* Undo, oops */
+#define XK_Redo 0xFF66 /* redo, again */
+#define XK_Menu 0xFF67
+#define XK_Find 0xFF68 /* Find, search */
+#define XK_Cancel 0xFF69 /* Cancel, stop, abort, exit */
+#define XK_Help 0xFF6A /* Help */
+#define XK_Break 0xFF6B
+#define XK_Mode_switch 0xFF7E /* Character set switch */
+#define XK_script_switch 0xFF7E /* Alias for mode_switch */
+#define XK_Num_Lock 0xFF7F
+
+/* Keypad Functions, keypad numbers cleverly chosen to map to ascii */
+
+#define XK_KP_Space 0xFF80 /* space */
+#define XK_KP_Tab 0xFF89
+#define XK_KP_Enter 0xFF8D /* enter */
+#define XK_KP_F1 0xFF91 /* PF1, KP_A, ... */
+#define XK_KP_F2 0xFF92
+#define XK_KP_F3 0xFF93
+#define XK_KP_F4 0xFF94
+#define XK_KP_Home 0xFF95
+#define XK_KP_Left 0xFF96
+#define XK_KP_Up 0xFF97
+#define XK_KP_Right 0xFF98
+#define XK_KP_Down 0xFF99
+#define XK_KP_Prior 0xFF9A
+#define XK_KP_Page_Up 0xFF9A
+#define XK_KP_Next 0xFF9B
+#define XK_KP_Page_Down 0xFF9B
+#define XK_KP_End 0xFF9C
+#define XK_KP_Begin 0xFF9D
+#define XK_KP_Insert 0xFF9E
+#define XK_KP_Delete 0xFF9F
+#define XK_KP_Equal 0xFFBD /* equals */
+#define XK_KP_Multiply 0xFFAA
+#define XK_KP_Add 0xFFAB
+#define XK_KP_Separator 0xFFAC /* separator, often comma */
+#define XK_KP_Subtract 0xFFAD
+#define XK_KP_Decimal 0xFFAE
+#define XK_KP_Divide 0xFFAF
+
+#define XK_KP_0 0xFFB0
+#define XK_KP_1 0xFFB1
+#define XK_KP_2 0xFFB2
+#define XK_KP_3 0xFFB3
+#define XK_KP_4 0xFFB4
+#define XK_KP_5 0xFFB5
+#define XK_KP_6 0xFFB6
+#define XK_KP_7 0xFFB7
+#define XK_KP_8 0xFFB8
+#define XK_KP_9 0xFFB9
+
+
+
+/*
+ * Auxilliary Functions; note the duplicate definitions for left and right
+ * function keys; Sun keyboards and a few other manufactures have such
+ * function key groups on the left and/or right sides of the keyboard.
+ * We've not found a keyboard with more than 35 function keys total.
+ */
+
+#define XK_F1 0xFFBE
+#define XK_F2 0xFFBF
+#define XK_F3 0xFFC0
+#define XK_F4 0xFFC1
+#define XK_F5 0xFFC2
+#define XK_F6 0xFFC3
+#define XK_F7 0xFFC4
+#define XK_F8 0xFFC5
+#define XK_F9 0xFFC6
+#define XK_F10 0xFFC7
+#define XK_F11 0xFFC8
+#define XK_L1 0xFFC8
+#define XK_F12 0xFFC9
+#define XK_L2 0xFFC9
+#define XK_F13 0xFFCA
+#define XK_L3 0xFFCA
+#define XK_F14 0xFFCB
+#define XK_L4 0xFFCB
+#define XK_F15 0xFFCC
+#define XK_L5 0xFFCC
+#define XK_F16 0xFFCD
+#define XK_L6 0xFFCD
+#define XK_F17 0xFFCE
+#define XK_L7 0xFFCE
+#define XK_F18 0xFFCF
+#define XK_L8 0xFFCF
+#define XK_F19 0xFFD0
+#define XK_L9 0xFFD0
+#define XK_F20 0xFFD1
+#define XK_L10 0xFFD1
+#define XK_F21 0xFFD2
+#define XK_R1 0xFFD2
+#define XK_F22 0xFFD3
+#define XK_R2 0xFFD3
+#define XK_F23 0xFFD4
+#define XK_R3 0xFFD4
+#define XK_F24 0xFFD5
+#define XK_R4 0xFFD5
+#define XK_F25 0xFFD6
+#define XK_R5 0xFFD6
+#define XK_F26 0xFFD7
+#define XK_R6 0xFFD7
+#define XK_F27 0xFFD8
+#define XK_R7 0xFFD8
+#define XK_F28 0xFFD9
+#define XK_R8 0xFFD9
+#define XK_F29 0xFFDA
+#define XK_R9 0xFFDA
+#define XK_F30 0xFFDB
+#define XK_R10 0xFFDB
+#define XK_F31 0xFFDC
+#define XK_R11 0xFFDC
+#define XK_F32 0xFFDD
+#define XK_R12 0xFFDD
+#define XK_F33 0xFFDE
+#define XK_R13 0xFFDE
+#define XK_F34 0xFFDF
+#define XK_R14 0xFFDF
+#define XK_F35 0xFFE0
+#define XK_R15 0xFFE0
+
+/* Modifiers */
+
+#define XK_Shift_L 0xFFE1 /* Left shift */
+#define XK_Shift_R 0xFFE2 /* Right shift */
+#define XK_Control_L 0xFFE3 /* Left control */
+#define XK_Control_R 0xFFE4 /* Right control */
+#define XK_Caps_Lock 0xFFE5 /* Caps lock */
+#define XK_Shift_Lock 0xFFE6 /* Shift lock */
+
+#define XK_Meta_L 0xFFE7 /* Left meta */
+#define XK_Meta_R 0xFFE8 /* Right meta */
+#define XK_Alt_L 0xFFE9 /* Left alt */
+#define XK_Alt_R 0xFFEA /* Right alt */
+#define XK_Super_L 0xFFEB /* Left super */
+#define XK_Super_R 0xFFEC /* Right super */
+#define XK_Hyper_L 0xFFED /* Left hyper */
+#define XK_Hyper_R 0xFFEE /* Right hyper */
+#endif /* XK_MISCELLANY */
+
+/*
+ * ISO 9995 Function and Modifier Keys
+ * Byte 3 = 0xFE
+ */
+
+#ifdef XK_XKB_KEYS
+#define XK_ISO_Lock 0xFE01
+#define XK_ISO_Level2_Latch 0xFE02
+#define XK_ISO_Level3_Shift 0xFE03
+#define XK_ISO_Level3_Latch 0xFE04
+#define XK_ISO_Level3_Lock 0xFE05
+#define XK_ISO_Group_Shift 0xFF7E /* Alias for mode_switch */
+#define XK_ISO_Group_Latch 0xFE06
+#define XK_ISO_Group_Lock 0xFE07
+#define XK_ISO_Next_Group 0xFE08
+#define XK_ISO_Next_Group_Lock 0xFE09
+#define XK_ISO_Prev_Group 0xFE0A
+#define XK_ISO_Prev_Group_Lock 0xFE0B
+#define XK_ISO_First_Group 0xFE0C
+#define XK_ISO_First_Group_Lock 0xFE0D
+#define XK_ISO_Last_Group 0xFE0E
+#define XK_ISO_Last_Group_Lock 0xFE0F
+
+#define XK_ISO_Left_Tab 0xFE20
+#define XK_ISO_Move_Line_Up 0xFE21
+#define XK_ISO_Move_Line_Down 0xFE22
+#define XK_ISO_Partial_Line_Up 0xFE23
+#define XK_ISO_Partial_Line_Down 0xFE24
+#define XK_ISO_Partial_Space_Left 0xFE25
+#define XK_ISO_Partial_Space_Right 0xFE26
+#define XK_ISO_Set_Margin_Left 0xFE27
+#define XK_ISO_Set_Margin_Right 0xFE28
+#define XK_ISO_Release_Margin_Left 0xFE29
+#define XK_ISO_Release_Margin_Right 0xFE2A
+#define XK_ISO_Release_Both_Margins 0xFE2B
+#define XK_ISO_Fast_Cursor_Left 0xFE2C
+#define XK_ISO_Fast_Cursor_Right 0xFE2D
+#define XK_ISO_Fast_Cursor_Up 0xFE2E
+#define XK_ISO_Fast_Cursor_Down 0xFE2F
+#define XK_ISO_Continuous_Underline 0xFE30
+#define XK_ISO_Discontinuous_Underline 0xFE31
+#define XK_ISO_Emphasize 0xFE32
+#define XK_ISO_Center_Object 0xFE33
+#define XK_ISO_Enter 0xFE34
+
+#define XK_dead_grave 0xFE50
+#define XK_dead_acute 0xFE51
+#define XK_dead_circumflex 0xFE52
+#define XK_dead_tilde 0xFE53
+#define XK_dead_macron 0xFE54
+#define XK_dead_breve 0xFE55
+#define XK_dead_abovedot 0xFE56
+#define XK_dead_diaeresis 0xFE57
+#define XK_dead_abovering 0xFE58
+#define XK_dead_doubleacute 0xFE59
+#define XK_dead_caron 0xFE5A
+#define XK_dead_cedilla 0xFE5B
+#define XK_dead_ogonek 0xFE5C
+#define XK_dead_iota 0xFE5D
+#define XK_dead_voiced_sound 0xFE5E
+#define XK_dead_semivoiced_sound 0xFE5F
+#define XK_dead_belowdot 0xFE60
+
+#define XK_First_Virtual_Screen 0xFED0
+#define XK_Prev_Virtual_Screen 0xFED1
+#define XK_Next_Virtual_Screen 0xFED2
+#define XK_Last_Virtual_Screen 0xFED4
+#define XK_Terminate_Server 0xFED5
+
+#define XK_AccessX_Enable 0xFE70
+#define XK_AccessX_Feedback_Enable 0xFE71
+#define XK_RepeatKeys_Enable 0xFE72
+#define XK_SlowKeys_Enable 0xFE73
+#define XK_BounceKeys_Enable 0xFE74
+#define XK_StickyKeys_Enable 0xFE75
+#define XK_MouseKeys_Enable 0xFE76
+#define XK_MouseKeys_Accel_Enable 0xFE77
+#define XK_Overlay1_Enable 0xFE78
+#define XK_Overlay2_Enable 0xFE79
+#define XK_AudibleBell_Enable 0xFE7A
+
+#define XK_Pointer_Left 0xFEE0
+#define XK_Pointer_Right 0xFEE1
+#define XK_Pointer_Up 0xFEE2
+#define XK_Pointer_Down 0xFEE3
+#define XK_Pointer_UpLeft 0xFEE4
+#define XK_Pointer_UpRight 0xFEE5
+#define XK_Pointer_DownLeft 0xFEE6
+#define XK_Pointer_DownRight 0xFEE7
+#define XK_Pointer_Button_Dflt 0xFEE8
+#define XK_Pointer_Button1 0xFEE9
+#define XK_Pointer_Button2 0xFEEA
+#define XK_Pointer_Button3 0xFEEB
+#define XK_Pointer_Button4 0xFEEC
+#define XK_Pointer_Button5 0xFEED
+#define XK_Pointer_DblClick_Dflt 0xFEEE
+#define XK_Pointer_DblClick1 0xFEEF
+#define XK_Pointer_DblClick2 0xFEF0
+#define XK_Pointer_DblClick3 0xFEF1
+#define XK_Pointer_DblClick4 0xFEF2
+#define XK_Pointer_DblClick5 0xFEF3
+#define XK_Pointer_Drag_Dflt 0xFEF4
+#define XK_Pointer_Drag1 0xFEF5
+#define XK_Pointer_Drag2 0xFEF6
+#define XK_Pointer_Drag3 0xFEF7
+#define XK_Pointer_Drag4 0xFEF8
+#define XK_Pointer_Drag5 0xFEFD
+
+#define XK_Pointer_EnableKeys 0xFEF9
+#define XK_Pointer_Accelerate 0xFEFA
+#define XK_Pointer_DfltBtnNext 0xFEFB
+#define XK_Pointer_DfltBtnPrev 0xFEFC
+
+#endif
+
+/*
+ * 3270 Terminal Keys
+ * Byte 3 = 0xFD
+ */
+
+#ifdef XK_3270
+#define XK_3270_Duplicate 0xFD01
+#define XK_3270_FieldMark 0xFD02
+#define XK_3270_Right2 0xFD03
+#define XK_3270_Left2 0xFD04
+#define XK_3270_BackTab 0xFD05
+#define XK_3270_EraseEOF 0xFD06
+#define XK_3270_EraseInput 0xFD07
+#define XK_3270_Reset 0xFD08
+#define XK_3270_Quit 0xFD09
+#define XK_3270_PA1 0xFD0A
+#define XK_3270_PA2 0xFD0B
+#define XK_3270_PA3 0xFD0C
+#define XK_3270_Test 0xFD0D
+#define XK_3270_Attn 0xFD0E
+#define XK_3270_CursorBlink 0xFD0F
+#define XK_3270_AltCursor 0xFD10
+#define XK_3270_KeyClick 0xFD11
+#define XK_3270_Jump 0xFD12
+#define XK_3270_Ident 0xFD13
+#define XK_3270_Rule 0xFD14
+#define XK_3270_Copy 0xFD15
+#define XK_3270_Play 0xFD16
+#define XK_3270_Setup 0xFD17
+#define XK_3270_Record 0xFD18
+#define XK_3270_ChangeScreen 0xFD19
+#define XK_3270_DeleteWord 0xFD1A
+#define XK_3270_ExSelect 0xFD1B
+#define XK_3270_CursorSelect 0xFD1C
+#define XK_3270_PrintScreen 0xFD1D
+#define XK_3270_Enter 0xFD1E
+#endif
+
+/*
+ * Latin 1
+ * Byte 3 = 0
+ */
+#ifdef XK_LATIN1
+#define XK_space 0x020
+#define XK_exclam 0x021
+#define XK_quotedbl 0x022
+#define XK_numbersign 0x023
+#define XK_dollar 0x024
+#define XK_percent 0x025
+#define XK_ampersand 0x026
+#define XK_apostrophe 0x027
+#define XK_quoteright 0x027 /* deprecated */
+#define XK_parenleft 0x028
+#define XK_parenright 0x029
+#define XK_asterisk 0x02a
+#define XK_plus 0x02b
+#define XK_comma 0x02c
+#define XK_minus 0x02d
+#define XK_period 0x02e
+#define XK_slash 0x02f
+#define XK_0 0x030
+#define XK_1 0x031
+#define XK_2 0x032
+#define XK_3 0x033
+#define XK_4 0x034
+#define XK_5 0x035
+#define XK_6 0x036
+#define XK_7 0x037
+#define XK_8 0x038
+#define XK_9 0x039
+#define XK_colon 0x03a
+#define XK_semicolon 0x03b
+#define XK_less 0x03c
+#define XK_equal 0x03d
+#define XK_greater 0x03e
+#define XK_question 0x03f
+#define XK_at 0x040
+#define XK_A 0x041
+#define XK_B 0x042
+#define XK_C 0x043
+#define XK_D 0x044
+#define XK_E 0x045
+#define XK_F 0x046
+#define XK_G 0x047
+#define XK_H 0x048
+#define XK_I 0x049
+#define XK_J 0x04a
+#define XK_K 0x04b
+#define XK_L 0x04c
+#define XK_M 0x04d
+#define XK_N 0x04e
+#define XK_O 0x04f
+#define XK_P 0x050
+#define XK_Q 0x051
+#define XK_R 0x052
+#define XK_S 0x053
+#define XK_T 0x054
+#define XK_U 0x055
+#define XK_V 0x056
+#define XK_W 0x057
+#define XK_X 0x058
+#define XK_Y 0x059
+#define XK_Z 0x05a
+#define XK_bracketleft 0x05b
+#define XK_backslash 0x05c
+#define XK_bracketright 0x05d
+#define XK_asciicircum 0x05e
+#define XK_underscore 0x05f
+#define XK_grave 0x060
+#define XK_quoteleft 0x060 /* deprecated */
+#define XK_a 0x061
+#define XK_b 0x062
+#define XK_c 0x063
+#define XK_d 0x064
+#define XK_e 0x065
+#define XK_f 0x066
+#define XK_g 0x067
+#define XK_h 0x068
+#define XK_i 0x069
+#define XK_j 0x06a
+#define XK_k 0x06b
+#define XK_l 0x06c
+#define XK_m 0x06d
+#define XK_n 0x06e
+#define XK_o 0x06f
+#define XK_p 0x070
+#define XK_q 0x071
+#define XK_r 0x072
+#define XK_s 0x073
+#define XK_t 0x074
+#define XK_u 0x075
+#define XK_v 0x076
+#define XK_w 0x077
+#define XK_x 0x078
+#define XK_y 0x079
+#define XK_z 0x07a
+#define XK_braceleft 0x07b
+#define XK_bar 0x07c
+#define XK_braceright 0x07d
+#define XK_asciitilde 0x07e
+
+#define XK_nobreakspace 0x0a0
+#define XK_exclamdown 0x0a1
+#define XK_cent 0x0a2
+#define XK_sterling 0x0a3
+#define XK_currency 0x0a4
+#define XK_yen 0x0a5
+#define XK_brokenbar 0x0a6
+#define XK_section 0x0a7
+#define XK_diaeresis 0x0a8
+#define XK_copyright 0x0a9
+#define XK_ordfeminine 0x0aa
+#define XK_guillemotleft 0x0ab /* left angle quotation mark */
+#define XK_notsign 0x0ac
+#define XK_hyphen 0x0ad
+#define XK_registered 0x0ae
+#define XK_macron 0x0af
+#define XK_degree 0x0b0
+#define XK_plusminus 0x0b1
+#define XK_twosuperior 0x0b2
+#define XK_threesuperior 0x0b3
+#define XK_acute 0x0b4
+#define XK_mu 0x0b5
+#define XK_paragraph 0x0b6
+#define XK_periodcentered 0x0b7
+#define XK_cedilla 0x0b8
+#define XK_onesuperior 0x0b9
+#define XK_masculine 0x0ba
+#define XK_guillemotright 0x0bb /* right angle quotation mark */
+#define XK_onequarter 0x0bc
+#define XK_onehalf 0x0bd
+#define XK_threequarters 0x0be
+#define XK_questiondown 0x0bf
+#define XK_Agrave 0x0c0
+#define XK_Aacute 0x0c1
+#define XK_Acircumflex 0x0c2
+#define XK_Atilde 0x0c3
+#define XK_Adiaeresis 0x0c4
+#define XK_Aring 0x0c5
+#define XK_AE 0x0c6
+#define XK_Ccedilla 0x0c7
+#define XK_Egrave 0x0c8
+#define XK_Eacute 0x0c9
+#define XK_Ecircumflex 0x0ca
+#define XK_Ediaeresis 0x0cb
+#define XK_Igrave 0x0cc
+#define XK_Iacute 0x0cd
+#define XK_Icircumflex 0x0ce
+#define XK_Idiaeresis 0x0cf
+#define XK_ETH 0x0d0
+#define XK_Eth 0x0d0 /* deprecated */
+#define XK_Ntilde 0x0d1
+#define XK_Ograve 0x0d2
+#define XK_Oacute 0x0d3
+#define XK_Ocircumflex 0x0d4
+#define XK_Otilde 0x0d5
+#define XK_Odiaeresis 0x0d6
+#define XK_multiply 0x0d7
+#define XK_Ooblique 0x0d8
+#define XK_Ugrave 0x0d9
+#define XK_Uacute 0x0da
+#define XK_Ucircumflex 0x0db
+#define XK_Udiaeresis 0x0dc
+#define XK_Yacute 0x0dd
+#define XK_THORN 0x0de
+#define XK_Thorn 0x0de /* deprecated */
+#define XK_ssharp 0x0df
+#define XK_agrave 0x0e0
+#define XK_aacute 0x0e1
+#define XK_acircumflex 0x0e2
+#define XK_atilde 0x0e3
+#define XK_adiaeresis 0x0e4
+#define XK_aring 0x0e5
+#define XK_ae 0x0e6
+#define XK_ccedilla 0x0e7
+#define XK_egrave 0x0e8
+#define XK_eacute 0x0e9
+#define XK_ecircumflex 0x0ea
+#define XK_ediaeresis 0x0eb
+#define XK_igrave 0x0ec
+#define XK_iacute 0x0ed
+#define XK_icircumflex 0x0ee
+#define XK_idiaeresis 0x0ef
+#define XK_eth 0x0f0
+#define XK_ntilde 0x0f1
+#define XK_ograve 0x0f2
+#define XK_oacute 0x0f3
+#define XK_ocircumflex 0x0f4
+#define XK_otilde 0x0f5
+#define XK_odiaeresis 0x0f6
+#define XK_division 0x0f7
+#define XK_oslash 0x0f8
+#define XK_ugrave 0x0f9
+#define XK_uacute 0x0fa
+#define XK_ucircumflex 0x0fb
+#define XK_udiaeresis 0x0fc
+#define XK_yacute 0x0fd
+#define XK_thorn 0x0fe
+#define XK_ydiaeresis 0x0ff
+#endif /* XK_LATIN1 */
+
+/*
+ * Latin 2
+ * Byte 3 = 1
+ */
+
+#ifdef XK_LATIN2
+#define XK_Aogonek 0x1a1
+#define XK_breve 0x1a2
+#define XK_Lstroke 0x1a3
+#define XK_Lcaron 0x1a5
+#define XK_Sacute 0x1a6
+#define XK_Scaron 0x1a9
+#define XK_Scedilla 0x1aa
+#define XK_Tcaron 0x1ab
+#define XK_Zacute 0x1ac
+#define XK_Zcaron 0x1ae
+#define XK_Zabovedot 0x1af
+#define XK_aogonek 0x1b1
+#define XK_ogonek 0x1b2
+#define XK_lstroke 0x1b3
+#define XK_lcaron 0x1b5
+#define XK_sacute 0x1b6
+#define XK_caron 0x1b7
+#define XK_scaron 0x1b9
+#define XK_scedilla 0x1ba
+#define XK_tcaron 0x1bb
+#define XK_zacute 0x1bc
+#define XK_doubleacute 0x1bd
+#define XK_zcaron 0x1be
+#define XK_zabovedot 0x1bf
+#define XK_Racute 0x1c0
+#define XK_Abreve 0x1c3
+#define XK_Lacute 0x1c5
+#define XK_Cacute 0x1c6
+#define XK_Ccaron 0x1c8
+#define XK_Eogonek 0x1ca
+#define XK_Ecaron 0x1cc
+#define XK_Dcaron 0x1cf
+#define XK_Dstroke 0x1d0
+#define XK_Nacute 0x1d1
+#define XK_Ncaron 0x1d2
+#define XK_Odoubleacute 0x1d5
+#define XK_Rcaron 0x1d8
+#define XK_Uring 0x1d9
+#define XK_Udoubleacute 0x1db
+#define XK_Tcedilla 0x1de
+#define XK_racute 0x1e0
+#define XK_abreve 0x1e3
+#define XK_lacute 0x1e5
+#define XK_cacute 0x1e6
+#define XK_ccaron 0x1e8
+#define XK_eogonek 0x1ea
+#define XK_ecaron 0x1ec
+#define XK_dcaron 0x1ef
+#define XK_dstroke 0x1f0
+#define XK_nacute 0x1f1
+#define XK_ncaron 0x1f2
+#define XK_odoubleacute 0x1f5
+#define XK_udoubleacute 0x1fb
+#define XK_rcaron 0x1f8
+#define XK_uring 0x1f9
+#define XK_tcedilla 0x1fe
+#define XK_abovedot 0x1ff
+#endif /* XK_LATIN2 */
+
+/*
+ * Latin 3
+ * Byte 3 = 2
+ */
+
+#ifdef XK_LATIN3
+#define XK_Hstroke 0x2a1
+#define XK_Hcircumflex 0x2a6
+#define XK_Iabovedot 0x2a9
+#define XK_Gbreve 0x2ab
+#define XK_Jcircumflex 0x2ac
+#define XK_hstroke 0x2b1
+#define XK_hcircumflex 0x2b6
+#define XK_idotless 0x2b9
+#define XK_gbreve 0x2bb
+#define XK_jcircumflex 0x2bc
+#define XK_Cabovedot 0x2c5
+#define XK_Ccircumflex 0x2c6
+#define XK_Gabovedot 0x2d5
+#define XK_Gcircumflex 0x2d8
+#define XK_Ubreve 0x2dd
+#define XK_Scircumflex 0x2de
+#define XK_cabovedot 0x2e5
+#define XK_ccircumflex 0x2e6
+#define XK_gabovedot 0x2f5
+#define XK_gcircumflex 0x2f8
+#define XK_ubreve 0x2fd
+#define XK_scircumflex 0x2fe
+#endif /* XK_LATIN3 */
+
+
+/*
+ * Latin 4
+ * Byte 3 = 3
+ */
+
+#ifdef XK_LATIN4
+#define XK_kra 0x3a2
+#define XK_kappa 0x3a2 /* deprecated */
+#define XK_Rcedilla 0x3a3
+#define XK_Itilde 0x3a5
+#define XK_Lcedilla 0x3a6
+#define XK_Emacron 0x3aa
+#define XK_Gcedilla 0x3ab
+#define XK_Tslash 0x3ac
+#define XK_rcedilla 0x3b3
+#define XK_itilde 0x3b5
+#define XK_lcedilla 0x3b6
+#define XK_emacron 0x3ba
+#define XK_gcedilla 0x3bb
+#define XK_tslash 0x3bc
+#define XK_ENG 0x3bd
+#define XK_eng 0x3bf
+#define XK_Amacron 0x3c0
+#define XK_Iogonek 0x3c7
+#define XK_Eabovedot 0x3cc
+#define XK_Imacron 0x3cf
+#define XK_Ncedilla 0x3d1
+#define XK_Omacron 0x3d2
+#define XK_Kcedilla 0x3d3
+#define XK_Uogonek 0x3d9
+#define XK_Utilde 0x3dd
+#define XK_Umacron 0x3de
+#define XK_amacron 0x3e0
+#define XK_iogonek 0x3e7
+#define XK_eabovedot 0x3ec
+#define XK_imacron 0x3ef
+#define XK_ncedilla 0x3f1
+#define XK_omacron 0x3f2
+#define XK_kcedilla 0x3f3
+#define XK_uogonek 0x3f9
+#define XK_utilde 0x3fd
+#define XK_umacron 0x3fe
+#endif /* XK_LATIN4 */
+
+/*
+ * Katakana
+ * Byte 3 = 4
+ */
+
+#ifdef XK_KATAKANA
+#define XK_overline 0x47e
+#define XK_kana_fullstop 0x4a1
+#define XK_kana_openingbracket 0x4a2
+#define XK_kana_closingbracket 0x4a3
+#define XK_kana_comma 0x4a4
+#define XK_kana_conjunctive 0x4a5
+#define XK_kana_middledot 0x4a5 /* deprecated */
+#define XK_kana_WO 0x4a6
+#define XK_kana_a 0x4a7
+#define XK_kana_i 0x4a8
+#define XK_kana_u 0x4a9
+#define XK_kana_e 0x4aa
+#define XK_kana_o 0x4ab
+#define XK_kana_ya 0x4ac
+#define XK_kana_yu 0x4ad
+#define XK_kana_yo 0x4ae
+#define XK_kana_tsu 0x4af
+#define XK_kana_tu 0x4af /* deprecated */
+#define XK_prolongedsound 0x4b0
+#define XK_kana_A 0x4b1
+#define XK_kana_I 0x4b2
+#define XK_kana_U 0x4b3
+#define XK_kana_E 0x4b4
+#define XK_kana_O 0x4b5
+#define XK_kana_KA 0x4b6
+#define XK_kana_KI 0x4b7
+#define XK_kana_KU 0x4b8
+#define XK_kana_KE 0x4b9
+#define XK_kana_KO 0x4ba
+#define XK_kana_SA 0x4bb
+#define XK_kana_SHI 0x4bc
+#define XK_kana_SU 0x4bd
+#define XK_kana_SE 0x4be
+#define XK_kana_SO 0x4bf
+#define XK_kana_TA 0x4c0
+#define XK_kana_CHI 0x4c1
+#define XK_kana_TI 0x4c1 /* deprecated */
+#define XK_kana_TSU 0x4c2
+#define XK_kana_TU 0x4c2 /* deprecated */
+#define XK_kana_TE 0x4c3
+#define XK_kana_TO 0x4c4
+#define XK_kana_NA 0x4c5
+#define XK_kana_NI 0x4c6
+#define XK_kana_NU 0x4c7
+#define XK_kana_NE 0x4c8
+#define XK_kana_NO 0x4c9
+#define XK_kana_HA 0x4ca
+#define XK_kana_HI 0x4cb
+#define XK_kana_FU 0x4cc
+#define XK_kana_HU 0x4cc /* deprecated */
+#define XK_kana_HE 0x4cd
+#define XK_kana_HO 0x4ce
+#define XK_kana_MA 0x4cf
+#define XK_kana_MI 0x4d0
+#define XK_kana_MU 0x4d1
+#define XK_kana_ME 0x4d2
+#define XK_kana_MO 0x4d3
+#define XK_kana_YA 0x4d4
+#define XK_kana_YU 0x4d5
+#define XK_kana_YO 0x4d6
+#define XK_kana_RA 0x4d7
+#define XK_kana_RI 0x4d8
+#define XK_kana_RU 0x4d9
+#define XK_kana_RE 0x4da
+#define XK_kana_RO 0x4db
+#define XK_kana_WA 0x4dc
+#define XK_kana_N 0x4dd
+#define XK_voicedsound 0x4de
+#define XK_semivoicedsound 0x4df
+#define XK_kana_switch 0xFF7E /* Alias for mode_switch */
+#endif /* XK_KATAKANA */
+
+/*
+ * Arabic
+ * Byte 3 = 5
+ */
+
+#ifdef XK_ARABIC
+#define XK_Arabic_comma 0x5ac
+#define XK_Arabic_semicolon 0x5bb
+#define XK_Arabic_question_mark 0x5bf
+#define XK_Arabic_hamza 0x5c1
+#define XK_Arabic_maddaonalef 0x5c2
+#define XK_Arabic_hamzaonalef 0x5c3
+#define XK_Arabic_hamzaonwaw 0x5c4
+#define XK_Arabic_hamzaunderalef 0x5c5
+#define XK_Arabic_hamzaonyeh 0x5c6
+#define XK_Arabic_alef 0x5c7
+#define XK_Arabic_beh 0x5c8
+#define XK_Arabic_tehmarbuta 0x5c9
+#define XK_Arabic_teh 0x5ca
+#define XK_Arabic_theh 0x5cb
+#define XK_Arabic_jeem 0x5cc
+#define XK_Arabic_hah 0x5cd
+#define XK_Arabic_khah 0x5ce
+#define XK_Arabic_dal 0x5cf
+#define XK_Arabic_thal 0x5d0
+#define XK_Arabic_ra 0x5d1
+#define XK_Arabic_zain 0x5d2
+#define XK_Arabic_seen 0x5d3
+#define XK_Arabic_sheen 0x5d4
+#define XK_Arabic_sad 0x5d5
+#define XK_Arabic_dad 0x5d6
+#define XK_Arabic_tah 0x5d7
+#define XK_Arabic_zah 0x5d8
+#define XK_Arabic_ain 0x5d9
+#define XK_Arabic_ghain 0x5da
+#define XK_Arabic_tatweel 0x5e0
+#define XK_Arabic_feh 0x5e1
+#define XK_Arabic_qaf 0x5e2
+#define XK_Arabic_kaf 0x5e3
+#define XK_Arabic_lam 0x5e4
+#define XK_Arabic_meem 0x5e5
+#define XK_Arabic_noon 0x5e6
+#define XK_Arabic_ha 0x5e7
+#define XK_Arabic_heh 0x5e7 /* deprecated */
+#define XK_Arabic_waw 0x5e8
+#define XK_Arabic_alefmaksura 0x5e9
+#define XK_Arabic_yeh 0x5ea
+#define XK_Arabic_fathatan 0x5eb
+#define XK_Arabic_dammatan 0x5ec
+#define XK_Arabic_kasratan 0x5ed
+#define XK_Arabic_fatha 0x5ee
+#define XK_Arabic_damma 0x5ef
+#define XK_Arabic_kasra 0x5f0
+#define XK_Arabic_shadda 0x5f1
+#define XK_Arabic_sukun 0x5f2
+#define XK_Arabic_switch 0xFF7E /* Alias for mode_switch */
+#endif /* XK_ARABIC */
+
+/*
+ * Cyrillic
+ * Byte 3 = 6
+ */
+#ifdef XK_CYRILLIC
+#define XK_Serbian_dje 0x6a1
+#define XK_Macedonia_gje 0x6a2
+#define XK_Cyrillic_io 0x6a3
+#define XK_Ukrainian_ie 0x6a4
+#define XK_Ukranian_je 0x6a4 /* deprecated */
+#define XK_Macedonia_dse 0x6a5
+#define XK_Ukrainian_i 0x6a6
+#define XK_Ukranian_i 0x6a6 /* deprecated */
+#define XK_Ukrainian_yi 0x6a7
+#define XK_Ukranian_yi 0x6a7 /* deprecated */
+#define XK_Cyrillic_je 0x6a8
+#define XK_Serbian_je 0x6a8 /* deprecated */
+#define XK_Cyrillic_lje 0x6a9
+#define XK_Serbian_lje 0x6a9 /* deprecated */
+#define XK_Cyrillic_nje 0x6aa
+#define XK_Serbian_nje 0x6aa /* deprecated */
+#define XK_Serbian_tshe 0x6ab
+#define XK_Macedonia_kje 0x6ac
+#define XK_Byelorussian_shortu 0x6ae
+#define XK_Cyrillic_dzhe 0x6af
+#define XK_Serbian_dze 0x6af /* deprecated */
+#define XK_numerosign 0x6b0
+#define XK_Serbian_DJE 0x6b1
+#define XK_Macedonia_GJE 0x6b2
+#define XK_Cyrillic_IO 0x6b3
+#define XK_Ukrainian_IE 0x6b4
+#define XK_Ukranian_JE 0x6b4 /* deprecated */
+#define XK_Macedonia_DSE 0x6b5
+#define XK_Ukrainian_I 0x6b6
+#define XK_Ukranian_I 0x6b6 /* deprecated */
+#define XK_Ukrainian_YI 0x6b7
+#define XK_Ukranian_YI 0x6b7 /* deprecated */
+#define XK_Cyrillic_JE 0x6b8
+#define XK_Serbian_JE 0x6b8 /* deprecated */
+#define XK_Cyrillic_LJE 0x6b9
+#define XK_Serbian_LJE 0x6b9 /* deprecated */
+#define XK_Cyrillic_NJE 0x6ba
+#define XK_Serbian_NJE 0x6ba /* deprecated */
+#define XK_Serbian_TSHE 0x6bb
+#define XK_Macedonia_KJE 0x6bc
+#define XK_Byelorussian_SHORTU 0x6be
+#define XK_Cyrillic_DZHE 0x6bf
+#define XK_Serbian_DZE 0x6bf /* deprecated */
+#define XK_Cyrillic_yu 0x6c0
+#define XK_Cyrillic_a 0x6c1
+#define XK_Cyrillic_be 0x6c2
+#define XK_Cyrillic_tse 0x6c3
+#define XK_Cyrillic_de 0x6c4
+#define XK_Cyrillic_ie 0x6c5
+#define XK_Cyrillic_ef 0x6c6
+#define XK_Cyrillic_ghe 0x6c7
+#define XK_Cyrillic_ha 0x6c8
+#define XK_Cyrillic_i 0x6c9
+#define XK_Cyrillic_shorti 0x6ca
+#define XK_Cyrillic_ka 0x6cb
+#define XK_Cyrillic_el 0x6cc
+#define XK_Cyrillic_em 0x6cd
+#define XK_Cyrillic_en 0x6ce
+#define XK_Cyrillic_o 0x6cf
+#define XK_Cyrillic_pe 0x6d0
+#define XK_Cyrillic_ya 0x6d1
+#define XK_Cyrillic_er 0x6d2
+#define XK_Cyrillic_es 0x6d3
+#define XK_Cyrillic_te 0x6d4
+#define XK_Cyrillic_u 0x6d5
+#define XK_Cyrillic_zhe 0x6d6
+#define XK_Cyrillic_ve 0x6d7
+#define XK_Cyrillic_softsign 0x6d8
+#define XK_Cyrillic_yeru 0x6d9
+#define XK_Cyrillic_ze 0x6da
+#define XK_Cyrillic_sha 0x6db
+#define XK_Cyrillic_e 0x6dc
+#define XK_Cyrillic_shcha 0x6dd
+#define XK_Cyrillic_che 0x6de
+#define XK_Cyrillic_hardsign 0x6df
+#define XK_Cyrillic_YU 0x6e0
+#define XK_Cyrillic_A 0x6e1
+#define XK_Cyrillic_BE 0x6e2
+#define XK_Cyrillic_TSE 0x6e3
+#define XK_Cyrillic_DE 0x6e4
+#define XK_Cyrillic_IE 0x6e5
+#define XK_Cyrillic_EF 0x6e6
+#define XK_Cyrillic_GHE 0x6e7
+#define XK_Cyrillic_HA 0x6e8
+#define XK_Cyrillic_I 0x6e9
+#define XK_Cyrillic_SHORTI 0x6ea
+#define XK_Cyrillic_KA 0x6eb
+#define XK_Cyrillic_EL 0x6ec
+#define XK_Cyrillic_EM 0x6ed
+#define XK_Cyrillic_EN 0x6ee
+#define XK_Cyrillic_O 0x6ef
+#define XK_Cyrillic_PE 0x6f0
+#define XK_Cyrillic_YA 0x6f1
+#define XK_Cyrillic_ER 0x6f2
+#define XK_Cyrillic_ES 0x6f3
+#define XK_Cyrillic_TE 0x6f4
+#define XK_Cyrillic_U 0x6f5
+#define XK_Cyrillic_ZHE 0x6f6
+#define XK_Cyrillic_VE 0x6f7
+#define XK_Cyrillic_SOFTSIGN 0x6f8
+#define XK_Cyrillic_YERU 0x6f9
+#define XK_Cyrillic_ZE 0x6fa
+#define XK_Cyrillic_SHA 0x6fb
+#define XK_Cyrillic_E 0x6fc
+#define XK_Cyrillic_SHCHA 0x6fd
+#define XK_Cyrillic_CHE 0x6fe
+#define XK_Cyrillic_HARDSIGN 0x6ff
+#endif /* XK_CYRILLIC */
+
+/*
+ * Greek
+ * Byte 3 = 7
+ */
+
+#ifdef XK_GREEK
+#define XK_Greek_ALPHAaccent 0x7a1
+#define XK_Greek_EPSILONaccent 0x7a2
+#define XK_Greek_ETAaccent 0x7a3
+#define XK_Greek_IOTAaccent 0x7a4
+#define XK_Greek_IOTAdiaeresis 0x7a5
+#define XK_Greek_OMICRONaccent 0x7a7
+#define XK_Greek_UPSILONaccent 0x7a8
+#define XK_Greek_UPSILONdieresis 0x7a9
+#define XK_Greek_OMEGAaccent 0x7ab
+#define XK_Greek_accentdieresis 0x7ae
+#define XK_Greek_horizbar 0x7af
+#define XK_Greek_alphaaccent 0x7b1
+#define XK_Greek_epsilonaccent 0x7b2
+#define XK_Greek_etaaccent 0x7b3
+#define XK_Greek_iotaaccent 0x7b4
+#define XK_Greek_iotadieresis 0x7b5
+#define XK_Greek_iotaaccentdieresis 0x7b6
+#define XK_Greek_omicronaccent 0x7b7
+#define XK_Greek_upsilonaccent 0x7b8
+#define XK_Greek_upsilondieresis 0x7b9
+#define XK_Greek_upsilonaccentdieresis 0x7ba
+#define XK_Greek_omegaaccent 0x7bb
+#define XK_Greek_ALPHA 0x7c1
+#define XK_Greek_BETA 0x7c2
+#define XK_Greek_GAMMA 0x7c3
+#define XK_Greek_DELTA 0x7c4
+#define XK_Greek_EPSILON 0x7c5
+#define XK_Greek_ZETA 0x7c6
+#define XK_Greek_ETA 0x7c7
+#define XK_Greek_THETA 0x7c8
+#define XK_Greek_IOTA 0x7c9
+#define XK_Greek_KAPPA 0x7ca
+#define XK_Greek_LAMDA 0x7cb
+#define XK_Greek_LAMBDA 0x7cb
+#define XK_Greek_MU 0x7cc
+#define XK_Greek_NU 0x7cd
+#define XK_Greek_XI 0x7ce
+#define XK_Greek_OMICRON 0x7cf
+#define XK_Greek_PI 0x7d0
+#define XK_Greek_RHO 0x7d1
+#define XK_Greek_SIGMA 0x7d2
+#define XK_Greek_TAU 0x7d4
+#define XK_Greek_UPSILON 0x7d5
+#define XK_Greek_PHI 0x7d6
+#define XK_Greek_CHI 0x7d7
+#define XK_Greek_PSI 0x7d8
+#define XK_Greek_OMEGA 0x7d9
+#define XK_Greek_alpha 0x7e1
+#define XK_Greek_beta 0x7e2
+#define XK_Greek_gamma 0x7e3
+#define XK_Greek_delta 0x7e4
+#define XK_Greek_epsilon 0x7e5
+#define XK_Greek_zeta 0x7e6
+#define XK_Greek_eta 0x7e7
+#define XK_Greek_theta 0x7e8
+#define XK_Greek_iota 0x7e9
+#define XK_Greek_kappa 0x7ea
+#define XK_Greek_lamda 0x7eb
+#define XK_Greek_lambda 0x7eb
+#define XK_Greek_mu 0x7ec
+#define XK_Greek_nu 0x7ed
+#define XK_Greek_xi 0x7ee
+#define XK_Greek_omicron 0x7ef
+#define XK_Greek_pi 0x7f0
+#define XK_Greek_rho 0x7f1
+#define XK_Greek_sigma 0x7f2
+#define XK_Greek_finalsmallsigma 0x7f3
+#define XK_Greek_tau 0x7f4
+#define XK_Greek_upsilon 0x7f5
+#define XK_Greek_phi 0x7f6
+#define XK_Greek_chi 0x7f7
+#define XK_Greek_psi 0x7f8
+#define XK_Greek_omega 0x7f9
+#define XK_Greek_switch 0xFF7E /* Alias for mode_switch */
+#endif /* XK_GREEK */
+
+/*
+ * Technical
+ * Byte 3 = 8
+ */
+
+#ifdef XK_TECHNICAL
+#define XK_leftradical 0x8a1
+#define XK_topleftradical 0x8a2
+#define XK_horizconnector 0x8a3
+#define XK_topintegral 0x8a4
+#define XK_botintegral 0x8a5
+#define XK_vertconnector 0x8a6
+#define XK_topleftsqbracket 0x8a7
+#define XK_botleftsqbracket 0x8a8
+#define XK_toprightsqbracket 0x8a9
+#define XK_botrightsqbracket 0x8aa
+#define XK_topleftparens 0x8ab
+#define XK_botleftparens 0x8ac
+#define XK_toprightparens 0x8ad
+#define XK_botrightparens 0x8ae
+#define XK_leftmiddlecurlybrace 0x8af
+#define XK_rightmiddlecurlybrace 0x8b0
+#define XK_topleftsummation 0x8b1
+#define XK_botleftsummation 0x8b2
+#define XK_topvertsummationconnector 0x8b3
+#define XK_botvertsummationconnector 0x8b4
+#define XK_toprightsummation 0x8b5
+#define XK_botrightsummation 0x8b6
+#define XK_rightmiddlesummation 0x8b7
+#define XK_lessthanequal 0x8bc
+#define XK_notequal 0x8bd
+#define XK_greaterthanequal 0x8be
+#define XK_integral 0x8bf
+#define XK_therefore 0x8c0
+#define XK_variation 0x8c1
+#define XK_infinity 0x8c2
+#define XK_nabla 0x8c5
+#define XK_approximate 0x8c8
+#define XK_similarequal 0x8c9
+#define XK_ifonlyif 0x8cd
+#define XK_implies 0x8ce
+#define XK_identical 0x8cf
+#define XK_radical 0x8d6
+#define XK_includedin 0x8da
+#define XK_includes 0x8db
+#define XK_intersection 0x8dc
+#define XK_union 0x8dd
+#define XK_logicaland 0x8de
+#define XK_logicalor 0x8df
+#define XK_partialderivative 0x8ef
+#define XK_function 0x8f6
+#define XK_leftarrow 0x8fb
+#define XK_uparrow 0x8fc
+#define XK_rightarrow 0x8fd
+#define XK_downarrow 0x8fe
+#endif /* XK_TECHNICAL */
+
+/*
+ * Special
+ * Byte 3 = 9
+ */
+
+#ifdef XK_SPECIAL
+#define XK_blank 0x9df
+#define XK_soliddiamond 0x9e0
+#define XK_checkerboard 0x9e1
+#define XK_ht 0x9e2
+#define XK_ff 0x9e3
+#define XK_cr 0x9e4
+#define XK_lf 0x9e5
+#define XK_nl 0x9e8
+#define XK_vt 0x9e9
+#define XK_lowrightcorner 0x9ea
+#define XK_uprightcorner 0x9eb
+#define XK_upleftcorner 0x9ec
+#define XK_lowleftcorner 0x9ed
+#define XK_crossinglines 0x9ee
+#define XK_horizlinescan1 0x9ef
+#define XK_horizlinescan3 0x9f0
+#define XK_horizlinescan5 0x9f1
+#define XK_horizlinescan7 0x9f2
+#define XK_horizlinescan9 0x9f3
+#define XK_leftt 0x9f4
+#define XK_rightt 0x9f5
+#define XK_bott 0x9f6
+#define XK_topt 0x9f7
+#define XK_vertbar 0x9f8
+#endif /* XK_SPECIAL */
+
+/*
+ * Publishing
+ * Byte 3 = a
+ */
+
+#ifdef XK_PUBLISHING
+#define XK_emspace 0xaa1
+#define XK_enspace 0xaa2
+#define XK_em3space 0xaa3
+#define XK_em4space 0xaa4
+#define XK_digitspace 0xaa5
+#define XK_punctspace 0xaa6
+#define XK_thinspace 0xaa7
+#define XK_hairspace 0xaa8
+#define XK_emdash 0xaa9
+#define XK_endash 0xaaa
+#define XK_signifblank 0xaac
+#define XK_ellipsis 0xaae
+#define XK_doubbaselinedot 0xaaf
+#define XK_onethird 0xab0
+#define XK_twothirds 0xab1
+#define XK_onefifth 0xab2
+#define XK_twofifths 0xab3
+#define XK_threefifths 0xab4
+#define XK_fourfifths 0xab5
+#define XK_onesixth 0xab6
+#define XK_fivesixths 0xab7
+#define XK_careof 0xab8
+#define XK_figdash 0xabb
+#define XK_leftanglebracket 0xabc
+#define XK_decimalpoint 0xabd
+#define XK_rightanglebracket 0xabe
+#define XK_marker 0xabf
+#define XK_oneeighth 0xac3
+#define XK_threeeighths 0xac4
+#define XK_fiveeighths 0xac5
+#define XK_seveneighths 0xac6
+#define XK_trademark 0xac9
+#define XK_signaturemark 0xaca
+#define XK_trademarkincircle 0xacb
+#define XK_leftopentriangle 0xacc
+#define XK_rightopentriangle 0xacd
+#define XK_emopencircle 0xace
+#define XK_emopenrectangle 0xacf
+#define XK_leftsinglequotemark 0xad0
+#define XK_rightsinglequotemark 0xad1
+#define XK_leftdoublequotemark 0xad2
+#define XK_rightdoublequotemark 0xad3
+#define XK_prescription 0xad4
+#define XK_minutes 0xad6
+#define XK_seconds 0xad7
+#define XK_latincross 0xad9
+#define XK_hexagram 0xada
+#define XK_filledrectbullet 0xadb
+#define XK_filledlefttribullet 0xadc
+#define XK_filledrighttribullet 0xadd
+#define XK_emfilledcircle 0xade
+#define XK_emfilledrect 0xadf
+#define XK_enopencircbullet 0xae0
+#define XK_enopensquarebullet 0xae1
+#define XK_openrectbullet 0xae2
+#define XK_opentribulletup 0xae3
+#define XK_opentribulletdown 0xae4
+#define XK_openstar 0xae5
+#define XK_enfilledcircbullet 0xae6
+#define XK_enfilledsqbullet 0xae7
+#define XK_filledtribulletup 0xae8
+#define XK_filledtribulletdown 0xae9
+#define XK_leftpointer 0xaea
+#define XK_rightpointer 0xaeb
+#define XK_club 0xaec
+#define XK_diamond 0xaed
+#define XK_heart 0xaee
+#define XK_maltesecross 0xaf0
+#define XK_dagger 0xaf1
+#define XK_doubledagger 0xaf2
+#define XK_checkmark 0xaf3
+#define XK_ballotcross 0xaf4
+#define XK_musicalsharp 0xaf5
+#define XK_musicalflat 0xaf6
+#define XK_malesymbol 0xaf7
+#define XK_femalesymbol 0xaf8
+#define XK_telephone 0xaf9
+#define XK_telephonerecorder 0xafa
+#define XK_phonographcopyright 0xafb
+#define XK_caret 0xafc
+#define XK_singlelowquotemark 0xafd
+#define XK_doublelowquotemark 0xafe
+#define XK_cursor 0xaff
+#endif /* XK_PUBLISHING */
+
+/*
+ * APL
+ * Byte 3 = b
+ */
+
+#ifdef XK_APL
+#define XK_leftcaret 0xba3
+#define XK_rightcaret 0xba6
+#define XK_downcaret 0xba8
+#define XK_upcaret 0xba9
+#define XK_overbar 0xbc0
+#define XK_downtack 0xbc2
+#define XK_upshoe 0xbc3
+#define XK_downstile 0xbc4
+#define XK_underbar 0xbc6
+#define XK_jot 0xbca
+#define XK_quad 0xbcc
+#define XK_uptack 0xbce
+#define XK_circle 0xbcf
+#define XK_upstile 0xbd3
+#define XK_downshoe 0xbd6
+#define XK_rightshoe 0xbd8
+#define XK_leftshoe 0xbda
+#define XK_lefttack 0xbdc
+#define XK_righttack 0xbfc
+#endif /* XK_APL */
+
+/*
+ * Hebrew
+ * Byte 3 = c
+ */
+
+#ifdef XK_HEBREW
+#define XK_hebrew_doublelowline 0xcdf
+#define XK_hebrew_aleph 0xce0
+#define XK_hebrew_bet 0xce1
+#define XK_hebrew_beth 0xce1 /* deprecated */
+#define XK_hebrew_gimel 0xce2
+#define XK_hebrew_gimmel 0xce2 /* deprecated */
+#define XK_hebrew_dalet 0xce3
+#define XK_hebrew_daleth 0xce3 /* deprecated */
+#define XK_hebrew_he 0xce4
+#define XK_hebrew_waw 0xce5
+#define XK_hebrew_zain 0xce6
+#define XK_hebrew_zayin 0xce6 /* deprecated */
+#define XK_hebrew_chet 0xce7
+#define XK_hebrew_het 0xce7 /* deprecated */
+#define XK_hebrew_tet 0xce8
+#define XK_hebrew_teth 0xce8 /* deprecated */
+#define XK_hebrew_yod 0xce9
+#define XK_hebrew_finalkaph 0xcea
+#define XK_hebrew_kaph 0xceb
+#define XK_hebrew_lamed 0xcec
+#define XK_hebrew_finalmem 0xced
+#define XK_hebrew_mem 0xcee
+#define XK_hebrew_finalnun 0xcef
+#define XK_hebrew_nun 0xcf0
+#define XK_hebrew_samech 0xcf1
+#define XK_hebrew_samekh 0xcf1 /* deprecated */
+#define XK_hebrew_ayin 0xcf2
+#define XK_hebrew_finalpe 0xcf3
+#define XK_hebrew_pe 0xcf4
+#define XK_hebrew_finalzade 0xcf5
+#define XK_hebrew_finalzadi 0xcf5 /* deprecated */
+#define XK_hebrew_zade 0xcf6
+#define XK_hebrew_zadi 0xcf6 /* deprecated */
+#define XK_hebrew_qoph 0xcf7
+#define XK_hebrew_kuf 0xcf7 /* deprecated */
+#define XK_hebrew_resh 0xcf8
+#define XK_hebrew_shin 0xcf9
+#define XK_hebrew_taw 0xcfa
+#define XK_hebrew_taf 0xcfa /* deprecated */
+#define XK_Hebrew_switch 0xFF7E /* Alias for mode_switch */
+#endif /* XK_HEBREW */
+
+/*
+ * Thai
+ * Byte 3 = d
+ */
+
+#ifdef XK_THAI
+#define XK_Thai_kokai 0xda1
+#define XK_Thai_khokhai 0xda2
+#define XK_Thai_khokhuat 0xda3
+#define XK_Thai_khokhwai 0xda4
+#define XK_Thai_khokhon 0xda5
+#define XK_Thai_khorakhang 0xda6
+#define XK_Thai_ngongu 0xda7
+#define XK_Thai_chochan 0xda8
+#define XK_Thai_choching 0xda9
+#define XK_Thai_chochang 0xdaa
+#define XK_Thai_soso 0xdab
+#define XK_Thai_chochoe 0xdac
+#define XK_Thai_yoying 0xdad
+#define XK_Thai_dochada 0xdae
+#define XK_Thai_topatak 0xdaf
+#define XK_Thai_thothan 0xdb0
+#define XK_Thai_thonangmontho 0xdb1
+#define XK_Thai_thophuthao 0xdb2
+#define XK_Thai_nonen 0xdb3
+#define XK_Thai_dodek 0xdb4
+#define XK_Thai_totao 0xdb5
+#define XK_Thai_thothung 0xdb6
+#define XK_Thai_thothahan 0xdb7
+#define XK_Thai_thothong 0xdb8
+#define XK_Thai_nonu 0xdb9
+#define XK_Thai_bobaimai 0xdba
+#define XK_Thai_popla 0xdbb
+#define XK_Thai_phophung 0xdbc
+#define XK_Thai_fofa 0xdbd
+#define XK_Thai_phophan 0xdbe
+#define XK_Thai_fofan 0xdbf
+#define XK_Thai_phosamphao 0xdc0
+#define XK_Thai_moma 0xdc1
+#define XK_Thai_yoyak 0xdc2
+#define XK_Thai_rorua 0xdc3
+#define XK_Thai_ru 0xdc4
+#define XK_Thai_loling 0xdc5
+#define XK_Thai_lu 0xdc6
+#define XK_Thai_wowaen 0xdc7
+#define XK_Thai_sosala 0xdc8
+#define XK_Thai_sorusi 0xdc9
+#define XK_Thai_sosua 0xdca
+#define XK_Thai_hohip 0xdcb
+#define XK_Thai_lochula 0xdcc
+#define XK_Thai_oang 0xdcd
+#define XK_Thai_honokhuk 0xdce
+#define XK_Thai_paiyannoi 0xdcf
+#define XK_Thai_saraa 0xdd0
+#define XK_Thai_maihanakat 0xdd1
+#define XK_Thai_saraaa 0xdd2
+#define XK_Thai_saraam 0xdd3
+#define XK_Thai_sarai 0xdd4
+#define XK_Thai_saraii 0xdd5
+#define XK_Thai_saraue 0xdd6
+#define XK_Thai_sarauee 0xdd7
+#define XK_Thai_sarau 0xdd8
+#define XK_Thai_sarauu 0xdd9
+#define XK_Thai_phinthu 0xdda
+#define XK_Thai_maihanakat_maitho 0xdde
+#define XK_Thai_baht 0xddf
+#define XK_Thai_sarae 0xde0
+#define XK_Thai_saraae 0xde1
+#define XK_Thai_sarao 0xde2
+#define XK_Thai_saraaimaimuan 0xde3
+#define XK_Thai_saraaimaimalai 0xde4
+#define XK_Thai_lakkhangyao 0xde5
+#define XK_Thai_maiyamok 0xde6
+#define XK_Thai_maitaikhu 0xde7
+#define XK_Thai_maiek 0xde8
+#define XK_Thai_maitho 0xde9
+#define XK_Thai_maitri 0xdea
+#define XK_Thai_maichattawa 0xdeb
+#define XK_Thai_thanthakhat 0xdec
+#define XK_Thai_nikhahit 0xded
+#define XK_Thai_leksun 0xdf0
+#define XK_Thai_leknung 0xdf1
+#define XK_Thai_leksong 0xdf2
+#define XK_Thai_leksam 0xdf3
+#define XK_Thai_leksi 0xdf4
+#define XK_Thai_lekha 0xdf5
+#define XK_Thai_lekhok 0xdf6
+#define XK_Thai_lekchet 0xdf7
+#define XK_Thai_lekpaet 0xdf8
+#define XK_Thai_lekkao 0xdf9
+#endif /* XK_THAI */
+
+/*
+ * Korean
+ * Byte 3 = e
+ */
+
+#ifdef XK_KOREAN
+
+#define XK_Hangul 0xff31 /* Hangul start/stop(toggle) */
+#define XK_Hangul_Start 0xff32 /* Hangul start */
+#define XK_Hangul_End 0xff33 /* Hangul end, English start */
+#define XK_Hangul_Hanja 0xff34 /* Start Hangul->Hanja Conversion */
+#define XK_Hangul_Jamo 0xff35 /* Hangul Jamo mode */
+#define XK_Hangul_Romaja 0xff36 /* Hangul Romaja mode */
+#define XK_Hangul_Codeinput 0xff37 /* Hangul code input mode */
+#define XK_Hangul_Jeonja 0xff38 /* Jeonja mode */
+#define XK_Hangul_Banja 0xff39 /* Banja mode */
+#define XK_Hangul_PreHanja 0xff3a /* Pre Hanja conversion */
+#define XK_Hangul_PostHanja 0xff3b /* Post Hanja conversion */
+#define XK_Hangul_SingleCandidate 0xff3c /* Single candidate */
+#define XK_Hangul_MultipleCandidate 0xff3d /* Multiple candidate */
+#define XK_Hangul_PreviousCandidate 0xff3e /* Previous candidate */
+#define XK_Hangul_Special 0xff3f /* Special symbols */
+#define XK_Hangul_switch 0xFF7E /* Alias for mode_switch */
+
+/* Hangul Consonant Characters */
+#define XK_Hangul_Kiyeog 0xea1
+#define XK_Hangul_SsangKiyeog 0xea2
+#define XK_Hangul_KiyeogSios 0xea3
+#define XK_Hangul_Nieun 0xea4
+#define XK_Hangul_NieunJieuj 0xea5
+#define XK_Hangul_NieunHieuh 0xea6
+#define XK_Hangul_Dikeud 0xea7
+#define XK_Hangul_SsangDikeud 0xea8
+#define XK_Hangul_Rieul 0xea9
+#define XK_Hangul_RieulKiyeog 0xeaa
+#define XK_Hangul_RieulMieum 0xeab
+#define XK_Hangul_RieulPieub 0xeac
+#define XK_Hangul_RieulSios 0xead
+#define XK_Hangul_RieulTieut 0xeae
+#define XK_Hangul_RieulPhieuf 0xeaf
+#define XK_Hangul_RieulHieuh 0xeb0
+#define XK_Hangul_Mieum 0xeb1
+#define XK_Hangul_Pieub 0xeb2
+#define XK_Hangul_SsangPieub 0xeb3
+#define XK_Hangul_PieubSios 0xeb4
+#define XK_Hangul_Sios 0xeb5
+#define XK_Hangul_SsangSios 0xeb6
+#define XK_Hangul_Ieung 0xeb7
+#define XK_Hangul_Jieuj 0xeb8
+#define XK_Hangul_SsangJieuj 0xeb9
+#define XK_Hangul_Cieuc 0xeba
+#define XK_Hangul_Khieuq 0xebb
+#define XK_Hangul_Tieut 0xebc
+#define XK_Hangul_Phieuf 0xebd
+#define XK_Hangul_Hieuh 0xebe
+
+/* Hangul Vowel Characters */
+#define XK_Hangul_A 0xebf
+#define XK_Hangul_AE 0xec0
+#define XK_Hangul_YA 0xec1
+#define XK_Hangul_YAE 0xec2
+#define XK_Hangul_EO 0xec3
+#define XK_Hangul_E 0xec4
+#define XK_Hangul_YEO 0xec5
+#define XK_Hangul_YE 0xec6
+#define XK_Hangul_O 0xec7
+#define XK_Hangul_WA 0xec8
+#define XK_Hangul_WAE 0xec9
+#define XK_Hangul_OE 0xeca
+#define XK_Hangul_YO 0xecb
+#define XK_Hangul_U 0xecc
+#define XK_Hangul_WEO 0xecd
+#define XK_Hangul_WE 0xece
+#define XK_Hangul_WI 0xecf
+#define XK_Hangul_YU 0xed0
+#define XK_Hangul_EU 0xed1
+#define XK_Hangul_YI 0xed2
+#define XK_Hangul_I 0xed3
+
+/* Hangul syllable-final (JongSeong) Characters */
+#define XK_Hangul_J_Kiyeog 0xed4
+#define XK_Hangul_J_SsangKiyeog 0xed5
+#define XK_Hangul_J_KiyeogSios 0xed6
+#define XK_Hangul_J_Nieun 0xed7
+#define XK_Hangul_J_NieunJieuj 0xed8
+#define XK_Hangul_J_NieunHieuh 0xed9
+#define XK_Hangul_J_Dikeud 0xeda
+#define XK_Hangul_J_Rieul 0xedb
+#define XK_Hangul_J_RieulKiyeog 0xedc
+#define XK_Hangul_J_RieulMieum 0xedd
+#define XK_Hangul_J_RieulPieub 0xede
+#define XK_Hangul_J_RieulSios 0xedf
+#define XK_Hangul_J_RieulTieut 0xee0
+#define XK_Hangul_J_RieulPhieuf 0xee1
+#define XK_Hangul_J_RieulHieuh 0xee2
+#define XK_Hangul_J_Mieum 0xee3
+#define XK_Hangul_J_Pieub 0xee4
+#define XK_Hangul_J_PieubSios 0xee5
+#define XK_Hangul_J_Sios 0xee6
+#define XK_Hangul_J_SsangSios 0xee7
+#define XK_Hangul_J_Ieung 0xee8
+#define XK_Hangul_J_Jieuj 0xee9
+#define XK_Hangul_J_Cieuc 0xeea
+#define XK_Hangul_J_Khieuq 0xeeb
+#define XK_Hangul_J_Tieut 0xeec
+#define XK_Hangul_J_Phieuf 0xeed
+#define XK_Hangul_J_Hieuh 0xeee
+
+/* Ancient Hangul Consonant Characters */
+#define XK_Hangul_RieulYeorinHieuh 0xeef
+#define XK_Hangul_SunkyeongeumMieum 0xef0
+#define XK_Hangul_SunkyeongeumPieub 0xef1
+#define XK_Hangul_PanSios 0xef2
+#define XK_Hangul_KkogjiDalrinIeung 0xef3
+#define XK_Hangul_SunkyeongeumPhieuf 0xef4
+#define XK_Hangul_YeorinHieuh 0xef5
+
+/* Ancient Hangul Vowel Characters */
+#define XK_Hangul_AraeA 0xef6
+#define XK_Hangul_AraeAE 0xef7
+
+/* Ancient Hangul syllable-final (JongSeong) Characters */
+#define XK_Hangul_J_PanSios 0xef8
+#define XK_Hangul_J_KkogjiDalrinIeung 0xef9
+#define XK_Hangul_J_YeorinHieuh 0xefa
+
+/* Korean currency symbol */
+#define XK_Korean_Won 0xeff
+
+#endif /* XK_KOREAN */
+
+/* Euro currency symbol */
+#define XK_EuroSign 0x20ac
+
+#endif
diff --git a/krfb/libvncserver/mac.c b/krfb/libvncserver/mac.c
new file mode 100644
index 00000000..a3c4f3c6
--- /dev/null
+++ b/krfb/libvncserver/mac.c
@@ -0,0 +1,604 @@
+
+/*
+ * OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
+ * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
+ * All Rights Reserved.
+ *
+ * Cut in two parts by Johannes Schindelin (2001): libvncserver and OSXvnc.
+ *
+ *
+ * This file implements every system specific function for Mac OS X.
+ *
+ * It includes the keyboard functions:
+ *
+ void KbdAddEvent(down, keySym, cl)
+ Bool down;
+ KeySym keySym;
+ rfbClientPtr cl;
+ void KbdReleaseAllKeys()
+ *
+ * the mouse functions:
+ *
+ void PtrAddEvent(buttonMask, x, y, cl)
+ int buttonMask;
+ int x;
+ int y;
+ rfbClientPtr cl;
+ *
+ */
+
+#define LOCAL_CONTROL
+
+#ifdef LOCAL_CONTROL
+#include "1instance.c"
+#endif
+
+#include <unistd.h>
+#include <ApplicationServices/ApplicationServices.h>
+#include <Carbon/Carbon.h>
+/* zlib doesn't like Byte already defined */
+#undef Byte
+#undef TRUE
+#undef Bool
+#include "rfb.h"
+#include "keysym.h"
+
+#include <IOKit/pwr_mgt/IOPMLib.h>
+#include <IOKit/pwr_mgt/IOPM.h>
+#include <stdio.h>
+#include <signal.h>
+#include <pthread.h>
+
+Bool rfbNoDimming = FALSE;
+Bool rfbNoSleep = TRUE;
+
+static pthread_mutex_t dimming_mutex;
+static unsigned long dim_time;
+static unsigned long sleep_time;
+static mach_port_t master_dev_port;
+static io_connect_t power_mgt;
+static Bool initialized = FALSE;
+static Bool dim_time_saved = FALSE;
+static Bool sleep_time_saved = FALSE;
+
+static int
+saveDimSettings(void)
+{
+ if (IOPMGetAggressiveness(power_mgt,
+ kPMMinutesToDim,
+ &dim_time) != kIOReturnSuccess)
+ return -1;
+
+ dim_time_saved = TRUE;
+ return 0;
+}
+
+static int
+restoreDimSettings(void)
+{
+ if (!dim_time_saved)
+ return -1;
+
+ if (IOPMSetAggressiveness(power_mgt,
+ kPMMinutesToDim,
+ dim_time) != kIOReturnSuccess)
+ return -1;
+
+ dim_time_saved = FALSE;
+ dim_time = 0;
+ return 0;
+}
+
+static int
+saveSleepSettings(void)
+{
+ if (IOPMGetAggressiveness(power_mgt,
+ kPMMinutesToSleep,
+ &sleep_time) != kIOReturnSuccess)
+ return -1;
+
+ sleep_time_saved = TRUE;
+ return 0;
+}
+
+static int
+restoreSleepSettings(void)
+{
+ if (!sleep_time_saved)
+ return -1;
+
+ if (IOPMSetAggressiveness(power_mgt,
+ kPMMinutesToSleep,
+ sleep_time) != kIOReturnSuccess)
+ return -1;
+
+ sleep_time_saved = FALSE;
+ sleep_time = 0;
+ return 0;
+}
+
+
+int
+rfbDimmingInit(void)
+{
+ pthread_mutex_init(&dimming_mutex, NULL);
+
+ if (IOMasterPort(bootstrap_port, &master_dev_port) != kIOReturnSuccess)
+ return -1;
+
+ if (!(power_mgt = IOPMFindPowerManagement(master_dev_port)))
+ return -1;
+
+ if (rfbNoDimming) {
+ if (saveDimSettings() < 0)
+ return -1;
+ if (IOPMSetAggressiveness(power_mgt,
+ kPMMinutesToDim, 0) != kIOReturnSuccess)
+ return -1;
+ }
+
+ if (rfbNoSleep) {
+ if (saveSleepSettings() < 0)
+ return -1;
+ if (IOPMSetAggressiveness(power_mgt,
+ kPMMinutesToSleep, 0) != kIOReturnSuccess)
+ return -1;
+ }
+
+ initialized = TRUE;
+ return 0;
+}
+
+
+int
+rfbUndim(void)
+{
+ int result = -1;
+
+ pthread_mutex_lock(&dimming_mutex);
+
+ if (!initialized)
+ goto DONE;
+
+ if (!rfbNoDimming) {
+ if (saveDimSettings() < 0)
+ goto DONE;
+ if (IOPMSetAggressiveness(power_mgt, kPMMinutesToDim, 0) != kIOReturnSuccess)
+ goto DONE;
+ if (restoreDimSettings() < 0)
+ goto DONE;
+ }
+
+ if (!rfbNoSleep) {
+ if (saveSleepSettings() < 0)
+ goto DONE;
+ if (IOPMSetAggressiveness(power_mgt, kPMMinutesToSleep, 0) != kIOReturnSuccess)
+ goto DONE;
+ if (restoreSleepSettings() < 0)
+ goto DONE;
+ }
+
+ result = 0;
+
+ DONE:
+ pthread_mutex_unlock(&dimming_mutex);
+ return result;
+}
+
+
+int
+rfbDimmingShutdown(void)
+{
+ int result = -1;
+
+ if (!initialized)
+ goto DONE;
+
+ pthread_mutex_lock(&dimming_mutex);
+ if (dim_time_saved)
+ if (restoreDimSettings() < 0)
+ goto DONE;
+ if (sleep_time_saved)
+ if (restoreSleepSettings() < 0)
+ goto DONE;
+
+ result = 0;
+
+ DONE:
+ pthread_mutex_unlock(&dimming_mutex);
+ return result;
+}
+
+rfbScreenInfoPtr rfbScreen;
+
+void rfbShutdown(rfbClientPtr cl);
+
+/* some variables to enable special behaviour */
+int startTime = -1, maxSecsToConnect = 0;
+Bool disconnectAfterFirstClient = TRUE;
+
+/* Where do I get the "official" list of Mac key codes?
+ Ripped these out of a Mac II emulator called Basilisk II
+ that I found on the net. */
+static int keyTable[] = {
+ /* The alphabet */
+ XK_A, 0, /* A */
+ XK_B, 11, /* B */
+ XK_C, 8, /* C */
+ XK_D, 2, /* D */
+ XK_E, 14, /* E */
+ XK_F, 3, /* F */
+ XK_G, 5, /* G */
+ XK_H, 4, /* H */
+ XK_I, 34, /* I */
+ XK_J, 38, /* J */
+ XK_K, 40, /* K */
+ XK_L, 37, /* L */
+ XK_M, 46, /* M */
+ XK_N, 45, /* N */
+ XK_O, 31, /* O */
+ XK_P, 35, /* P */
+ XK_Q, 12, /* Q */
+ XK_R, 15, /* R */
+ XK_S, 1, /* S */
+ XK_T, 17, /* T */
+ XK_U, 32, /* U */
+ XK_V, 9, /* V */
+ XK_W, 13, /* W */
+ XK_X, 7, /* X */
+ XK_Y, 16, /* Y */
+ XK_Z, 6, /* Z */
+ XK_a, 0, /* a */
+ XK_b, 11, /* b */
+ XK_c, 8, /* c */
+ XK_d, 2, /* d */
+ XK_e, 14, /* e */
+ XK_f, 3, /* f */
+ XK_g, 5, /* g */
+ XK_h, 4, /* h */
+ XK_i, 34, /* i */
+ XK_j, 38, /* j */
+ XK_k, 40, /* k */
+ XK_l, 37, /* l */
+ XK_m, 46, /* m */
+ XK_n, 45, /* n */
+ XK_o, 31, /* o */
+ XK_p, 35, /* p */
+ XK_q, 12, /* q */
+ XK_r, 15, /* r */
+ XK_s, 1, /* s */
+ XK_t, 17, /* t */
+ XK_u, 32, /* u */
+ XK_v, 9, /* v */
+ XK_w, 13, /* w */
+ XK_x, 7, /* x */
+ XK_y, 16, /* y */
+ XK_z, 6, /* z */
+
+ /* Numbers */
+ XK_0, 29, /* 0 */
+ XK_1, 18, /* 1 */
+ XK_2, 19, /* 2 */
+ XK_3, 20, /* 3 */
+ XK_4, 21, /* 4 */
+ XK_5, 23, /* 5 */
+ XK_6, 22, /* 6 */
+ XK_7, 26, /* 7 */
+ XK_8, 28, /* 8 */
+ XK_9, 25, /* 9 */
+
+ /* Symbols */
+ XK_exclam, 18, /* ! */
+ XK_at, 19, /* @ */
+ XK_numbersign, 20, /* # */
+ XK_dollar, 21, /* $ */
+ XK_percent, 23, /* % */
+ XK_asciicircum, 22, /* ^ */
+ XK_ampersand, 26, /* & */
+ XK_asterisk, 28, /* * */
+ XK_parenleft, 25, /* ( */
+ XK_parenright, 29, /* ) */
+ XK_minus, 27, /* - */
+ XK_underscore, 27, /* _ */
+ XK_equal, 24, /* = */
+ XK_plus, 24, /* + */
+ XK_grave, 10, /* ` */ /* XXX ? */
+ XK_asciitilde, 10, /* ~ */
+ XK_bracketleft, 33, /* [ */
+ XK_braceleft, 33, /* { */
+ XK_bracketright, 30, /* ] */
+ XK_braceright, 30, /* } */
+ XK_semicolon, 41, /* ; */
+ XK_colon, 41, /* : */
+ XK_apostrophe, 39, /* ' */
+ XK_quotedbl, 39, /* " */
+ XK_comma, 43, /* , */
+ XK_less, 43, /* < */
+ XK_period, 47, /* . */
+ XK_greater, 47, /* > */
+ XK_slash, 44, /* / */
+ XK_question, 44, /* ? */
+ XK_backslash, 42, /* \ */
+ XK_bar, 42, /* | */
+
+ /* "Special" keys */
+ XK_space, 49, /* Space */
+ XK_Return, 36, /* Return */
+ XK_Delete, 117, /* Delete */
+ XK_Tab, 48, /* Tab */
+ XK_Escape, 53, /* Esc */
+ XK_Caps_Lock, 57, /* Caps Lock */
+ XK_Num_Lock, 71, /* Num Lock */
+ XK_Scroll_Lock, 107, /* Scroll Lock */
+ XK_Pause, 113, /* Pause */
+ XK_BackSpace, 51, /* Backspace */
+ XK_Insert, 114, /* Insert */
+
+ /* Cursor movement */
+ XK_Up, 126, /* Cursor Up */
+ XK_Down, 125, /* Cursor Down */
+ XK_Left, 123, /* Cursor Left */
+ XK_Right, 124, /* Cursor Right */
+ XK_Page_Up, 116, /* Page Up */
+ XK_Page_Down, 121, /* Page Down */
+ XK_Home, 115, /* Home */
+ XK_End, 119, /* End */
+
+ /* Numeric keypad */
+ XK_KP_0, 82, /* KP 0 */
+ XK_KP_1, 83, /* KP 1 */
+ XK_KP_2, 84, /* KP 2 */
+ XK_KP_3, 85, /* KP 3 */
+ XK_KP_4, 86, /* KP 4 */
+ XK_KP_5, 87, /* KP 5 */
+ XK_KP_6, 88, /* KP 6 */
+ XK_KP_7, 89, /* KP 7 */
+ XK_KP_8, 91, /* KP 8 */
+ XK_KP_9, 92, /* KP 9 */
+ XK_KP_Enter, 76, /* KP Enter */
+ XK_KP_Decimal, 65, /* KP . */
+ XK_KP_Add, 69, /* KP + */
+ XK_KP_Subtract, 78, /* KP - */
+ XK_KP_Multiply, 67, /* KP * */
+ XK_KP_Divide, 75, /* KP / */
+
+ /* Function keys */
+ XK_F1, 122, /* F1 */
+ XK_F2, 120, /* F2 */
+ XK_F3, 99, /* F3 */
+ XK_F4, 118, /* F4 */
+ XK_F5, 96, /* F5 */
+ XK_F6, 97, /* F6 */
+ XK_F7, 98, /* F7 */
+ XK_F8, 100, /* F8 */
+ XK_F9, 101, /* F9 */
+ XK_F10, 109, /* F10 */
+ XK_F11, 103, /* F11 */
+ XK_F12, 111, /* F12 */
+
+ /* Modifier keys */
+ XK_Shift_L, 56, /* Shift Left */
+ XK_Shift_R, 56, /* Shift Right */
+ XK_Control_L, 59, /* Ctrl Left */
+ XK_Control_R, 59, /* Ctrl Right */
+ XK_Meta_L, 58, /* Logo Left (-> Option) */
+ XK_Meta_R, 58, /* Logo Right (-> Option) */
+ XK_Alt_L, 55, /* Alt Left (-> Command) */
+ XK_Alt_R, 55, /* Alt Right (-> Command) */
+
+ /* Weirdness I can't figure out */
+ /* XK_3270_PrintScreen, 105, /* PrintScrn */ /* XXX ? */
+ /* ??? 94, 50, /* International */
+ XK_Menu, 50, /* Menu (-> International) */
+};
+
+void
+KbdAddEvent(Bool down, KeySym keySym, struct _rfbClientRec* cl)
+{
+ int i;
+ CGKeyCode keyCode = -1;
+ int found = 0;
+
+ if(((int)cl->clientData)==-1) return; /* viewOnly */
+
+ rfbUndim();
+
+ for (i = 0; i < (sizeof(keyTable) / sizeof(int)); i += 2) {
+ if (keyTable[i] == keySym) {
+ keyCode = keyTable[i+1];
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ rfbLog("warning: couldn't figure out keycode for X keysym %d (0x%x)\n",
+ (int)keySym, (int)keySym);
+ } else {
+ /* Hopefully I can get away with not specifying a CGCharCode.
+ (Why would you need both?) */
+ CGPostKeyboardEvent((CGCharCode)0, keyCode, down);
+ }
+}
+
+void
+PtrAddEvent(buttonMask, x, y, cl)
+ int buttonMask;
+ int x;
+ int y;
+ rfbClientPtr cl;
+{
+ CGPoint position;
+
+ if(((int)cl->clientData)==-1) return; /* viewOnly */
+
+ rfbUndim();
+
+ position.x = x;
+ position.y = y;
+
+ CGPostMouseEvent(position, TRUE, 8,
+ (buttonMask & (1 << 0)) ? TRUE : FALSE,
+ (buttonMask & (1 << 1)) ? TRUE : FALSE,
+ (buttonMask & (1 << 2)) ? TRUE : FALSE,
+ (buttonMask & (1 << 3)) ? TRUE : FALSE,
+ (buttonMask & (1 << 4)) ? TRUE : FALSE,
+ (buttonMask & (1 << 5)) ? TRUE : FALSE,
+ (buttonMask & (1 << 6)) ? TRUE : FALSE,
+ (buttonMask & (1 << 7)) ? TRUE : FALSE);
+}
+
+Bool viewOnly = FALSE, sharedMode = FALSE;
+
+void
+ScreenInit(int argc, char**argv)
+{
+ int bitsPerSample=CGDisplayBitsPerSample(kCGDirectMainDisplay);
+ rfbScreen = rfbGetScreen(&argc,argv,
+ CGDisplayPixelsWide(kCGDirectMainDisplay),
+ CGDisplayPixelsHigh(kCGDirectMainDisplay),
+ bitsPerSample,
+ CGDisplaySamplesPerPixel(kCGDirectMainDisplay),4);
+ rfbScreen->rfbServerFormat.redShift = bitsPerSample*2;
+ rfbScreen->rfbServerFormat.greenShift = bitsPerSample*1;
+ rfbScreen->rfbServerFormat.blueShift = 0;
+
+ gethostname(rfbScreen->rfbThisHost, 255);
+ rfbScreen->paddedWidthInBytes = CGDisplayBytesPerRow(kCGDirectMainDisplay);
+ rfbScreen->frameBuffer =
+ (char *)CGDisplayBaseAddress(kCGDirectMainDisplay);
+
+ rfbScreen->ptrAddEvent = PtrAddEvent;
+ rfbScreen->kbdAddEvent = KbdAddEvent;
+
+ if(sharedMode) {
+ rfbScreen->rfbAlwaysShared = TRUE;
+ }
+
+ rfbInitServer(rfbScreen);
+}
+
+#ifdef LOCAL_CONTROL
+single_instance_struct single_instance = { "/tmp/OSXvnc_control" };
+#endif
+
+static void
+refreshCallback(CGRectCount count, const CGRect *rectArray, void *ignore)
+{
+ int i;
+
+#ifdef LOCAL_CONTROL
+ char message[1024];
+
+ if(get_next_message(message,1024,&single_instance,50)) {
+ if(message[0]=='l' && message[1]==0) {
+ rfbClientPtr cl;
+ int i;
+ for(i=0,cl=rfbScreen->rfbClientHead;cl;cl=cl->next,i++)
+ fprintf(stderr,"%02d: %s\n",i,cl->host);
+ } else if(message[0]=='t') {
+ rfbClientPtr cl;
+ for(cl=rfbScreen->rfbClientHead;cl;cl=cl->next)
+ if(!strcmp(message+1,cl->host)) {
+ cl->clientData=(void*)((cl->clientData==0)?-1:0);
+ break;
+ }
+ }
+#ifdef BACKCHANNEL
+ else if(message[0]=='b')
+ rfbSendBackChannel(rfbScreen,message+1,strlen(message+1));
+#endif
+ }
+#endif
+
+ if(startTime>0 && time(0)>startTime+maxSecsToConnect)
+ rfbShutdown(0);
+
+ for (i = 0; i < count; i++)
+ rfbMarkRectAsModified(rfbScreen,
+ rectArray[i].origin.x,rectArray[i].origin.y,
+ rectArray[i].origin.x + rectArray[i].size.width,
+ rectArray[i].origin.y + rectArray[i].size.height);
+}
+
+void clientGone(rfbClientPtr cl)
+{
+ rfbShutdown(cl);
+}
+
+enum rfbNewClientAction newClient(rfbClientPtr cl)
+{
+ if(startTime>0 && time(0)>startTime+maxSecsToConnect)
+ rfbShutdown(cl);
+
+ if(disconnectAfterFirstClient)
+ cl->clientGoneHook = clientGone;
+
+ cl->clientData=(void*)((viewOnly)?-1:0);
+
+ return(RFB_CLIENT_ACCEPT);
+}
+
+int main(int argc,char *argv[])
+{
+ int i;
+
+#ifdef LOCAL_CONTROL
+ char message[1024];
+
+ open_control_file(&single_instance);
+#endif
+
+ for(i=argc-1;i>0;i--)
+#ifdef LOCAL_CONTROL
+ if(i<argc-1 && !strcmp(argv[i],"-toggleviewonly")) {
+ snprintf(message, sizeof(message), "t%s",argv[i+1]);
+ send_message(&single_instance,message);
+ exit(0);
+ } else if(!strcmp(argv[i],"-listclients")) {
+ fprintf(stderr,"list clients\n");
+ send_message(&single_instance,"l");
+ exit(0);
+ } else
+#ifdef BACKCHANNEL
+ if(i<argc-1 && !strcmp(argv[i],"-backchannel")) {
+ snprintf(message, sizeof(message), "b%s",argv[i+1]);
+ send_message(&single_instance,message);
+ exit(0);
+ } else
+#endif
+#endif
+ if(i<argc-1 && strcmp(argv[i],"-wait4client")==0) {
+ maxSecsToConnect = atoi(argv[i+1])/1000;
+ startTime = time(0);
+ } else if(strcmp(argv[i],"-runforever")==0) {
+ disconnectAfterFirstClient = FALSE;
+ } else if(strcmp(argv[i],"-viewonly")==0) {
+ viewOnly=TRUE;
+ } else if(strcmp(argv[i],"-shared")==0) {
+ sharedMode=TRUE;
+ }
+
+ rfbDimmingInit();
+
+ ScreenInit(argc,argv);
+ rfbScreen->newClientHook = newClient;
+
+ /* enter background event loop */
+ rfbRunEventLoop(rfbScreen,40,TRUE);
+
+ /* enter OS X loop */
+ CGRegisterScreenRefreshCallback(refreshCallback, NULL);
+ RunApplicationEventLoop();
+
+ rfbDimmingShutdown();
+
+ return(0); /* never ... */
+}
+
+void rfbShutdown(rfbClientPtr cl)
+{
+ rfbScreenCleanup(rfbScreen);
+ rfbDimmingShutdown();
+ exit(0);
+}
diff --git a/krfb/libvncserver/main.c b/krfb/libvncserver/main.c
new file mode 100644
index 00000000..207e512d
--- /dev/null
+++ b/krfb/libvncserver/main.c
@@ -0,0 +1,729 @@
+/*
+ * This file is called main.c, because it contains most of the new functions
+ * for use with LibVNCServer.
+ *
+ * LibVNCServer (C) 2001 Johannes E. Schindelin <Johannes.Schindelin@gmx.de>
+ * Original OSXvnc (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
+ * Original Xvnc (C) 1999 AT&T Laboratories Cambridge.
+ * All Rights Reserved.
+ *
+ * see GPL (latest version) for full details
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <errno.h>
+
+#ifndef false
+#define false 0
+#define true -1
+#endif
+
+#include <sys/types.h>
+#ifdef __osf__
+typedef int socklen_t;
+#endif
+#ifndef WIN32
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#endif
+#include <signal.h>
+#include <time.h>
+
+#include "rfb.h"
+#include "sraRegion.h"
+
+/* minimum interval between attempts to send something */
+#define PING_MS 10000
+
+MUTEX(logMutex);
+
+int rfbEnableLogging=1;
+
+/* we cannot compare to _LITTLE_ENDIAN, because some systems
+ (as Solaris) assume little endian if _LITTLE_ENDIAN is
+ defined, even if _BYTE_ORDER is not _LITTLE_ENDIAN */
+char rfbEndianTest = (_BYTE_ORDER == 1234);
+
+/* from rfbserver.c */
+void rfbIncrClientRef(rfbClientPtr cl);
+void rfbDecrClientRef(rfbClientPtr cl);
+
+void rfbLogEnable(int enabled) {
+ rfbEnableLogging=enabled;
+}
+
+/*
+ * rfbLog prints a time-stamped message to the log file (stderr).
+ */
+
+void
+rfbLog(const char *format, ...)
+{
+ va_list args;
+ char buf[256];
+ time_t log_clock;
+
+ if(!rfbEnableLogging)
+ return;
+
+ LOCK(logMutex);
+ va_start(args, format);
+
+ time(&log_clock);
+ strftime(buf, 255, "%d/%m/%Y %T ", localtime(&log_clock));
+ fprintf(stderr, "%s", buf);
+
+ vfprintf(stderr, format, args);
+ fflush(stderr);
+
+ va_end(args);
+ UNLOCK(logMutex);
+}
+
+void rfbLogPerror(const char *str)
+{
+ rfbLog("%s: %s\n", str, strerror(errno));
+}
+
+void rfbScheduleCopyRegion(rfbScreenInfoPtr rfbScreen,sraRegionPtr copyRegion,int dx,int dy)
+{
+ rfbClientIteratorPtr iterator;
+ rfbClientPtr cl;
+
+ rfbUndrawCursor(rfbScreen);
+
+ iterator=rfbGetClientIterator(rfbScreen);
+ while((cl=rfbClientIteratorNext(iterator))) {
+ LOCK(cl->updateMutex);
+ if(cl->useCopyRect) {
+ sraRegionPtr modifiedRegionBackup;
+ if(!sraRgnEmpty(cl->copyRegion)) {
+ if(cl->copyDX!=dx || cl->copyDY!=dy) {
+ /* if a copyRegion was not yet executed, treat it as a
+ * modifiedRegion. The idea: in this case it could be
+ * source of the new copyRect or modified anyway. */
+ sraRgnOr(cl->modifiedRegion,cl->copyRegion);
+ sraRgnMakeEmpty(cl->copyRegion);
+ } else {
+ /* we have to set the intersection of the source of the copy
+ * and the old copy to modified. */
+ modifiedRegionBackup=sraRgnCreateRgn(copyRegion);
+ sraRgnOffset(modifiedRegionBackup,-dx,-dy);
+ sraRgnAnd(modifiedRegionBackup,cl->copyRegion);
+ sraRgnOr(cl->modifiedRegion,modifiedRegionBackup);
+ sraRgnDestroy(modifiedRegionBackup);
+ }
+ }
+
+ sraRgnOr(cl->copyRegion,copyRegion);
+ cl->copyDX = dx;
+ cl->copyDY = dy;
+
+ /* if there were modified regions, which are now copied,
+ * mark them as modified, because the source of these can be overlapped
+ * either by new modified or now copied regions. */
+ modifiedRegionBackup=sraRgnCreateRgn(cl->modifiedRegion);
+ sraRgnOffset(modifiedRegionBackup,dx,dy);
+ sraRgnAnd(modifiedRegionBackup,cl->copyRegion);
+ sraRgnOr(cl->modifiedRegion,modifiedRegionBackup);
+ sraRgnDestroy(modifiedRegionBackup);
+
+#if 0
+//TODO: is this needed? Or does it mess up deferring?
+ /* while(!sraRgnEmpty(cl->copyRegion)) */ {
+#ifdef HAVE_PTHREADS
+ if(!cl->screen->backgroundLoop)
+#endif
+ {
+ sraRegionPtr updateRegion = sraRgnCreateRgn(cl->modifiedRegion);
+ sraRgnOr(updateRegion,cl->copyRegion);
+ UNLOCK(cl->updateMutex);
+ rfbSendFramebufferUpdate(cl,updateRegion);
+ sraRgnDestroy(updateRegion);
+ continue;
+ }
+ }
+#endif
+ } else {
+ sraRgnOr(cl->modifiedRegion,copyRegion);
+ }
+ TSIGNAL(cl->updateCond);
+ UNLOCK(cl->updateMutex);
+ }
+
+ rfbReleaseClientIterator(iterator);
+}
+
+void rfbDoCopyRegion(rfbScreenInfoPtr rfbScreen,sraRegionPtr copyRegion,int dx,int dy)
+{
+ sraRectangleIterator* i;
+ sraRect rect;
+ int j,widthInBytes,bpp=rfbScreen->rfbServerFormat.bitsPerPixel/8,
+ rowstride=rfbScreen->paddedWidthInBytes;
+ char *in,*out;
+
+ rfbUndrawCursor(rfbScreen);
+
+ /* copy it, really */
+ i = sraRgnGetReverseIterator(copyRegion,dx<0,dy<0);
+ while(sraRgnIteratorNext(i,&rect)) {
+ widthInBytes = (rect.x2-rect.x1)*bpp;
+ out = rfbScreen->frameBuffer+rect.x1*bpp+rect.y1*rowstride;
+ in = rfbScreen->frameBuffer+(rect.x1-dx)*bpp+(rect.y1-dy)*rowstride;
+ if(dy<0)
+ for(j=rect.y1;j<rect.y2;j++,out+=rowstride,in+=rowstride)
+ memmove(out,in,widthInBytes);
+ else {
+ out += rowstride*(rect.y2-rect.y1-1);
+ in += rowstride*(rect.y2-rect.y1-1);
+ for(j=rect.y2-1;j>=rect.y1;j--,out-=rowstride,in-=rowstride)
+ memmove(out,in,widthInBytes);
+ }
+ }
+
+ rfbScheduleCopyRegion(rfbScreen,copyRegion,dx,dy);
+}
+
+void rfbDoCopyRect(rfbScreenInfoPtr rfbScreen,int x1,int y1,int x2,int y2,int dx,int dy)
+{
+ sraRegionPtr region = sraRgnCreateRect(x1,y1,x2,y2);
+ rfbDoCopyRegion(rfbScreen,region,dx,dy);
+}
+
+void rfbScheduleCopyRect(rfbScreenInfoPtr rfbScreen,int x1,int y1,int x2,int y2,int dx,int dy)
+{
+ sraRegionPtr region = sraRgnCreateRect(x1,y1,x2,y2);
+ rfbScheduleCopyRegion(rfbScreen,region,dx,dy);
+}
+
+void rfbMarkRegionAsModified(rfbScreenInfoPtr rfbScreen,sraRegionPtr modRegion)
+{
+ rfbClientIteratorPtr iterator;
+ rfbClientPtr cl;
+
+ iterator=rfbGetClientIterator(rfbScreen);
+ while((cl=rfbClientIteratorNext(iterator))) {
+ LOCK(cl->updateMutex);
+ sraRgnOr(cl->modifiedRegion,modRegion);
+ TSIGNAL(cl->updateCond);
+ UNLOCK(cl->updateMutex);
+ }
+
+ rfbReleaseClientIterator(iterator);
+}
+
+void rfbMarkRectAsModified(rfbScreenInfoPtr rfbScreen,int x1,int y1,int x2,int y2)
+{
+ sraRegionPtr region;
+ int i;
+
+ if(x1>x2) { i=x1; x1=x2; x2=i; }
+ if(x1<0) x1=0;
+ if(x2>=rfbScreen->width) x2=rfbScreen->width-1;
+ if(x1==x2) return;
+
+ if(y1>y2) { i=y1; y1=y2; y2=i; }
+ if(y1<0) y1=0;
+ if(y2>=rfbScreen->height) y2=rfbScreen->height-1;
+ if(y1==y2) return;
+
+ region = sraRgnCreateRect(x1,y1,x2,y2);
+ rfbMarkRegionAsModified(rfbScreen,region);
+ sraRgnDestroy(region);
+}
+
+#ifdef HAVE_PTHREADS
+static void *
+clientOutput(void *data)
+{
+ rfbClientPtr cl = (rfbClientPtr)data;
+ Bool haveUpdate;
+ sraRegion* updateRegion;
+
+ while (1) {
+ haveUpdate = false;
+ while (!haveUpdate) {
+ if (cl->sock == -1) {
+ /* Client has disconnected. */
+ return NULL;
+ }
+ LOCK(cl->updateMutex);
+ haveUpdate = FB_UPDATE_PENDING(cl);
+ if(!haveUpdate) {
+ updateRegion = sraRgnCreateRgn(cl->modifiedRegion);
+ haveUpdate = sraRgnAnd(updateRegion,cl->requestedRegion);
+ sraRgnDestroy(updateRegion);
+ }
+ UNLOCK(cl->updateMutex);
+
+ if (!haveUpdate) {
+ LOCK(cl->updateMutex);
+ TIMEDWAIT(cl->updateCond, cl->updateMutex, PING_MS);
+ UNLOCK(cl->updateMutex); /* we really needn't lock now. */
+ if (!haveUpdate)
+ rfbSendPing(cl);
+ }
+ }
+
+ /* OK, now, to save bandwidth, wait a little while for more
+ updates to come along. */
+ usleep(cl->screen->rfbDeferUpdateTime * 1000);
+
+ /* Now, get the region we're going to update, and remove
+ it from cl->modifiedRegion _before_ we send the update.
+ That way, if anything that overlaps the region we're sending
+ is updated, we'll be sure to do another update later. */
+ LOCK(cl->updateMutex);
+ updateRegion = sraRgnCreateRgn(cl->modifiedRegion);
+ UNLOCK(cl->updateMutex);
+
+ /* Now actually send the update. */
+ rfbIncrClientRef(cl);
+ rfbSendFramebufferUpdate(cl, updateRegion);
+ rfbDecrClientRef(cl);
+
+ sraRgnDestroy(updateRegion);
+ }
+
+ return NULL;
+}
+
+static void *
+clientInput(void *data)
+{
+ rfbClientPtr cl = (rfbClientPtr)data;
+ pthread_t output_thread;
+ pthread_create(&output_thread, NULL, clientOutput, (void *)cl);
+
+ while (1) {
+ rfbProcessClientMessage(cl);
+ if (cl->sock == -1) {
+ /* Client has disconnected. */
+ break;
+ }
+ }
+
+ /* Get rid of the output thread. */
+ LOCK(cl->updateMutex);
+ TSIGNAL(cl->updateCond);
+ UNLOCK(cl->updateMutex);
+ IF_PTHREADS(pthread_join(output_thread, NULL));
+
+ rfbClientConnectionGone(cl);
+
+ return NULL;
+}
+
+static void*
+listenerRun(void *data)
+{
+ rfbScreenInfoPtr rfbScreen=(rfbScreenInfoPtr)data;
+ int client_fd;
+ struct sockaddr_in peer;
+ rfbClientPtr cl;
+ size_t len;
+
+ if (rfbScreen->inetdSock != -1) {
+ cl = rfbNewClient(rfbScreen, rfbScreen->inetdSock);
+ if (cl && !cl->onHold)
+ rfbStartOnHoldClient(cl);
+ else if (rfbScreen->inetdDisconnectHook && !cl)
+ rfbScreen->inetdDisconnectHook();
+ return 0;
+ }
+
+ len = sizeof(peer);
+
+ /* TODO: this thread wont die by restarting the server */
+ while ((client_fd = accept(rfbScreen->rfbListenSock,
+ (struct sockaddr*)&peer, &len)) >= 0) {
+ cl = rfbNewClient(rfbScreen,client_fd);
+ len = sizeof(peer);
+
+ if (cl && !cl->onHold )
+ rfbStartOnHoldClient(cl);
+ }
+ return NULL;
+}
+
+void
+rfbStartOnHoldClient(rfbClientPtr cl)
+{
+ pthread_create(&cl->client_thread, NULL, clientInput, (void *)cl);
+}
+
+#else
+
+void
+rfbStartOnHoldClient(rfbClientPtr cl)
+{
+ cl->onHold = FALSE;
+}
+
+#endif
+
+void
+rfbRefuseOnHoldClient(rfbClientPtr cl)
+{
+ rfbCloseClient(cl);
+ rfbClientConnectionGone(cl);
+}
+
+static void
+defaultKbdAddEvent(Bool down, KeySym keySym, rfbClientPtr cl)
+{
+}
+
+void
+defaultPtrAddEvent(int buttonMask, int x, int y, rfbClientPtr cl)
+{
+ if(x!=cl->screen->cursorX || y!=cl->screen->cursorY) {
+ cl->cursorWasMoved = TRUE;
+ if(cl->screen->cursorIsDrawn)
+ rfbUndrawCursor(cl->screen);
+ LOCK(cl->screen->cursorMutex);
+ if(!cl->screen->cursorIsDrawn) {
+ cl->screen->cursorX = x;
+ cl->screen->cursorY = y;
+ }
+ UNLOCK(cl->screen->cursorMutex);
+ }
+}
+
+void defaultSetXCutText(char* text, int len, rfbClientPtr cl)
+{
+}
+
+/* TODO: add a nice VNC or RFB cursor */
+
+#if defined(WIN32) || defined(sparc) || defined(_AIX) || defined(__osf__)
+static rfbCursor myCursor =
+{
+ "\000\102\044\030\044\102\000",
+ "\347\347\176\074\176\347\347",
+ 8, 7, 3, 3,
+ 0, 0, 0,
+ 0xffff, 0xffff, 0xffff,
+ 0
+};
+#else
+static rfbCursor myCursor =
+{
+ source: "\000\102\044\030\044\102\000",
+ mask: "\347\347\176\074\176\347\347",
+ width: 8, height: 7, xhot: 3, yhot: 3,
+ /*
+ width: 8, height: 7, xhot: 0, yhot: 0,
+ source: "\000\074\176\146\176\074\000",
+ mask: "\176\377\377\377\377\377\176",
+ */
+ foreRed: 0, foreGreen: 0, foreBlue: 0,
+ backRed: 0xffff, backGreen: 0xffff, backBlue: 0xffff,
+ richSource: 0
+};
+#endif
+
+rfbCursorPtr defaultGetCursorPtr(rfbClientPtr cl)
+{
+ return(cl->screen->cursor);
+}
+
+/* response is cl->authChallenge vncEncrypted with passwd */
+Bool defaultPasswordCheck(rfbClientPtr cl,const char* response,int len)
+{
+ int i;
+ char *passwd=vncDecryptPasswdFromFile(cl->screen->rfbAuthPasswdData);
+
+ if(!passwd) {
+ rfbLog("Couldn't read password file: %s\n",cl->screen->rfbAuthPasswdData);
+ return(FALSE);
+ }
+
+ vncEncryptBytes(cl->authChallenge, passwd);
+
+ /* Lose the password from memory */
+ for (i = strlen(passwd); i >= 0; i--) {
+ passwd[i] = '\0';
+ }
+
+ free(passwd);
+
+ if (memcmp(cl->authChallenge, response, len) != 0) {
+ rfbLog("rfbAuthProcessClientMessage: authentication failed from %s\n",
+ cl->host);
+ return(FALSE);
+ }
+
+ return(TRUE);
+}
+
+/* for this method, rfbAuthPasswdData is really a pointer to an array
+ of char*'s, where the last pointer is 0. */
+Bool rfbCheckPasswordByList(rfbClientPtr cl,const char* response,int len)
+{
+ char **passwds;
+
+ for(passwds=(char**)cl->screen->rfbAuthPasswdData;*passwds;passwds++) {
+ vncEncryptBytes(cl->authChallenge, *passwds);
+
+ if (memcmp(cl->authChallenge, response, len) == 0)
+ return(TRUE);
+ }
+
+ rfbLog("rfbAuthProcessClientMessage: authentication failed from %s\n",
+ cl->host);
+ return(FALSE);
+}
+
+void doNothingWithClient(rfbClientPtr cl)
+{
+}
+
+enum rfbNewClientAction defaultNewClientHook(rfbClientPtr cl)
+{
+ return RFB_CLIENT_ACCEPT;
+}
+
+rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,
+ int width,int height,int bitsPerSample,int samplesPerPixel,
+ int bytesPerPixel)
+{
+ rfbScreenInfoPtr rfbScreen=malloc(sizeof(rfbScreenInfo));
+ rfbPixelFormat* format=&rfbScreen->rfbServerFormat;
+
+ INIT_MUTEX(logMutex);
+
+ if(width&3)
+ fprintf(stderr,"WARNING: Width (%d) is not a multiple of 4. VncViewer has problems with that.\n",width);
+
+ rfbScreen->autoPort=FALSE;
+ rfbScreen->rfbClientHead=0;
+ rfbScreen->rfbPort=5900;
+ rfbScreen->socketInitDone=FALSE;
+
+ rfbScreen->inetdInitDone = FALSE;
+ rfbScreen->inetdSock=-1;
+
+ rfbScreen->udpSock=-1;
+ rfbScreen->udpSockConnected=FALSE;
+ rfbScreen->udpPort=0;
+ rfbScreen->udpClient=0;
+
+ rfbScreen->maxFd=0;
+ rfbScreen->rfbListenSock=-1;
+
+ rfbScreen->httpInitDone=FALSE;
+ rfbScreen->httpPort=0;
+ rfbScreen->httpDir=NULL;
+ rfbScreen->httpListenSock=-1;
+ rfbScreen->httpSock=-1;
+ rfbScreen->httpFP=NULL;
+
+ rfbScreen->desktopName = "LibVNCServer";
+ rfbScreen->rfbAlwaysShared = FALSE;
+ rfbScreen->rfbNeverShared = FALSE;
+ rfbScreen->rfbDontDisconnect = FALSE;
+ rfbScreen->rfbAuthPasswdData = 0;
+
+ rfbScreen->width = width;
+ rfbScreen->height = height;
+ rfbScreen->bitsPerPixel = rfbScreen->depth = 8*bytesPerPixel;
+
+ rfbScreen->passwordCheck = defaultPasswordCheck;
+
+ rfbProcessArguments(rfbScreen,argc,argv);
+
+#ifdef WIN32
+ {
+ DWORD dummy=255;
+ GetComputerName(rfbScreen->rfbThisHost,&dummy);
+ }
+#else
+ gethostname(rfbScreen->rfbThisHost, 255);
+#endif
+
+ rfbScreen->paddedWidthInBytes = width*bytesPerPixel;
+
+ /* format */
+
+ format->bitsPerPixel = rfbScreen->bitsPerPixel;
+ format->depth = rfbScreen->depth;
+ format->bigEndian = rfbEndianTest?FALSE:TRUE;
+ format->trueColour = TRUE;
+ rfbScreen->colourMap.count = 0;
+ rfbScreen->colourMap.is16 = 0;
+ rfbScreen->colourMap.data.bytes = NULL;
+
+ if(bytesPerPixel == 1) {
+ format->redMax = 7;
+ format->greenMax = 7;
+ format->blueMax = 3;
+ format->redShift = 0;
+ format->greenShift = 3;
+ format->blueShift = 6;
+ } else {
+ format->redMax = (1 << bitsPerSample) - 1;
+ format->greenMax = (1 << bitsPerSample) - 1;
+ format->blueMax = (1 << bitsPerSample) - 1;
+ if(rfbEndianTest) {
+ format->redShift = 0;
+ format->greenShift = bitsPerSample;
+ format->blueShift = bitsPerSample * 2;
+ } else {
+ if(bytesPerPixel==3) {
+ format->redShift = bitsPerSample*2;
+ format->greenShift = bitsPerSample*1;
+ format->blueShift = 0;
+ } else {
+ format->redShift = bitsPerSample*3;
+ format->greenShift = bitsPerSample*2;
+ format->blueShift = bitsPerSample;
+ }
+ }
+ }
+
+ /* cursor */
+
+ rfbScreen->cursorIsDrawn = FALSE;
+ rfbScreen->dontSendFramebufferUpdate = FALSE;
+ rfbScreen->cursorX=rfbScreen->cursorY=rfbScreen->underCursorBufferLen=0;
+ rfbScreen->underCursorBuffer=NULL;
+ rfbScreen->dontConvertRichCursorToXCursor = FALSE;
+ rfbScreen->cursor = &myCursor;
+ INIT_MUTEX(rfbScreen->cursorMutex);
+
+ IF_PTHREADS(rfbScreen->backgroundLoop = FALSE);
+
+ rfbScreen->rfbDeferUpdateTime=5;
+
+ /* proc's and hook's */
+
+ rfbScreen->kbdAddEvent = defaultKbdAddEvent;
+ rfbScreen->kbdReleaseAllKeys = doNothingWithClient;
+ rfbScreen->ptrAddEvent = defaultPtrAddEvent;
+ rfbScreen->setXCutText = defaultSetXCutText;
+ rfbScreen->getCursorPtr = defaultGetCursorPtr;
+ rfbScreen->setTranslateFunction = rfbSetTranslateFunction;
+ rfbScreen->newClientHook = defaultNewClientHook;
+ rfbScreen->displayHook = 0;
+ rfbScreen->inetdDisconnectHook = 0;
+
+ /* initialize client list and iterator mutex */
+ rfbClientListInit(rfbScreen);
+
+ return(rfbScreen);
+}
+
+void rfbScreenCleanup(rfbScreenInfoPtr rfbScreen)
+{
+ rfbClientIteratorPtr i=rfbGetClientIterator(rfbScreen);
+ rfbClientPtr cl,cl1=rfbClientIteratorNext(i);
+ while(cl1) {
+ cl=rfbClientIteratorNext(i);
+ rfbClientConnectionGone(cl1);
+ cl1=cl;
+ }
+ rfbReleaseClientIterator(i);
+
+ /* TODO: hang up on all clients and free all reserved memory */
+#define FREE_IF(x) if(rfbScreen->x) free(rfbScreen->x)
+ FREE_IF(colourMap.data.bytes);
+ FREE_IF(underCursorBuffer);
+ TINI_MUTEX(rfbScreen->cursorMutex);
+ free(rfbScreen);
+}
+
+void rfbInitServer(rfbScreenInfoPtr rfbScreen)
+{
+#ifdef WIN32
+ WSADATA trash;
+ int i=WSAStartup(MAKEWORD(2,2),&trash);
+#endif
+ rfbInitSockets(rfbScreen);
+ httpInitSockets(rfbScreen);
+}
+
+#ifdef WIN32
+#include <fcntl.h>
+#include <conio.h>
+#include <sys/timeb.h>
+
+void gettimeofday(struct timeval* tv,char* dummy)
+{
+ SYSTEMTIME t;
+ GetSystemTime(&t);
+ tv->tv_sec=t.wHour*3600+t.wMinute*60+t.wSecond;
+ tv->tv_usec=t.wMilliseconds*1000;
+}
+#endif
+
+void
+rfbProcessEvents(rfbScreenInfoPtr rfbScreen,long usec)
+{
+ rfbClientIteratorPtr i;
+ rfbClientPtr cl,clPrev;
+ struct timeval tv;
+
+ if(usec<0)
+ usec=rfbScreen->rfbDeferUpdateTime*1000;
+
+ rfbCheckFds(rfbScreen,usec);
+ httpCheckFds(rfbScreen);
+#ifdef CORBA
+ corbaCheckFds(rfbScreen);
+#endif
+
+ i = rfbGetClientIterator(rfbScreen);
+ cl=rfbClientIteratorNext(i);
+ while(cl) {
+ if(cl->sock>=0 && (!cl->onHold) && FB_UPDATE_PENDING(cl)) {
+ if(cl->screen->rfbDeferUpdateTime == 0) {
+ rfbSendFramebufferUpdate(cl,cl->modifiedRegion);
+ } else if(cl->startDeferring.tv_usec == 0) {
+ gettimeofday(&cl->startDeferring,NULL);
+ if(cl->startDeferring.tv_usec == 0)
+ cl->startDeferring.tv_usec++;
+ } else {
+ gettimeofday(&tv,NULL);
+ if(tv.tv_sec < cl->startDeferring.tv_sec /* at midnight */
+ || ((tv.tv_sec-cl->startDeferring.tv_sec)*1000
+ +(tv.tv_usec-cl->startDeferring.tv_usec)/1000)
+ > cl->screen->rfbDeferUpdateTime) {
+ cl->startDeferring.tv_usec = 0;
+ rfbSendFramebufferUpdate(cl,cl->modifiedRegion);
+ }
+ }
+ }
+ clPrev=cl;
+ cl=rfbClientIteratorNext(i);
+ if(clPrev->sock==-1)
+ rfbClientConnectionGone(clPrev);
+ }
+ rfbReleaseClientIterator(i);
+}
+
+void rfbRunEventLoop(rfbScreenInfoPtr rfbScreen, long usec, Bool runInBackground)
+{
+ if(runInBackground) {
+#ifdef HAVE_PTHREADS
+ pthread_t listener_thread;
+
+ rfbScreen->backgroundLoop = TRUE;
+
+ pthread_create(&listener_thread, NULL, listenerRun, rfbScreen);
+ return;
+#else
+ fprintf(stderr,"Can't run in background, because I don't have PThreads!\n");
+ exit(-1);
+#endif
+ }
+
+ if(usec<0)
+ usec=rfbScreen->rfbDeferUpdateTime*1000;
+
+ while(1)
+ rfbProcessEvents(rfbScreen,usec);
+}
diff --git a/krfb/libvncserver/pnmshow.c b/krfb/libvncserver/pnmshow.c
new file mode 100644
index 00000000..05e45b9c
--- /dev/null
+++ b/krfb/libvncserver/pnmshow.c
@@ -0,0 +1,81 @@
+#include <stdio.h>
+#include "rfb.h"
+#include "keysym.h"
+
+void HandleKey(Bool down,KeySym key,rfbClientPtr cl)
+{
+ if(down && (key==XK_Escape || key=='q' || key=='Q'))
+ rfbCloseClient(cl);
+}
+
+int main(int argc,char** argv)
+{
+ FILE* in=stdin;
+ int i,j,k,width,height,paddedWidth;
+ unsigned char buffer[1024];
+ rfbScreenInfoPtr rfbScreen;
+
+ if(argc>1) {
+ in=fopen(argv[1],"rb");
+ if(!in) {
+ printf("Couldn't find file %s.\n",argv[1]);
+ exit(1);
+ }
+ }
+
+ fgets(buffer,1024,in);
+ if(strncmp(buffer,"P6",2)) {
+ printf("Not a ppm.\n");
+ exit(2);
+ }
+
+ /* skip comments */
+ do {
+ fgets(buffer,1024,in);
+ } while(buffer[0]=='#');
+
+ /* get width & height */
+ sscanf(buffer,"%d %d",&width,&height);
+ fprintf(stderr,"Got width %d and height %d.\n",width,height);
+ fgets(buffer,1024,in);
+
+ /* vncviewers have problems with widths which are no multiple of 4. */
+ paddedWidth = width;
+ if(width&3)
+ paddedWidth+=4-(width&3);
+
+ /* initialize data for vnc server */
+ rfbScreen = rfbGetScreen(&argc,argv,paddedWidth,height,8,3,4);
+ if(argc>1)
+ rfbScreen->desktopName = argv[1];
+ else
+ rfbScreen->desktopName = "Picture";
+ rfbScreen->rfbAlwaysShared = TRUE;
+ rfbScreen->kbdAddEvent = HandleKey;
+
+ /* enable http */
+ rfbScreen->httpDir = "./classes";
+
+ /* allocate picture and read it */
+ rfbScreen->frameBuffer = (char*)malloc(paddedWidth*4*height);
+ fread(rfbScreen->frameBuffer,width*3,height,in);
+ fclose(in);
+
+ /* correct the format to 4 bytes instead of 3 (and pad to paddedWidth) */
+ for(j=height-1;j>=0;j--) {
+ for(i=width-1;i>=0;i--)
+ for(k=2;k>=0;k--)
+ rfbScreen->frameBuffer[(j*paddedWidth+i)*4+k]=
+ rfbScreen->frameBuffer[(j*width+i)*3+k];
+ for(i=width*4;i<paddedWidth*4;i++)
+ rfbScreen->frameBuffer[j*paddedWidth*4+i]=0;
+ }
+
+ /* initialize server */
+ rfbInitServer(rfbScreen);
+
+ /* run event loop */
+ rfbRunEventLoop(rfbScreen,40000,FALSE);
+
+ return(0);
+}
diff --git a/krfb/libvncserver/pnmshow24.c b/krfb/libvncserver/pnmshow24.c
new file mode 100644
index 00000000..3978f00e
--- /dev/null
+++ b/krfb/libvncserver/pnmshow24.c
@@ -0,0 +1,90 @@
+#ifndef ALLOW24BPP
+#error "I need the ALLOW24BPP flag to work"
+#endif
+
+#include <stdio.h>
+#include "rfb.h"
+#include "keysym.h"
+
+void HandleKey(Bool down,KeySym key,rfbClientPtr cl)
+{
+ if(down && (key==XK_Escape || key=='q' || key=='Q'))
+ rfbCloseClient(cl);
+}
+
+int main(int argc,char** argv)
+{
+ FILE* in=stdin;
+ int j,width,height,paddedWidth;
+ unsigned char buffer[1024];
+ rfbScreenInfoPtr rfbScreen;
+
+ if(argc>1) {
+ in=fopen(argv[1],"rb");
+ if(!in) {
+ printf("Couldn't find file %s.\n",argv[1]);
+ exit(1);
+ }
+ }
+
+ fgets(buffer,1024,in);
+ if(strncmp(buffer,"P6",2)) {
+ printf("Not a ppm.\n");
+ exit(2);
+ }
+
+ /* skip comments */
+ do {
+ fgets(buffer,1024,in);
+ } while(buffer[0]=='#');
+
+ /* get width & height */
+ sscanf(buffer,"%d %d",&width,&height);
+ fprintf(stderr,"Got width %d and height %d.\n",width,height);
+ fgets(buffer,1024,in);
+
+ /* vncviewers have problems with widths which are no multiple of 4. */
+ paddedWidth = width;
+
+ /* if your vncviewer doesn't have problems with a width
+ which is not a multiple of 4, you can comment this. */
+ if(width&3)
+ paddedWidth+=4-(width&3);
+
+ /* initialize data for vnc server */
+ rfbScreen = rfbGetScreen(&argc,argv,paddedWidth,height,8,3,3);
+ if(argc>1)
+ rfbScreen->desktopName = argv[1];
+ else
+ rfbScreen->desktopName = "Picture";
+ rfbScreen->rfbAlwaysShared = TRUE;
+ rfbScreen->kbdAddEvent = HandleKey;
+
+ /* enable http */
+ rfbScreen->httpDir = "./classes";
+
+ /* allocate picture and read it */
+ rfbScreen->frameBuffer = (char*)malloc(paddedWidth*3*height);
+ fread(rfbScreen->frameBuffer,width*3,height,in);
+ fclose(in);
+
+ /* pad to paddedWidth */
+ if(width != paddedWidth) {
+ int padCount = 3*(paddedWidth - width);
+ for(j=height-1;j>=0;j--) {
+ memmove(rfbScreen->frameBuffer+3*paddedWidth*j,
+ rfbScreen->frameBuffer+3*width*j,
+ 3*width);
+ memset(rfbScreen->frameBuffer+3*paddedWidth*(j+1)-padCount,
+ 0,padCount);
+ }
+ }
+
+ /* initialize server */
+ rfbInitServer(rfbScreen);
+
+ /* run event loop */
+ rfbRunEventLoop(rfbScreen,40000,FALSE);
+
+ return(0);
+}
diff --git a/krfb/libvncserver/radon.h b/krfb/libvncserver/radon.h
new file mode 100644
index 00000000..6aa5242f
--- /dev/null
+++ b/krfb/libvncserver/radon.h
@@ -0,0 +1,195 @@
+unsigned char radonFontData[2280]={
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 32 */
+0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x10,0x10,0x00,0x00, /* 33 */
+0x00,0x28,0x28,0x28,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 34 */
+0x00,0x44,0x44,0xba,0x44,0x44,0x44,0xba,0x44,0x44,0x00,0x00, /* 35 */
+0x10,0x7e,0x80,0x90,0x80,0x7c,0x02,0x12,0x02,0xfc,0x10,0x00, /* 36 */
+0x00,0x62,0x92,0x94,0x68,0x10,0x2c,0x52,0x92,0x8c,0x00,0x00, /* 37 */
+0x00,0x60,0x90,0x90,0x40,0x20,0x90,0x8a,0x84,0x7a,0x00,0x00, /* 38 */
+0x00,0x10,0x10,0x10,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 39 */
+0x00,0x08,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x08,0x00,0x00, /* 40 */
+0x00,0x10,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x10,0x00,0x00, /* 41 */
+0x00,0x10,0x92,0x54,0x10,0x10,0x54,0x92,0x10,0x00,0x00,0x00, /* 42 */
+0x00,0x00,0x10,0x10,0x10,0xd6,0x10,0x10,0x10,0x00,0x00,0x00, /* 43 */
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x08,0x30,0x00, /* 44 */
+0x00,0x00,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0x00,0x00,0x00, /* 45 */
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x00,0x00, /* 46 */
+0x00,0x02,0x02,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x00,0x00, /* 47 */
+0x00,0x7c,0x82,0x82,0x82,0xba,0x82,0x82,0x82,0x7c,0x00,0x00, /* 48 */
+0x00,0x08,0x28,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x00, /* 49 */
+0x00,0xfc,0x02,0x02,0x02,0x7c,0x80,0x80,0x00,0xfe,0x00,0x00, /* 50 */
+0x00,0xfc,0x02,0x02,0x02,0x3c,0x02,0x02,0x02,0xfc,0x00,0x00, /* 51 */
+0x00,0x82,0x82,0x82,0x82,0x7a,0x02,0x02,0x02,0x02,0x00,0x00, /* 52 */
+0x00,0xfe,0x00,0x80,0x80,0x7c,0x02,0x02,0x02,0xfc,0x00,0x00, /* 53 */
+0x00,0x7c,0x80,0x80,0xbc,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 54 */
+0x00,0xfc,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x00, /* 55 */
+0x00,0x7c,0x82,0x82,0x82,0x7c,0x82,0x82,0x82,0x7c,0x00,0x00, /* 56 */
+0x00,0x7c,0x82,0x82,0x82,0x82,0x7a,0x02,0x02,0xfc,0x00,0x00, /* 57 */
+0x00,0x00,0x10,0x10,0x00,0x00,0x00,0x10,0x10,0x00,0x00,0x00, /* 58 */
+0x00,0x00,0x10,0x10,0x00,0x00,0x00,0x10,0x10,0x60,0x00,0x00, /* 59 */
+0x00,0x08,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x08,0x00,0x00, /* 60 */
+0x00,0x00,0x00,0x00,0xfe,0x00,0xfe,0x00,0x00,0x00,0x00,0x00, /* 61 */
+0x00,0x10,0x10,0x08,0x04,0x02,0x04,0x08,0x10,0x10,0x00,0x00, /* 62 */
+0x00,0xfc,0x02,0x02,0x02,0x1c,0x20,0x20,0x00,0x20,0x00,0x00, /* 63 */
+0x00,0x7c,0x82,0x8a,0x92,0x92,0x92,0x8c,0x80,0x7c,0x00,0x00, /* 64 */
+0x00,0x7c,0x82,0x82,0x82,0x82,0xba,0x82,0x82,0x82,0x00,0x00, /* 65 */
+0x00,0xbc,0x82,0x82,0x82,0xbc,0x82,0x82,0x82,0xbc,0x00,0x00, /* 66 */
+0x00,0x7c,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x7c,0x00,0x00, /* 67 */
+0x00,0xbc,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0xbc,0x00,0x00, /* 68 */
+0x00,0x7c,0x80,0x80,0x80,0xb8,0x80,0x80,0x80,0x7c,0x00,0x00, /* 69 */
+0x00,0x7c,0x80,0x80,0x80,0xb8,0x80,0x80,0x80,0x80,0x00,0x00, /* 70 */
+0x00,0x7c,0x80,0x80,0x80,0x80,0x9a,0x82,0x82,0x7c,0x00,0x00, /* 71 */
+0x00,0x82,0x82,0x82,0x82,0xba,0x82,0x82,0x82,0x82,0x00,0x00, /* 72 */
+0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 73 */
+0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x84,0x78,0x00,0x00, /* 74 */
+0x00,0x82,0x82,0x82,0x82,0xbc,0x82,0x82,0x82,0x82,0x00,0x00, /* 75 */
+0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x7e,0x00,0x00, /* 76 */
+0x00,0x7c,0x82,0x92,0x92,0x92,0x92,0x82,0x82,0x82,0x00,0x00, /* 77 */
+0x00,0x7c,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x00,0x00, /* 78 */
+0x00,0x7c,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 79 */
+0x00,0xbc,0x82,0x82,0x82,0xbc,0x80,0x80,0x80,0x80,0x00,0x00, /* 80 */
+0x00,0x7c,0x82,0x82,0x82,0x82,0x8a,0x8a,0x82,0x7c,0x00,0x00, /* 81 */
+0x00,0xbc,0x82,0x82,0x82,0xbc,0x82,0x82,0x82,0x82,0x00,0x00, /* 82 */
+0x00,0x7e,0x80,0x80,0x80,0x7c,0x02,0x02,0x02,0xfc,0x00,0x00, /* 83 */
+0x00,0xfe,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 84 */
+0x00,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 85 */
+0x00,0x82,0x82,0x82,0x82,0x82,0x84,0x88,0x90,0xa0,0x00,0x00, /* 86 */
+0x00,0x82,0x82,0x82,0x82,0x92,0x92,0x92,0x82,0x7c,0x00,0x00, /* 87 */
+0x00,0x82,0x82,0x82,0x82,0x7c,0x82,0x82,0x82,0x82,0x00,0x00, /* 88 */
+0x00,0x82,0x82,0x82,0x82,0x7c,0x00,0x10,0x10,0x10,0x00,0x00, /* 89 */
+0x00,0xfc,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x7e,0x00,0x00, /* 90 */
+0x00,0x1c,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x1c,0x00,0x00, /* 91 */
+0x00,0x80,0x80,0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x00,0x00, /* 92 */
+0x00,0x38,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x38,0x00,0x00, /* 93 */
+0x00,0x38,0x44,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 94 */
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00, /* 95 */
+0x00,0x08,0x08,0x08,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 96 */
+0x00,0x00,0x00,0x00,0x3c,0x02,0x3a,0x42,0x42,0x3c,0x00,0x00, /* 97 */
+0x00,0x00,0x40,0x40,0x5c,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 98 */
+0x00,0x00,0x00,0x00,0x3c,0x40,0x40,0x40,0x40,0x3c,0x00,0x00, /* 99 */
+0x00,0x00,0x02,0x02,0x3a,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 100 */
+0x00,0x00,0x00,0x00,0x3c,0x42,0x42,0x5c,0x40,0x3c,0x00,0x00, /* 101 */
+0x00,0x00,0x0c,0x10,0x10,0x10,0x54,0x10,0x10,0x10,0x00,0x00, /* 102 */
+0x00,0x00,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x3a,0x02,0x3c, /* 103 */
+0x00,0x00,0x40,0x40,0x5c,0x42,0x42,0x42,0x42,0x42,0x00,0x00, /* 104 */
+0x00,0x00,0x08,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x00, /* 105 */
+0x00,0x00,0x08,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x30, /* 106 */
+0x00,0x00,0x40,0x40,0x42,0x42,0x5c,0x42,0x42,0x42,0x00,0x00, /* 107 */
+0x00,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x00, /* 108 */
+0x00,0x00,0x00,0x00,0x7c,0x82,0x92,0x92,0x92,0x92,0x00,0x00, /* 109 */
+0x00,0x00,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x42,0x00,0x00, /* 110 */
+0x00,0x00,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 111 */
+0x00,0x00,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x5c,0x40,0x40, /* 112 */
+0x00,0x00,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x3a,0x02,0x02, /* 113 */
+0x00,0x00,0x00,0x00,0x0c,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 114 */
+0x00,0x00,0x00,0x00,0x3e,0x40,0x3c,0x02,0x02,0x7c,0x00,0x00, /* 115 */
+0x00,0x00,0x10,0x10,0x10,0x54,0x10,0x10,0x10,0x0c,0x00,0x00, /* 116 */
+0x00,0x00,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 117 */
+0x00,0x00,0x00,0x00,0x42,0x42,0x42,0x44,0x48,0x50,0x00,0x00, /* 118 */
+0x00,0x00,0x00,0x00,0x92,0x92,0x92,0x92,0x82,0x7c,0x00,0x00, /* 119 */
+0x00,0x00,0x00,0x00,0x42,0x42,0x3c,0x42,0x42,0x42,0x00,0x00, /* 120 */
+0x00,0x00,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x3a,0x02,0x3c, /* 121 */
+0x00,0x00,0x00,0x00,0x7c,0x02,0x0c,0x30,0x40,0x3e,0x00,0x00, /* 122 */
+0x00,0x1c,0x20,0x20,0x20,0x40,0x20,0x20,0x20,0x1c,0x00,0x00, /* 123 */
+0x00,0x10,0x10,0x10,0x10,0x00,0x10,0x10,0x10,0x10,0x00,0x00, /* 124 */
+0x00,0x38,0x04,0x04,0x04,0x02,0x04,0x04,0x04,0x38,0x00,0x00, /* 125 */
+0x00,0x04,0x38,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 126 */
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160 */
+0x00,0x10,0x10,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 161 */
+0x00,0x00,0x08,0x3e,0x40,0x48,0x48,0x40,0x3e,0x08,0x00,0x00, /* 162 */
+0x00,0x1c,0x20,0x20,0x20,0xa8,0x20,0x20,0x42,0xbc,0x00,0x00, /* 163 */
+0x00,0x00,0x82,0x38,0x44,0x44,0x44,0x38,0x82,0x00,0x00,0x00, /* 164 */
+0x00,0x82,0x82,0x82,0x7c,0x00,0x54,0x10,0x54,0x10,0x00,0x00, /* 165 */
+0x00,0x10,0x10,0x10,0x00,0x00,0x00,0x10,0x10,0x10,0x00,0x00, /* 166 */
+0x00,0x38,0x40,0x38,0x44,0x44,0x44,0x44,0x38,0x04,0x38,0x00, /* 167 */
+0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 168 */
+0x00,0x7c,0x82,0x9a,0xa2,0xa2,0xa2,0x9a,0x82,0x7c,0x00,0x00, /* 169 */
+0x38,0x04,0x34,0x44,0x38,0x00,0x7c,0x00,0x00,0x00,0x00,0x00, /* 170 */
+0x00,0x00,0x00,0x24,0x48,0x00,0x48,0x24,0x00,0x00,0x00,0x00, /* 171 */
+0x00,0x00,0x00,0x00,0x00,0xfc,0x02,0x02,0x02,0x00,0x00,0x00, /* 172 */
+0x00,0x00,0x00,0x00,0x00,0x7c,0x00,0x00,0x00,0x00,0x00,0x00, /* 173 */
+0x00,0x7c,0x82,0x92,0xaa,0xb2,0xaa,0xaa,0x82,0x7c,0x00,0x00, /* 174 */
+0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 175 */
+0x38,0x44,0x44,0x44,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 176 */
+0x00,0x10,0x10,0xd6,0x10,0x10,0x00,0xfe,0x00,0x00,0x00,0x00, /* 177 */
+0x38,0x04,0x18,0x20,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 178 */
+0x38,0x04,0x38,0x04,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 179 */
+0x18,0x20,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 180 */
+0x00,0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x58,0x40,0x40, /* 181 */
+0x00,0x79,0xfa,0xfa,0xfa,0x7a,0x02,0x0a,0x0a,0x0a,0x0a,0x00, /* 182 */
+0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00, /* 183 */
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0x00, /* 184 */
+0x08,0x18,0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 185 */
+0x38,0x44,0x44,0x38,0x00,0x7c,0x00,0x00,0x00,0x00,0x00,0x00, /* 186 */
+0x00,0x00,0x00,0x48,0x24,0x00,0x24,0x48,0x00,0x00,0x00,0x00, /* 187 */
+0x20,0xa2,0x22,0x22,0x24,0x08,0x10,0x29,0x49,0x85,0x01,0x01, /* 188 */
+0x20,0xa2,0x22,0x22,0x24,0x08,0x10,0x2e,0x41,0x86,0x08,0x0f, /* 189 */
+0xe0,0x12,0xe2,0x12,0xe4,0x08,0x10,0x29,0x49,0x85,0x01,0x01, /* 190 */
+0x00,0x08,0x00,0x08,0x08,0x70,0x80,0x80,0x80,0x7e,0x00,0x00, /* 191 */
+0x20,0x18,0x00,0x7c,0x82,0x82,0x82,0xba,0x82,0x82,0x00,0x00, /* 192 */
+0x08,0x30,0x00,0x7c,0x82,0x82,0x82,0xba,0x82,0x82,0x00,0x00, /* 193 */
+0x38,0x44,0x00,0x7c,0x82,0x82,0x82,0xba,0x82,0x82,0x00,0x00, /* 194 */
+0x32,0x4c,0x00,0x7c,0x82,0x82,0x82,0xba,0x82,0x82,0x00,0x00, /* 195 */
+0x6c,0x00,0x00,0x7c,0x82,0x82,0x82,0xba,0x82,0x82,0x00,0x00, /* 196 */
+0x38,0x44,0x38,0x7c,0x82,0x82,0x82,0xba,0x82,0x82,0x00,0x00, /* 197 */
+0x00,0x77,0x88,0x88,0x88,0x8b,0xa8,0x88,0x88,0x8b,0x00,0x00, /* 198 */
+0x00,0x7c,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x6c,0x10,0x20, /* 199 */
+0x20,0x18,0x00,0x7c,0x80,0x80,0xb8,0x80,0x80,0x7c,0x00,0x00, /* 200 */
+0x08,0x30,0x00,0x7c,0x80,0x80,0xb8,0x80,0x80,0x7c,0x00,0x00, /* 201 */
+0x38,0x44,0x00,0x7c,0x80,0x80,0xb8,0x80,0x80,0x7c,0x00,0x00, /* 202 */
+0x6c,0x00,0x00,0x7c,0x80,0x80,0xb8,0x80,0x80,0x7c,0x00,0x00, /* 203 */
+0x20,0x18,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 204 */
+0x08,0x30,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 205 */
+0x38,0x44,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 206 */
+0x6c,0x00,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 207 */
+0x00,0xbc,0x82,0x82,0x82,0xb2,0x82,0x82,0x82,0xbc,0x00,0x00, /* 208 */
+0x32,0x4c,0x00,0x7c,0x82,0x82,0x82,0x82,0x82,0x82,0x00,0x00, /* 209 */
+0x20,0x18,0x00,0x7c,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 210 */
+0x08,0x30,0x00,0x7c,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 211 */
+0x38,0x44,0x00,0x7c,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 212 */
+0x32,0x4c,0x00,0x7c,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 213 */
+0x6c,0x00,0x00,0x7c,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 214 */
+0x00,0x00,0x00,0x00,0x44,0x28,0x00,0x28,0x44,0x00,0x00,0x00, /* 215 */
+0x00,0x7a,0x84,0x82,0x8a,0x92,0xa2,0x82,0x42,0xbc,0x00,0x00, /* 216 */
+0x20,0x18,0x00,0x82,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 217 */
+0x08,0x30,0x00,0x82,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 218 */
+0x38,0x44,0x00,0x82,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 219 */
+0x6c,0x00,0x00,0x82,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 220 */
+0x08,0xb2,0x82,0x82,0x82,0x7c,0x00,0x10,0x10,0x10,0x00,0x00, /* 221 */
+0x00,0x80,0x80,0xbc,0x82,0x82,0x82,0xbc,0x80,0x80,0x00,0x00, /* 222 */
+0x00,0x3c,0x42,0x42,0x42,0x5c,0x42,0x42,0x42,0x9c,0x00,0x00, /* 223 */
+0x20,0x18,0x00,0x00,0x3c,0x02,0x3a,0x42,0x42,0x3c,0x00,0x00, /* 224 */
+0x08,0x30,0x00,0x00,0x3c,0x02,0x3a,0x42,0x42,0x3c,0x00,0x00, /* 225 */
+0x38,0x44,0x00,0x00,0x3c,0x02,0x3a,0x42,0x42,0x3c,0x00,0x00, /* 226 */
+0x32,0x4c,0x00,0x00,0x3c,0x02,0x3a,0x42,0x42,0x3c,0x00,0x00, /* 227 */
+0x6c,0x00,0x00,0x00,0x3c,0x02,0x3a,0x42,0x42,0x3c,0x00,0x00, /* 228 */
+0x18,0x24,0x18,0x00,0x3c,0x02,0x3a,0x42,0x42,0x3c,0x00,0x00, /* 229 */
+0x00,0x00,0x00,0x00,0x6c,0x12,0x52,0x94,0x90,0x6e,0x00,0x00, /* 230 */
+0x00,0x00,0x00,0x00,0x3c,0x40,0x40,0x40,0x40,0x34,0x08,0x10, /* 231 */
+0x20,0x18,0x00,0x00,0x3c,0x42,0x42,0x5c,0x40,0x3c,0x00,0x00, /* 232 */
+0x08,0x30,0x00,0x00,0x3c,0x42,0x42,0x5c,0x40,0x3c,0x00,0x00, /* 233 */
+0x38,0x44,0x00,0x00,0x3c,0x42,0x42,0x5c,0x40,0x3c,0x00,0x00, /* 234 */
+0x6c,0x00,0x00,0x00,0x3c,0x42,0x42,0x5c,0x40,0x3c,0x00,0x00, /* 235 */
+0x20,0x18,0x00,0x10,0x00,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 236 */
+0x08,0x30,0x00,0x10,0x00,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 237 */
+0x38,0x44,0x00,0x10,0x00,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 238 */
+0x6c,0x00,0x00,0x10,0x00,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 239 */
+0x00,0x14,0x08,0x14,0x02,0x3a,0x42,0x42,0x42,0x3c,0x00,0x00, /* 240 */
+0x00,0x32,0x4c,0x00,0x3c,0x42,0x42,0x42,0x42,0x42,0x00,0x00, /* 241 */
+0x20,0x18,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 242 */
+0x08,0x30,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 243 */
+0x38,0x44,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 244 */
+0x32,0x4c,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 245 */
+0x6c,0x00,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 246 */
+0x00,0x00,0x00,0x00,0x38,0x00,0xfe,0x00,0x38,0x00,0x00,0x00, /* 247 */
+0x00,0x00,0x00,0x00,0x3a,0x44,0x4a,0x52,0x22,0x5c,0x00,0x00, /* 248 */
+0x20,0x18,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 249 */
+0x08,0x30,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 250 */
+0x38,0x44,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 251 */
+0x6c,0x00,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 252 */
+0x04,0x18,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x3a,0x02,0x3c, /* 253 */
+0x00,0x80,0x80,0x9c,0xa2,0x82,0xa2,0x9c,0x80,0x80,0x00,0x00, /* 254 */
+};
+int radonFontMetaData[256*5]={
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,12,0,-2,12,8,12,0,-2,24,8,12,0,-2,36,8,12,0,-2,48,8,12,0,-2,60,8,12,0,-2,72,8,12,0,-2,84,8,12,0,-2,96,8,12,0,-2,108,8,12,0,-2,120,8,12,0,-2,132,8,12,0,-2,144,8,12,0,-2,156,8,12,0,-2,168,8,12,0,-2,180,8,12,0,-2,192,8,12,0,-2,204,8,12,0,-2,216,8,12,0,-2,228,8,12,0,-2,240,8,12,0,-2,252,8,12,0,-2,264,8,12,0,-2,276,8,12,0,-2,288,8,12,0,-2,300,8,12,0,-2,312,8,12,0,-2,324,8,12,0,-2,336,8,12,0,-2,348,8,12,0,-2,360,8,12,0,-2,372,8,12,0,-2,384,8,12,0,-2,396,8,12,0,-2,408,8,12,0,-2,420,8,12,0,-2,432,8,12,0,-2,444,8,12,0,-2,456,8,12,0,-2,468,8,12,0,-2,480,8,12,0,-2,492,8,12,0,-2,504,8,12,0,-2,516,8,12,0,-2,528,8,12,0,-2,540,8,12,0,-2,552,8,12,0,-2,564,8,12,0,-2,576,8,12,0,-2,588,8,12,0,-2,600,8,12,0,-2,612,8,12,0,-2,624,8,12,0,-2,636,8,12,0,-2,648,8,12,0,-2,660,8,12,0,-2,672,8,12,0,-2,684,8,12,0,-2,696,8,12,0,-2,708,8,12,0,-2,720,8,12,0,-2,732,8,12,0,-2,744,8,12,0,-2,756,8,12,0,-2,768,8,12,0,-2,780,8,12,0,-2,792,8,12,0,-2,804,8,12,0,-2,816,8,12,0,-2,828,8,12,0,-2,840,8,12,0,-2,852,8,12,0,-2,864,8,12,0,-2,876,8,12,0,-2,888,8,12,0,-2,900,8,12,0,-2,912,8,12,0,-2,924,8,12,0,-2,936,8,12,0,-2,948,8,12,0,-2,960,8,12,0,-2,972,8,12,0,-2,984,8,12,0,-2,996,8,12,0,-2,1008,8,12,0,-2,1020,8,12,0,-2,1032,8,12,0,-2,1044,8,12,0,-2,1056,8,12,0,-2,1068,8,12,0,-2,1080,8,12,0,-2,1092,8,12,0,-2,1104,8,12,0,-2,1116,8,12,0,-2,1128,8,12,0,-2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1140,8,12,0,-2,1152,8,12,0,-2,1164,8,12,0,-2,1176,8,12,0,-2,1188,8,12,0,-2,1200,8,12,0,-2,1212,8,12,0,-2,1224,8,12,0,-2,1236,8,12,0,-2,1248,8,12,0,-2,1260,8,12,0,-2,1272,8,12,0,-2,1284,8,12,0,-2,1296,8,12,0,-2,1308,8,12,0,-2,1320,8,12,0,-2,1332,8,12,0,-2,1344,8,12,0,-2,1356,8,12,0,-2,1368,8,12,0,-2,1380,8,12,0,-2,1392,8,12,0,-2,1404,8,12,0,-2,1416,8,12,0,-2,1428,8,12,0,-2,1440,8,12,0,-2,1452,8,12,0,-2,1464,8,12,0,-2,1476,8,12,0,-2,1488,8,12,0,-2,1500,8,12,0,-2,1512,8,12,0,-2,1524,8,12,0,-2,1536,8,12,0,-2,1548,8,12,0,-2,1560,8,12,0,-2,1572,8,12,0,-2,1584,8,12,0,-2,1596,8,12,0,-2,1608,8,12,0,-2,1620,8,12,0,-2,1632,8,12,0,-2,1644,8,12,0,-2,1656,8,12,0,-2,1668,8,12,0,-2,1680,8,12,0,-2,1692,8,12,0,-2,1704,8,12,0,-2,1716,8,12,0,-2,1728,8,12,0,-2,1740,8,12,0,-2,1752,8,12,0,-2,1764,8,12,0,-2,1776,8,12,0,-2,1788,8,12,0,-2,1800,8,12,0,-2,1812,8,12,0,-2,1824,8,12,0,-2,1836,8,12,0,-2,1848,8,12,0,-2,1860,8,12,0,-2,1872,8,12,0,-2,1884,8,12,0,-2,1896,8,12,0,-2,1908,8,12,0,-2,1920,8,12,0,-2,1932,8,12,0,-2,1944,8,12,0,-2,1956,8,12,0,-2,1968,8,12,0,-2,1980,8,12,0,-2,1992,8,12,0,-2,2004,8,12,0,-2,2016,8,12,0,-2,2028,8,12,0,-2,2040,8,12,0,-2,2052,8,12,0,-2,2064,8,12,0,-2,2076,8,12,0,-2,2088,8,12,0,-2,2100,8,12,0,-2,2112,8,12,0,-2,2124,8,12,0,-2,2136,8,12,0,-2,2148,8,12,0,-2,2160,8,12,0,-2,2172,8,12,0,-2,2184,8,12,0,-2,2196,8,12,0,-2,2208,8,12,0,-2,2220,8,12,0,-2,2232,8,12,0,-2,2244,8,12,0,-2,2256,8,12,0,-2,2268,8,12,0,-2,0,0,0,0,0,};
+rfbFontData radonFont={radonFontData, radonFontMetaData};
diff --git a/krfb/libvncserver/rfb.h b/krfb/libvncserver/rfb.h
new file mode 100644
index 00000000..53996812
--- /dev/null
+++ b/krfb/libvncserver/rfb.h
@@ -0,0 +1,865 @@
+#ifndef RFB_H
+#define RFB_H
+
+/*
+ * rfb.h - header file for RFB DDX implementation.
+ */
+
+/*
+ * OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
+ * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
+ * All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#if(defined __cplusplus)
+extern "C"
+{
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <zlib.h>
+#include "keysym.h"
+
+/* TODO: this stuff has to go into autoconf */
+typedef unsigned char CARD8;
+typedef unsigned short CARD16;
+
+#ifdef LONG64
+typedef unsigned long CARD64;
+typedef unsigned int CARD32;
+#else
+typedef unsigned long CARD32;
+#endif
+
+typedef CARD32 Pixel;
+/* typedef CARD32 KeySym; */
+#ifndef __osf__
+typedef unsigned long KeySym;
+#endif
+#define SIGNED signed
+/* for some strange reason, "typedef signed char Bool;" yields a four byte
+ signed int on IRIX, but only for rfbserver.o!!! */
+#ifdef Bool
+#undef Bool
+#endif
+#define Bool signed char
+#undef FALSE
+#define FALSE 0
+#undef TRUE
+#define TRUE -1
+
+#include "rfbproto.h"
+
+#ifdef __linux__
+#include <endian.h>
+#elif defined(__APPLE__) || defined(__FreeBSD__)
+#include <sys/types.h>
+#include <machine/endian.h>
+#ifndef _BYTE_ORDER
+#define _BYTE_ORDER BYTE_ORDER
+#endif
+#ifndef _LITTLE_ENDIAN
+#define _LITTLE_ENDIAN LITTLE_ENDIAN
+#endif
+#elif defined (__SVR4) && defined (__sun) /* Solaris */
+#include <sys/types.h>
+#if defined(__sparc)
+ /* SPARC here (big endian) */
+#define _BYTE_ORDER 4321
+#elif defined(__i386)
+#define _BYTE_ORDER 1234
+#else
+#error Solaris 2.5.1 had ppc support did it not? :-)
+#endif
+#undef Bool
+#define Bool char
+#undef SIGNED
+#define SIGNED
+#include <sys/types.h>
+/* typedef unsigned int pthread_t; */
+#elif defined(WIN32)
+#define _LITTLE_ENDIAN 1234
+#define _BYTE_ORDER _LITTLE_ENDIAN
+#undef Bool
+#define Bool int
+#elif defined(_AIX)
+#define _BYTE_ORDER 4321
+#undef Bool
+#define Bool int
+#else
+#ifdef __osf__
+#include <machine/endian.h>
+#define _BYTE_ORDER BYTE_ORDER
+#else
+#include <sys/endian.h>
+#endif
+#endif
+
+#ifndef _BYTE_ORDER
+#define _BYTE_ORDER __BYTE_ORDER
+#endif
+
+#if !defined(_LITTLE_ENDIAN) && defined(__LITTLE_ENDIAN)
+#define _LITTLE_ENDIAN __LITTLE_ENDIAN
+#endif
+
+#ifdef WIN32
+#include <sys/timeb.h>
+#include <winsock.h>
+#undef SOCKET
+#define SOCKET int
+#else
+#define max(a,b) (((a)>(b))?(a):(b))
+#include <sys/time.h>
+#include <netinet/in.h>
+#define SOCKET int
+#endif
+
+#ifndef INADDR_NONE
+#define INADDR_NONE ((in_addr_t) 0xffffffff)
+#endif
+
+#ifdef HAVE_PTHREADS
+#include <pthread.h>
+#if 0 /* debugging */
+#define LOCK(mutex) fprintf(stderr,"%s:%d LOCK(%s,0x%x)\n",__FILE__,__LINE__,#mutex,&(mutex))
+#define UNLOCK(mutex) fprintf(stderr,"%s:%d UNLOCK(%s,0x%x)\n",__FILE__,__LINE__,#mutex,&(mutex))
+#define MUTEX(mutex) int mutex
+#define INIT_MUTEX(mutex) fprintf(stderr,"%s:%d INIT_MUTEX(%s,0x%x)\n",__FILE__,__LINE__,#mutex,&(mutex))
+#define TINI_MUTEX(mutex) fprintf(stderr,"%s:%d TINI_MUTEX(%s)\n",__FILE__,__LINE__,#mutex)
+#define SIGNAL(cond) fprintf(stderr,"%s:%d SIGNAL(%s)\n",__FILE__,__LINE__,#cond)
+#define WAIT(cond,mutex) /* fprintf(stderr,"%s:%d WAIT(%s,%s)\n",__FILE__,__LINE__,#cond,#mutex) */
+#define COND(cond)
+#define INIT_COND(cond) fprintf(stderr,"%s:%d INIT_COND(%s)\n",__FILE__,__LINE__,#cond)
+#define TINI_COND(cond) fprintf(stderr,"%s:%d TINI_COND(%s)\n",__FILE__,__LINE__,#cond)
+#define IF_PTHREADS(x)
+#else
+#define LOCK(mutex) pthread_mutex_lock(&(mutex));
+#define UNLOCK(mutex) pthread_mutex_unlock(&(mutex));
+#define MUTEX(mutex) pthread_mutex_t (mutex)
+#define INIT_MUTEX(mutex) pthread_mutex_init(&(mutex),NULL)
+#define TINI_MUTEX(mutex) pthread_mutex_destroy(&(mutex))
+#define TSIGNAL(cond) pthread_cond_signal(&(cond))
+#define WAIT(cond,mutex) pthread_cond_wait(&(cond),&(mutex))
+#define TIMEDWAIT(cond,mutex,t) {struct timeval tv;\
+ tv.tv_sec = (t) / 1000;\
+ tv.tv_usec = ((t) % 1000) * 1000;\
+ pthread_cond_timedwait(&(cond),&(mutex),&tv);}
+#define COND(cond) pthread_cond_t (cond)
+#define INIT_COND(cond) pthread_cond_init(&(cond),NULL)
+#define TINI_COND(cond) pthread_cond_destroy(&(cond))
+#define IF_PTHREADS(x) x
+#endif
+#else
+#define LOCK(mutex)
+#define UNLOCK(mutex)
+#define MUTEX(mutex)
+#define INIT_MUTEX(mutex)
+#define TINI_MUTEX(mutex)
+#define TSIGNAL(cond)
+#define WAIT(cond,mutex) this_is_unsupported
+#define COND(cond)
+#define INIT_COND(cond)
+#define TINI_COND(cond)
+#define IF_PTHREADS(x)
+#endif
+
+/* end of stuff for autoconf */
+
+/* if you use pthreads, but don't define HAVE_PTHREADS, the structs
+ get all mixed up. So this gives a linker error reminding you to compile
+ the library and your application (at least the parts including rfb.h)
+ with the same support for pthreads. */
+#ifdef HAVE_PTHREADS
+#define rfbInitServer rfbInitServerWithPthreads
+#else
+#define rfbInitServer rfbInitServerWithoutPthreads
+#endif
+
+#define MAX_ENCODINGS 10
+
+struct _rfbClientRec;
+struct _rfbScreenInfo;
+struct rfbCursor;
+
+enum rfbNewClientAction {
+ RFB_CLIENT_ACCEPT,
+ RFB_CLIENT_ON_HOLD,
+ RFB_CLIENT_REFUSE
+};
+
+typedef void (*KbdAddEventProcPtr) (Bool down, KeySym keySym, struct _rfbClientRec* cl);
+typedef void (*KbdReleaseAllKeysProcPtr) (struct _rfbClientRec* cl);
+typedef void (*PtrAddEventProcPtr) (int buttonMask, int x, int y, struct _rfbClientRec* cl);
+typedef void (*SetXCutTextProcPtr) (char* str,int len, struct _rfbClientRec* cl);
+typedef struct rfbCursor* (*GetCursorProcPtr) (struct _rfbClientRec* pScreen);
+typedef Bool (*SetTranslateFunctionProcPtr)(struct _rfbClientRec* cl);
+typedef Bool (*PasswordCheckProcPtr)(struct _rfbClientRec* cl,const char* encryptedPassWord,int len);
+typedef enum rfbNewClientAction (*NewClientHookPtr)(struct _rfbClientRec* cl);
+typedef void (*DisplayHookPtr)(struct _rfbClientRec* cl);
+typedef void (*InetdDisconnectPtr)();
+
+typedef struct {
+ CARD32 count;
+ Bool is16; /* is the data format short? */
+ union {
+ CARD8* bytes;
+ CARD16* shorts;
+ } data; /* there have to be count*3 entries */
+} rfbColourMap;
+
+/*
+ * Per-screen (framebuffer) structure. There can be as many as you wish,
+ * each serving different clients. However, you have to call
+ * rfbProcessEvents for each of these.
+ */
+
+typedef struct _rfbScreenInfo
+{
+ int width;
+ int paddedWidthInBytes;
+ int height;
+ int depth;
+ int bitsPerPixel;
+ int sizeInBytes;
+
+ Pixel blackPixel;
+ Pixel whitePixel;
+
+ /* some screen specific data can be put into a struct where screenData
+ * points to. You need this if you have more than one screen at the
+ * same time while using the same functions.
+ */
+ void* screenData;
+
+ /* The following two members are used to minimise the amount of unnecessary
+ drawing caused by cursor movement. Whenever any drawing affects the
+ part of the screen where the cursor is, the cursor is removed first and
+ then the drawing is done (this is what the sprite routines test for).
+ Afterwards, however, we do not replace the cursor, even when the cursor
+ is logically being moved across the screen. We only draw the cursor
+ again just as we are about to send the client a framebuffer update.
+
+ We need to be careful when removing and drawing the cursor because of
+ their relationship with the normal drawing routines. The drawing
+ routines can invoke the cursor routines, but also the cursor routines
+ themselves end up invoking drawing routines.
+
+ Removing the cursor (rfbUndrawCursor) is eventually achieved by
+ doing a CopyArea from a pixmap to the screen, where the pixmap contains
+ the saved contents of the screen under the cursor. Before doing this,
+ however, we set cursorIsDrawn to FALSE. Then, when CopyArea is called,
+ it sees that cursorIsDrawn is FALSE and so doesn't feel the need to
+ (recursively!) remove the cursor before doing it.
+
+ Putting up the cursor (rfbDrawCursor) involves a call to
+ PushPixels. While this is happening, cursorIsDrawn must be FALSE so
+ that PushPixels doesn't think it has to remove the cursor first.
+ Obviously cursorIsDrawn is set to TRUE afterwards.
+
+ Another problem we face is that drawing routines sometimes cause a
+ framebuffer update to be sent to the RFB client. When the RFB client is
+ already waiting for a framebuffer update and some drawing to the
+ framebuffer then happens, the drawing routine sees that the client is
+ ready, so it calls rfbSendFramebufferUpdate. If the cursor is not drawn
+ at this stage, it must be put up, and so rfbSpriteRestoreCursor is
+ called. However, if the original drawing routine was actually called
+ from within rfbSpriteRestoreCursor or rfbSpriteRemoveCursor we don't
+ want this to happen. So both the cursor routines set
+ dontSendFramebufferUpdate to TRUE, and all the drawing routines check
+ this before calling rfbSendFramebufferUpdate. */
+
+ Bool cursorIsDrawn; /* TRUE if the cursor is currently drawn */
+ Bool dontSendFramebufferUpdate; /* TRUE while removing or drawing the
+ cursor */
+
+ /* additions by libvncserver */
+
+ rfbPixelFormat rfbServerFormat;
+ rfbColourMap colourMap; /* set this if rfbServerFormat.trueColour==FALSE */
+ const char* desktopName;
+ char rfbThisHost[255];
+
+ Bool autoPort;
+ int rfbPort;
+ SOCKET rfbListenSock;
+ int maxSock;
+ int maxFd;
+ fd_set allFds;
+
+ Bool socketInitDone;
+ SOCKET inetdSock;
+ Bool inetdInitDone;
+
+ int udpPort;
+ SOCKET udpSock;
+ struct _rfbClientRec* udpClient;
+ Bool udpSockConnected;
+ struct sockaddr_in udpRemoteAddr;
+
+ int rfbMaxClientWait;
+
+ /* http stuff */
+ Bool httpInitDone;
+ int httpPort;
+ char* httpDir;
+ SOCKET httpListenSock;
+ SOCKET httpSock;
+ FILE* httpFP;
+
+ PasswordCheckProcPtr passwordCheck;
+ void* rfbAuthPasswdData;
+
+ /* this is the amount of milliseconds to wait at least before sending
+ * an update. */
+ int rfbDeferUpdateTime;
+ char* rfbScreen;
+ Bool rfbAlwaysShared;
+ Bool rfbNeverShared;
+ Bool rfbDontDisconnect;
+ struct _rfbClientRec* rfbClientHead;
+
+ /* cursor */
+ int cursorX, cursorY,underCursorBufferLen;
+ char* underCursorBuffer;
+ Bool dontConvertRichCursorToXCursor;
+ struct rfbCursor* cursor;
+
+ /* the frameBufferhas to be supplied by the serving process.
+ * The buffer will not be freed by
+ */
+ char* frameBuffer;
+ KbdAddEventProcPtr kbdAddEvent;
+ KbdReleaseAllKeysProcPtr kbdReleaseAllKeys;
+ PtrAddEventProcPtr ptrAddEvent;
+ SetXCutTextProcPtr setXCutText;
+ GetCursorProcPtr getCursorPtr;
+ SetTranslateFunctionProcPtr setTranslateFunction;
+
+ /* newClientHook is called just after a new client is created */
+ NewClientHookPtr newClientHook;
+ /* displayHook is called just before a frame buffer update */
+ DisplayHookPtr displayHook;
+ /* inetdDisconnectHook is called when the connection has been
+ interrupted before a client could connect. */
+ InetdDisconnectPtr inetdDisconnectHook;
+#ifdef HAVE_PTHREADS
+ MUTEX(cursorMutex);
+ Bool backgroundLoop;
+#endif
+
+} rfbScreenInfo, *rfbScreenInfoPtr;
+
+
+/*
+ * rfbTranslateFnType is the type of translation functions.
+ */
+
+typedef void (*rfbTranslateFnType)(char *table, rfbPixelFormat *in,
+ rfbPixelFormat *out,
+ char *iptr, char *optr,
+ int bytesBetweenInputLines,
+ int width, int height);
+
+
+/*
+ * vncauth.h - describes the functions provided by the vncauth library.
+ */
+
+#define MAXPWLEN 8
+#define CHALLENGESIZE 16
+
+extern int vncEncryptAndStorePasswd(char *passwd, char *fname);
+extern char *vncDecryptPasswdFromFile(char *fname);
+extern void vncRandomBytes(unsigned char *bytes);
+extern void vncEncryptBytes(unsigned char *bytes, char *passwd);
+
+/* region stuff */
+
+struct sraRegion;
+typedef struct sraRegion* sraRegionPtr;
+
+/*
+ * Per-client structure.
+ */
+
+typedef void (*ClientGoneHookPtr)(struct _rfbClientRec* cl);
+typedef void (*NegotiationFinishedHookPtr)(struct _rfbClientRec* cl);
+
+typedef struct _rfbClientRec {
+
+ /* back pointer to the screen */
+ rfbScreenInfoPtr screen;
+
+ /* private data. You should put any application client specific data
+ * into a struct and let clientData point to it. Don't forget to
+ * free the struct via clientGoneHook!
+ *
+ * This is useful if the IO functions have to behave client specific.
+ */
+ void* clientData;
+
+ ClientGoneHookPtr clientGoneHook;
+
+ /* negotiationFinishedHook is called when the negotiation phase has ended */
+ NegotiationFinishedHookPtr negotiationFinishedHook;
+
+ SOCKET sock;
+ char *host;
+
+#ifdef HAVE_PTHREADS
+ pthread_t client_thread;
+#endif
+ /* Possible client states: */
+ enum {
+ RFB_PROTOCOL_VERSION, /* establishing protocol version */
+ RFB_AUTHENTICATION, /* authenticating */
+ RFB_INITIALISATION, /* sending initialisation messages */
+ RFB_NORMAL /* normal protocol messages */
+ } state;
+
+ Bool reverseConnection;
+ Bool onHold;
+ Bool readyForSetColourMapEntries;
+ Bool useCopyRect;
+ int preferredEncoding;
+ int correMaxWidth, correMaxHeight;
+
+ /* The following member is only used during VNC authentication */
+ CARD8 authChallenge[CHALLENGESIZE];
+
+ /* The following members represent the update needed to get the client's
+ framebuffer from its present state to the current state of our
+ framebuffer.
+
+ If the client does not accept CopyRect encoding then the update is
+ simply represented as the region of the screen which has been modified
+ (modifiedRegion).
+
+ If the client does accept CopyRect encoding, then the update consists of
+ two parts. First we have a single copy from one region of the screen to
+ another (the destination of the copy is copyRegion), and second we have
+ the region of the screen which has been modified in some other way
+ (modifiedRegion).
+
+ Although the copy is of a single region, this region may have many
+ rectangles. When sending an update, the copyRegion is always sent
+ before the modifiedRegion. This is because the modifiedRegion may
+ overlap parts of the screen which are in the source of the copy.
+
+ In fact during normal processing, the modifiedRegion may even overlap
+ the destination copyRegion. Just before an update is sent we remove
+ from the copyRegion anything in the modifiedRegion. */
+
+ sraRegionPtr copyRegion; /* the destination region of the copy */
+ int copyDX, copyDY; /* the translation by which the copy happens */
+
+ sraRegionPtr modifiedRegion;
+
+ /* As part of the FramebufferUpdateRequest, a client can express interest
+ in a subrectangle of the whole framebuffer. This is stored in the
+ requestedRegion member. In the normal case this is the whole
+ framebuffer if the client is ready, empty if it's not. */
+
+ sraRegionPtr requestedRegion;
+
+ /* The following member represents the state of the "deferred update" timer
+ - when the framebuffer is modified and the client is ready, in most
+ cases it is more efficient to defer sending the update by a few
+ milliseconds so that several changes to the framebuffer can be combined
+ into a single update. */
+
+ struct timeval startDeferring;
+
+ /* translateFn points to the translation function which is used to copy
+ and translate a rectangle from the framebuffer to an output buffer. */
+
+ rfbTranslateFnType translateFn;
+ char *translateLookupTable;
+ rfbPixelFormat format;
+
+ /*
+ * UPDATE_BUF_SIZE must be big enough to send at least one whole line of the
+ * framebuffer. So for a max screen width of say 2K with 32-bit pixels this
+ * means 8K minimum.
+ */
+
+#define UPDATE_BUF_SIZE 30000
+
+ char updateBuf[UPDATE_BUF_SIZE];
+ int ublen;
+
+ /* statistics */
+
+ int rfbBytesSent[MAX_ENCODINGS];
+ int rfbRectanglesSent[MAX_ENCODINGS];
+ int rfbLastRectMarkersSent;
+ int rfbLastRectBytesSent;
+ int rfbCursorBytesSent;
+ int rfbCursorUpdatesSent;
+ int rfbFramebufferUpdateMessagesSent;
+ int rfbRawBytesEquivalent;
+ int rfbKeyEventsRcvd;
+ int rfbPointerEventsRcvd;
+
+ /* zlib encoding -- necessary compression state info per client */
+
+ struct z_stream_s compStream;
+ Bool compStreamInited;
+ CARD32 zlibCompressLevel;
+
+ /* tight encoding -- preserve zlib streams' state for each client */
+
+ z_stream zsStruct[4];
+ Bool zsActive[4];
+ int zsLevel[4];
+ int tightCompressLevel;
+ int tightQualityLevel;
+
+ /* soft cursor images */
+ unsigned char *softSource;
+ int softSourceLen;
+ rfbSoftCursorSetImage *softCursorImages[rfbSoftCursorMaxImages];
+ int nextUnusedSoftCursorImage;
+
+ Bool enableLastRectEncoding; /* client supports LastRect encoding */
+ Bool enableSoftCursorUpdates; /* client supports softcursor updates */
+ Bool disableBackground; /* client wants to disable background */
+ Bool enableCursorShapeUpdates; /* client supports cursor shape updates */
+ Bool useRichCursorEncoding; /* rfbEncodingRichCursor is preferred */
+ Bool cursorWasChanged; /* cursor shape update should be sent */
+ Bool cursorWasMoved; /* cursor move shape update should be sent */
+#ifdef BACKCHANNEL
+ Bool enableBackChannel;
+#endif
+
+ struct _rfbClientRec *prev;
+ struct _rfbClientRec *next;
+
+#ifdef HAVE_PTHREADS
+ /* whenever a client is referenced, the refCount has to be incremented
+ and afterwards decremented, so that the client is not cleaned up
+ while being referenced.
+ Use the functions rfbIncrClientRef(cl) and rfbDecrClientRef(cl);
+ */
+ int refCount;
+ MUTEX(refCountMutex);
+ COND(deleteCond);
+
+ MUTEX(outputMutex);
+ MUTEX(updateMutex);
+ COND(updateCond);
+#endif
+
+} rfbClientRec, *rfbClientPtr;
+
+/*
+ * This macro is used to test whether there is a framebuffer update needing to
+ * be sent to the client.
+ */
+
+#define FB_UPDATE_PENDING(cl) \
+ ((!(cl)->enableCursorShapeUpdates && !(cl)->screen->cursorIsDrawn) || \
+ ((cl)->enableCursorShapeUpdates && (cl)->cursorWasChanged) || \
+ !sraRgnEmpty((cl)->copyRegion) || !sraRgnEmpty((cl)->modifiedRegion))
+
+/*
+ * Macros for endian swapping.
+ */
+
+#define Swap16(s) ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff))
+
+#define Swap24(l) ((((l) & 0xff) << 16) | (((l) >> 16) & 0xff) | \
+ (((l) & 0x00ff00)))
+
+#define Swap32(l) (((l) >> 24) | \
+ (((l) & 0x00ff0000) >> 8) | \
+ (((l) & 0x0000ff00) << 8) | \
+ ((l) << 24))
+
+
+extern char rfbEndianTest;
+
+#define Swap16IfLE(s) (rfbEndianTest ? Swap16(s) : (s))
+#define Swap24IfLE(l) (rfbEndianTest ? Swap24(l) : (l))
+#define Swap32IfLE(l) (rfbEndianTest ? Swap32(l) : (l))
+
+/* sockets.c */
+
+extern int rfbMaxClientWait;
+
+extern void rfbInitSockets(rfbScreenInfoPtr rfbScreen);
+extern void rfbDisconnectUDPSock(rfbScreenInfoPtr rfbScreen);
+extern void rfbCloseClient(rfbClientPtr cl);
+extern int ReadExact(rfbClientPtr cl, char *buf, int len);
+extern int ReadExactTimeout(rfbClientPtr cl, char *buf, int len,int timeout);
+extern int WriteExact(rfbClientPtr cl, const char *buf, int len);
+extern void rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec);
+extern int rfbConnect(rfbScreenInfoPtr rfbScreen, char* host, int port);
+extern int ConnectToTcpAddr(char* host, int port);
+extern int ListenOnTCPPort(int port);
+extern int ListenOnUDPPort(int port);
+
+/* rfbserver.c */
+
+extern rfbClientPtr pointerClient;
+
+
+/* Routines to iterate over the client list in a thread-safe way.
+ Only a single iterator can be in use at a time process-wide. */
+typedef struct rfbClientIterator *rfbClientIteratorPtr;
+
+extern void rfbClientListInit(rfbScreenInfoPtr rfbScreen);
+extern rfbClientIteratorPtr rfbGetClientIterator(rfbScreenInfoPtr rfbScreen);
+extern rfbClientPtr rfbClientIteratorNext(rfbClientIteratorPtr iterator);
+extern void rfbReleaseClientIterator(rfbClientIteratorPtr iterator);
+
+extern void rfbNewClientConnection(rfbScreenInfoPtr rfbScreen,int sock);
+extern rfbClientPtr rfbNewClient(rfbScreenInfoPtr rfbScreen,int sock);
+extern rfbClientPtr rfbNewUDPClient(rfbScreenInfoPtr rfbScreen);
+extern rfbClientPtr rfbReverseConnection(rfbScreenInfoPtr rfbScreen,char *host, int port);
+extern void rfbClientConnectionGone(rfbClientPtr cl);
+extern void rfbProcessClientMessage(rfbClientPtr cl);
+extern void rfbClientConnFailed(rfbClientPtr cl, char *reason);
+extern void rfbNewUDPConnection(rfbScreenInfoPtr rfbScreen,int sock);
+extern void rfbProcessUDPInput(rfbScreenInfoPtr rfbScreen);
+extern Bool rfbSendPing(rfbClientPtr cl);
+extern Bool rfbSendFramebufferUpdate(rfbClientPtr cl, sraRegionPtr updateRegion);
+extern Bool rfbSendRectEncodingRaw(rfbClientPtr cl, int x,int y,int w,int h);
+extern Bool rfbSendUpdateBuf(rfbClientPtr cl);
+extern void rfbSendServerCutText(rfbScreenInfoPtr rfbScreen,char *str, int len);
+extern Bool rfbSendCopyRegion(rfbClientPtr cl,sraRegionPtr reg,int dx,int dy);
+extern Bool rfbSendLastRectMarker(rfbClientPtr cl);
+extern Bool rfbSendSetColourMapEntries(rfbClientPtr cl, int firstColour, int nColours);
+extern void rfbSendBell(rfbScreenInfoPtr rfbScreen);
+
+void rfbGotXCutText(rfbScreenInfoPtr rfbScreen, char *str, int len);
+
+#ifdef BACKCHANNEL
+extern void rfbSendBackChannel(rfbScreenInfoPtr s,char* message,int len);
+#endif
+
+/* translate.c */
+
+extern Bool rfbEconomicTranslate;
+
+extern void rfbTranslateNone(char *table, rfbPixelFormat *in,
+ rfbPixelFormat *out,
+ char *iptr, char *optr,
+ int bytesBetweenInputLines,
+ int width, int height);
+extern Bool rfbSetTranslateFunction(rfbClientPtr cl);
+extern Bool rfbSetClientColourMap(rfbClientPtr cl, int firstColour, int nColours);
+extern void rfbSetClientColourMaps(rfbScreenInfoPtr rfbScreen, int firstColour, int nColours);
+
+/* httpd.c */
+
+extern int httpPort;
+extern char *httpDir;
+
+extern void httpInitSockets(rfbScreenInfoPtr rfbScreen);
+extern void httpCheckFds(rfbScreenInfoPtr rfbScreen);
+
+
+
+/* auth.c */
+
+extern void rfbAuthNewClient(rfbClientPtr cl);
+extern void rfbAuthProcessClientMessage(rfbClientPtr cl);
+
+
+/* rre.c */
+
+extern Bool rfbSendRectEncodingRRE(rfbClientPtr cl, int x,int y,int w,int h);
+
+
+/* corre.c */
+
+extern Bool rfbSendRectEncodingCoRRE(rfbClientPtr cl, int x,int y,int w,int h);
+
+
+/* hextile.c */
+
+extern Bool rfbSendRectEncodingHextile(rfbClientPtr cl, int x, int y, int w,
+ int h);
+
+
+/* zlib.c */
+
+/* Minimum zlib rectangle size in bytes. Anything smaller will
+ * not compress well due to overhead.
+ */
+#define VNC_ENCODE_ZLIB_MIN_COMP_SIZE (17)
+
+/* Set maximum zlib rectangle size in pixels. Always allow at least
+ * two scan lines.
+ */
+#define ZLIB_MAX_RECT_SIZE (128*256)
+#define ZLIB_MAX_SIZE(min) ((( min * 2 ) > ZLIB_MAX_RECT_SIZE ) ? \
+ ( min * 2 ) : ZLIB_MAX_RECT_SIZE )
+
+extern Bool rfbSendRectEncodingZlib(rfbClientPtr cl, int x, int y, int w,
+ int h);
+
+
+/* tight.c */
+
+#define TIGHT_DEFAULT_COMPRESSION 6
+
+extern Bool rfbTightDisableGradient;
+
+extern int rfbNumCodedRectsTight(rfbClientPtr cl, int x,int y,int w,int h);
+extern Bool rfbSendRectEncodingTight(rfbClientPtr cl, int x,int y,int w,int h);
+
+
+/* cursor.c */
+
+typedef struct rfbCursor {
+ unsigned char *source; /* points to bits */
+ unsigned char *mask; /* points to bits */
+ unsigned short width, height, xhot, yhot; /* metrics */
+ unsigned short foreRed, foreGreen, foreBlue; /* device-independent colour */
+ unsigned short backRed, backGreen, backBlue; /* device-independent colour */
+ unsigned char *richSource; /* source bytes for a rich cursor */
+} rfbCursor, *rfbCursorPtr;
+
+extern Bool rfbSendCursorShape(rfbClientPtr cl/*, rfbScreenInfoPtr pScreen*/);
+extern Bool rfbSendSoftCursor(rfbClientPtr cl, Bool cursorWasChanged);
+extern unsigned char rfbReverseByte[0x100];
+extern void rfbConvertLSBCursorBitmapOrMask(int width,int height,unsigned char* bitmap);
+extern rfbCursorPtr rfbMakeXCursor(int width,int height,char* cursorString,char* maskString);
+extern char* rfbMakeMaskForXCursor(int width,int height,char* cursorString);
+extern void MakeXCursorFromRichCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr cursor);
+extern void MakeRichCursorFromXCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr cursor);
+extern void MakeSoftCursor(rfbClientPtr cl,rfbCursorPtr cursor);
+extern void rfbFreeCursor(rfbCursorPtr cursor);
+extern void rfbDrawCursor(rfbScreenInfoPtr rfbScreen);
+extern void rfbUndrawCursor(rfbScreenInfoPtr rfbScreen);
+extern void rfbSetCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr c,Bool freeOld);
+
+/* cursor handling for the pointer */
+extern void defaultPtrAddEvent(int buttonMask,int x,int y,rfbClientPtr cl);
+
+/* stats.c */
+
+extern void rfbResetStats(rfbClientPtr cl);
+extern void rfbPrintStats(rfbClientPtr cl);
+
+/* font.c */
+
+typedef struct rfbFontData {
+ unsigned char* data;
+ /*
+ metaData is a 256*5 array:
+ for each character
+ (offset,width,height,x,y)
+ */
+ int* metaData;
+} rfbFontData,* rfbFontDataPtr;
+
+int rfbDrawChar(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,int x,int y,unsigned char c,Pixel colour);
+void rfbDrawString(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,int x,int y,const char* string,Pixel colour);
+/* if colour==backColour, background is transparent */
+int rfbDrawCharWithClip(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,int x,int y,unsigned char c,int x1,int y1,int x2,int y2,Pixel colour,Pixel backColour);
+void rfbDrawStringWithClip(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,int x,int y,const char* string,int x1,int y1,int x2,int y2,Pixel colour,Pixel backColour);
+int rfbWidthOfString(rfbFontDataPtr font,const char* string);
+int rfbWidthOfChar(rfbFontDataPtr font,unsigned char c);
+void rfbFontBBox(rfbFontDataPtr font,unsigned char c,int* x1,int* y1,int* x2,int* y2);
+/* this returns the smallest box enclosing any character of font. */
+void rfbWholeFontBBox(rfbFontDataPtr font,int *x1, int *y1, int *x2, int *y2);
+
+/* dynamically load a linux console font (4096 bytes, 256 glyphs a 8x16 */
+rfbFontDataPtr rfbLoadConsoleFont(char *filename);
+/* free a dynamically loaded font */
+void rfbFreeFont(rfbFontDataPtr font);
+
+/* draw.c */
+
+/* You have to call rfbUndrawCursor before using these functions */
+void rfbFillRect(rfbScreenInfoPtr s,int x1,int y1,int x2,int y2,Pixel col);
+void rfbDrawPixel(rfbScreenInfoPtr s,int x,int y,Pixel col);
+void rfbDrawLine(rfbScreenInfoPtr s,int x1,int y1,int x2,int y2,Pixel col);
+
+/* selbox.c */
+
+/* this opens a modal select box. list is an array of strings, the end marked
+ with a NULL.
+ It returns the index in the list or -1 if cancelled or something else
+ wasn't kosher. */
+typedef void (*SelectionChangedHookPtr)(int _index);
+extern int rfbSelectBox(rfbScreenInfoPtr rfbScreen,
+ rfbFontDataPtr font, char** list,
+ int x1, int y1, int x2, int y2,
+ Pixel foreColour, Pixel backColour,
+ int border,SelectionChangedHookPtr selChangedHook);
+
+/* cargs.c */
+
+extern void rfbUsage(void);
+extern void rfbPurgeArguments(int* argc,int* position,int count,char *argv[]);
+extern void rfbProcessArguments(rfbScreenInfoPtr rfbScreen,int* argc, char *argv[]);
+extern void rfbProcessSizeArguments(int* width,int* height,int* bpp,int* argc, char *argv[]);
+
+/* main.c */
+
+extern void rfbLogEnable(int enabled);
+extern void rfbLog(const char *format, ...);
+extern void rfbLogPerror(const char *str);
+
+void rfbScheduleCopyRect(rfbScreenInfoPtr rfbScreen,int x1,int y1,int x2,int y2,int dx,int dy);
+void rfbScheduleCopyRegion(rfbScreenInfoPtr rfbScreen,sraRegionPtr copyRegion,int dx,int dy);
+
+void rfbDoCopyRect(rfbScreenInfoPtr rfbScreen,int x1,int y1,int x2,int y2,int dx,int dy);
+void rfbDoCopyRegion(rfbScreenInfoPtr rfbScreen,sraRegionPtr copyRegion,int dx,int dy);
+
+void rfbMarkRectAsModified(rfbScreenInfoPtr rfbScreen,int x1,int y1,int x2,int y2);
+void rfbMarkRegionAsModified(rfbScreenInfoPtr rfbScreen,sraRegionPtr modRegion);
+void doNothingWithClient(rfbClientPtr cl);
+enum rfbNewClientAction defaultNewClientHook(rfbClientPtr cl);
+
+/* to check against plain passwords */
+Bool rfbCheckPasswordByList(rfbClientPtr cl,const char* response,int len);
+
+/* functions to make a vnc server */
+extern rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,
+ int width,int height,int bitsPerSample,int samplesPerPixel,
+ int bytesPerPixel);
+extern void rfbInitServer(rfbScreenInfoPtr rfbScreen);
+extern void rfbScreenCleanup(rfbScreenInfoPtr screenInfo);
+
+/* functions to accept/refuse a client that has been put on hold
+ by a NewClientHookPtr function. Must not be called in other
+ situations. */
+extern void rfbStartOnHoldClient(rfbClientPtr cl);
+extern void rfbRefuseOnHoldClient(rfbClientPtr cl);
+
+/* call one of these two functions to service the vnc clients.
+ usec are the microseconds the select on the fds waits.
+ if you are using the event loop, set this to some value > 0, so the
+ server doesn't get a high load just by listening. */
+
+extern void rfbRunEventLoop(rfbScreenInfoPtr screenInfo, long usec, Bool runInBackground);
+extern void rfbProcessEvents(rfbScreenInfoPtr screenInfo,long usec);
+
+#endif
+
+#if(defined __cplusplus)
+}
+#endif
diff --git a/krfb/libvncserver/rfbproto.h b/krfb/libvncserver/rfbproto.h
new file mode 100644
index 00000000..9f9f6bc9
--- /dev/null
+++ b/krfb/libvncserver/rfbproto.h
@@ -0,0 +1,848 @@
+#ifndef RFBPROTO_H
+#define RFBPROTO_H
+
+/*
+ * Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved.
+ * Copyright (C) 2000 Tridia Corporation. All Rights Reserved.
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+/*
+ * rfbproto.h - header file for the RFB protocol version 3.3
+ *
+ * Uses types CARD<n> for an n-bit unsigned integer, INT<n> for an n-bit signed
+ * integer (for n = 8, 16 and 32).
+ *
+ * All multiple byte integers are in big endian (network) order (most
+ * significant byte first). Unless noted otherwise there is no special
+ * alignment of protocol structures.
+ *
+ *
+ * Once the initial handshaking is done, all messages start with a type byte,
+ * (usually) followed by message-specific data. The order of definitions in
+ * this file is as follows:
+ *
+ * (1) Structures used in several types of message.
+ * (2) Structures used in the initial handshaking.
+ * (3) Message types.
+ * (4) Encoding types.
+ * (5) For each message type, the form of the data following the type byte.
+ * Sometimes this is defined by a single structure but the more complex
+ * messages have to be explained by comments.
+ */
+
+
+/*****************************************************************************
+ *
+ * Structures used in several messages
+ *
+ *****************************************************************************/
+
+/*-----------------------------------------------------------------------------
+ * Structure used to specify a rectangle. This structure is a multiple of 4
+ * bytes so that it can be interspersed with 32-bit pixel data without
+ * affecting alignment.
+ */
+
+typedef struct {
+ CARD16 x;
+ CARD16 y;
+ CARD16 w;
+ CARD16 h;
+} rfbRectangle;
+
+#define sz_rfbRectangle 8
+
+
+/*-----------------------------------------------------------------------------
+ * Structure used to specify pixel format.
+ */
+
+typedef struct {
+
+ CARD8 bitsPerPixel; /* 8,16,32 only */
+
+ CARD8 depth; /* 8 to 32 */
+
+ CARD8 bigEndian; /* True if multi-byte pixels are interpreted
+ as big endian, or if single-bit-per-pixel
+ has most significant bit of the byte
+ corresponding to first (leftmost) pixel. Of
+ course this is meaningless for 8 bits/pix */
+
+ CARD8 trueColour; /* If false then we need a "colour map" to
+ convert pixels to RGB. If true, xxxMax and
+ xxxShift specify bits used for red, green
+ and blue */
+
+ /* the following fields are only meaningful if trueColour is true */
+
+ CARD16 redMax; /* maximum red value (= 2^n - 1 where n is the
+ number of bits used for red). Note this
+ value is always in big endian order. */
+
+ CARD16 greenMax; /* similar for green */
+
+ CARD16 blueMax; /* and blue */
+
+ CARD8 redShift; /* number of shifts needed to get the red
+ value in a pixel to the least significant
+ bit. To find the red value from a given
+ pixel, do the following:
+ 1) Swap pixel value according to bigEndian
+ (e.g. if bigEndian is false and host byte
+ order is big endian, then swap).
+ 2) Shift right by redShift.
+ 3) AND with redMax (in host byte order).
+ 4) You now have the red value between 0 and
+ redMax. */
+
+ CARD8 greenShift; /* similar for green */
+
+ CARD8 blueShift; /* and blue */
+
+ CARD8 pad1;
+ CARD16 pad2;
+
+} rfbPixelFormat;
+
+#define sz_rfbPixelFormat 16
+
+
+
+/*****************************************************************************
+ *
+ * Initial handshaking messages
+ *
+ *****************************************************************************/
+
+/*-----------------------------------------------------------------------------
+ * Protocol Version
+ *
+ * The server always sends 12 bytes to start which identifies the latest RFB
+ * protocol version number which it supports. These bytes are interpreted
+ * as a string of 12 ASCII characters in the format "RFB xxx.yyy\n" where
+ * xxx and yyy are the major and minor version numbers (for version 3.3
+ * this is "RFB 003.003\n").
+ *
+ * The client then replies with a similar 12-byte message giving the version
+ * number of the protocol which should actually be used (which may be different
+ * to that quoted by the server).
+ *
+ * It is intended that both clients and servers may provide some level of
+ * backwards compatibility by this mechanism. Servers in particular should
+ * attempt to provide backwards compatibility, and even forwards compatibility
+ * to some extent. For example if a client demands version 3.1 of the
+ * protocol, a 3.0 server can probably assume that by ignoring requests for
+ * encoding types it doesn't understand, everything will still work OK. This
+ * will probably not be the case for changes in the major version number.
+ *
+ * The format string below can be used in sprintf or sscanf to generate or
+ * decode the version string respectively.
+ */
+
+#define rfbProtocolVersionFormat "RFB %03d.%03d\n"
+#define rfbProtocolMajorVersion 3
+#define rfbProtocolMinorVersion 3
+
+typedef char rfbProtocolVersionMsg[13]; /* allow extra byte for null */
+
+#define sz_rfbProtocolVersionMsg 12
+
+
+/*-----------------------------------------------------------------------------
+ * Authentication
+ *
+ * Once the protocol version has been decided, the server then sends a 32-bit
+ * word indicating whether any authentication is needed on the connection.
+ * The value of this word determines the authentication scheme in use. For
+ * version 3.0 of the protocol this may have one of the following values:
+ */
+
+#define rfbConnFailed 0
+#define rfbNoAuth 1
+#define rfbVncAuth 2
+
+/*
+ * rfbConnFailed: For some reason the connection failed (e.g. the server
+ * cannot support the desired protocol version). This is
+ * followed by a string describing the reason (where a
+ * string is specified as a 32-bit length followed by that
+ * many ASCII characters).
+ *
+ * rfbNoAuth: No authentication is needed.
+ *
+ * rfbVncAuth: The VNC authentication scheme is to be used. A 16-byte
+ * challenge follows, which the client encrypts as
+ * appropriate using the password and sends the resulting
+ * 16-byte response. If the response is correct, the
+ * server sends the 32-bit word rfbVncAuthOK. If a simple
+ * failure happens, the server sends rfbVncAuthFailed and
+ * closes the connection. If the server decides that too
+ * many failures have occurred, it sends rfbVncAuthTooMany
+ * and closes the connection. In the latter case, the
+ * server should not allow an immediate reconnection by
+ * the client.
+ */
+
+#define rfbVncAuthOK 0
+#define rfbVncAuthFailed 1
+#define rfbVncAuthTooMany 2
+
+
+/*-----------------------------------------------------------------------------
+ * Client Initialisation Message
+ *
+ * Once the client and server are sure that they're happy to talk to one
+ * another, the client sends an initialisation message. At present this
+ * message only consists of a boolean indicating whether the server should try
+ * to share the desktop by leaving other clients connected, or give exclusive
+ * access to this client by disconnecting all other clients.
+ */
+
+typedef struct {
+ CARD8 shared;
+} rfbClientInitMsg;
+
+#define sz_rfbClientInitMsg 1
+
+
+/*-----------------------------------------------------------------------------
+ * Server Initialisation Message
+ *
+ * After the client initialisation message, the server sends one of its own.
+ * This tells the client the width and height of the server's framebuffer,
+ * its pixel format and the name associated with the desktop.
+ */
+
+typedef struct {
+ CARD16 framebufferWidth;
+ CARD16 framebufferHeight;
+ rfbPixelFormat format; /* the server's preferred pixel format */
+ CARD32 nameLength;
+ /* followed by char name[nameLength] */
+} rfbServerInitMsg;
+
+#define sz_rfbServerInitMsg (8 + sz_rfbPixelFormat)
+
+
+/*
+ * Following the server initialisation message it's up to the client to send
+ * whichever protocol messages it wants. Typically it will send a
+ * SetPixelFormat message and a SetEncodings message, followed by a
+ * FramebufferUpdateRequest. From then on the server will send
+ * FramebufferUpdate messages in response to the client's
+ * FramebufferUpdateRequest messages. The client should send
+ * FramebufferUpdateRequest messages with incremental set to true when it has
+ * finished processing one FramebufferUpdate and is ready to process another.
+ * With a fast client, the rate at which FramebufferUpdateRequests are sent
+ * should be regulated to avoid hogging the network.
+ */
+
+
+
+/*****************************************************************************
+ *
+ * Message types
+ *
+ *****************************************************************************/
+
+/* server -> client */
+
+#define rfbFramebufferUpdate 0
+#define rfbSetColourMapEntries 1
+#define rfbBell 2
+#define rfbServerCutText 3
+#ifdef BACKCHANNEL
+#define rfbBackChannel 15
+#endif
+
+/* client -> server */
+
+#define rfbSetPixelFormat 0
+#define rfbFixColourMapEntries 1 /* not currently supported */
+#define rfbSetEncodings 2
+#define rfbFramebufferUpdateRequest 3
+#define rfbKeyEvent 4
+#define rfbPointerEvent 5
+#define rfbClientCutText 6
+
+
+
+
+/*****************************************************************************
+ *
+ * Encoding types
+ *
+ *****************************************************************************/
+
+#define rfbEncodingRaw 0
+#define rfbEncodingCopyRect 1
+#define rfbEncodingRRE 2
+#define rfbEncodingCoRRE 4
+#define rfbEncodingHextile 5
+#define rfbEncodingZlib 6
+#define rfbEncodingTight 7
+#define rfbEncodingZlibHex 8
+#ifdef BACKCHANNEL
+#define rfbEncodingBackChannel 15
+#endif
+
+/*
+ * Special encoding numbers:
+ * 0xFFFFFF00 .. 0xFFFFFF0F -- encoding-specific compression levels;
+ * 0xFFFFFF10 .. 0xFFFFFF1F -- mouse cursor shape data;
+ * 0xFFFFFF20 .. 0xFFFFFF2F -- various protocol extensions;
+ * 0xFFFFFF30 .. 0xFFFFFFDF -- not allocated yet;
+ * 0xFFFFFFE0 .. 0xFFFFFFEF -- quality level for JPEG compressor;
+ * 0xFFFFFFF0 .. 0xFFFFFFFF -- cross-encoding compression levels.
+ */
+
+#define rfbEncodingCompressLevel0 0xFFFFFF00
+#define rfbEncodingCompressLevel1 0xFFFFFF01
+#define rfbEncodingCompressLevel2 0xFFFFFF02
+#define rfbEncodingCompressLevel3 0xFFFFFF03
+#define rfbEncodingCompressLevel4 0xFFFFFF04
+#define rfbEncodingCompressLevel5 0xFFFFFF05
+#define rfbEncodingCompressLevel6 0xFFFFFF06
+#define rfbEncodingCompressLevel7 0xFFFFFF07
+#define rfbEncodingCompressLevel8 0xFFFFFF08
+#define rfbEncodingCompressLevel9 0xFFFFFF09
+
+#define rfbEncodingXCursor 0xFFFFFF10
+#define rfbEncodingRichCursor 0xFFFFFF11
+#define rfbEncodingSoftCursor 0xFFFFFF12
+
+#define rfbEncodingLastRect 0xFFFFFF20
+#define rfbEncodingBackground 0xFFFFFF25
+
+#define rfbEncodingQualityLevel0 0xFFFFFFE0
+#define rfbEncodingQualityLevel1 0xFFFFFFE1
+#define rfbEncodingQualityLevel2 0xFFFFFFE2
+#define rfbEncodingQualityLevel3 0xFFFFFFE3
+#define rfbEncodingQualityLevel4 0xFFFFFFE4
+#define rfbEncodingQualityLevel5 0xFFFFFFE5
+#define rfbEncodingQualityLevel6 0xFFFFFFE6
+#define rfbEncodingQualityLevel7 0xFFFFFFE7
+#define rfbEncodingQualityLevel8 0xFFFFFFE8
+#define rfbEncodingQualityLevel9 0xFFFFFFE9
+
+
+/*****************************************************************************
+ *
+ * Server -> client message definitions
+ *
+ *****************************************************************************/
+
+
+/*-----------------------------------------------------------------------------
+ * FramebufferUpdate - a block of rectangles to be copied to the framebuffer.
+ *
+ * This message consists of a header giving the number of rectangles of pixel
+ * data followed by the rectangles themselves. The header is padded so that
+ * together with the type byte it is an exact multiple of 4 bytes (to help
+ * with alignment of 32-bit pixels):
+ */
+
+typedef struct {
+ CARD8 type; /* always rfbFramebufferUpdate */
+ CARD8 pad;
+ CARD16 nRects;
+ /* followed by nRects rectangles */
+} rfbFramebufferUpdateMsg;
+
+#define sz_rfbFramebufferUpdateMsg 4
+
+/*
+ * Each rectangle of pixel data consists of a header describing the position
+ * and size of the rectangle and a type word describing the encoding of the
+ * pixel data, followed finally by the pixel data. Note that if the client has
+ * not sent a SetEncodings message then it will only receive raw pixel data.
+ * Also note again that this structure is a multiple of 4 bytes.
+ */
+
+typedef struct {
+ rfbRectangle r;
+ CARD32 encoding; /* one of the encoding types rfbEncoding... */
+} rfbFramebufferUpdateRectHeader;
+
+#define sz_rfbFramebufferUpdateRectHeader (sz_rfbRectangle + 4)
+
+
+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * Raw Encoding. Pixels are sent in top-to-bottom scanline order,
+ * left-to-right within a scanline with no padding in between.
+ */
+
+
+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * CopyRect Encoding. The pixels are specified simply by the x and y position
+ * of the source rectangle.
+ */
+
+typedef struct {
+ CARD16 srcX;
+ CARD16 srcY;
+} rfbCopyRect;
+
+#define sz_rfbCopyRect 4
+
+
+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * RRE - Rise-and-Run-length Encoding. We have an rfbRREHeader structure
+ * giving the number of subrectangles following. Finally the data follows in
+ * the form [<bgpixel><subrect><subrect>...] where each <subrect> is
+ * [<pixel><rfbRectangle>].
+ */
+
+typedef struct {
+ CARD32 nSubrects;
+} rfbRREHeader;
+
+#define sz_rfbRREHeader 4
+
+
+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * CoRRE - Compact RRE Encoding. We have an rfbRREHeader structure giving
+ * the number of subrectangles following. Finally the data follows in the form
+ * [<bgpixel><subrect><subrect>...] where each <subrect> is
+ * [<pixel><rfbCoRRERectangle>]. This means that
+ * the whole rectangle must be at most 255x255 pixels.
+ */
+
+typedef struct {
+ CARD8 x;
+ CARD8 y;
+ CARD8 w;
+ CARD8 h;
+} rfbCoRRERectangle;
+
+#define sz_rfbCoRRERectangle 4
+
+
+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * Hextile Encoding. The rectangle is divided up into "tiles" of 16x16 pixels,
+ * starting at the top left going in left-to-right, top-to-bottom order. If
+ * the width of the rectangle is not an exact multiple of 16 then the width of
+ * the last tile in each row will be correspondingly smaller. Similarly if the
+ * height is not an exact multiple of 16 then the height of each tile in the
+ * final row will also be smaller. Each tile begins with a "subencoding" type
+ * byte, which is a mask made up of a number of bits. If the Raw bit is set
+ * then the other bits are irrelevant; w*h pixel values follow (where w and h
+ * are the width and height of the tile). Otherwise the tile is encoded in a
+ * similar way to RRE, except that the position and size of each subrectangle
+ * can be specified in just two bytes. The other bits in the mask are as
+ * follows:
+ *
+ * BackgroundSpecified - if set, a pixel value follows which specifies
+ * the background colour for this tile. The first non-raw tile in a
+ * rectangle must have this bit set. If this bit isn't set then the
+ * background is the same as the last tile.
+ *
+ * ForegroundSpecified - if set, a pixel value follows which specifies
+ * the foreground colour to be used for all subrectangles in this tile.
+ * If this bit is set then the SubrectsColoured bit must be zero.
+ *
+ * AnySubrects - if set, a single byte follows giving the number of
+ * subrectangles following. If not set, there are no subrectangles (i.e.
+ * the whole tile is just solid background colour).
+ *
+ * SubrectsColoured - if set then each subrectangle is preceded by a pixel
+ * value giving the colour of that subrectangle. If not set, all
+ * subrectangles are the same colour, the foreground colour; if the
+ * ForegroundSpecified bit wasn't set then the foreground is the same as
+ * the last tile.
+ *
+ * The position and size of each subrectangle is specified in two bytes. The
+ * Pack macros below can be used to generate the two bytes from x, y, w, h,
+ * and the Extract macros can be used to extract the x, y, w, h values from
+ * the two bytes.
+ */
+
+#define rfbHextileRaw (1 << 0)
+#define rfbHextileBackgroundSpecified (1 << 1)
+#define rfbHextileForegroundSpecified (1 << 2)
+#define rfbHextileAnySubrects (1 << 3)
+#define rfbHextileSubrectsColoured (1 << 4)
+
+#define rfbHextilePackXY(x,y) (((x) << 4) | (y))
+#define rfbHextilePackWH(w,h) ((((w)-1) << 4) | ((h)-1))
+#define rfbHextileExtractX(byte) ((byte) >> 4)
+#define rfbHextileExtractY(byte) ((byte) & 0xf)
+#define rfbHextileExtractW(byte) (((byte) >> 4) + 1)
+#define rfbHextileExtractH(byte) (((byte) & 0xf) + 1)
+
+
+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * zlib - zlib compressed Encoding. We have an rfbZlibHeader structure
+ * giving the number of bytes following. Finally the data follows is
+ * zlib compressed version of the raw pixel data as negotiated.
+ */
+
+typedef struct {
+ CARD32 nBytes;
+} rfbZlibHeader;
+
+#define sz_rfbZlibHeader 4
+
+
+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * Tight Encoding. FIXME: Add more documentation.
+ */
+
+#define rfbTightExplicitFilter 0x04
+#define rfbTightFill 0x08
+#define rfbTightJpeg 0x09
+#define rfbTightMaxSubencoding 0x09
+
+/* Filters to improve compression efficiency */
+#define rfbTightFilterCopy 0x00
+#define rfbTightFilterPalette 0x01
+#define rfbTightFilterGradient 0x02
+
+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * XCursor encoding. This is a special encoding used to transmit X-style
+ * cursor shapes from server to clients. Note that for this encoding,
+ * coordinates in rfbFramebufferUpdateRectHeader structure hold hotspot
+ * position (r.x, r.y) and cursor size (r.w, r.h). If (w * h != 0), two RGB
+ * samples are sent after header in the rfbXCursorColors structure. They
+ * denote foreground and background colors of the cursor. If a client
+ * supports only black-and-white cursors, it should ignore these colors and
+ * assume that foreground is black and background is white. Next, two bitmaps
+ * (1 bits per pixel) follow: first one with actual data (value 0 denotes
+ * background color, value 1 denotes foreground color), second one with
+ * transparency data (bits with zero value mean that these pixels are
+ * transparent). Both bitmaps represent cursor data in a byte stream, from
+ * left to right, from top to bottom, and each row is byte-aligned. Most
+ * significant bits correspond to leftmost pixels. The number of bytes in
+ * each row can be calculated as ((w + 7) / 8). If (w * h == 0), cursor
+ * should be hidden (or default local cursor should be set by the client).
+ */
+
+typedef struct {
+ CARD8 foreRed;
+ CARD8 foreGreen;
+ CARD8 foreBlue;
+ CARD8 backRed;
+ CARD8 backGreen;
+ CARD8 backBlue;
+} rfbXCursorColors;
+
+#define sz_rfbXCursorColors 6
+
+
+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * RichCursor encoding. This is a special encoding used to transmit cursor
+ * shapes from server to clients. It is similar to the XCursor encoding but
+ * uses client pixel format instead of two RGB colors to represent cursor
+ * image. For this encoding, coordinates in rfbFramebufferUpdateRectHeader
+ * structure hold hotspot position (r.x, r.y) and cursor size (r.w, r.h).
+ * After header, two pixmaps follow: first one with cursor image in current
+ * client pixel format (like in raw encoding), second with transparency data
+ * (1 bit per pixel, exactly the same format as used for transparency bitmap
+ * in the XCursor encoding). If (w * h == 0), cursor should be hidden (or
+ * default local cursor should be set by the client).
+ */
+
+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * SoftCursor encoding. This encoding is used to transmit image and position
+ * of the remote cursor. It has two sub-messages: SetImage is used to upload
+ * one of 16 images, and Move selects the image and sets the position of the
+ * cursor.
+ * Each SoftCursor message starts with a CARD8. If it is in the 0-15 range
+ * it specifies the number of the cursor image and is followed by the
+ * rfbSoftCursorMove message. If the given cursor has not been set yet the
+ * message will be ignored. If the first CARD8 is in the 128-143 range it
+ * specifies the cursor that will be set in the following
+ * rfbSoftCursorSetImage message. To hide the cursor send a SetImage
+ * message with width and height 0 and imageLength 0.
+ * SetImage transmits the hotspot coordinates in the x/y fields of the
+ * rfbFramebufferUpdateRectHeader, width and height of the image are in the
+ * header's width and height fields.
+ * Move transmits the pointer coordinates in the w/h fields of the
+ * header, x/y are always 0.
+ */
+
+typedef struct {
+ CARD8 imageIndex;
+ CARD8 buttonMask; /* bits 0-7 are buttons 1-8, 0=up, 1=down */
+} rfbSoftCursorMove;
+
+typedef struct {
+ CARD8 imageIndex;
+ CARD8 padding;
+ CARD16 imageLength;
+ /*
+ * Followed by an image of the cursor in the client's image format
+ * with the following RLE mask compression. It begins with CARD8 that
+ * specifies the number of mask'ed pixels that will be NOT transmitted.
+ * Then follows a CARD8 that specified by the number of unmask'd pixels
+ * that will be transmitted next. Then a CARD8 with the number of mask'd
+ * pixels and so on.
+ */
+} rfbSoftCursorSetImage;
+
+typedef union {
+ CARD8 type;
+ rfbSoftCursorMove move;
+ rfbSoftCursorSetImage setImage;
+} rfbSoftCursorMsg;
+
+#define rfbSoftCursorMaxImages 16
+#define rfbSoftCursorSetIconOffset 128
+
+
+/*-----------------------------------------------------------------------------
+ * SetColourMapEntries - these messages are only sent if the pixel
+ * format uses a "colour map" (i.e. trueColour false) and the client has not
+ * fixed the entire colour map using FixColourMapEntries. In addition they
+ * will only start being sent after the client has sent its first
+ * FramebufferUpdateRequest. So if the client always tells the server to use
+ * trueColour then it never needs to process this type of message.
+ */
+
+typedef struct {
+ CARD8 type; /* always rfbSetColourMapEntries */
+ CARD8 pad;
+ CARD16 firstColour;
+ CARD16 nColours;
+
+ /* Followed by nColours * 3 * CARD16
+ r1, g1, b1, r2, g2, b2, r3, g3, b3, ..., rn, bn, gn */
+
+} rfbSetColourMapEntriesMsg;
+
+#define sz_rfbSetColourMapEntriesMsg 6
+
+
+
+/*-----------------------------------------------------------------------------
+ * Bell - ring a bell on the client if it has one.
+ */
+
+typedef struct {
+ CARD8 type; /* always rfbBell */
+} rfbBellMsg;
+
+#define sz_rfbBellMsg 1
+
+
+
+/*-----------------------------------------------------------------------------
+ * ServerCutText - the server has new text in its cut buffer.
+ */
+
+typedef struct {
+ CARD8 type; /* always rfbServerCutText */
+ CARD8 pad1;
+ CARD16 pad2;
+ CARD32 length;
+ /* followed by char text[length] */
+} rfbServerCutTextMsg;
+
+#define sz_rfbServerCutTextMsg 8
+
+#ifdef BACKCHANNEL
+typedef rfbServerCutTextMsg rfbBackChannelMsg;
+#define sz_rfbBackChannelMsg 8
+#endif
+
+
+/*-----------------------------------------------------------------------------
+ * Union of all server->client messages.
+ */
+
+typedef union {
+ CARD8 type;
+ rfbFramebufferUpdateMsg fu;
+ rfbSetColourMapEntriesMsg scme;
+ rfbBellMsg b;
+ rfbServerCutTextMsg sct;
+} rfbServerToClientMsg;
+
+
+
+/*****************************************************************************
+ *
+ * Message definitions (client -> server)
+ *
+ *****************************************************************************/
+
+
+/*-----------------------------------------------------------------------------
+ * SetPixelFormat - tell the RFB server the format in which the client wants
+ * pixels sent.
+ */
+
+typedef struct {
+ CARD8 type; /* always rfbSetPixelFormat */
+ CARD8 pad1;
+ CARD16 pad2;
+ rfbPixelFormat format;
+} rfbSetPixelFormatMsg;
+
+#define sz_rfbSetPixelFormatMsg (sz_rfbPixelFormat + 4)
+
+
+/*-----------------------------------------------------------------------------
+ * FixColourMapEntries - when the pixel format uses a "colour map", fix
+ * read-only colour map entries.
+ *
+ * ***************** NOT CURRENTLY SUPPORTED *****************
+ */
+
+typedef struct {
+ CARD8 type; /* always rfbFixColourMapEntries */
+ CARD8 pad;
+ CARD16 firstColour;
+ CARD16 nColours;
+
+ /* Followed by nColours * 3 * CARD16
+ r1, g1, b1, r2, g2, b2, r3, g3, b3, ..., rn, bn, gn */
+
+} rfbFixColourMapEntriesMsg;
+
+#define sz_rfbFixColourMapEntriesMsg 6
+
+
+/*-----------------------------------------------------------------------------
+ * SetEncodings - tell the RFB server which encoding types we accept. Put them
+ * in order of preference, if we have any. We may always receive raw
+ * encoding, even if we don't specify it here.
+ */
+
+typedef struct {
+ CARD8 type; /* always rfbSetEncodings */
+ CARD8 pad;
+ CARD16 nEncodings;
+ /* followed by nEncodings * CARD32 encoding types */
+} rfbSetEncodingsMsg;
+
+#define sz_rfbSetEncodingsMsg 4
+
+
+/*-----------------------------------------------------------------------------
+ * FramebufferUpdateRequest - request for a framebuffer update. If incremental
+ * is true then the client just wants the changes since the last update. If
+ * false then it wants the whole of the specified rectangle.
+ */
+
+typedef struct {
+ CARD8 type; /* always rfbFramebufferUpdateRequest */
+ CARD8 incremental;
+ CARD16 x;
+ CARD16 y;
+ CARD16 w;
+ CARD16 h;
+} rfbFramebufferUpdateRequestMsg;
+
+#define sz_rfbFramebufferUpdateRequestMsg 10
+
+
+/*-----------------------------------------------------------------------------
+ * KeyEvent - key press or release
+ *
+ * Keys are specified using the "keysym" values defined by the X Window System.
+ * For most ordinary keys, the keysym is the same as the corresponding ASCII
+ * value. Other common keys are:
+ *
+ * BackSpace 0xff08
+ * Tab 0xff09
+ * Return or Enter 0xff0d
+ * Escape 0xff1b
+ * Insert 0xff63
+ * Delete 0xffff
+ * Home 0xff50
+ * End 0xff57
+ * Page Up 0xff55
+ * Page Down 0xff56
+ * Left 0xff51
+ * Up 0xff52
+ * Right 0xff53
+ * Down 0xff54
+ * F1 0xffbe
+ * F2 0xffbf
+ * ... ...
+ * F12 0xffc9
+ * Shift 0xffe1
+ * Control 0xffe3
+ * Meta 0xffe7
+ * Alt 0xffe9
+ */
+
+typedef struct {
+ CARD8 type; /* always rfbKeyEvent */
+ CARD8 down; /* true if down (press), false if up */
+ CARD16 pad;
+ CARD32 key; /* key is specified as an X keysym */
+} rfbKeyEventMsg;
+
+#define sz_rfbKeyEventMsg 8
+
+
+/*-----------------------------------------------------------------------------
+ * PointerEvent - mouse/pen move and/or button press.
+ */
+
+typedef struct {
+ CARD8 type; /* always rfbPointerEvent */
+ CARD8 buttonMask; /* bits 0-7 are buttons 1-8, 0=up, 1=down */
+ CARD16 x;
+ CARD16 y;
+} rfbPointerEventMsg;
+
+#define rfbButton1Mask 1
+#define rfbButton2Mask 2
+#define rfbButton3Mask 4
+
+#define sz_rfbPointerEventMsg 6
+
+
+
+/*-----------------------------------------------------------------------------
+ * ClientCutText - the client has new text in its cut buffer.
+ */
+
+typedef struct {
+ CARD8 type; /* always rfbClientCutText */
+ CARD8 pad1;
+ CARD16 pad2;
+ CARD32 length;
+ /* followed by char text[length] */
+} rfbClientCutTextMsg;
+
+#define sz_rfbClientCutTextMsg 8
+
+
+
+/*-----------------------------------------------------------------------------
+ * Union of all client->server messages.
+ */
+
+typedef union {
+ CARD8 type;
+ rfbSetPixelFormatMsg spf;
+ rfbFixColourMapEntriesMsg fcme;
+ rfbSetEncodingsMsg se;
+ rfbFramebufferUpdateRequestMsg fur;
+ rfbKeyEventMsg ke;
+ rfbPointerEventMsg pe;
+ rfbClientCutTextMsg cct;
+} rfbClientToServerMsg;
+
+#endif
diff --git a/krfb/libvncserver/rfbserver.c b/krfb/libvncserver/rfbserver.c
new file mode 100644
index 00000000..78d40798
--- /dev/null
+++ b/krfb/libvncserver/rfbserver.c
@@ -0,0 +1,1590 @@
+/*
+ * rfbserver.c - deal with server-side of the RFB protocol.
+ */
+
+/*
+ * OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
+ * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
+ * All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "rfb.h"
+#include "sraRegion.h"
+#ifdef WIN32
+#define write(sock,buf,len) send(sock,buf,len,0)
+#else
+#include <unistd.h>
+#include <pwd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif
+#include <sys/types.h>
+#ifdef __osf__
+typedef int socklen_t;
+#endif
+
+#ifdef CORBA
+#include <vncserverctrl.h>
+#endif
+
+#ifdef DEBUGPROTO
+#undef DEBUGPROTO
+#define DEBUGPROTO(x) x
+#else
+#define DEBUGPROTO(x)
+#endif
+
+rfbClientPtr pointerClient = NULL; /* Mutex for pointer events */
+
+static void rfbProcessClientProtocolVersion(rfbClientPtr cl);
+static void rfbProcessClientNormalMessage(rfbClientPtr cl);
+static void rfbProcessClientInitMessage(rfbClientPtr cl);
+
+#ifdef HAVE_PTHREADS
+void rfbIncrClientRef(rfbClientPtr cl)
+{
+ LOCK(cl->refCountMutex);
+ cl->refCount++;
+ UNLOCK(cl->refCountMutex);
+}
+
+void rfbDecrClientRef(rfbClientPtr cl)
+{
+ LOCK(cl->refCountMutex);
+ cl->refCount--;
+ if(cl->refCount<=0) /* just to be sure also < 0 */
+ TSIGNAL(cl->deleteCond);
+ UNLOCK(cl->refCountMutex);
+}
+#else
+void rfbIncrClientRef(rfbClientPtr cl)
+{
+}
+
+void rfbDecrClientRef(rfbClientPtr cl)
+{
+}
+#endif
+
+MUTEX(rfbClientListMutex);
+
+struct rfbClientIterator {
+ rfbClientPtr next;
+ rfbScreenInfoPtr screen;
+};
+
+void
+rfbClientListInit(rfbScreenInfoPtr rfbScreen)
+{
+ rfbScreen->rfbClientHead = NULL;
+ INIT_MUTEX(rfbClientListMutex);
+}
+
+rfbClientIteratorPtr
+rfbGetClientIterator(rfbScreenInfoPtr rfbScreen)
+{
+ rfbClientIteratorPtr i =
+ (rfbClientIteratorPtr)malloc(sizeof(struct rfbClientIterator));
+ i->next = 0;
+ i->screen = rfbScreen;
+ return i;
+}
+
+rfbClientPtr
+rfbClientIteratorNext(rfbClientIteratorPtr i)
+{
+ if(i->next == 0) {
+ LOCK(rfbClientListMutex);
+ i->next = i->screen->rfbClientHead;
+ UNLOCK(rfbClientListMutex);
+ } else {
+ IF_PTHREADS(rfbClientPtr cl = i->next);
+ i->next = i->next->next;
+ IF_PTHREADS(rfbDecrClientRef(cl));
+ }
+
+#ifdef HAVE_PTHREADS
+ while(i->next && i->next->sock<0)
+ i->next = i->next->next;
+ if(i->next)
+ rfbIncrClientRef(i->next);
+#endif
+
+ return i->next;
+}
+
+void
+rfbReleaseClientIterator(rfbClientIteratorPtr iterator)
+{
+ IF_PTHREADS(if(iterator->next) rfbDecrClientRef(iterator->next));
+}
+
+
+/*
+ * rfbNewClientConnection is called from sockets.c when a new connection
+ * comes in.
+ */
+
+void
+rfbNewClientConnection(rfbScreen,sock)
+ rfbScreenInfoPtr rfbScreen;
+ int sock;
+{
+ rfbClientPtr cl;
+
+ cl = rfbNewClient(rfbScreen,sock);
+#ifdef CORBA
+ if(cl!=NULL)
+ newConnection(cl, (KEYBOARD_DEVICE|POINTER_DEVICE),1,1,1);
+#endif
+}
+
+
+/*
+ * rfbReverseConnection is called by the CORBA stuff to make an outward
+ * connection to a "listening" RFB client.
+ */
+
+rfbClientPtr
+rfbReverseConnection(rfbScreen,host, port)
+ rfbScreenInfoPtr rfbScreen;
+ char *host;
+ int port;
+{
+ int sock;
+ rfbClientPtr cl;
+
+ if ((sock = rfbConnect(rfbScreen, host, port)) < 0)
+ return (rfbClientPtr)NULL;
+
+ cl = rfbNewClient(rfbScreen, sock);
+
+ if (cl) {
+ cl->reverseConnection = TRUE;
+ }
+
+ return cl;
+}
+
+
+/*
+ * rfbNewClient is called when a new connection has been made by whatever
+ * means.
+ */
+
+static rfbClientPtr
+rfbNewTCPOrUDPClient(rfbScreen,sock,isUDP)
+ rfbScreenInfoPtr rfbScreen;
+ int sock;
+ Bool isUDP;
+{
+ rfbProtocolVersionMsg pv;
+ rfbClientIteratorPtr iterator;
+ rfbClientPtr cl,cl_;
+ struct sockaddr_in addr;
+ size_t addrlen = sizeof(struct sockaddr_in);
+ int i;
+
+ cl = (rfbClientPtr)calloc(sizeof(rfbClientRec),1);
+
+ cl->screen = rfbScreen;
+ cl->sock = sock;
+ rfbResetStats(cl);
+
+ if(isUDP) {
+ rfbLog(" accepted UDP client\n");
+ } else {
+ getpeername(sock, (struct sockaddr *)&addr, &addrlen);
+ cl->host = strdup(inet_ntoa(addr.sin_addr));
+
+ rfbLog(" other clients:\n");
+ iterator = rfbGetClientIterator(rfbScreen);
+ while ((cl_ = rfbClientIteratorNext(iterator)) != NULL) {
+ rfbLog(" %s\n",cl_->host);
+ }
+ rfbReleaseClientIterator(iterator);
+
+ FD_SET(sock,&(rfbScreen->allFds));
+ rfbScreen->maxFd = max(sock,rfbScreen->maxFd);
+
+ INIT_MUTEX(cl->outputMutex);
+ INIT_MUTEX(cl->refCountMutex);
+ INIT_COND(cl->deleteCond);
+
+ cl->state = RFB_PROTOCOL_VERSION;
+
+ cl->reverseConnection = FALSE;
+ cl->readyForSetColourMapEntries = FALSE;
+ cl->useCopyRect = FALSE;
+ cl->preferredEncoding = rfbEncodingRaw;
+ cl->correMaxWidth = 48;
+ cl->correMaxHeight = 48;
+
+ cl->copyRegion = sraRgnCreate();
+ cl->copyDX = 0;
+ cl->copyDY = 0;
+
+ cl->modifiedRegion =
+ sraRgnCreateRect(0,0,rfbScreen->width,rfbScreen->height);
+
+ INIT_MUTEX(cl->updateMutex);
+ INIT_COND(cl->updateCond);
+
+ cl->requestedRegion = sraRgnCreate();
+
+ cl->format = cl->screen->rfbServerFormat;
+ cl->translateFn = rfbTranslateNone;
+ cl->translateLookupTable = NULL;
+
+ LOCK(rfbClientListMutex);
+
+ IF_PTHREADS(cl->refCount = 0);
+ cl->next = rfbScreen->rfbClientHead;
+ cl->prev = NULL;
+ if (rfbScreen->rfbClientHead)
+ rfbScreen->rfbClientHead->prev = cl;
+
+ rfbScreen->rfbClientHead = cl;
+ UNLOCK(rfbClientListMutex);
+
+ cl->tightCompressLevel = TIGHT_DEFAULT_COMPRESSION;
+ cl->tightQualityLevel = -1;
+ for (i = 0; i < 4; i++)
+ cl->zsActive[i] = FALSE;
+
+ cl->enableCursorShapeUpdates = FALSE;
+ cl->useRichCursorEncoding = FALSE;
+ cl->enableLastRectEncoding = FALSE;
+ cl->disableBackground = FALSE;
+
+ cl->compStreamInited = FALSE;
+ cl->compStream.total_in = 0;
+ cl->compStream.total_out = 0;
+ cl->compStream.zalloc = Z_NULL;
+ cl->compStream.zfree = Z_NULL;
+ cl->compStream.opaque = Z_NULL;
+
+ cl->zlibCompressLevel = 5;
+
+ sprintf(pv,rfbProtocolVersionFormat,rfbProtocolMajorVersion,
+ rfbProtocolMinorVersion);
+
+ if (WriteExact(cl, pv, sz_rfbProtocolVersionMsg) < 0) {
+ rfbLogPerror("rfbNewClient: write");
+ rfbCloseClient(cl);
+ /* TODO: memory leak here (cl is never freed)
+ * can rfbClientConnectionGone called at this time?
+ * tim@tjansen.de
+ */
+ return NULL;
+ }
+ }
+
+ cl->clientData = NULL;
+ cl->clientGoneHook = doNothingWithClient;
+ cl->negotiationFinishedHook = doNothingWithClient;
+ switch (cl->screen->newClientHook(cl)) {
+ case RFB_CLIENT_ON_HOLD:
+ cl->onHold = TRUE;
+ break;
+ case RFB_CLIENT_ACCEPT:
+ cl->onHold = FALSE;
+ break;
+ case RFB_CLIENT_REFUSE:
+ rfbCloseClient(cl);
+ rfbClientConnectionGone(cl);
+ cl = NULL;
+ break;
+ }
+ return cl;
+}
+
+rfbClientPtr
+rfbNewClient(rfbScreen,sock)
+ rfbScreenInfoPtr rfbScreen;
+ int sock;
+{
+ return(rfbNewTCPOrUDPClient(rfbScreen,sock,FALSE));
+}
+
+rfbClientPtr
+rfbNewUDPClient(rfbScreen)
+ rfbScreenInfoPtr rfbScreen;
+{
+ return((rfbScreen->udpClient=
+ rfbNewTCPOrUDPClient(rfbScreen,rfbScreen->udpSock,TRUE)));
+}
+
+/*
+ * rfbClientConnectionGone is called from sockets.c just after a connection
+ * has gone away.
+ */
+
+void
+rfbClientConnectionGone(cl)
+ rfbClientPtr cl;
+{
+ int i;
+
+ LOCK(rfbClientListMutex);
+
+ if (cl->prev)
+ cl->prev->next = cl->next;
+ else
+ cl->screen->rfbClientHead = cl->next;
+ if (cl->next)
+ cl->next->prev = cl->prev;
+
+#ifdef HAVE_PTHREADS
+ LOCK(cl->refCountMutex);
+ if(cl->refCount) {
+ UNLOCK(cl->refCountMutex);
+ WAIT(cl->deleteCond,cl->refCountMutex);
+ } else {
+ UNLOCK(cl->refCountMutex);
+ }
+#endif
+
+ if(cl->sock>=0)
+ FD_CLR(cl->sock,&(cl->screen->allFds));
+
+ cl->clientGoneHook(cl);
+
+ rfbLog("Client %s gone\n",cl->host);
+ free(cl->host);
+
+ /* Release the compression state structures if any. */
+ if ( cl->compStreamInited ) {
+ deflateEnd( &(cl->compStream) );
+ }
+
+ for (i = 0; i < 4; i++) {
+ if (cl->zsActive[i])
+ deflateEnd(&cl->zsStruct[i]);
+ }
+
+ if (pointerClient == cl)
+ pointerClient = NULL;
+
+ sraRgnDestroy(cl->modifiedRegion);
+
+ UNLOCK(rfbClientListMutex);
+
+ if (cl->translateLookupTable) free(cl->translateLookupTable);
+
+ TINI_COND(cl->updateCond);
+ TINI_MUTEX(cl->updateMutex);
+
+ LOCK(cl->outputMutex);
+ TINI_MUTEX(cl->outputMutex);
+
+#ifdef CORBA
+ destroyConnection(cl);
+#endif
+
+ rfbPrintStats(cl);
+
+ free(cl);
+}
+
+
+/*
+ * rfbProcessClientMessage is called when there is data to read from a client.
+ */
+
+void
+rfbProcessClientMessage(cl)
+ rfbClientPtr cl;
+{
+ switch (cl->state) {
+ case RFB_PROTOCOL_VERSION:
+ rfbProcessClientProtocolVersion(cl);
+ return;
+ case RFB_AUTHENTICATION:
+ rfbAuthProcessClientMessage(cl);
+ return;
+ case RFB_INITIALISATION:
+ rfbProcessClientInitMessage(cl);
+ return;
+ default:
+ rfbProcessClientNormalMessage(cl);
+ return;
+ }
+}
+
+
+/*
+ * rfbProcessClientProtocolVersion is called when the client sends its
+ * protocol version.
+ */
+
+static void
+rfbProcessClientProtocolVersion(cl)
+ rfbClientPtr cl;
+{
+ rfbProtocolVersionMsg pv;
+ int n, major_, minor_;
+ char failureReason[256];
+
+ if ((n = ReadExact(cl, pv, sz_rfbProtocolVersionMsg)) <= 0) {
+ if (n == 0)
+ rfbLog("rfbProcessClientProtocolVersion: client gone\n");
+ else
+ rfbLogPerror("rfbProcessClientProtocolVersion: read");
+ rfbCloseClient(cl);
+ return;
+ }
+
+ pv[sz_rfbProtocolVersionMsg] = 0;
+ if (sscanf(pv,rfbProtocolVersionFormat,&major_,&minor_) != 2) {
+ rfbLog("rfbProcessClientProtocolVersion: not a valid RFB client\n");
+ rfbCloseClient(cl);
+ return;
+ }
+ rfbLog("Protocol version %d.%d\n", major_, minor_);
+
+ if (major_ != rfbProtocolMajorVersion) {
+ /* Major version mismatch - send a ConnFailed message */
+
+ rfbLog("Major version mismatch\n");
+ sprintf(failureReason,
+ "RFB protocol version mismatch - server %d.%d, client %d.%d",
+ rfbProtocolMajorVersion,rfbProtocolMinorVersion,major_,minor_);
+ rfbClientConnFailed(cl, failureReason);
+ return;
+ }
+
+ if (minor_ != rfbProtocolMinorVersion) {
+ /* Minor version mismatch - warn but try to continue */
+ rfbLog("Ignoring minor version mismatch\n");
+ }
+
+ rfbAuthNewClient(cl);
+}
+
+
+/*
+ * rfbClientConnFailed is called when a client connection has failed either
+ * because it talks the wrong protocol or it has failed authentication.
+ */
+
+void
+rfbClientConnFailed(cl, reason)
+ rfbClientPtr cl;
+ char *reason;
+{
+ char *buf;
+ int len = strlen(reason);
+
+ buf = (char *)malloc(8 + len);
+ ((CARD32 *)buf)[0] = Swap32IfLE(rfbConnFailed);
+ ((CARD32 *)buf)[1] = Swap32IfLE(len);
+ memcpy(buf + 8, reason, len);
+
+ if (WriteExact(cl, buf, 8 + len) < 0)
+ rfbLogPerror("rfbClientConnFailed: write");
+ free(buf);
+ rfbCloseClient(cl);
+}
+
+
+/*
+ * rfbProcessClientInitMessage is called when the client sends its
+ * initialisation message.
+ */
+
+static void
+rfbProcessClientInitMessage(cl)
+ rfbClientPtr cl;
+{
+ rfbClientInitMsg ci;
+ char buf[256];
+ rfbServerInitMsg *si = (rfbServerInitMsg *)buf;
+ int len, n;
+ rfbClientIteratorPtr iterator;
+ rfbClientPtr otherCl;
+
+ if ((n = ReadExact(cl, (char *)&ci,sz_rfbClientInitMsg)) <= 0) {
+ if (n == 0)
+ rfbLog("rfbProcessClientInitMessage: client gone\n");
+ else
+ rfbLogPerror("rfbProcessClientInitMessage: read");
+ rfbCloseClient(cl);
+ return;
+ }
+
+ si->framebufferWidth = Swap16IfLE(cl->screen->width);
+ si->framebufferHeight = Swap16IfLE(cl->screen->height);
+ si->format = cl->screen->rfbServerFormat;
+ si->format.redMax = Swap16IfLE(si->format.redMax);
+ si->format.greenMax = Swap16IfLE(si->format.greenMax);
+ si->format.blueMax = Swap16IfLE(si->format.blueMax);
+
+ if (strlen(cl->screen->desktopName) > 128) /* sanity check on desktop name len */
+ ((char*)cl->screen->desktopName)[128] = 0;
+
+ strcpy(buf + sz_rfbServerInitMsg, cl->screen->desktopName);
+ len = strlen(buf + sz_rfbServerInitMsg);
+ si->nameLength = Swap32IfLE(len);
+
+ if (WriteExact(cl, buf, sz_rfbServerInitMsg + len) < 0) {
+ rfbLogPerror("rfbProcessClientInitMessage: write");
+ rfbCloseClient(cl);
+ return;
+ }
+
+ cl->state = RFB_NORMAL;
+
+ if (!cl->reverseConnection &&
+ (cl->screen->rfbNeverShared || (!cl->screen->rfbAlwaysShared && !ci.shared))) {
+
+ if (cl->screen->rfbDontDisconnect) {
+ iterator = rfbGetClientIterator(cl->screen);
+ while ((otherCl = rfbClientIteratorNext(iterator)) != NULL) {
+ if ((otherCl != cl) && (otherCl->state == RFB_NORMAL)) {
+ rfbLog("-dontdisconnect: Not shared & existing client\n");
+ rfbLog(" refusing new client %s\n", cl->host);
+ rfbCloseClient(cl);
+ rfbReleaseClientIterator(iterator);
+ return;
+ }
+ }
+ rfbReleaseClientIterator(iterator);
+ } else {
+ iterator = rfbGetClientIterator(cl->screen);
+ while ((otherCl = rfbClientIteratorNext(iterator)) != NULL) {
+ if ((otherCl != cl) && (otherCl->state == RFB_NORMAL)) {
+ rfbLog("Not shared - closing connection to client %s\n",
+ otherCl->host);
+ rfbCloseClient(otherCl);
+ }
+ }
+ rfbReleaseClientIterator(iterator);
+ }
+ }
+}
+
+
+/*
+ * rfbProcessClientNormalMessage is called when the client has sent a normal
+ * protocol message.
+ */
+
+static void
+rfbProcessClientNormalMessage(cl)
+ rfbClientPtr cl;
+{
+ int n=0;
+ rfbClientToServerMsg msg;
+ char *str;
+
+ if ((n = ReadExact(cl, (char *)&msg, 1)) <= 0) {
+ if (n != 0)
+ rfbLogPerror("rfbProcessClientNormalMessage: read");
+ rfbCloseClient(cl);
+ return;
+ }
+
+ switch (msg.type) {
+
+ case rfbSetPixelFormat:
+
+ if ((n = ReadExact(cl, ((char *)&msg) + 1,
+ sz_rfbSetPixelFormatMsg - 1)) <= 0) {
+ if (n != 0)
+ rfbLogPerror("rfbProcessClientNormalMessage: read");
+ rfbCloseClient(cl);
+ return;
+ }
+
+ cl->format.bitsPerPixel = msg.spf.format.bitsPerPixel;
+ cl->format.depth = msg.spf.format.depth;
+ cl->format.bigEndian = (msg.spf.format.bigEndian ? TRUE : FALSE);
+ cl->format.trueColour = (msg.spf.format.trueColour ? TRUE : FALSE);
+ cl->format.redMax = Swap16IfLE(msg.spf.format.redMax);
+ cl->format.greenMax = Swap16IfLE(msg.spf.format.greenMax);
+ cl->format.blueMax = Swap16IfLE(msg.spf.format.blueMax);
+ cl->format.redShift = msg.spf.format.redShift;
+ cl->format.greenShift = msg.spf.format.greenShift;
+ cl->format.blueShift = msg.spf.format.blueShift;
+
+ cl->readyForSetColourMapEntries = TRUE;
+ cl->screen->setTranslateFunction(cl);
+
+ return;
+
+
+ case rfbFixColourMapEntries:
+ if ((n = ReadExact(cl, ((char *)&msg) + 1,
+ sz_rfbFixColourMapEntriesMsg - 1)) <= 0) {
+ if (n != 0)
+ rfbLogPerror("rfbProcessClientNormalMessage: read");
+ rfbCloseClient(cl);
+ return;
+ }
+ rfbLog("rfbProcessClientNormalMessage: %s",
+ "FixColourMapEntries unsupported\n");
+ rfbCloseClient(cl);
+ return;
+
+
+ case rfbSetEncodings:
+ {
+ int i;
+ CARD32 enc;
+
+ if ((n = ReadExact(cl, ((char *)&msg) + 1,
+ sz_rfbSetEncodingsMsg - 1)) <= 0) {
+ if (n != 0)
+ rfbLogPerror("rfbProcessClientNormalMessage: read");
+ rfbCloseClient(cl);
+ return;
+ }
+
+ msg.se.nEncodings = Swap16IfLE(msg.se.nEncodings);
+
+ cl->preferredEncoding = -1;
+ cl->useCopyRect = FALSE;
+ cl->enableCursorShapeUpdates = FALSE;
+ cl->enableLastRectEncoding = FALSE;
+ cl->disableBackground = FALSE;
+
+ for (i = 0; i < msg.se.nEncodings; i++) {
+ if ((n = ReadExact(cl, (char *)&enc, 4)) <= 0) {
+ if (n != 0)
+ rfbLogPerror("rfbProcessClientNormalMessage: read");
+ rfbCloseClient(cl);
+ return;
+ }
+ enc = Swap32IfLE(enc);
+
+ switch (enc) {
+
+ case rfbEncodingCopyRect:
+ cl->useCopyRect = TRUE;
+ break;
+ case rfbEncodingRaw:
+ if (cl->preferredEncoding == -1) {
+ cl->preferredEncoding = enc;
+ rfbLog("Using raw encoding for client %s\n",
+ cl->host);
+ }
+ break;
+ case rfbEncodingRRE:
+ if (cl->preferredEncoding == -1) {
+ cl->preferredEncoding = enc;
+ rfbLog("Using rre encoding for client %s\n",
+ cl->host);
+ }
+ break;
+ case rfbEncodingCoRRE:
+ if (cl->preferredEncoding == -1) {
+ cl->preferredEncoding = enc;
+ rfbLog("Using CoRRE encoding for client %s\n",
+ cl->host);
+ }
+ break;
+ case rfbEncodingHextile:
+ if (cl->preferredEncoding == -1) {
+ cl->preferredEncoding = enc;
+ rfbLog("Using hextile encoding for client %s\n",
+ cl->host);
+ }
+ break;
+ case rfbEncodingZlib:
+ if (cl->preferredEncoding == -1) {
+ cl->preferredEncoding = enc;
+ rfbLog("Using zlib encoding for client %s\n",
+ cl->host);
+ }
+ break;
+ case rfbEncodingTight:
+ if (cl->preferredEncoding == -1) {
+ cl->preferredEncoding = enc;
+ rfbLog("Using tight encoding for client %s\n",
+ cl->host);
+ }
+ break;
+ case rfbEncodingXCursor:
+ if (cl->enableSoftCursorUpdates)
+ break;
+ if(!cl->screen->dontConvertRichCursorToXCursor) {
+ rfbLog("Enabling X-style cursor updates for client %s\n",
+ cl->host);
+ cl->enableCursorShapeUpdates = TRUE;
+ cl->cursorWasChanged = TRUE;
+ }
+ break;
+ case rfbEncodingRichCursor:
+ rfbLog("Enabling full-color cursor updates for client "
+ "%s\n", cl->host);
+ if (cl->enableSoftCursorUpdates)
+ break;
+ cl->enableCursorShapeUpdates = TRUE;
+ cl->useRichCursorEncoding = TRUE;
+ cl->cursorWasChanged = TRUE;
+ break;
+ case rfbEncodingSoftCursor:
+ rfbLog("Enabling soft cursor updates for client "
+ "%s\n", cl->host);
+ cl->enableSoftCursorUpdates = TRUE;
+ cl->cursorWasChanged = TRUE;
+ cl->cursorWasMoved = TRUE;
+ cl->enableCursorShapeUpdates = FALSE;
+ cl->useRichCursorEncoding = FALSE;
+ break;
+ case rfbEncodingLastRect:
+ if (!cl->enableLastRectEncoding) {
+ rfbLog("Enabling LastRect protocol extension for client "
+ "%s\n", cl->host);
+ cl->enableLastRectEncoding = TRUE;
+ }
+ break;
+ case rfbEncodingBackground:
+ rfbLog("Disabling background for client "
+ "%s\n", cl->host);
+ cl->disableBackground = TRUE;
+ break;
+#ifdef BACKCHANNEL
+ case rfbEncodingBackChannel:
+ if (!cl->enableBackChannel) {
+ rfbLog("Enabling BackChannel protocol extension for "
+ "client %s\n", cl->host);
+ cl->enableBackChannel = TRUE;
+ }
+ break;
+#endif
+ default:
+ if ( enc >= (CARD32)rfbEncodingCompressLevel0 &&
+ enc <= (CARD32)rfbEncodingCompressLevel9 ) {
+ cl->zlibCompressLevel = enc & 0x0F;
+ cl->tightCompressLevel = enc & 0x0F;
+ rfbLog("Using compression level %d for client %s\n",
+ cl->tightCompressLevel, cl->host);
+ } else if ( enc >= (CARD32)rfbEncodingQualityLevel0 &&
+ enc <= (CARD32)rfbEncodingQualityLevel9 ) {
+ cl->tightQualityLevel = enc & 0x0F;
+ rfbLog("Using image quality level %d for client %s\n",
+ cl->tightQualityLevel, cl->host);
+ } else
+ rfbLog("rfbProcessClientNormalMessage: ignoring unknown "
+ "encoding type %d\n", (int)enc);
+ }
+ }
+
+ if (cl->preferredEncoding == -1) {
+ cl->preferredEncoding = rfbEncodingRaw;
+ }
+
+ cl->negotiationFinishedHook(cl);
+
+ return;
+ }
+
+
+ case rfbFramebufferUpdateRequest:
+ {
+ sraRegionPtr tmpRegion;
+
+ if ((n = ReadExact(cl, ((char *)&msg) + 1,
+ sz_rfbFramebufferUpdateRequestMsg-1)) <= 0) {
+ if (n != 0)
+ rfbLogPerror("rfbProcessClientNormalMessage: read");
+ rfbCloseClient(cl);
+ return;
+ }
+
+ tmpRegion =
+ sraRgnCreateRect(Swap16IfLE(msg.fur.x),
+ Swap16IfLE(msg.fur.y),
+ Swap16IfLE(msg.fur.x)+Swap16IfLE(msg.fur.w),
+ Swap16IfLE(msg.fur.y)+Swap16IfLE(msg.fur.h));
+
+ LOCK(cl->updateMutex);
+ sraRgnOr(cl->requestedRegion,tmpRegion);
+
+ if (!cl->readyForSetColourMapEntries) {
+ /* client hasn't sent a SetPixelFormat so is using server's */
+ cl->readyForSetColourMapEntries = TRUE;
+ if (!cl->format.trueColour) {
+ if (!rfbSetClientColourMap(cl, 0, 0)) {
+ sraRgnDestroy(tmpRegion);
+ UNLOCK(cl->updateMutex);
+ return;
+ }
+ }
+ }
+
+ if (!msg.fur.incremental) {
+ sraRgnOr(cl->modifiedRegion,tmpRegion);
+ sraRgnSubtract(cl->copyRegion,tmpRegion);
+ }
+ TSIGNAL(cl->updateCond);
+ UNLOCK(cl->updateMutex);
+
+ sraRgnDestroy(tmpRegion);
+
+ return;
+ }
+
+ case rfbKeyEvent:
+
+ cl->rfbKeyEventsRcvd++;
+
+ if ((n = ReadExact(cl, ((char *)&msg) + 1,
+ sz_rfbKeyEventMsg - 1)) <= 0) {
+ if (n != 0)
+ rfbLogPerror("rfbProcessClientNormalMessage: read");
+ rfbCloseClient(cl);
+ return;
+ }
+
+ cl->screen->kbdAddEvent(msg.ke.down, (KeySym)Swap32IfLE(msg.ke.key), cl);
+ return;
+
+
+ case rfbPointerEvent:
+
+ cl->rfbPointerEventsRcvd++;
+
+ if ((n = ReadExact(cl, ((char *)&msg) + 1,
+ sz_rfbPointerEventMsg - 1)) <= 0) {
+ if (n != 0)
+ rfbLogPerror("rfbProcessClientNormalMessage: read");
+ rfbCloseClient(cl);
+ return;
+ }
+
+ if (pointerClient && (pointerClient != cl))
+ return;
+
+ if (msg.pe.buttonMask == 0)
+ pointerClient = NULL;
+ else
+ pointerClient = cl;
+
+ cl->screen->ptrAddEvent(msg.pe.buttonMask,
+ Swap16IfLE(msg.pe.x), Swap16IfLE(msg.pe.y), cl);
+ return;
+
+
+ case rfbClientCutText:
+
+ if ((n = ReadExact(cl, ((char *)&msg) + 1,
+ sz_rfbClientCutTextMsg - 1)) <= 0) {
+ if (n != 0)
+ rfbLogPerror("rfbProcessClientNormalMessage: read");
+ rfbCloseClient(cl);
+ return;
+ }
+
+ msg.cct.length = Swap32IfLE(msg.cct.length);
+
+ str = (char *)malloc(msg.cct.length);
+
+ if ((n = ReadExact(cl, str, msg.cct.length)) <= 0) {
+ if (n != 0)
+ rfbLogPerror("rfbProcessClientNormalMessage: read");
+ free(str);
+ rfbCloseClient(cl);
+ return;
+ }
+
+ cl->screen->setXCutText(str, msg.cct.length, cl);
+
+ free(str);
+ return;
+
+
+ default:
+
+ rfbLog("rfbProcessClientNormalMessage: unknown message type %d\n",
+ msg.type);
+ rfbLog(" ... closing connection\n");
+ rfbCloseClient(cl);
+ return;
+ }
+}
+
+
+/*
+ * rfbSendPing - send an empty framebuffer request
+ */
+
+Bool
+rfbSendPing(cl)
+ rfbClientPtr cl;
+{
+ rfbFramebufferUpdateMsg *fu = (rfbFramebufferUpdateMsg *)cl->updateBuf;
+ cl->rfbFramebufferUpdateMessagesSent++;
+ fu->type = rfbFramebufferUpdate;
+ fu->nRects = Swap16IfLE((CARD16)0);
+ cl->ublen = sz_rfbFramebufferUpdateMsg;
+ return TRUE;
+}
+
+
+/*
+ * rfbSendFramebufferUpdate - send the currently pending framebuffer update to
+ * the RFB client.
+ * givenUpdateRegion is not changed.
+ */
+
+Bool
+rfbSendFramebufferUpdate(cl, givenUpdateRegion)
+ rfbClientPtr cl;
+ sraRegionPtr givenUpdateRegion;
+{
+ sraRectangleIterator* i;
+ sraRect rect;
+ int nUpdateRegionRects;
+ rfbFramebufferUpdateMsg *fu = (rfbFramebufferUpdateMsg *)cl->updateBuf;
+ sraRegionPtr updateRegion,updateCopyRegion,tmpRegion;
+ int dx, dy;
+ Bool sendCursorShape = FALSE;
+ int sendSoftCursorRects = 0;
+
+ if(cl->screen->displayHook)
+ cl->screen->displayHook(cl);
+
+ /*
+ * If this client understands cursor shape updates, cursor should be
+ * removed from the framebuffer. Otherwise, make sure it's put up.
+ */
+
+ if (cl->enableCursorShapeUpdates) {
+ if (cl->screen->cursorIsDrawn) {
+ rfbUndrawCursor(cl->screen);
+ }
+ if (!cl->screen->cursorIsDrawn && cl->cursorWasChanged &&
+ cl->readyForSetColourMapEntries)
+ sendCursorShape = TRUE;
+ }
+ else if (cl->enableSoftCursorUpdates) {
+ if (cl->screen->cursorIsDrawn) {
+ rfbUndrawCursor(cl->screen);
+ }
+ if (cl->cursorWasChanged)
+ sendSoftCursorRects=2;
+ else if (cl->cursorWasMoved)
+ sendSoftCursorRects=1;
+ } else {
+ if (!cl->screen->cursorIsDrawn) {
+ rfbDrawCursor(cl->screen);
+ }
+ }
+
+ LOCK(cl->updateMutex);
+
+ /*
+ * The modifiedRegion may overlap the destination copyRegion. We remove
+ * any overlapping bits from the copyRegion (since they'd only be
+ * overwritten anyway).
+ */
+
+ sraRgnSubtract(cl->copyRegion,cl->modifiedRegion);
+
+ /*
+ * The client is interested in the region requestedRegion. The region
+ * which should be updated now is the intersection of requestedRegion
+ * and the union of modifiedRegion and copyRegion. If it's empty then
+ * no update is needed.
+ */
+
+ updateRegion = sraRgnCreateRgn(givenUpdateRegion);
+ sraRgnOr(updateRegion,cl->copyRegion);
+ if(!sraRgnAnd(updateRegion,cl->requestedRegion) &&
+ !(sendCursorShape || sendSoftCursorRects)) {
+ sraRgnDestroy(updateRegion);
+ UNLOCK(cl->updateMutex);
+ return TRUE;
+ }
+
+ /*
+ * We assume that the client doesn't have any pixel data outside the
+ * requestedRegion. In other words, both the source and destination of a
+ * copy must lie within requestedRegion. So the region we can send as a
+ * copy is the intersection of the copyRegion with both the requestedRegion
+ * and the requestedRegion translated by the amount of the copy. We set
+ * updateCopyRegion to this.
+ */
+
+ updateCopyRegion = sraRgnCreateRgn(cl->copyRegion);
+ sraRgnAnd(updateCopyRegion,cl->requestedRegion);
+ tmpRegion = sraRgnCreateRgn(cl->requestedRegion);
+ sraRgnOffset(tmpRegion,cl->copyDX,cl->copyDY);
+ sraRgnAnd(updateCopyRegion,tmpRegion);
+ sraRgnDestroy(tmpRegion);
+ dx = cl->copyDX;
+ dy = cl->copyDY;
+
+ /*
+ * Next we remove updateCopyRegion from updateRegion so that updateRegion
+ * is the part of this update which is sent as ordinary pixel data (i.e not
+ * a copy).
+ */
+
+ sraRgnSubtract(updateRegion,updateCopyRegion);
+
+ /*
+ * Finally we leave modifiedRegion to be the remainder (if any) of parts of
+ * the screen which are modified but outside the requestedRegion. We also
+ * empty both the requestedRegion and the copyRegion - note that we never
+ * carry over a copyRegion for a future update.
+ */
+
+
+ sraRgnOr(cl->modifiedRegion,cl->copyRegion);
+ sraRgnSubtract(cl->modifiedRegion,updateRegion);
+ sraRgnSubtract(cl->modifiedRegion,updateCopyRegion);
+
+ /* sraRgnMakeEmpty(cl->requestedRegion); */
+ sraRgnMakeEmpty(cl->copyRegion);
+ cl->copyDX = 0;
+ cl->copyDY = 0;
+
+ UNLOCK(cl->updateMutex);
+
+ /*
+ * Now send the update.
+ */
+
+ cl->rfbFramebufferUpdateMessagesSent++;
+
+ if (cl->preferredEncoding == rfbEncodingCoRRE) {
+ nUpdateRegionRects = 0;
+
+ for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){
+ int x = rect.x1;
+ int y = rect.y1;
+ int w = rect.x2 - x;
+ int h = rect.y2 - y;
+ nUpdateRegionRects += (((w-1) / cl->correMaxWidth + 1)
+ * ((h-1) / cl->correMaxHeight + 1));
+ }
+ } else if (cl->preferredEncoding == rfbEncodingZlib) {
+ nUpdateRegionRects = 0;
+
+ for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){
+ int x = rect.x1;
+ int y = rect.y1;
+ int w = rect.x2 - x;
+ int h = rect.y2 - y;
+ nUpdateRegionRects += (((h-1) / (ZLIB_MAX_SIZE( w ) / w)) + 1);
+ }
+ } else if (cl->preferredEncoding == rfbEncodingTight) {
+ nUpdateRegionRects = 0;
+
+ for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){
+ int x = rect.x1;
+ int y = rect.y1;
+ int w = rect.x2 - x;
+ int h = rect.y2 - y;
+ int n = rfbNumCodedRectsTight(cl, x, y, w, h);
+ if (n == 0) {
+ nUpdateRegionRects = 0xFFFF;
+ break;
+ }
+ nUpdateRegionRects += n;
+ }
+ } else {
+ nUpdateRegionRects = sraRgnCountRects(updateRegion);
+ }
+
+ fu->type = rfbFramebufferUpdate;
+ if (nUpdateRegionRects != 0xFFFF) {
+ fu->nRects = Swap16IfLE((CARD16)(sraRgnCountRects(updateCopyRegion)
+ + nUpdateRegionRects
+ + !!sendCursorShape + sendSoftCursorRects));
+ } else {
+ fu->nRects = 0xFFFF;
+ }
+ cl->ublen = sz_rfbFramebufferUpdateMsg;
+
+ if (sendCursorShape) {
+ cl->cursorWasChanged = FALSE;
+ if (!rfbSendCursorShape(cl)) {
+ sraRgnDestroy(updateRegion);
+ return FALSE;
+ }
+ }
+
+ if (sendSoftCursorRects) {
+ if (!rfbSendSoftCursor(cl, cl->cursorWasChanged)) {
+ sraRgnDestroy(updateRegion);
+ return FALSE;
+ }
+ cl->cursorWasChanged = FALSE;
+ cl->cursorWasMoved = FALSE;
+ }
+
+ if (!sraRgnEmpty(updateCopyRegion)) {
+ if (!rfbSendCopyRegion(cl,updateCopyRegion,dx,dy)) {
+ sraRgnDestroy(updateRegion);
+ sraRgnDestroy(updateCopyRegion);
+ return FALSE;
+ }
+ }
+
+ sraRgnDestroy(updateCopyRegion);
+
+ for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){
+ int x = rect.x1;
+ int y = rect.y1;
+ int w = rect.x2 - x;
+ int h = rect.y2 - y;
+
+ cl->rfbRawBytesEquivalent += (sz_rfbFramebufferUpdateRectHeader
+ + w * (cl->format.bitsPerPixel / 8) * h);
+
+ switch (cl->preferredEncoding) {
+ case rfbEncodingRaw:
+ if (!rfbSendRectEncodingRaw(cl, x, y, w, h)) {
+ sraRgnDestroy(updateRegion);
+ return FALSE;
+ }
+ break;
+ case rfbEncodingRRE:
+ if (!rfbSendRectEncodingRRE(cl, x, y, w, h)) {
+ sraRgnDestroy(updateRegion);
+ return FALSE;
+ }
+ break;
+ case rfbEncodingCoRRE:
+ if (!rfbSendRectEncodingCoRRE(cl, x, y, w, h)) {
+ sraRgnDestroy(updateRegion);
+ return FALSE;
+ }
+ break;
+ case rfbEncodingHextile:
+ if (!rfbSendRectEncodingHextile(cl, x, y, w, h)) {
+ sraRgnDestroy(updateRegion);
+ return FALSE;
+ }
+ break;
+ case rfbEncodingZlib:
+ if (!rfbSendRectEncodingZlib(cl, x, y, w, h)) {
+ sraRgnDestroy(updateRegion);
+ return FALSE;
+ }
+ break;
+ case rfbEncodingTight:
+ if (!rfbSendRectEncodingTight(cl, x, y, w, h)) {
+ sraRgnDestroy(updateRegion);
+ return FALSE;
+ }
+ break;
+ }
+ }
+
+ if ( nUpdateRegionRects == 0xFFFF &&
+ !rfbSendLastRectMarker(cl) ) {
+ sraRgnDestroy(updateRegion);
+ return FALSE;
+ }
+
+ if (!rfbSendUpdateBuf(cl)) {
+ sraRgnDestroy(updateRegion);
+ return FALSE;
+ }
+
+ sraRgnDestroy(updateRegion);
+ return TRUE;
+}
+
+
+/*
+ * Send the copy region as a string of CopyRect encoded rectangles.
+ * The only slightly tricky thing is that we should send the messages in
+ * the correct order so that an earlier CopyRect will not corrupt the source
+ * of a later one.
+ */
+
+Bool
+rfbSendCopyRegion(cl, reg, dx, dy)
+ rfbClientPtr cl;
+ sraRegionPtr reg;
+ int dx, dy;
+{
+ int x, y, w, h;
+ rfbFramebufferUpdateRectHeader rect;
+ rfbCopyRect cr;
+ sraRectangleIterator* i;
+ sraRect rect1;
+
+ /* printf("copyrect: "); sraRgnPrint(reg); putchar('\n');fflush(stdout); */
+ i = sraRgnGetReverseIterator(reg,dx>0,dy>0);
+
+ while(sraRgnIteratorNext(i,&rect1)) {
+ x = rect1.x1;
+ y = rect1.y1;
+ w = rect1.x2 - x;
+ h = rect1.y2 - y;
+
+ rect.r.x = Swap16IfLE(x);
+ rect.r.y = Swap16IfLE(y);
+ rect.r.w = Swap16IfLE(w);
+ rect.r.h = Swap16IfLE(h);
+ rect.encoding = Swap32IfLE(rfbEncodingCopyRect);
+
+ memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
+ sz_rfbFramebufferUpdateRectHeader);
+ cl->ublen += sz_rfbFramebufferUpdateRectHeader;
+
+ cr.srcX = Swap16IfLE(x - dx);
+ cr.srcY = Swap16IfLE(y - dy);
+
+ memcpy(&cl->updateBuf[cl->ublen], (char *)&cr, sz_rfbCopyRect);
+ cl->ublen += sz_rfbCopyRect;
+
+ cl->rfbRectanglesSent[rfbEncodingCopyRect]++;
+ cl->rfbBytesSent[rfbEncodingCopyRect]
+ += sz_rfbFramebufferUpdateRectHeader + sz_rfbCopyRect;
+
+ }
+
+ return TRUE;
+}
+
+/*
+ * Send a given rectangle in raw encoding (rfbEncodingRaw).
+ */
+
+Bool
+rfbSendRectEncodingRaw(cl, x, y, w, h)
+ rfbClientPtr cl;
+ int x, y, w, h;
+{
+ rfbFramebufferUpdateRectHeader rect;
+ int nlines;
+ int bytesPerLine = w * (cl->format.bitsPerPixel / 8);
+ char *fbptr = (cl->screen->frameBuffer + (cl->screen->paddedWidthInBytes * y)
+ + (x * (cl->screen->bitsPerPixel / 8)));
+
+ if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ rect.r.x = Swap16IfLE(x);
+ rect.r.y = Swap16IfLE(y);
+ rect.r.w = Swap16IfLE(w);
+ rect.r.h = Swap16IfLE(h);
+ rect.encoding = Swap32IfLE(rfbEncodingRaw);
+
+ memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader);
+ cl->ublen += sz_rfbFramebufferUpdateRectHeader;
+
+ cl->rfbRectanglesSent[rfbEncodingRaw]++;
+ cl->rfbBytesSent[rfbEncodingRaw]
+ += sz_rfbFramebufferUpdateRectHeader + bytesPerLine * h;
+
+ nlines = (UPDATE_BUF_SIZE - cl->ublen) / bytesPerLine;
+
+ while (TRUE) {
+ if (nlines > h)
+ nlines = h;
+
+ (*cl->translateFn)(cl->translateLookupTable,
+ &(cl->screen->rfbServerFormat),
+ &cl->format, fbptr, &cl->updateBuf[cl->ublen],
+ cl->screen->paddedWidthInBytes, w, nlines);
+
+ cl->ublen += nlines * bytesPerLine;
+ h -= nlines;
+
+ if (h == 0) /* rect fitted in buffer, do next one */
+ return TRUE;
+
+ /* buffer full - flush partial rect and do another nlines */
+
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+
+ fbptr += (cl->screen->paddedWidthInBytes * nlines);
+
+ nlines = (UPDATE_BUF_SIZE - cl->ublen) / bytesPerLine;
+ if (nlines == 0) {
+ rfbLog("rfbSendRectEncodingRaw: send buffer too small for %d "
+ "bytes per line\n", bytesPerLine);
+ rfbCloseClient(cl);
+ return FALSE;
+ }
+ }
+}
+
+
+
+/*
+ * Send an empty rectangle with encoding field set to value of
+ * rfbEncodingLastRect to notify client that this is the last
+ * rectangle in framebuffer update ("LastRect" extension of RFB
+ * protocol).
+ */
+
+Bool
+rfbSendLastRectMarker(cl)
+ rfbClientPtr cl;
+{
+ rfbFramebufferUpdateRectHeader rect;
+
+ if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ rect.encoding = Swap32IfLE(rfbEncodingLastRect);
+ rect.r.x = 0;
+ rect.r.y = 0;
+ rect.r.w = 0;
+ rect.r.h = 0;
+
+ memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader);
+ cl->ublen += sz_rfbFramebufferUpdateRectHeader;
+
+ cl->rfbLastRectMarkersSent++;
+ cl->rfbLastRectBytesSent += sz_rfbFramebufferUpdateRectHeader;
+
+ return TRUE;
+}
+
+
+/*
+ * Send the contents of cl->updateBuf. Returns 1 if successful, -1 if
+ * not (errno should be set).
+ */
+
+Bool
+rfbSendUpdateBuf(cl)
+ rfbClientPtr cl;
+{
+ if(cl->sock<0)
+ return FALSE;
+
+ if (WriteExact(cl, cl->updateBuf, cl->ublen) < 0) {
+ rfbLogPerror("rfbSendUpdateBuf: write");
+ rfbCloseClient(cl);
+ return FALSE;
+ }
+
+ cl->ublen = 0;
+ return TRUE;
+}
+
+/*
+ * rfbSendSetColourMapEntries sends a SetColourMapEntries message to the
+ * client, using values from the currently installed colormap.
+ */
+
+Bool
+rfbSendSetColourMapEntries(cl, firstColour, nColours)
+ rfbClientPtr cl;
+ int firstColour;
+ int nColours;
+{
+ char buf[sz_rfbSetColourMapEntriesMsg + 256 * 3 * 2];
+ rfbSetColourMapEntriesMsg *scme = (rfbSetColourMapEntriesMsg *)buf;
+ CARD16 *rgb = (CARD16 *)(&buf[sz_rfbSetColourMapEntriesMsg]);
+ rfbColourMap* cm = &cl->screen->colourMap;
+
+ int i, len;
+
+ scme->type = rfbSetColourMapEntries;
+
+ scme->firstColour = Swap16IfLE(firstColour);
+ scme->nColours = Swap16IfLE(nColours);
+
+ len = sz_rfbSetColourMapEntriesMsg;
+
+ for (i = 0; i < nColours; i++) {
+ if(i<(int)cm->count) {
+ if(cm->is16) {
+ rgb[i*3] = Swap16IfLE(cm->data.shorts[i*3]);
+ rgb[i*3+1] = Swap16IfLE(cm->data.shorts[i*3+1]);
+ rgb[i*3+2] = Swap16IfLE(cm->data.shorts[i*3+2]);
+ } else {
+ rgb[i*3] = Swap16IfLE(cm->data.bytes[i*3]);
+ rgb[i*3+1] = Swap16IfLE(cm->data.bytes[i*3+1]);
+ rgb[i*3+2] = Swap16IfLE(cm->data.bytes[i*3+2]);
+ }
+ }
+ }
+
+ len += nColours * 3 * 2;
+
+ if (WriteExact(cl, buf, len) < 0) {
+ rfbLogPerror("rfbSendSetColourMapEntries: write");
+ rfbCloseClient(cl);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/*
+ * rfbSendBell sends a Bell message to all the clients.
+ */
+
+void
+rfbSendBell(rfbScreenInfoPtr rfbScreen)
+{
+ rfbClientIteratorPtr i;
+ rfbClientPtr cl;
+ rfbBellMsg b;
+
+ i = rfbGetClientIterator(rfbScreen);
+ while((cl=rfbClientIteratorNext(i))) {
+ b.type = rfbBell;
+ if (WriteExact(cl, (char *)&b, sz_rfbBellMsg) < 0) {
+ rfbLogPerror("rfbSendBell: write");
+ rfbCloseClient(cl);
+ }
+ }
+ rfbReleaseClientIterator(i);
+}
+
+
+/*
+ * rfbSendServerCutText sends a ServerCutText message to all the clients.
+ */
+
+void
+rfbSendServerCutText(rfbScreenInfoPtr rfbScreen,char *str, int len)
+{
+ rfbClientPtr cl;
+ rfbServerCutTextMsg sct;
+ rfbClientIteratorPtr iterator;
+
+ iterator = rfbGetClientIterator(rfbScreen);
+ while ((cl = rfbClientIteratorNext(iterator)) != NULL) {
+ sct.type = rfbServerCutText;
+ sct.length = Swap32IfLE(len);
+ if (WriteExact(cl, (char *)&sct,
+ sz_rfbServerCutTextMsg) < 0) {
+ rfbLogPerror("rfbSendServerCutText: write");
+ rfbCloseClient(cl);
+ continue;
+ }
+ if (WriteExact(cl, str, len) < 0) {
+ rfbLogPerror("rfbSendServerCutText: write");
+ rfbCloseClient(cl);
+ }
+ }
+ rfbReleaseClientIterator(iterator);
+}
+
+/*****************************************************************************
+ *
+ * UDP can be used for keyboard and pointer events when the underlying
+ * network is highly reliable. This is really here to support ORL's
+ * videotile, whose TCP implementation doesn't like sending lots of small
+ * packets (such as 100s of pen readings per second!).
+ */
+
+unsigned char ptrAcceleration = 50;
+
+void
+rfbNewUDPConnection(rfbScreenInfoPtr rfbScreen, int sock)
+{
+ if (write(sock, &ptrAcceleration, 1) < 0) {
+ rfbLogPerror("rfbNewUDPConnection: write");
+ }
+}
+
+/*
+ * Because UDP is a message based service, we can't read the first byte and
+ * then the rest of the packet separately like we do with TCP. We will always
+ * get a whole packet delivered in one go, so we ask read() for the maximum
+ * number of bytes we can possibly get.
+ */
+
+void
+rfbProcessUDPInput(rfbScreenInfoPtr rfbScreen)
+{
+ int n;
+ rfbClientPtr cl=rfbScreen->udpClient;
+ rfbClientToServerMsg msg;
+
+ if((!cl) || cl->onHold)
+ return;
+
+ if ((n = read(rfbScreen->udpSock, (char *)&msg, sizeof(msg))) <= 0) {
+ if (n < 0) {
+ rfbLogPerror("rfbProcessUDPInput: read");
+ }
+ rfbDisconnectUDPSock(rfbScreen);
+ return;
+ }
+
+ switch (msg.type) {
+
+ case rfbKeyEvent:
+ if (n != sz_rfbKeyEventMsg) {
+ rfbLog("rfbProcessUDPInput: key event incorrect length\n");
+ rfbDisconnectUDPSock(rfbScreen);
+ return;
+ }
+ cl->screen->kbdAddEvent(msg.ke.down, (KeySym)Swap32IfLE(msg.ke.key), cl);
+ break;
+
+ case rfbPointerEvent:
+ if (n != sz_rfbPointerEventMsg) {
+ rfbLog("rfbProcessUDPInput: ptr event incorrect length\n");
+ rfbDisconnectUDPSock(rfbScreen);
+ return;
+ }
+ cl->screen->ptrAddEvent(msg.pe.buttonMask,
+ Swap16IfLE(msg.pe.x), Swap16IfLE(msg.pe.y), cl);
+ break;
+
+ default:
+ rfbLog("rfbProcessUDPInput: unknown message type %d\n",
+ msg.type);
+ rfbDisconnectUDPSock(rfbScreen);
+ }
+}
+
+#ifdef BACKCHANNEL
+void rfbSendBackChannel(rfbScreenInfoPtr rfbScreen,char* str,int len)
+{
+ rfbClientPtr cl;
+ rfbBackChannelMsg sct;
+ rfbClientIteratorPtr iterator;
+
+ iterator = rfbGetClientIterator(rfbScreen);
+ while ((cl = rfbClientIteratorNext(iterator)) != NULL) {
+ if (cl->enableBackChannel) {
+ sct.type = rfbBackChannel;
+ sct.length = Swap32IfLE(len);
+ if (WriteExact(cl, (char *)&sct,
+ sz_rfbBackChannelMsg) < 0) {
+ rfbLogPerror("rfbSendBackChannel: write");
+ rfbCloseClient(cl);
+ continue;
+ }
+ if (WriteExact(cl, str, len) < 0) {
+ rfbLogPerror("rfbSendBackChannel: write");
+ rfbCloseClient(cl);
+ }
+ }
+ }
+ rfbReleaseClientIterator(iterator);
+}
+#endif
diff --git a/krfb/libvncserver/rre.c b/krfb/libvncserver/rre.c
new file mode 100644
index 00000000..9a552cb0
--- /dev/null
+++ b/krfb/libvncserver/rre.c
@@ -0,0 +1,322 @@
+/*
+ * rre.c
+ *
+ * Routines to implement Rise-and-Run-length Encoding (RRE). This
+ * code is based on krw's original javatel rfbserver.
+ */
+
+/*
+ * OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
+ * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
+ * All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include <stdio.h>
+#include "rfb.h"
+
+/*
+ * rreBeforeBuf contains pixel data in the client's format.
+ * rreAfterBuf contains the RRE encoded version. If the RRE encoded version is
+ * larger than the raw data or if it exceeds rreAfterBufSize then
+ * raw encoding is used instead.
+ */
+
+static int rreBeforeBufSize = 0;
+static char *rreBeforeBuf = NULL;
+
+static int rreAfterBufSize = 0;
+static char *rreAfterBuf = NULL;
+static int rreAfterBufLen;
+
+static int subrectEncode8(CARD8 *data, int w, int h);
+static int subrectEncode16(CARD16 *data, int w, int h);
+static int subrectEncode32(CARD32 *data, int w, int h);
+static CARD32 getBgColour(char *data, int size, int bpp);
+
+
+/*
+ * rfbSendRectEncodingRRE - send a given rectangle using RRE encoding.
+ */
+
+Bool
+rfbSendRectEncodingRRE(cl, x, y, w, h)
+ rfbClientPtr cl;
+ int x, y, w, h;
+{
+ rfbFramebufferUpdateRectHeader rect;
+ rfbRREHeader hdr;
+ int nSubrects;
+ int i;
+ char *fbptr = (cl->screen->frameBuffer + (cl->screen->paddedWidthInBytes * y)
+ + (x * (cl->screen->bitsPerPixel / 8)));
+
+ int maxRawSize = (cl->screen->width * cl->screen->height
+ * (cl->format.bitsPerPixel / 8));
+
+ if (rreBeforeBufSize < maxRawSize) {
+ rreBeforeBufSize = maxRawSize;
+ if (rreBeforeBuf == NULL)
+ rreBeforeBuf = (char *)malloc(rreBeforeBufSize);
+ else
+ rreBeforeBuf = (char *)realloc(rreBeforeBuf, rreBeforeBufSize);
+ }
+
+ if (rreAfterBufSize < maxRawSize) {
+ rreAfterBufSize = maxRawSize;
+ if (rreAfterBuf == NULL)
+ rreAfterBuf = (char *)malloc(rreAfterBufSize);
+ else
+ rreAfterBuf = (char *)realloc(rreAfterBuf, rreAfterBufSize);
+ }
+
+ (*cl->translateFn)(cl->translateLookupTable,
+ &(cl->screen->rfbServerFormat),
+ &cl->format, fbptr, rreBeforeBuf,
+ cl->screen->paddedWidthInBytes, w, h);
+
+ switch (cl->format.bitsPerPixel) {
+ case 8:
+ nSubrects = subrectEncode8((CARD8 *)rreBeforeBuf, w, h);
+ break;
+ case 16:
+ nSubrects = subrectEncode16((CARD16 *)rreBeforeBuf, w, h);
+ break;
+ case 32:
+ nSubrects = subrectEncode32((CARD32 *)rreBeforeBuf, w, h);
+ break;
+ default:
+ rfbLog("getBgColour: bpp %d?\n",cl->format.bitsPerPixel);
+ exit(1);
+ }
+
+ if (nSubrects < 0) {
+
+ /* RRE encoding was too large, use raw */
+
+ return rfbSendRectEncodingRaw(cl, x, y, w, h);
+ }
+
+ cl->rfbRectanglesSent[rfbEncodingRRE]++;
+ cl->rfbBytesSent[rfbEncodingRRE] += (sz_rfbFramebufferUpdateRectHeader
+ + sz_rfbRREHeader + rreAfterBufLen);
+
+ if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader
+ > UPDATE_BUF_SIZE)
+ {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ rect.r.x = Swap16IfLE(x);
+ rect.r.y = Swap16IfLE(y);
+ rect.r.w = Swap16IfLE(w);
+ rect.r.h = Swap16IfLE(h);
+ rect.encoding = Swap32IfLE(rfbEncodingRRE);
+
+ memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
+ sz_rfbFramebufferUpdateRectHeader);
+ cl->ublen += sz_rfbFramebufferUpdateRectHeader;
+
+ hdr.nSubrects = Swap32IfLE(nSubrects);
+
+ memcpy(&cl->updateBuf[cl->ublen], (char *)&hdr, sz_rfbRREHeader);
+ cl->ublen += sz_rfbRREHeader;
+
+ for (i = 0; i < rreAfterBufLen;) {
+
+ int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen;
+
+ if (i + bytesToCopy > rreAfterBufLen) {
+ bytesToCopy = rreAfterBufLen - i;
+ }
+
+ memcpy(&cl->updateBuf[cl->ublen], &rreAfterBuf[i], bytesToCopy);
+
+ cl->ublen += bytesToCopy;
+ i += bytesToCopy;
+
+ if (cl->ublen == UPDATE_BUF_SIZE) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+
+/*
+ * subrectEncode() encodes the given multicoloured rectangle as a background
+ * colour overwritten by single-coloured rectangles. It returns the number
+ * of subrectangles in the encoded buffer, or -1 if subrect encoding won't
+ * fit in the buffer. It puts the encoded rectangles in rreAfterBuf. The
+ * single-colour rectangle partition is not optimal, but does find the biggest
+ * horizontal or vertical rectangle top-left anchored to each consecutive
+ * coordinate position.
+ *
+ * The coding scheme is simply [<bgcolour><subrect><subrect>...] where each
+ * <subrect> is [<colour><x><y><w><h>].
+ */
+
+#define DEFINE_SUBRECT_ENCODE(bpp) \
+static int \
+subrectEncode##bpp(data,w,h) \
+ CARD##bpp *data; \
+ int w; \
+ int h; \
+{ \
+ CARD##bpp cl; \
+ rfbRectangle subrect; \
+ int x,y; \
+ int i,j; \
+ int hx=0,hy,vx=0,vy; \
+ int hyflag; \
+ CARD##bpp *seg; \
+ CARD##bpp *line; \
+ int hw,hh,vw,vh; \
+ int thex,they,thew,theh; \
+ int numsubs = 0; \
+ int newLen; \
+ CARD##bpp bg = (CARD##bpp)getBgColour((char*)data,w*h,bpp); \
+ \
+ *((CARD##bpp*)rreAfterBuf) = bg; \
+ \
+ rreAfterBufLen = (bpp/8); \
+ \
+ for (y=0; y<h; y++) { \
+ line = data+(y*w); \
+ for (x=0; x<w; x++) { \
+ if (line[x] != bg) { \
+ cl = line[x]; \
+ hy = y-1; \
+ hyflag = 1; \
+ for (j=y; j<h; j++) { \
+ seg = data+(j*w); \
+ if (seg[x] != cl) {break;} \
+ i = x; \
+ while ((seg[i] == cl) && (i < w)) i += 1; \
+ i -= 1; \
+ if (j == y) vx = hx = i; \
+ if (i < vx) vx = i; \
+ if ((hyflag > 0) && (i >= hx)) {hy += 1;} else {hyflag = 0;} \
+ } \
+ vy = j-1; \
+ \
+ /* We now have two possible subrects: (x,y,hx,hy) and (x,y,vx,vy) \
+ * We'll choose the bigger of the two. \
+ */ \
+ hw = hx-x+1; \
+ hh = hy-y+1; \
+ vw = vx-x+1; \
+ vh = vy-y+1; \
+ \
+ thex = x; \
+ they = y; \
+ \
+ if ((hw*hh) > (vw*vh)) { \
+ thew = hw; \
+ theh = hh; \
+ } else { \
+ thew = vw; \
+ theh = vh; \
+ } \
+ \
+ subrect.x = Swap16IfLE(thex); \
+ subrect.y = Swap16IfLE(they); \
+ subrect.w = Swap16IfLE(thew); \
+ subrect.h = Swap16IfLE(theh); \
+ \
+ newLen = rreAfterBufLen + (bpp/8) + sz_rfbRectangle; \
+ if ((newLen > (w * h * (bpp/8))) || (newLen > rreAfterBufSize)) \
+ return -1; \
+ \
+ numsubs += 1; \
+ *((CARD##bpp*)(rreAfterBuf + rreAfterBufLen)) = cl; \
+ rreAfterBufLen += (bpp/8); \
+ memcpy(&rreAfterBuf[rreAfterBufLen],&subrect,sz_rfbRectangle); \
+ rreAfterBufLen += sz_rfbRectangle; \
+ \
+ /* \
+ * Now mark the subrect as done. \
+ */ \
+ for (j=they; j < (they+theh); j++) { \
+ for (i=thex; i < (thex+thew); i++) { \
+ data[j*w+i] = bg; \
+ } \
+ } \
+ } \
+ } \
+ } \
+ \
+ return numsubs; \
+}
+
+DEFINE_SUBRECT_ENCODE(8)
+DEFINE_SUBRECT_ENCODE(16)
+DEFINE_SUBRECT_ENCODE(32)
+
+
+/*
+ * getBgColour() gets the most prevalent colour in a byte array.
+ */
+static CARD32
+getBgColour(data,size,bpp)
+ char *data;
+ int size;
+ int bpp;
+{
+
+#define NUMCLRS 256
+
+ static int counts[NUMCLRS];
+ int i,j,k;
+
+ int maxcount = 0;
+ CARD8 maxclr = 0;
+
+ if (bpp != 8) {
+ if (bpp == 16) {
+ return ((CARD16 *)data)[0];
+ } else if (bpp == 32) {
+ return ((CARD32 *)data)[0];
+ } else {
+ rfbLog("getBgColour: bpp %d?\n",bpp);
+ exit(1);
+ }
+ }
+
+ for (i=0; i<NUMCLRS; i++) {
+ counts[i] = 0;
+ }
+
+ for (j=0; j<size; j++) {
+ k = (int)(((CARD8 *)data)[j]);
+ if (k >= NUMCLRS) {
+ rfbLog("getBgColour: unusual colour = %d\n", k);
+ exit(1);
+ }
+ counts[k] += 1;
+ if (counts[k] > maxcount) {
+ maxcount = counts[k];
+ maxclr = ((CARD8 *)data)[j];
+ }
+ }
+
+ return maxclr;
+}
diff --git a/krfb/libvncserver/selbox.c b/krfb/libvncserver/selbox.c
new file mode 100644
index 00000000..6cdb4590
--- /dev/null
+++ b/krfb/libvncserver/selbox.c
@@ -0,0 +1,301 @@
+#include <ctype.h>
+#include "rfb.h"
+#include "keysym.h"
+
+typedef struct {
+ rfbScreenInfoPtr screen;
+ rfbFontDataPtr font;
+ char** list;
+ int listSize;
+ int selected;
+ int displayStart;
+ int x1,y1,x2,y2,textH,pageH;
+ int xhot,yhot;
+ int buttonWidth,okBX,cancelBX,okX,cancelX,okY;
+ Bool okInverted,cancelInverted;
+ int lastButtons;
+ Pixel colour,backColour;
+ SelectionChangedHookPtr selChangedHook;
+ enum { SELECTING, OK, CANCEL } state;
+} rfbSelectData;
+
+static const char okStr[] = "OK";
+static const char cancelStr[] = "Cancel";
+
+static void selPaintButtons(rfbSelectData* m,Bool invertOk,Bool invertCancel)
+{
+ rfbScreenInfoPtr s = m->screen;
+ Pixel bcolour = m->backColour;
+ Pixel colour = m->colour;
+
+ rfbFillRect(s,m->x1,m->okY-m->textH,m->x2,m->okY,bcolour);
+
+ if(invertOk) {
+ rfbFillRect(s,m->okBX,m->okY-m->textH,m->okBX+m->buttonWidth,m->okY,colour);
+ rfbDrawStringWithClip(s,m->font,m->okX+m->xhot,m->okY-1+m->yhot,okStr,
+ m->x1,m->okY-m->textH,m->x2,m->okY,
+ bcolour,colour);
+ } else
+ rfbDrawString(s,m->font,m->okX+m->xhot,m->okY-1+m->yhot,okStr,colour);
+
+ if(invertCancel) {
+ rfbFillRect(s,m->cancelBX,m->okY-m->textH,
+ m->cancelBX+m->buttonWidth,m->okY,colour);
+ rfbDrawStringWithClip(s,m->font,m->cancelX+m->xhot,m->okY-1+m->yhot,
+ cancelStr,m->x1,m->okY-m->textH,m->x2,m->okY,
+ bcolour,colour);
+ } else
+ rfbDrawString(s,m->font,m->cancelX+m->xhot,m->okY-1+m->yhot,cancelStr,colour);
+
+ m->okInverted = invertOk;
+ m->cancelInverted = invertCancel;
+}
+
+/* line is relative to displayStart */
+static void selPaintLine(rfbSelectData* m,int line,Bool invert)
+{
+ int y1 = m->y1+line*m->textH, y2 = y1+m->textH;
+ if(y2>m->y2)
+ y2=m->y2;
+ rfbFillRect(m->screen,m->x1,y1,m->x2,y2,invert?m->colour:m->backColour);
+ if(m->displayStart+line<m->listSize)
+ rfbDrawStringWithClip(m->screen,m->font,m->x1+m->xhot,y2-1+m->yhot,
+ m->list[m->displayStart+line],
+ m->x1,y1,m->x2,y2,
+ invert?m->backColour:m->colour,
+ invert?m->backColour:m->colour);
+}
+
+static void selSelect(rfbSelectData* m,int _index)
+{
+ int delta;
+
+ if(_index==m->selected || _index<0 || _index>=m->listSize)
+ return;
+
+ if(m->selected>=0)
+ selPaintLine(m,m->selected-m->displayStart,FALSE);
+
+ if(_index<m->displayStart || _index>=m->displayStart+m->pageH) {
+ /* targetLine is the screen line in which the selected line will
+ be displayed.
+ targetLine = m->pageH/2 doesn't look so nice */
+ int targetLine = m->selected-m->displayStart;
+ int lineStart,lineEnd;
+
+ /* scroll */
+ if(_index<targetLine)
+ targetLine = _index;
+ else if(_index+m->pageH-targetLine>=m->listSize)
+ targetLine = _index+m->pageH-m->listSize;
+ delta = _index-(m->displayStart+targetLine);
+
+ if(delta>-m->pageH && delta<m->pageH) {
+ if(delta>0) {
+ lineStart = m->pageH-delta;
+ lineEnd = m->pageH;
+ rfbDoCopyRect(m->screen,m->x1,m->y1,m->x2,m->y1+lineStart*m->textH,
+ 0,-delta*m->textH);
+ } else {
+ lineStart = 0;
+ lineEnd = -delta;
+ rfbDoCopyRect(m->screen,
+ m->x1,m->y1+lineEnd*m->textH,m->x2,m->y2,
+ 0,-delta*m->textH);
+ }
+ } else {
+ lineStart = 0;
+ lineEnd = m->pageH;
+ }
+ m->displayStart += delta;
+ for(delta=lineStart;delta<lineEnd;delta++)
+ if(delta!=_index)
+ selPaintLine(m,delta,FALSE);
+ }
+
+ m->selected = _index;
+ selPaintLine(m,m->selected-m->displayStart,TRUE);
+
+ if(m->selChangedHook)
+ m->selChangedHook(_index);
+
+ /* todo: scrollbars */
+}
+
+static void selKbdAddEvent(Bool down,KeySym keySym,rfbClientPtr cl)
+{
+ if(down) {
+ if(keySym>' ' && keySym<0xff) {
+ int i;
+ rfbSelectData* m = (rfbSelectData*)cl->screen->screenData;
+ char c = tolower(keySym);
+
+ for(i=m->selected+1;m->list[i] && tolower(m->list[i][0])!=c;i++);
+ if(!m->list[i])
+ for(i=0;i<m->selected && tolower(m->list[i][0])!=c;i++);
+ selSelect(m,i);
+ } else if(keySym==XK_Escape) {
+ rfbSelectData* m = (rfbSelectData*)cl->screen->screenData;
+ m->state = CANCEL;
+ } else if(keySym==XK_Return) {
+ rfbSelectData* m = (rfbSelectData*)cl->screen->screenData;
+ m->state = OK;
+ } else {
+ rfbSelectData* m = (rfbSelectData*)cl->screen->screenData;
+ int curSel=m->selected;
+ if(keySym==XK_Up) {
+ if(curSel>0)
+ selSelect(m,curSel-1);
+ } else if(keySym==XK_Down) {
+ if(curSel+1<m->listSize)
+ selSelect(m,curSel+1);
+ } else {
+ if(keySym==XK_Page_Down) {
+ if(curSel+m->pageH<m->listSize)
+ selSelect(m,curSel+m->pageH);
+ else
+ selSelect(m,m->listSize-1);
+ } else if(keySym==XK_Page_Up) {
+ if(curSel-m->pageH>=0)
+ selSelect(m,curSel-m->pageH);
+ else
+ selSelect(m,0);
+ }
+ }
+ }
+ }
+}
+
+static void selPtrAddEvent(int buttonMask,int x,int y,rfbClientPtr cl)
+{
+ rfbSelectData* m = (rfbSelectData*)cl->screen->screenData;
+ if(y<m->okY && y>=m->okY-m->textH) {
+ if(x>=m->okBX && x<m->okBX+m->buttonWidth) {
+ if(!m->okInverted)
+ selPaintButtons(m,TRUE,FALSE);
+ if(buttonMask)
+ m->state = OK;
+ } else if(x>=m->cancelBX && x<m->cancelBX+m->buttonWidth) {
+ if(!m->cancelInverted)
+ selPaintButtons(m,FALSE,TRUE);
+ if(buttonMask)
+ m->state = CANCEL;
+ } else if(m->okInverted || m->cancelInverted)
+ selPaintButtons(m,FALSE,FALSE);
+ } else {
+ if(m->okInverted || m->cancelInverted)
+ selPaintButtons(m,FALSE,FALSE);
+ if(!m->lastButtons && buttonMask) {
+ if(x>=m->x1 && x<m->x2 && y>=m->y1 && y<m->y2)
+ selSelect(m,m->displayStart+(y-m->y1)/m->textH);
+ }
+ }
+ m->lastButtons = buttonMask;
+
+ /* todo: scrollbars */
+}
+
+static rfbCursorPtr selGetCursorPtr(rfbClientPtr cl)
+{
+ return(0);
+}
+
+int rfbSelectBox(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,
+ char** list,
+ int x1,int y1,int x2,int y2,
+ Pixel colour,Pixel backColour,
+ int border,SelectionChangedHookPtr selChangedHook)
+{
+ int bpp = rfbScreen->bitsPerPixel/8;
+ char* frameBufferBackup;
+ void* screenDataBackup = rfbScreen->screenData;
+ KbdAddEventProcPtr kbdAddEventBackup = rfbScreen->kbdAddEvent;
+ PtrAddEventProcPtr ptrAddEventBackup = rfbScreen->ptrAddEvent;
+ GetCursorProcPtr getCursorPtrBackup = rfbScreen->getCursorPtr;
+ DisplayHookPtr displayHookBackup = rfbScreen->displayHook;
+ rfbSelectData selData;
+ int i,j,k;
+ int fx1,fy1,fx2,fy2; /* for font bbox */
+
+ if(list==0 || *list==0)
+ return(-1);
+
+ rfbWholeFontBBox(font, &fx1, &fy1, &fx2, &fy2);
+ selData.textH = fy2-fy1;
+ /* I need at least one line for the choice and one for the buttons */
+ if(y2-y1<selData.textH*2+3*border)
+ return(-1);
+ selData.xhot = -fx1;
+ selData.yhot = -fy2;
+ selData.x1 = x1+border;
+ selData.y1 = y1+border;
+ selData.y2 = y2-selData.textH-3*border;
+ selData.x2 = x2-2*border;
+ selData.pageH = (selData.y2-selData.y1)/selData.textH;
+
+ i = rfbWidthOfString(font,okStr);
+ j = rfbWidthOfString(font,cancelStr);
+ selData.buttonWidth= k = 4*border+(i<j)?j:i;
+ selData.okBX = x1+(x2-x1-2*k)/3;
+ if(selData.okBX<x1+border) /* too narrow! */
+ return(-1);
+ selData.cancelBX = x1+k+(x2-x1-2*k)*2/3;
+ selData.okX = selData.okBX+(k-i)/2;
+ selData.cancelX = selData.cancelBX+(k-j)/2;
+ selData.okY = y2-border;
+
+ rfbUndrawCursor(rfbScreen);
+ frameBufferBackup = (char*)malloc(bpp*(x2-x1)*(y2-y1));
+
+ selData.state = SELECTING;
+ selData.screen = rfbScreen;
+ selData.font = font;
+ selData.list = list;
+ selData.colour = colour;
+ selData.backColour = backColour;
+ for(i=0;list[i];i++);
+ selData.selected = i;
+ selData.listSize = i;
+ selData.displayStart = i;
+ selData.lastButtons = 0;
+ selData.selChangedHook = selChangedHook;
+
+ rfbScreen->screenData = &selData;
+ rfbScreen->kbdAddEvent = selKbdAddEvent;
+ rfbScreen->ptrAddEvent = selPtrAddEvent;
+ rfbScreen->getCursorPtr = selGetCursorPtr;
+ rfbScreen->displayHook = 0;
+
+ /* backup screen */
+ for(j=0;j<y2-y1;j++)
+ memcpy(frameBufferBackup+j*(x2-x1)*bpp,
+ rfbScreen->frameBuffer+j*rfbScreen->paddedWidthInBytes+x1*bpp,
+ (x2-x1)*bpp);
+
+ /* paint list and buttons */
+ rfbFillRect(rfbScreen,x1,y1,x2,y2,colour);
+ selPaintButtons(&selData,FALSE,FALSE);
+ selSelect(&selData,0);
+
+ /* modal loop */
+ while(selData.state == SELECTING)
+ rfbProcessEvents(rfbScreen,20000);
+
+ /* copy back screen data */
+ for(j=0;j<y2-y1;j++)
+ memcpy(rfbScreen->frameBuffer+j*rfbScreen->paddedWidthInBytes+x1*bpp,
+ frameBufferBackup+j*(x2-x1)*bpp,
+ (x2-x1)*bpp);
+ free(frameBufferBackup);
+ rfbMarkRectAsModified(rfbScreen,x1,y1,x2,y2);
+ rfbScreen->screenData = screenDataBackup;
+ rfbScreen->kbdAddEvent = kbdAddEventBackup;
+ rfbScreen->ptrAddEvent = ptrAddEventBackup;
+ rfbScreen->getCursorPtr = getCursorPtrBackup;
+ rfbScreen->displayHook = displayHookBackup;
+
+ if(selData.state==CANCEL)
+ selData.selected=-1;
+ return(selData.selected);
+}
+
diff --git a/krfb/libvncserver/sockets.c b/krfb/libvncserver/sockets.c
new file mode 100644
index 00000000..69c4810a
--- /dev/null
+++ b/krfb/libvncserver/sockets.c
@@ -0,0 +1,592 @@
+/*
+ * sockets.c - deal with TCP & UDP sockets.
+ *
+ * This code should be independent of any changes in the RFB protocol. It just
+ * deals with the X server scheduling stuff, calling rfbNewClientConnection and
+ * rfbProcessClientMessage to actually deal with the protocol. If a socket
+ * needs to be closed for any reason then rfbCloseClient should be called, and
+ * this in turn will call rfbClientConnectionGone. To make an active
+ * connection out, call rfbConnect - note that this does _not_ call
+ * rfbNewClientConnection.
+ *
+ * This file is divided into two types of function. Those beginning with
+ * "rfb" are specific to sockets using the RFB protocol. Those without the
+ * "rfb" prefix are more general socket routines (which are used by the http
+ * code).
+ *
+ * Thanks to Karl Hakimian for pointing out that some platforms return EAGAIN
+ * not EWOULDBLOCK.
+ */
+
+/*
+ * OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
+ * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
+ * All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#ifdef WIN32
+#pragma warning (disable: 4018 4761)
+#define close closesocket
+#define read(sock,buf,len) recv(sock,buf,len,0)
+#define EWOULDBLOCK WSAEWOULDBLOCK
+#define ETIMEDOUT WSAETIMEDOUT
+#define write(sock,buf,len) send(sock,buf,len,0)
+#else
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#endif
+#if defined(__osf__)
+typedef int socklen_t;
+#endif
+#if defined(__linux__) && defined(NEED_TIMEVAL)
+struct timeval
+{
+ long int tv_sec,tv_usec;
+}
+;
+#endif
+#include <fcntl.h>
+#include <errno.h>
+
+#ifdef USE_LIBWRAP
+#include <syslog.h>
+#include <tcpd.h>
+int allow_severity=LOG_INFO;
+int deny_severity=LOG_WARNING;
+#endif
+
+#include "rfb.h"
+
+/*#ifndef WIN32
+int max(int i,int j) { return(i<j?j:i); }
+#endif
+*/
+
+int rfbMaxClientWait = 20000; /* time (ms) after which we decide client has
+ gone away - needed to stop us hanging */
+
+/*
+ * rfbInitSockets sets up the TCP and UDP sockets to listen for RFB
+ * connections. It does nothing if called again.
+ */
+
+void
+rfbInitSockets(rfbScreenInfoPtr rfbScreen)
+{
+ if (rfbScreen->socketInitDone)
+ return;
+
+ rfbScreen->socketInitDone = TRUE;
+
+ if (rfbScreen->inetdSock != -1) {
+ const int one = 1;
+
+#ifndef WIN32
+ if (fcntl(rfbScreen->inetdSock, F_SETFL, O_NONBLOCK) < 0) {
+ rfbLogPerror("fcntl");
+ exit(1);
+ }
+#endif
+
+ if (setsockopt(rfbScreen->inetdSock, IPPROTO_TCP, TCP_NODELAY,
+ (char *)&one, sizeof(one)) < 0) {
+ rfbLogPerror("setsockopt");
+ exit(1);
+ }
+
+ FD_ZERO(&(rfbScreen->allFds));
+ FD_SET(rfbScreen->inetdSock, &(rfbScreen->allFds));
+ rfbScreen->maxFd = rfbScreen->inetdSock;
+ return;
+ }
+
+ if(rfbScreen->autoPort) {
+ int i;
+ rfbLog("Autoprobing TCP port \n");
+
+ for (i = 5900; i < 6000; i++) {
+ if ((rfbScreen->rfbListenSock = ListenOnTCPPort(i)) >= 0) {
+ rfbScreen->rfbPort = i;
+ break;
+ }
+ }
+
+ if (i >= 6000) {
+ rfbLogPerror("Failure autoprobing");
+ exit(1);
+ }
+
+ rfbLog("Autoprobing selected port %d\n", rfbScreen->rfbPort);
+ FD_ZERO(&(rfbScreen->allFds));
+ FD_SET(rfbScreen->rfbListenSock, &(rfbScreen->allFds));
+ rfbScreen->maxFd = rfbScreen->rfbListenSock;
+ }
+ else if(rfbScreen->rfbPort>0) {
+ rfbLog("Listening for VNC connections on TCP port %d\n", rfbScreen->rfbPort);
+
+ if ((rfbScreen->rfbListenSock = ListenOnTCPPort(rfbScreen->rfbPort)) < 0) {
+ rfbLogPerror("ListenOnTCPPort");
+ exit(1);
+ }
+
+ FD_ZERO(&(rfbScreen->allFds));
+ FD_SET(rfbScreen->rfbListenSock, &(rfbScreen->allFds));
+ rfbScreen->maxFd = rfbScreen->rfbListenSock;
+ }
+
+ if (rfbScreen->udpPort != 0) {
+ rfbLog("rfbInitSockets: listening for input on UDP port %d\n",rfbScreen->udpPort);
+
+ if ((rfbScreen->udpSock = ListenOnUDPPort(rfbScreen->udpPort)) < 0) {
+ rfbLogPerror("ListenOnUDPPort");
+ exit(1);
+ }
+ FD_SET(rfbScreen->udpSock, &(rfbScreen->allFds));
+ rfbScreen->maxFd = max((int)rfbScreen->udpSock,rfbScreen->maxFd);
+ }
+}
+
+
+/*
+ * rfbCheckFds is called from ProcessInputEvents to check for input on the RFB
+ * socket(s). If there is input to process, the appropriate function in the
+ * RFB server code will be called (rfbNewClientConnection,
+ * rfbProcessClientMessage, etc).
+ */
+
+void
+rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec)
+{
+ int nfds;
+ fd_set fds;
+ struct timeval tv;
+ struct sockaddr_in addr;
+ size_t addrlen = sizeof(addr);
+ char buf[6];
+ const int one = 1;
+ int sock;
+ rfbClientIteratorPtr i;
+ rfbClientPtr cl;
+
+ if (!rfbScreen->inetdInitDone && rfbScreen->inetdSock != -1) {
+ rfbNewClientConnection(rfbScreen,rfbScreen->inetdSock);
+ rfbScreen->inetdInitDone = TRUE;
+ }
+
+ memcpy((char *)&fds, (char *)&(rfbScreen->allFds), sizeof(fd_set));
+ tv.tv_sec = 0;
+ tv.tv_usec = usec;
+ nfds = select(rfbScreen->maxFd + 1, &fds, NULL, NULL /* &fds */, &tv);
+ if (nfds == 0) {
+ return;
+ }
+ if (nfds < 0) {
+#ifdef WIN32
+ errno = WSAGetLastError();
+#endif
+ rfbLogPerror("rfbCheckFds: select");
+ return;
+ }
+
+ if (rfbScreen->rfbListenSock != -1 && FD_ISSET(rfbScreen->rfbListenSock, &fds)) {
+
+ if ((sock = accept(rfbScreen->rfbListenSock,
+ (struct sockaddr *)&addr, &addrlen)) < 0) {
+ rfbLogPerror("rfbCheckFds: accept");
+ return;
+ }
+
+#ifndef WIN32
+ if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) {
+ rfbLogPerror("rfbCheckFds: fcntl");
+ close(sock);
+ return;
+ }
+#endif
+
+ if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
+ (char *)&one, sizeof(one)) < 0) {
+ rfbLogPerror("rfbCheckFds: setsockopt");
+ close(sock);
+ return;
+ }
+
+#ifdef USE_LIBWRAP
+ if(!hosts_ctl("vnc",STRING_UNKNOWN,inet_ntoa(addr.sin_addr),
+ STRING_UNKNOWN)) {
+ rfbLog("Rejected connection from client %s\n",
+ inet_ntoa(addr.sin_addr));
+ close(sock);
+ return;
+ }
+#endif
+
+ rfbLog("Got connection from client %s\n", inet_ntoa(addr.sin_addr));
+
+ rfbNewClient(rfbScreen,sock);
+
+ FD_CLR(rfbScreen->rfbListenSock, &fds);
+ if (--nfds == 0)
+ return;
+ }
+
+ if ((rfbScreen->udpSock != -1) && FD_ISSET(rfbScreen->udpSock, &fds)) {
+ if(!rfbScreen->udpClient)
+ rfbNewUDPClient(rfbScreen);
+ if (recvfrom(rfbScreen->udpSock, buf, 1, MSG_PEEK,
+ (struct sockaddr *)&addr, &addrlen) < 0) {
+ rfbLogPerror("rfbCheckFds: UDP: recvfrom");
+ rfbDisconnectUDPSock(rfbScreen);
+ rfbScreen->udpSockConnected = FALSE;
+ } else {
+ if (!rfbScreen->udpSockConnected ||
+ (memcmp(&addr, &rfbScreen->udpRemoteAddr, addrlen) != 0))
+ {
+ /* new remote end */
+ rfbLog("rfbCheckFds: UDP: got connection\n");
+
+ memcpy(&rfbScreen->udpRemoteAddr, &addr, addrlen);
+ rfbScreen->udpSockConnected = TRUE;
+
+ if (connect(rfbScreen->udpSock,
+ (struct sockaddr *)&addr, addrlen) < 0) {
+ rfbLogPerror("rfbCheckFds: UDP: connect");
+ rfbDisconnectUDPSock(rfbScreen);
+ return;
+ }
+
+ rfbNewUDPConnection(rfbScreen,rfbScreen->udpSock);
+ }
+
+ rfbProcessUDPInput(rfbScreen);
+ }
+
+ FD_CLR(rfbScreen->udpSock, &fds);
+ if (--nfds == 0)
+ return;
+ }
+
+ i = rfbGetClientIterator(rfbScreen);
+ while((cl = rfbClientIteratorNext(i))) {
+ if (cl->onHold)
+ continue;
+ if (FD_ISSET(cl->sock, &fds) && FD_ISSET(cl->sock, &(rfbScreen->allFds)))
+ rfbProcessClientMessage(cl);
+ }
+ rfbReleaseClientIterator(i);
+}
+
+
+void
+rfbDisconnectUDPSock(rfbScreenInfoPtr rfbScreen)
+{
+ rfbScreen->udpSockConnected = FALSE;
+}
+
+
+
+void
+rfbCloseClient(cl)
+ rfbClientPtr cl;
+{
+ LOCK(cl->updateMutex);
+ if (cl->sock != -1) {
+ FD_CLR(cl->sock,&(cl->screen->allFds));
+ shutdown(cl->sock,SHUT_RDWR);
+ close(cl->sock);
+ cl->sock = -1;
+ }
+ TSIGNAL(cl->updateCond);
+ UNLOCK(cl->updateMutex);
+}
+
+
+/*
+ * rfbConnect is called to make a connection out to a given TCP address.
+ */
+
+int
+rfbConnect(rfbScreen, host, port)
+ rfbScreenInfoPtr rfbScreen;
+ char *host;
+ int port;
+{
+ int sock;
+ int one = 1;
+
+ rfbLog("Making connection to client on host %s port %d\n",
+ host,port);
+
+ if ((sock = ConnectToTcpAddr(host, port)) < 0) {
+ rfbLogPerror("connection failed");
+ return -1;
+ }
+
+#ifndef WIN32
+ if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) {
+ rfbLogPerror("fcntl failed");
+ close(sock);
+ return -1;
+ }
+#endif
+
+ if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
+ (char *)&one, sizeof(one)) < 0) {
+ rfbLogPerror("setsockopt failed");
+ close(sock);
+ return -1;
+ }
+
+ /* AddEnabledDevice(sock); */
+ FD_SET(sock, &rfbScreen->allFds);
+ rfbScreen->maxFd = max(sock,rfbScreen->maxFd);
+
+ return sock;
+}
+
+/*
+ * ReadExact reads an exact number of bytes from a client. Returns 1 if
+ * those bytes have been read, 0 if the other end has closed, or -1 if an error
+ * occurred (errno is set to ETIMEDOUT if it timed out).
+ * timeout is the timeout in ms, 0 for no timeout.
+ */
+
+int
+ReadExactTimeout(rfbClientPtr cl, char* buf, int len, int timeout)
+{
+ int sock = cl->sock;
+ int n;
+ fd_set fds;
+ struct timeval tv;
+ int to = 20000;
+ if (timeout)
+ to = timeout;
+
+ while (len > 0) {
+ n = read(sock, buf, len);
+
+ if (n > 0) {
+
+ buf += n;
+ len -= n;
+
+ } else if (n == 0) {
+
+ return 0;
+
+ } else {
+#ifdef WIN32
+ errno = WSAGetLastError();
+#endif
+ if (errno != EWOULDBLOCK && errno != EAGAIN) {
+ return n;
+ }
+
+ FD_ZERO(&fds);
+ FD_SET(sock, &fds);
+ tv.tv_sec = to / 1000;
+ tv.tv_usec = (to % 1000) * 1000;
+ n = select(sock+1, &fds, NULL, &fds, &tv);
+ if (n < 0) {
+ rfbLogPerror("ReadExact: select");
+ return n;
+ }
+ if ((n == 0) && timeout) {
+ errno = ETIMEDOUT;
+ return -1;
+ }
+ }
+ }
+ return 1;
+}
+
+int ReadExact(rfbClientPtr cl,char* buf,int len)
+{
+ return ReadExactTimeout(cl, buf, len, 0);
+}
+
+/*
+ * WriteExact writes an exact number of bytes to a client. Returns 1 if
+ * those bytes have been written, or -1 if an error occurred (errno is set to
+ * ETIMEDOUT if it timed out).
+ */
+
+int
+WriteExact(cl, buf, len)
+ rfbClientPtr cl;
+ const char *buf;
+ int len;
+{
+ int sock = cl->sock;
+ int n;
+ fd_set fds;
+ struct timeval tv;
+ int totalTimeWaited = 0;
+
+ LOCK(cl->outputMutex);
+ while (len > 0) {
+ n = write(sock, buf, len);
+
+ if (n > 0) {
+
+ buf += n;
+ len -= n;
+
+ } else if (n == 0) {
+
+ rfbLog("WriteExact: write returned 0?\n");
+ exit(1);
+
+ } else {
+#ifdef WIN32
+ errno = WSAGetLastError();
+#endif
+ if (errno != EWOULDBLOCK && errno != EAGAIN) {
+ UNLOCK(cl->outputMutex);
+ return n;
+ }
+
+ /* Retry every 5 seconds until we exceed rfbMaxClientWait. We
+ need to do this because select doesn't necessarily return
+ immediately when the other end has gone away */
+
+ FD_ZERO(&fds);
+ FD_SET(sock, &fds);
+ tv.tv_sec = 5;
+ tv.tv_usec = 0;
+ n = select(sock+1, NULL, &fds, NULL /* &fds */, &tv);
+ if (n < 0) {
+ rfbLogPerror("WriteExact: select");
+ UNLOCK(cl->outputMutex);
+ return n;
+ }
+ if (n == 0) {
+ totalTimeWaited += 5000;
+ if (totalTimeWaited >= rfbMaxClientWait) {
+ errno = ETIMEDOUT;
+ UNLOCK(cl->outputMutex);
+ return -1;
+ }
+ } else {
+ totalTimeWaited = 0;
+ }
+ }
+ }
+ UNLOCK(cl->outputMutex);
+ return 1;
+}
+
+int
+ListenOnTCPPort(port)
+ int port;
+{
+ struct sockaddr_in addr;
+ int sock;
+ int one = 1;
+
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(port);
+ /* addr.sin_addr.s_addr = interface.s_addr; */
+ addr.sin_addr.s_addr = INADDR_ANY;
+
+ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+ return -1;
+ }
+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
+ (char *)&one, sizeof(one)) < 0) {
+ close(sock);
+ return -1;
+ }
+ if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ close(sock);
+ return -1;
+ }
+ if (listen(sock, 5) < 0) {
+ close(sock);
+ return -1;
+ }
+
+ return sock;
+}
+
+int
+ConnectToTcpAddr(host, port)
+ char *host;
+ int port;
+{
+ struct hostent *hp;
+ int sock;
+ struct sockaddr_in addr;
+
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(port);
+
+ if ((addr.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE)
+ {
+ if (!(hp = gethostbyname(host))) {
+ errno = EINVAL;
+ return -1;
+ }
+ addr.sin_addr.s_addr = *(unsigned long *)hp->h_addr;
+ }
+
+ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+ return -1;
+ }
+
+ if (connect(sock, (struct sockaddr *)&addr, (sizeof(addr))) < 0) {
+ close(sock);
+ return -1;
+ }
+
+ return sock;
+}
+
+int
+ListenOnUDPPort(port)
+ int port;
+{
+ struct sockaddr_in addr;
+ int sock;
+ int one = 1;
+
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(port);
+ /* addr.sin_addr.s_addr = interface.s_addr; */
+ addr.sin_addr.s_addr = INADDR_ANY;
+
+ if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ return -1;
+ }
+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
+ (char *)&one, sizeof(one)) < 0) {
+ return -1;
+ }
+ if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ return -1;
+ }
+
+ return sock;
+}
diff --git a/krfb/libvncserver/sraRegion.c b/krfb/libvncserver/sraRegion.c
new file mode 100644
index 00000000..315ce5b1
--- /dev/null
+++ b/krfb/libvncserver/sraRegion.c
@@ -0,0 +1,889 @@
+/* -=- sraRegion.c
+ * Copyright (c) 2001 James "Wez" Weatherall, Johannes E. Schindelin
+ *
+ * A general purpose region clipping library
+ * Only deals with rectangular regions, though.
+ */
+
+#include "rfb.h"
+#include "sraRegion.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+/* -=- Internal Span structure */
+
+struct sraRegion;
+
+typedef struct sraSpan {
+ struct sraSpan *_next;
+ struct sraSpan *_prev;
+ int start;
+ int end;
+ struct sraRegion *subspan;
+} sraSpan;
+
+typedef struct sraRegion {
+ sraSpan front;
+ sraSpan back;
+} sraSpanList;
+
+/* -=- Span routines */
+
+sraSpanList *sraSpanListDup(const sraSpanList *src);
+void sraSpanListDestroy(sraSpanList *list);
+
+static sraSpan *
+sraSpanCreate(int start, int end, const sraSpanList *subspan) {
+ sraSpan *item = (sraSpan*)malloc(sizeof(sraSpan));
+ item->_next = item->_prev = NULL;
+ item->start = start;
+ item->end = end;
+ item->subspan = sraSpanListDup(subspan);
+ return item;
+}
+
+static sraSpan *
+sraSpanDup(const sraSpan *src) {
+ sraSpan *span;
+ if (!src) return NULL;
+ span = sraSpanCreate(src->start, src->end, src->subspan);
+ return span;
+}
+
+static void
+sraSpanInsertAfter(sraSpan *newspan, sraSpan *after) {
+ newspan->_next = after->_next;
+ newspan->_prev = after;
+ after->_next->_prev = newspan;
+ after->_next = newspan;
+}
+
+static void
+sraSpanInsertBefore(sraSpan *newspan, sraSpan *before) {
+ newspan->_next = before;
+ newspan->_prev = before->_prev;
+ before->_prev->_next = newspan;
+ before->_prev = newspan;
+}
+
+static void
+sraSpanRemove(sraSpan *span) {
+ span->_prev->_next = span->_next;
+ span->_next->_prev = span->_prev;
+}
+
+static void
+sraSpanDestroy(sraSpan *span) {
+ if (span->subspan) sraSpanListDestroy(span->subspan);
+ free(span);
+}
+
+#ifdef DEBUG
+static void
+sraSpanCheck(const sraSpan *span, const char *text) {
+ /* Check the span is valid! */
+ if (span->start == span->end) {
+ printf(text);
+ printf(":%d-%d\n", span->start, span->end);
+ }
+}
+#endif
+
+/* -=- SpanList routines */
+
+static void sraSpanPrint(const sraSpan *s);
+
+static void
+sraSpanListPrint(const sraSpanList *l) {
+ sraSpan *curr;
+ if (!l) {
+ printf("NULL");
+ return;
+ }
+ curr = l->front._next;
+ printf("[");
+ while (curr != &(l->back)) {
+ sraSpanPrint(curr);
+ curr = curr->_next;
+ }
+ printf("]");
+}
+
+void
+sraSpanPrint(const sraSpan *s) {
+ printf("(%d-%d)", (s->start), (s->end));
+ if (s->subspan)
+ sraSpanListPrint(s->subspan);
+}
+
+static sraSpanList *
+sraSpanListCreate(void) {
+ sraSpanList *item = (sraSpanList*)malloc(sizeof(sraSpanList));
+ item->front._next = &(item->back);
+ item->front._prev = NULL;
+ item->back._prev = &(item->front);
+ item->back._next = NULL;
+ return item;
+}
+
+sraSpanList *
+sraSpanListDup(const sraSpanList *src) {
+ sraSpanList *newlist;
+ sraSpan *newspan, *curr;
+
+ if (!src) return NULL;
+ newlist = sraSpanListCreate();
+ curr = src->front._next;
+ while (curr != &(src->back)) {
+ newspan = sraSpanDup(curr);
+ sraSpanInsertBefore(newspan, &(newlist->back));
+ curr = curr->_next;
+ }
+
+ return newlist;
+}
+
+void
+sraSpanListDestroy(sraSpanList *list) {
+ sraSpan *curr, *next;
+ while (list->front._next != &(list->back)) {
+ curr = list->front._next;
+ next = curr->_next;
+ sraSpanRemove(curr);
+ sraSpanDestroy(curr);
+ curr = next;
+ }
+ free(list);
+}
+
+static void
+sraSpanListMakeEmpty(sraSpanList *list) {
+ sraSpan *curr, *next;
+ while (list->front._next != &(list->back)) {
+ curr = list->front._next;
+ next = curr->_next;
+ sraSpanRemove(curr);
+ sraSpanDestroy(curr);
+ curr = next;
+ }
+ list->front._next = &(list->back);
+ list->front._prev = NULL;
+ list->back._prev = &(list->front);
+ list->back._next = NULL;
+}
+
+static Bool
+sraSpanListEqual(const sraSpanList *s1, const sraSpanList *s2) {
+ sraSpan *sp1, *sp2;
+
+ if (!s1) {
+ if (!s2) {
+ return 1;
+ } else {
+ printf("sraSpanListEqual:incompatible spans (only one NULL!)\n");
+ return FALSE;
+ }
+ }
+
+ sp1 = s1->front._next;
+ sp2 = s2->front._next;
+ while ((sp1 != &(s1->back)) &&
+ (sp2 != &(s2->back))) {
+ if ((sp1->start != sp2->start) ||
+ (sp1->end != sp2->end) ||
+ (!sraSpanListEqual(sp1->subspan, sp2->subspan))) {
+ return 0;
+ }
+ sp1 = sp1->_next;
+ sp2 = sp2->_next;
+ }
+
+ if ((sp1 == &(s1->back)) && (sp2 == &(s2->back))) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static Bool
+sraSpanListEmpty(const sraSpanList *list) {
+ return (list->front._next == &(list->back));
+}
+
+static unsigned long
+sraSpanListCount(const sraSpanList *list) {
+ sraSpan *curr = list->front._next;
+ unsigned long count = 0;
+ while (curr != &(list->back)) {
+ if (curr->subspan) {
+ count += sraSpanListCount(curr->subspan);
+ } else {
+ count += 1;
+ }
+ curr = curr->_next;
+ }
+ return count;
+}
+
+static void
+sraSpanMergePrevious(sraSpan *dest) {
+ sraSpan *prev = dest->_prev;
+
+ while ((prev->_prev) &&
+ (prev->end == dest->start) &&
+ (sraSpanListEqual(prev->subspan, dest->subspan))) {
+ /*
+ printf("merge_prev:");
+ sraSpanPrint(prev);
+ printf(" & ");
+ sraSpanPrint(dest);
+ printf("\n");
+ */
+ dest->start = prev->start;
+ sraSpanRemove(prev);
+ sraSpanDestroy(prev);
+ prev = dest->_prev;
+ }
+}
+
+static void
+sraSpanMergeNext(sraSpan *dest) {
+ sraSpan *next = dest->_next;
+ while ((next->_next) &&
+ (next->start == dest->end) &&
+ (sraSpanListEqual(next->subspan, dest->subspan))) {
+/*
+ printf("merge_next:");
+ sraSpanPrint(dest);
+ printf(" & ");
+ sraSpanPrint(next);
+ printf("\n");
+ */
+ dest->end = next->end;
+ sraSpanRemove(next);
+ sraSpanDestroy(next);
+ next = dest->_next;
+ }
+}
+
+static void
+sraSpanListOr(sraSpanList *dest, const sraSpanList *src) {
+ sraSpan *d_curr, *s_curr;
+ int s_start, s_end;
+
+ if (!dest) {
+ if (!src) {
+ return;
+ } else {
+ printf("sraSpanListOr:incompatible spans (only one NULL!)\n");
+ return;
+ }
+ }
+
+ d_curr = dest->front._next;
+ s_curr = src->front._next;
+ s_start = s_curr->start;
+ s_end = s_curr->end;
+ while (s_curr != &(src->back)) {
+
+ /* - If we are at end of destination list OR
+ If the new span comes before the next destination one */
+ if ((d_curr == &(dest->back)) ||
+ (d_curr->start >= s_end)) {
+ /* - Add the span */
+ sraSpanInsertBefore(sraSpanCreate(s_start, s_end,
+ s_curr->subspan),
+ d_curr);
+ if (d_curr != &(dest->back))
+ sraSpanMergePrevious(d_curr);
+ s_curr = s_curr->_next;
+ s_start = s_curr->start;
+ s_end = s_curr->end;
+ } else {
+
+ /* - If the new span overlaps the existing one */
+ if ((s_start < d_curr->end) &&
+ (s_end > d_curr->start)) {
+
+ /* - Insert new span before the existing destination one? */
+ if (s_start < d_curr->start) {
+ sraSpanInsertBefore(sraSpanCreate(s_start,
+ d_curr->start,
+ s_curr->subspan),
+ d_curr);
+ sraSpanMergePrevious(d_curr);
+ }
+
+ /* Split the existing span if necessary */
+ if (s_end < d_curr->end) {
+ sraSpanInsertAfter(sraSpanCreate(s_end,
+ d_curr->end,
+ d_curr->subspan),
+ d_curr);
+ d_curr->end = s_end;
+ }
+ if (s_start > d_curr->start) {
+ sraSpanInsertBefore(sraSpanCreate(d_curr->start,
+ s_start,
+ d_curr->subspan),
+ d_curr);
+ d_curr->start = s_start;
+ }
+
+ /* Recursively OR subspans */
+ sraSpanListOr(d_curr->subspan, s_curr->subspan);
+
+ /* Merge this span with previous or next? */
+ if (d_curr->_prev != &(dest->front))
+ sraSpanMergePrevious(d_curr);
+ if (d_curr->_next != &(dest->back))
+ sraSpanMergeNext(d_curr);
+
+ /* Move onto the next pair to compare */
+ if (s_end > d_curr->end) {
+ s_start = d_curr->end;
+ d_curr = d_curr->_next;
+ } else {
+ s_curr = s_curr->_next;
+ s_start = s_curr->start;
+ s_end = s_curr->end;
+ }
+ } else {
+ /* - No overlap. Move to the next destination span */
+ d_curr = d_curr->_next;
+ }
+ }
+ }
+}
+
+static Bool
+sraSpanListAnd(sraSpanList *dest, const sraSpanList *src) {
+ sraSpan *d_curr, *s_curr, *d_next;
+
+ if (!dest) {
+ if (!src) {
+ return 1;
+ } else {
+ printf("sraSpanListAnd:incompatible spans (only one NULL!)\n");
+ return FALSE;
+ }
+ }
+
+ d_curr = dest->front._next;
+ s_curr = src->front._next;
+ while ((s_curr != &(src->back)) && (d_curr != &(dest->back))) {
+
+ /* - If we haven't reached a destination span yet then move on */
+ if (d_curr->start >= s_curr->end) {
+ s_curr = s_curr->_next;
+ continue;
+ }
+
+ /* - If we are beyond the current destination span then remove it */
+ if (d_curr->end <= s_curr->start) {
+ sraSpan *next = d_curr->_next;
+ sraSpanRemove(d_curr);
+ sraSpanDestroy(d_curr);
+ d_curr = next;
+ continue;
+ }
+
+ /* - If we partially overlap a span then split it up or remove bits */
+ if (s_curr->start > d_curr->start) {
+ /* - The top bit of the span does not match */
+ d_curr->start = s_curr->start;
+ }
+ if (s_curr->end < d_curr->end) {
+ /* - The end of the span does not match */
+ sraSpanInsertAfter(sraSpanCreate(s_curr->end,
+ d_curr->end,
+ d_curr->subspan),
+ d_curr);
+ d_curr->end = s_curr->end;
+ }
+
+ /* - Now recursively process the affected span */
+ if (!sraSpanListAnd(d_curr->subspan, s_curr->subspan)) {
+ /* - The destination subspan is now empty, so we should remove it */
+ sraSpan *next = d_curr->_next;
+ sraSpanRemove(d_curr);
+ sraSpanDestroy(d_curr);
+ d_curr = next;
+ } else {
+ /* Merge this span with previous or next? */
+ if (d_curr->_prev != &(dest->front))
+ sraSpanMergePrevious(d_curr);
+
+ /* - Move on to the next span */
+ d_next = d_curr;
+ if (s_curr->end >= d_curr->end) {
+ d_next = d_curr->_next;
+ }
+ if (s_curr->end <= d_curr->end) {
+ s_curr = s_curr->_next;
+ }
+ d_curr = d_next;
+ }
+ }
+
+ while (d_curr != &(dest->back)) {
+ sraSpan *next = d_curr->_next;
+ sraSpanRemove(d_curr);
+ sraSpanDestroy(d_curr);
+ d_curr=next;
+ }
+
+ return !sraSpanListEmpty(dest);
+}
+
+static Bool
+sraSpanListSubtract(sraSpanList *dest, const sraSpanList *src) {
+ sraSpan *d_curr, *s_curr;
+
+ if (!dest) {
+ if (!src) {
+ return 1;
+ } else {
+ printf("sraSpanListSubtract:incompatible spans (only one NULL!)\n");
+ return FALSE;
+ }
+ }
+
+ d_curr = dest->front._next;
+ s_curr = src->front._next;
+ while ((s_curr != &(src->back)) && (d_curr != &(dest->back))) {
+
+ /* - If we haven't reached a destination span yet then move on */
+ if (d_curr->start >= s_curr->end) {
+ s_curr = s_curr->_next;
+ continue;
+ }
+
+ /* - If we are beyond the current destination span then skip it */
+ if (d_curr->end <= s_curr->start) {
+ d_curr = d_curr->_next;
+ continue;
+ }
+
+ /* - If we partially overlap the current span then split it up */
+ if (s_curr->start > d_curr->start) {
+ sraSpanInsertBefore(sraSpanCreate(d_curr->start,
+ s_curr->start,
+ d_curr->subspan),
+ d_curr);
+ d_curr->start = s_curr->start;
+ }
+ if (s_curr->end < d_curr->end) {
+ sraSpanInsertAfter(sraSpanCreate(s_curr->end,
+ d_curr->end,
+ d_curr->subspan),
+ d_curr);
+ d_curr->end = s_curr->end;
+ }
+
+ /* - Now recursively process the affected span */
+ if ((!d_curr->subspan) || !sraSpanListSubtract(d_curr->subspan, s_curr->subspan)) {
+ /* - The destination subspan is now empty, so we should remove it */
+ sraSpan *next = d_curr->_next;
+ sraSpanRemove(d_curr);
+ sraSpanDestroy(d_curr);
+ d_curr = next;
+ } else {
+ /* Merge this span with previous or next? */
+ if (d_curr->_prev != &(dest->front))
+ sraSpanMergePrevious(d_curr);
+ if (d_curr->_next != &(dest->back))
+ sraSpanMergeNext(d_curr);
+
+ /* - Move on to the next span */
+ if (s_curr->end > d_curr->end) {
+ d_curr = d_curr->_next;
+ } else {
+ s_curr = s_curr->_next;
+ }
+ }
+ }
+
+ return !sraSpanListEmpty(dest);
+}
+
+/* -=- Region routines */
+
+sraRegion *
+sraRgnCreate() {
+ return (sraRegion*)sraSpanListCreate();
+}
+
+sraRegion *
+sraRgnCreateRect(int x1, int y1, int x2, int y2) {
+ sraSpanList *vlist, *hlist;
+ sraSpan *vspan, *hspan;
+
+ /* - Build the horizontal portion of the span */
+ hlist = sraSpanListCreate();
+ hspan = sraSpanCreate(x1, x2, NULL);
+ sraSpanInsertAfter(hspan, &(hlist->front));
+
+ /* - Build the vertical portion of the span */
+ vlist = sraSpanListCreate();
+ vspan = sraSpanCreate(y1, y2, hlist);
+ sraSpanInsertAfter(vspan, &(vlist->front));
+
+ sraSpanListDestroy(hlist);
+
+ return (sraRegion*)vlist;
+}
+
+sraRegion *
+sraRgnCreateRgn(const sraRegion *src) {
+ return (sraRegion*)sraSpanListDup((sraSpanList*)src);
+}
+
+void
+sraRgnDestroy(sraRegion *rgn) {
+ sraSpanListDestroy((sraSpanList*)rgn);
+}
+
+void
+sraRgnMakeEmpty(sraRegion *rgn) {
+ sraSpanListMakeEmpty((sraSpanList*)rgn);
+}
+
+/* -=- Boolean Region ops */
+
+Bool
+sraRgnAnd(sraRegion *dst, const sraRegion *src) {
+ return sraSpanListAnd((sraSpanList*)dst, (sraSpanList*)src);
+}
+
+void
+sraRgnOr(sraRegion *dst, const sraRegion *src) {
+ sraSpanListOr((sraSpanList*)dst, (sraSpanList*)src);
+}
+
+Bool
+sraRgnSubtract(sraRegion *dst, const sraRegion *src) {
+ return sraSpanListSubtract((sraSpanList*)dst, (sraSpanList*)src);
+}
+
+void
+sraRgnOffset(sraRegion *dst, int dx, int dy) {
+ sraSpan *vcurr, *hcurr;
+
+ vcurr = ((sraSpanList*)dst)->front._next;
+ while (vcurr != &(((sraSpanList*)dst)->back)) {
+ vcurr->start += dy;
+ vcurr->end += dy;
+
+ hcurr = vcurr->subspan->front._next;
+ while (hcurr != &(vcurr->subspan->back)) {
+ hcurr->start += dx;
+ hcurr->end += dx;
+ hcurr = hcurr->_next;
+ }
+
+ vcurr = vcurr->_next;
+ }
+}
+
+sraRegion *sraRgnBBox(const sraRegion *src) {
+ int xmin=((unsigned int)(int)-1)>>1,ymin=xmin,xmax=1-xmin,ymax=xmax;
+ sraSpan *vcurr, *hcurr;
+
+ if(!src)
+ return sraRgnCreate();
+
+ vcurr = ((sraSpanList*)src)->front._next;
+ while (vcurr != &(((sraSpanList*)src)->back)) {
+ if(vcurr->start<ymin)
+ ymin=vcurr->start;
+ if(vcurr->end>ymax)
+ ymax=vcurr->end;
+
+ hcurr = vcurr->subspan->front._next;
+ while (hcurr != &(vcurr->subspan->back)) {
+ if(hcurr->start<xmin)
+ xmin=hcurr->start;
+ if(hcurr->end>xmax)
+ xmax=hcurr->end;
+ hcurr = hcurr->_next;
+ }
+
+ vcurr = vcurr->_next;
+ }
+
+ if(xmax<xmin || ymax<ymin)
+ return sraRgnCreate();
+
+ return sraRgnCreateRect(xmin,ymin,xmax,ymax);
+}
+
+Bool
+sraRgnPopRect(sraRegion *rgn, sraRect *rect, unsigned long flags) {
+ sraSpan *vcurr, *hcurr;
+ sraSpan *vend, *hend;
+ Bool right2left = flags & 2;
+ Bool bottom2top = flags & 1;
+
+ /* - Pick correct order */
+ if (bottom2top) {
+ vcurr = ((sraSpanList*)rgn)->back._prev;
+ vend = &(((sraSpanList*)rgn)->front);
+ } else {
+ vcurr = ((sraSpanList*)rgn)->front._next;
+ vend = &(((sraSpanList*)rgn)->back);
+ }
+
+ if (vcurr != vend) {
+ rect->y1 = vcurr->start;
+ rect->y2 = vcurr->end;
+
+ /* - Pick correct order */
+ if (right2left) {
+ hcurr = vcurr->subspan->back._prev;
+ hend = &(vcurr->subspan->front);
+ } else {
+ hcurr = vcurr->subspan->front._next;
+ hend = &(vcurr->subspan->back);
+ }
+
+ if (hcurr != hend) {
+ rect->x1 = hcurr->start;
+ rect->x2 = hcurr->end;
+
+ sraSpanRemove(hcurr);
+ sraSpanDestroy(hcurr);
+
+ if (sraSpanListEmpty(vcurr->subspan)) {
+ sraSpanRemove(vcurr);
+ sraSpanDestroy(vcurr);
+ }
+
+#if 0
+ printf("poprect:(%dx%d)-(%dx%d)\n",
+ rect->x1, rect->y1, rect->x2, rect->y2);
+#endif
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+unsigned long
+sraRgnCountRects(const sraRegion *rgn) {
+ unsigned long count = sraSpanListCount((sraSpanList*)rgn);
+ return count;
+}
+
+Bool
+sraRgnEmpty(const sraRegion *rgn) {
+ return sraSpanListEmpty((sraSpanList*)rgn);
+}
+
+/* iterator stuff */
+sraRectangleIterator *sraRgnGetIterator(sraRegion *s)
+{
+ /* these values have to be multiples of 4 */
+#define DEFSIZE 4
+#define DEFSTEP 8
+ sraRectangleIterator *i =
+ (sraRectangleIterator*)malloc(sizeof(sraRectangleIterator));
+ if(!i)
+ return NULL;
+
+ /* we have to recurse eventually. So, the first sPtr is the pointer to
+ the sraSpan in the first level. the second sPtr is the pointer to
+ the sraRegion.back. The third and fourth sPtr are for the second
+ recursion level and so on. */
+ i->sPtrs = (sraSpan**)malloc(sizeof(sraSpan*)*DEFSIZE);
+ if(!i->sPtrs) {
+ free(i);
+ return NULL;
+ }
+ i->ptrSize = DEFSIZE;
+ i->sPtrs[0] = &(s->front);
+ i->sPtrs[1] = &(s->back);
+ i->ptrPos = 0;
+ i->reverseX = 0;
+ i->reverseY = 0;
+ return i;
+}
+
+sraRectangleIterator *sraRgnGetReverseIterator(sraRegion *s,Bool reverseX,Bool reverseY)
+{
+ sraRectangleIterator *i = sraRgnGetIterator(s);
+ if(reverseY) {
+ i->sPtrs[1] = &(s->front);
+ i->sPtrs[0] = &(s->back);
+ }
+ i->reverseX = reverseX;
+ i->reverseY = reverseY;
+ return(i);
+}
+
+static Bool sraReverse(sraRectangleIterator *i)
+{
+ return( ((i->ptrPos&2) && i->reverseX) ||
+ (!(i->ptrPos&2) && i->reverseY));
+}
+
+static sraSpan* sraNextSpan(sraRectangleIterator *i)
+{
+ if(sraReverse(i))
+ return(i->sPtrs[i->ptrPos]->_prev);
+ else
+ return(i->sPtrs[i->ptrPos]->_next);
+}
+
+Bool sraRgnIteratorNext(sraRectangleIterator* i,sraRect* r)
+{
+ /* is the subspan finished? */
+ while(sraNextSpan(i) == i->sPtrs[i->ptrPos+1]) {
+ i->ptrPos -= 2;
+ if(i->ptrPos < 0) /* the end */
+ return(0);
+ }
+
+ i->sPtrs[i->ptrPos] = sraNextSpan(i);
+
+ /* is this a new subspan? */
+ while(i->sPtrs[i->ptrPos]->subspan) {
+ if(i->ptrPos+2 > i->ptrSize) { /* array is too small */
+ i->ptrSize += DEFSTEP;
+ i->sPtrs = (sraSpan**)realloc(i->sPtrs, sizeof(sraSpan*)*i->ptrSize);
+ }
+ i->ptrPos =+ 2;
+ if(sraReverse(i)) {
+ i->sPtrs[i->ptrPos] = i->sPtrs[i->ptrPos-2]->subspan->back._prev;
+ i->sPtrs[i->ptrPos+1] = &(i->sPtrs[i->ptrPos-2]->subspan->front);
+ } else {
+ i->sPtrs[i->ptrPos] = i->sPtrs[i->ptrPos-2]->subspan->front._next;
+ i->sPtrs[i->ptrPos+1] = &(i->sPtrs[i->ptrPos-2]->subspan->back);
+ }
+ }
+
+ if((i->ptrPos%4)!=2) {
+ printf("sraRgnIteratorNext: offset is wrong (%d%%4!=2)\n",i->ptrPos);
+ return FALSE;
+ }
+
+ r->y1 = i->sPtrs[i->ptrPos-2]->start;
+ r->y2 = i->sPtrs[i->ptrPos-2]->end;
+ r->x1 = i->sPtrs[i->ptrPos]->start;
+ r->x2 = i->sPtrs[i->ptrPos]->end;
+
+ return(-1);
+}
+
+void sraRgnReleaseIterator(sraRectangleIterator* i)
+{
+ free(i->sPtrs);
+ free(i);
+}
+
+void
+sraRgnPrint(const sraRegion *rgn) {
+ sraSpanListPrint((sraSpanList*)rgn);
+}
+
+Bool
+sraClipRect(int *x, int *y, int *w, int *h,
+ int cx, int cy, int cw, int ch) {
+ if (*x < cx) {
+ *w -= (cx-*x);
+ *x = cx;
+ }
+ if (*y < cy) {
+ *h -= (cy-*y);
+ *y = cy;
+ }
+ if (*x+*w > cx+cw) {
+ *w = (cx+cw)-*x;
+ }
+ if (*y+*h > cy+ch) {
+ *h = (cy+ch)-*y;
+ }
+ return (*w>0) && (*h>0);
+}
+
+Bool
+sraClipRect2(int *x, int *y, int *x2, int *y2,
+ int cx, int cy, int cx2, int cy2) {
+ if (*x < cx)
+ *x = cx;
+ if (*y < cy)
+ *y = cy;
+ if (*x >= cx2)
+ *x = cx2-1;
+ if (*y >= cy2)
+ *y = cy2-1;
+ if (*x2 <= cx)
+ *x2 = cx+1;
+ if (*y2 <= cy)
+ *y2 = cy+1;
+ if (*x2 > cx2)
+ *x2 = cx2;
+ if (*y2 > cy2)
+ *y2 = cy2;
+ return (*x2>*x) && (*y2>*y);
+}
+
+/* test */
+
+#ifdef SRA_TEST
+/* pipe the output to sort|uniq -u and you'll get the errors. */
+int main(int argc, char** argv)
+{
+ sraRegionPtr region, region1, region2;
+ sraRectangleIterator* i;
+ sraRect rect;
+ Bool b;
+
+ region = sraRgnCreateRect(10, 10, 600, 300);
+ region1 = sraRgnCreateRect(40, 50, 350, 200);
+ region2 = sraRgnCreateRect(0, 0, 20, 40);
+
+ sraRgnPrint(region);
+ printf("\n[(10-300)[(10-600)]]\n\n");
+
+ b = sraRgnSubtract(region, region1);
+ printf("%s ",b?"true":"false");
+ sraRgnPrint(region);
+ printf("\ntrue [(10-50)[(10-600)](50-200)[(10-40)(350-600)](200-300)[(10-600)]]\n\n");
+
+ sraRgnOr(region, region2);
+ printf("%ld\n6\n\n", sraRgnCountRects(region));
+
+ i = sraRgnGetIterator(region);
+ while(sraRgnIteratorNext(i, &rect))
+ printf("%dx%d+%d+%d ",
+ rect.x2-rect.x1,rect.y2-rect.y1,
+ rect.x1,rect.y1);
+ sraRgnReleaseIterator(i);
+ printf("\n20x10+0+0 600x30+0+10 590x10+10+40 30x150+10+50 250x150+350+50 590x100+10+200 \n\n");
+
+ i = sraRgnGetReverseIterator(region,1,0);
+ while(sraRgnIteratorNext(i, &rect))
+ printf("%dx%d+%d+%d ",
+ rect.x2-rect.x1,rect.y2-rect.y1,
+ rect.x1,rect.y1);
+ sraRgnReleaseIterator(i);
+ printf("\n20x10+0+0 600x30+0+10 590x10+10+40 250x150+350+50 30x150+10+50 590x100+10+200 \n\n");
+
+ i = sraRgnGetReverseIterator(region,1,1);
+ while(sraRgnIteratorNext(i, &rect))
+ printf("%dx%d+%d+%d ",
+ rect.x2-rect.x1,rect.y2-rect.y1,
+ rect.x1,rect.y1);
+ sraRgnReleaseIterator(i);
+ printf("\n590x100+10+200 250x150+350+50 30x150+10+50 590x10+10+40 600x30+0+10 20x10+0+0 \n\n");
+
+ sraRgnDestroy(region);
+ sraRgnDestroy(region1);
+ sraRgnDestroy(region2);
+
+ return(0);
+}
+#endif
diff --git a/krfb/libvncserver/sraRegion.h b/krfb/libvncserver/sraRegion.h
new file mode 100644
index 00000000..9526ac37
--- /dev/null
+++ b/krfb/libvncserver/sraRegion.h
@@ -0,0 +1,65 @@
+#ifndef SRAREGION_H
+#define SRAREGION_H
+
+/* -=- SRA - Simple Region Algorithm
+ * A simple rectangular region implementation.
+ * Copyright (c) 2001 James "Wez" Weatherall, Johannes E. Schindelin
+ */
+
+/* -=- sraRect */
+
+typedef struct _rect {
+ int x1;
+ int y1;
+ int x2;
+ int y2;
+} sraRect;
+
+typedef struct sraRegion sraRegion;
+
+/* -=- Region manipulation functions */
+
+extern sraRegion *sraRgnCreate();
+extern sraRegion *sraRgnCreateRect(int x1, int y1, int x2, int y2);
+extern sraRegion *sraRgnCreateRgn(const sraRegion *src);
+
+extern void sraRgnDestroy(sraRegion *rgn);
+extern void sraRgnMakeEmpty(sraRegion *rgn);
+extern Bool sraRgnAnd(sraRegion *dst, const sraRegion *src);
+extern void sraRgnOr(sraRegion *dst, const sraRegion *src);
+extern Bool sraRgnSubtract(sraRegion *dst, const sraRegion *src);
+
+extern void sraRgnOffset(sraRegion *dst, int dx, int dy);
+
+extern Bool sraRgnPopRect(sraRegion *region, sraRect *rect,
+ unsigned long flags);
+
+extern unsigned long sraRgnCountRects(const sraRegion *rgn);
+extern Bool sraRgnEmpty(const sraRegion *rgn);
+
+extern sraRegion *sraRgnBBox(const sraRegion *src);
+
+/* -=- rectangle iterator */
+
+typedef struct sraRectangleIterator {
+ Bool reverseX,reverseY;
+ int ptrSize,ptrPos;
+ struct sraSpan** sPtrs;
+} sraRectangleIterator;
+
+extern sraRectangleIterator *sraRgnGetIterator(sraRegion *s);
+extern sraRectangleIterator *sraRgnGetReverseIterator(sraRegion *s,Bool reverseX,Bool reverseY);
+extern Bool sraRgnIteratorNext(sraRectangleIterator *i,sraRect *r);
+extern void sraRgnReleaseIterator(sraRectangleIterator *i);
+
+void sraRgnPrint(const sraRegion *s);
+
+/* -=- Rectangle clipper (for speed) */
+
+extern Bool sraClipRect(int *x, int *y, int *w, int *h,
+ int cx, int cy, int cw, int ch);
+
+extern Bool sraClipRect2(int *x, int *y, int *x2, int *y2,
+ int cx, int cy, int cx2, int cy2);
+
+#endif
diff --git a/krfb/libvncserver/stats.c b/krfb/libvncserver/stats.c
new file mode 100644
index 00000000..7774d2fa
--- /dev/null
+++ b/krfb/libvncserver/stats.c
@@ -0,0 +1,103 @@
+/*
+ * stats.c
+ */
+
+/*
+ * OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
+ * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
+ * All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "rfb.h"
+
+static const char* encNames[] = {
+ "raw", "copyRect", "RRE", "[encoding 3]", "CoRRE", "hextile",
+ "zlib", "tight", "[encoding 8]", "[encoding 9]"
+};
+
+
+void
+rfbResetStats(rfbClientPtr cl)
+{
+ int i;
+ for (i = 0; i < MAX_ENCODINGS; i++) {
+ cl->rfbBytesSent[i] = 0;
+ cl->rfbRectanglesSent[i] = 0;
+ }
+ cl->rfbLastRectMarkersSent = 0;
+ cl->rfbLastRectBytesSent = 0;
+ cl->rfbCursorBytesSent = 0;
+ cl->rfbCursorUpdatesSent = 0;
+ cl->rfbFramebufferUpdateMessagesSent = 0;
+ cl->rfbRawBytesEquivalent = 0;
+ cl->rfbKeyEventsRcvd = 0;
+ cl->rfbPointerEventsRcvd = 0;
+}
+
+void
+rfbPrintStats(rfbClientPtr cl)
+{
+ int i;
+ int totalRectanglesSent = 0;
+ int totalBytesSent = 0;
+
+ rfbLog("Statistics:\n");
+
+ if ((cl->rfbKeyEventsRcvd != 0) || (cl->rfbPointerEventsRcvd != 0))
+ rfbLog(" key events received %d, pointer events %d\n",
+ cl->rfbKeyEventsRcvd, cl->rfbPointerEventsRcvd);
+
+ for (i = 0; i < MAX_ENCODINGS; i++) {
+ totalRectanglesSent += cl->rfbRectanglesSent[i];
+ totalBytesSent += cl->rfbBytesSent[i];
+ }
+
+ totalRectanglesSent += (cl->rfbCursorUpdatesSent +
+ cl->rfbLastRectMarkersSent);
+ totalBytesSent += (cl->rfbCursorBytesSent + cl->rfbLastRectBytesSent);
+
+ rfbLog(" framebuffer updates %d, rectangles %d, bytes %d\n",
+ cl->rfbFramebufferUpdateMessagesSent, totalRectanglesSent,
+ totalBytesSent);
+
+ if (cl->rfbLastRectMarkersSent != 0)
+ rfbLog(" LastRect markers %d, bytes %d\n",
+ cl->rfbLastRectMarkersSent, cl->rfbLastRectBytesSent);
+
+ if (cl->rfbCursorUpdatesSent != 0)
+ rfbLog(" cursor shape updates %d, bytes %d\n",
+ cl->rfbCursorUpdatesSent, cl->rfbCursorBytesSent);
+
+ for (i = 0; i < MAX_ENCODINGS; i++) {
+ if (cl->rfbRectanglesSent[i] != 0)
+ rfbLog(" %s rectangles %d, bytes %d\n",
+ encNames[i], cl->rfbRectanglesSent[i], cl->rfbBytesSent[i]);
+ }
+
+ if ((totalBytesSent - cl->rfbBytesSent[rfbEncodingCopyRect]) != 0) {
+ rfbLog(" raw bytes equivalent %d, compression ratio %f\n",
+ cl->rfbRawBytesEquivalent,
+ (double)cl->rfbRawBytesEquivalent
+ / (double)(totalBytesSent
+ - cl->rfbBytesSent[rfbEncodingCopyRect]-
+ cl->rfbCursorBytesSent -
+ cl->rfbLastRectBytesSent));
+ }
+}
diff --git a/krfb/libvncserver/storepasswd.c b/krfb/libvncserver/storepasswd.c
new file mode 100644
index 00000000..1470e4db
--- /dev/null
+++ b/krfb/libvncserver/storepasswd.c
@@ -0,0 +1,46 @@
+/*
+ * OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
+ * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
+ * All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include <stdio.h>
+#include "rfb.h"
+
+void usage(void)
+{
+ printf("\nusage: storepasswd <password> <filename>\n\n");
+
+ printf("Stores a password in encrypted format.\n");
+ printf("The resulting file can be used with the -rfbauth argument to OSXvnc.\n\n");
+ exit(1);
+}
+
+int main(int argc, char *argv[])
+{
+ if (argc != 3)
+ usage();
+
+ if (vncEncryptAndStorePasswd(argv[1], argv[2]) != 0) {
+ printf("storing password failed.\n");
+ return 1;
+ } else {
+ printf("storing password succeeded.\n");
+ return 0;
+ }
+}
diff --git a/krfb/libvncserver/tableinit24.c b/krfb/libvncserver/tableinit24.c
new file mode 100644
index 00000000..f1e63a50
--- /dev/null
+++ b/krfb/libvncserver/tableinit24.c
@@ -0,0 +1,157 @@
+/*
+ 24 bit
+ */
+
+/*
+ * OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
+ * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
+ * All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+static void
+rfbInitOneRGBTable24 (CARD8 *table, int inMax, int outMax, int outShift,int swap);
+
+
+static void
+rfbInitColourMapSingleTable24(char **table, rfbPixelFormat *in,
+ rfbPixelFormat *out,rfbColourMap* colourMap)
+{
+ CARD32 i, r, g, b, outValue;
+ CARD8 *t;
+ CARD8 c;
+ unsigned int nEntries = 1 << in->bitsPerPixel;
+ int shift = colourMap->is16?16:8;
+
+ if (*table) free(*table);
+ *table = (char *)malloc(nEntries * 3 + 1);
+ t = (CARD8 *)*table;
+
+ for (i = 0; i < nEntries; i++) {
+ r = g = b = 0;
+ if(i < colourMap->count) {
+ if(colourMap->is16) {
+ r = colourMap->data.shorts[3*i+0];
+ g = colourMap->data.shorts[3*i+1];
+ b = colourMap->data.shorts[3*i+2];
+ } else {
+ r = colourMap->data.bytes[3*i+0];
+ g = colourMap->data.bytes[3*i+1];
+ b = colourMap->data.bytes[3*i+2];
+ }
+ }
+ outValue = ((((r * (1 + out->redMax)) >> shift) << out->redShift) |
+ (((g * (1 + out->greenMax)) >> shift) << out->greenShift) |
+ (((b * (1 + out->blueMax)) >> shift) << out->blueShift));
+ *(CARD32*)&t[3*i] = outValue;
+ if(!rfbEndianTest)
+ memmove(t+3*i,t+3*i+1,3);
+ if (out->bigEndian != in->bigEndian) {
+ c = t[3*i]; t[3*i] = t[3*i+2]; t[3*i+2] = c;
+ }
+ }
+}
+
+/*
+ * rfbInitTrueColourSingleTable sets up a single lookup table for truecolour
+ * translation.
+ */
+
+static void
+rfbInitTrueColourSingleTable24 (char **table, rfbPixelFormat *in,
+ rfbPixelFormat *out)
+{
+ int i,outValue;
+ int inRed, inGreen, inBlue, outRed, outGreen, outBlue;
+ CARD8 *t;
+ CARD8 c;
+ int nEntries = 1 << in->bitsPerPixel;
+
+ if (*table) free(*table);
+ *table = (char *)malloc(nEntries * 3 + 1);
+ t = (CARD8 *)*table;
+
+ for (i = 0; i < nEntries; i++) {
+ inRed = (i >> in->redShift) & in->redMax;
+ inGreen = (i >> in->greenShift) & in->greenMax;
+ inBlue = (i >> in->blueShift) & in->blueMax;
+
+ outRed = (inRed * out->redMax + in->redMax / 2) / in->redMax;
+ outGreen = (inGreen * out->greenMax + in->greenMax / 2) / in->greenMax;
+ outBlue = (inBlue * out->blueMax + in->blueMax / 2) / in->blueMax;
+
+ outValue = ((outRed << out->redShift) |
+ (outGreen << out->greenShift) |
+ (outBlue << out->blueShift));
+ *(CARD32*)&t[3*i] = outValue;
+ if(!rfbEndianTest)
+ memmove(t+3*i,t+3*i+1,3);
+ if (out->bigEndian != in->bigEndian) {
+ c = t[3*i]; t[3*i] = t[3*i+2]; t[3*i+2] = c;
+ }
+ }
+}
+
+
+/*
+ * rfbInitTrueColourRGBTables sets up three separate lookup tables for the
+ * red, green and blue values.
+ */
+
+static void
+rfbInitTrueColourRGBTables24 (char **table, rfbPixelFormat *in,
+ rfbPixelFormat *out)
+{
+ CARD8 *redTable;
+ CARD8 *greenTable;
+ CARD8 *blueTable;
+
+ if (*table) free(*table);
+ *table = (char *)malloc((in->redMax + in->greenMax + in->blueMax + 3)
+ * 3 + 1);
+ redTable = (CARD8 *)*table;
+ greenTable = redTable + 3*(in->redMax + 1);
+ blueTable = greenTable + 3*(in->greenMax + 1);
+
+ rfbInitOneRGBTable24 (redTable, in->redMax, out->redMax,
+ out->redShift, (out->bigEndian != in->bigEndian));
+ rfbInitOneRGBTable24 (greenTable, in->greenMax, out->greenMax,
+ out->greenShift, (out->bigEndian != in->bigEndian));
+ rfbInitOneRGBTable24 (blueTable, in->blueMax, out->blueMax,
+ out->blueShift, (out->bigEndian != in->bigEndian));
+}
+
+static void
+rfbInitOneRGBTable24 (CARD8 *table, int inMax, int outMax, int outShift,
+ int swap)
+{
+ int i;
+ int nEntries = inMax + 1;
+ CARD32 outValue;
+ CARD8 c;
+
+ for (i = 0; i < nEntries; i++) {
+ outValue = ((i * outMax + inMax / 2) / inMax) << outShift;
+ *(CARD32 *)&table[3*i] = outValue;
+ if(!rfbEndianTest)
+ memmove(table+3*i,table+3*i+1,3);
+ if (swap) {
+ c = table[3*i]; table[3*i] = table[3*i+2];
+ table[3*i+2] = c;
+ }
+ }
+}
diff --git a/krfb/libvncserver/tableinitcmtemplate.c b/krfb/libvncserver/tableinitcmtemplate.c
new file mode 100644
index 00000000..2d10ea57
--- /dev/null
+++ b/krfb/libvncserver/tableinitcmtemplate.c
@@ -0,0 +1,84 @@
+/*
+ * tableinitcmtemplate.c - template for initialising lookup tables for
+ * translation from a colour map to true colour.
+ *
+ * This file shouldn't be compiled. It is included multiple times by
+ * translate.c, each time with a different definition of the macro OUT.
+ * For each value of OUT, this file defines a function which allocates an
+ * appropriately sized lookup table and initialises it.
+ *
+ * I know this code isn't nice to read because of all the macros, but
+ * efficiency is important here.
+ */
+
+/*
+ * OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
+ * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
+ * All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#if !defined(OUT)
+#error "This file shouldn't be compiled."
+#error "It is included as part of translate.c"
+#endif
+
+#define OUT_T CONCAT2E(CARD,OUT)
+#define SwapOUT(x) CONCAT2E(Swap,OUT(x))
+#define rfbInitColourMapSingleTableOUT \
+ CONCAT2E(rfbInitColourMapSingleTable,OUT)
+
+static void
+rfbInitColourMapSingleTableOUT(char **table, rfbPixelFormat *in,
+ rfbPixelFormat *out,rfbColourMap* colourMap)
+{
+ CARD32 i, r, g, b;
+ OUT_T *t;
+ CARD32 nEntries = 1 << in->bitsPerPixel;
+ int shift = colourMap->is16?16:8;
+
+ if (*table) free(*table);
+ *table = (char *)malloc(nEntries * sizeof(OUT_T));
+ t = (OUT_T *)*table;
+
+ for (i = 0; i < nEntries; i++) {
+ r = g = b = 0;
+ if(i < colourMap->count) {
+ if(colourMap->is16) {
+ r = colourMap->data.shorts[3*i+0];
+ g = colourMap->data.shorts[3*i+1];
+ b = colourMap->data.shorts[3*i+2];
+ } else {
+ r = colourMap->data.bytes[3*i+0];
+ g = colourMap->data.bytes[3*i+1];
+ b = colourMap->data.bytes[3*i+2];
+ }
+ }
+ t[i] = ((((r * (1 + out->redMax)) >> shift) << out->redShift) |
+ (((g * (1 + out->greenMax)) >> shift) << out->greenShift) |
+ (((b * (1 + out->blueMax)) >> shift) << out->blueShift));
+#if (OUT != 8)
+ if (out->bigEndian != in->bigEndian) {
+ t[i] = SwapOUT(t[i]);
+ }
+#endif
+ }
+}
+
+#undef OUT_T
+#undef SwapOUT
+#undef rfbInitColourMapSingleTableOUT
diff --git a/krfb/libvncserver/tableinittctemplate.c b/krfb/libvncserver/tableinittctemplate.c
new file mode 100644
index 00000000..93223d97
--- /dev/null
+++ b/krfb/libvncserver/tableinittctemplate.c
@@ -0,0 +1,142 @@
+/*
+ * tableinittctemplate.c - template for initialising lookup tables for
+ * truecolour to truecolour translation.
+ *
+ * This file shouldn't be compiled. It is included multiple times by
+ * translate.c, each time with a different definition of the macro OUT.
+ * For each value of OUT, this file defines two functions for initialising
+ * lookup tables. One is for truecolour translation using a single lookup
+ * table, the other is for truecolour translation using three separate
+ * lookup tables for the red, green and blue values.
+ *
+ * I know this code isn't nice to read because of all the macros, but
+ * efficiency is important here.
+ */
+
+/*
+ * OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
+ * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
+ * All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#if !defined(OUT)
+#error "This file shouldn't be compiled."
+#error "It is included as part of translate.c"
+#endif
+
+#define OUT_T CONCAT2E(CARD,OUT)
+#define SwapOUT(x) CONCAT2E(Swap,OUT(x))
+#define rfbInitTrueColourSingleTableOUT \
+ CONCAT2E(rfbInitTrueColourSingleTable,OUT)
+#define rfbInitTrueColourRGBTablesOUT CONCAT2E(rfbInitTrueColourRGBTables,OUT)
+#define rfbInitOneRGBTableOUT CONCAT2E(rfbInitOneRGBTable,OUT)
+
+static void
+rfbInitOneRGBTableOUT (OUT_T *table, int inMax, int outMax, int outShift,
+ int swap);
+
+
+/*
+ * rfbInitTrueColourSingleTable sets up a single lookup table for truecolour
+ * translation.
+ */
+
+static void
+rfbInitTrueColourSingleTableOUT (char **table, rfbPixelFormat *in,
+ rfbPixelFormat *out)
+{
+ int i;
+ int inRed, inGreen, inBlue, outRed, outGreen, outBlue;
+ OUT_T *t;
+ int nEntries = 1 << in->bitsPerPixel;
+
+ if (*table) free(*table);
+ *table = (char *)malloc(nEntries * sizeof(OUT_T));
+ t = (OUT_T *)*table;
+
+ for (i = 0; i < nEntries; i++) {
+ inRed = (i >> in->redShift) & in->redMax;
+ inGreen = (i >> in->greenShift) & in->greenMax;
+ inBlue = (i >> in->blueShift) & in->blueMax;
+
+ outRed = (inRed * out->redMax + in->redMax / 2) / in->redMax;
+ outGreen = (inGreen * out->greenMax + in->greenMax / 2) / in->greenMax;
+ outBlue = (inBlue * out->blueMax + in->blueMax / 2) / in->blueMax;
+
+ t[i] = ((outRed << out->redShift) |
+ (outGreen << out->greenShift) |
+ (outBlue << out->blueShift));
+#if (OUT != 8)
+ if (out->bigEndian != in->bigEndian) {
+ t[i] = SwapOUT(t[i]);
+ }
+#endif
+ }
+}
+
+
+/*
+ * rfbInitTrueColourRGBTables sets up three separate lookup tables for the
+ * red, green and blue values.
+ */
+
+static void
+rfbInitTrueColourRGBTablesOUT (char **table, rfbPixelFormat *in,
+ rfbPixelFormat *out)
+{
+ OUT_T *redTable;
+ OUT_T *greenTable;
+ OUT_T *blueTable;
+
+ if (*table) free(*table);
+ *table = (char *)malloc((in->redMax + in->greenMax + in->blueMax + 3)
+ * sizeof(OUT_T));
+ redTable = (OUT_T *)*table;
+ greenTable = redTable + in->redMax + 1;
+ blueTable = greenTable + in->greenMax + 1;
+
+ rfbInitOneRGBTableOUT (redTable, in->redMax, out->redMax,
+ out->redShift, (out->bigEndian != in->bigEndian));
+ rfbInitOneRGBTableOUT (greenTable, in->greenMax, out->greenMax,
+ out->greenShift, (out->bigEndian != in->bigEndian));
+ rfbInitOneRGBTableOUT (blueTable, in->blueMax, out->blueMax,
+ out->blueShift, (out->bigEndian != in->bigEndian));
+}
+
+static void
+rfbInitOneRGBTableOUT (OUT_T *table, int inMax, int outMax, int outShift,
+ int swap)
+{
+ int i;
+ int nEntries = inMax + 1;
+
+ for (i = 0; i < nEntries; i++) {
+ table[i] = ((i * outMax + inMax / 2) / inMax) << outShift;
+#if (OUT != 8)
+ if (swap) {
+ table[i] = SwapOUT(table[i]);
+ }
+#endif
+ }
+}
+
+#undef OUT_T
+#undef SwapOUT
+#undef rfbInitTrueColourSingleTableOUT
+#undef rfbInitTrueColourRGBTablesOUT
+#undef rfbInitOneRGBTableOUT
diff --git a/krfb/libvncserver/tabletrans24template.c b/krfb/libvncserver/tabletrans24template.c
new file mode 100644
index 00000000..44a37cb7
--- /dev/null
+++ b/krfb/libvncserver/tabletrans24template.c
@@ -0,0 +1,281 @@
+/*
+ * tabletranstemplate.c - template for translation using lookup tables.
+ *
+ * This file shouldn't be compiled. It is included multiple times by
+ * translate.c, each time with different definitions of the macros IN and OUT.
+ *
+ * For each pair of values IN and OUT, this file defines two functions for
+ * translating a given rectangle of pixel data. One uses a single lookup
+ * table, and the other uses three separate lookup tables for the red, green
+ * and blue values.
+ *
+ * I know this code isn't nice to read because of all the macros, but
+ * efficiency is important here.
+ */
+
+/*
+ * OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
+ * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
+ * All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#if !defined(BPP)
+#error "This file shouldn't be compiled."
+#error "It is included as part of translate.c"
+#endif
+
+#if BPP == 24
+
+/*
+ * rfbTranslateWithSingleTableINtoOUT translates a rectangle of pixel data
+ * using a single lookup table.
+ */
+
+static void
+rfbTranslateWithSingleTable24to24 (char *table, rfbPixelFormat *in,
+ rfbPixelFormat *out,
+ char *iptr, char *optr,
+ int bytesBetweenInputLines,
+ int width, int height)
+{
+ CARD8 *ip = (CARD8 *)iptr;
+ CARD8 *op = (CARD8 *)optr;
+ int ipextra = bytesBetweenInputLines - width * 3;
+ CARD8 *opLineEnd;
+ CARD8 *t = (CARD8 *)table;
+ int shift = rfbEndianTest?0:8;
+ CARD8 c;
+
+ while (height > 0) {
+ opLineEnd = op + width*3;
+
+ while (op < opLineEnd) {
+ *(CARD32*)op = t[((*(CARD32 *)ip)>>shift)&0x00ffffff];
+ if(!rfbEndianTest)
+ memmove(op,op+1,3);
+ if (out->bigEndian != in->bigEndian) {
+ c = op[0]; op[0] = op[2]; op[2] = c;
+ }
+ op += 3;
+ ip += 3;
+ }
+
+ ip += ipextra;
+ height--;
+ }
+}
+
+/*
+ * rfbTranslateWithRGBTablesINtoOUT translates a rectangle of pixel data
+ * using three separate lookup tables for the red, green and blue values.
+ */
+
+static void
+rfbTranslateWithRGBTables24to24 (char *table, rfbPixelFormat *in,
+ rfbPixelFormat *out,
+ char *iptr, char *optr,
+ int bytesBetweenInputLines,
+ int width, int height)
+{
+ CARD8 *ip = (CARD8 *)iptr;
+ CARD8 *op = (CARD8 *)optr;
+ int ipextra = bytesBetweenInputLines - width*3;
+ CARD8 *opLineEnd;
+ CARD8 *redTable = (CARD8 *)table;
+ CARD8 *greenTable = redTable + 3*(in->redMax + 1);
+ CARD8 *blueTable = greenTable + 3*(in->greenMax + 1);
+ CARD32 outValue,inValue;
+ int shift = rfbEndianTest?0:8;
+
+ while (height > 0) {
+ opLineEnd = op+3*width;
+
+ while (op < opLineEnd) {
+ inValue = ((*(CARD32 *)ip)>>shift)&0x00ffffff;
+ outValue = (redTable[(inValue >> in->redShift) & in->redMax] |
+ greenTable[(inValue >> in->greenShift) & in->greenMax] |
+ blueTable[(inValue >> in->blueShift) & in->blueMax]);
+ memcpy(op,&outValue,3);
+ op += 3;
+ ip+=3;
+ }
+ ip += ipextra;
+ height--;
+ }
+}
+
+#else
+
+#define IN_T CONCAT2E(CARD,BPP)
+#define OUT_T CONCAT2E(CARD,BPP)
+#define rfbTranslateWithSingleTable24toOUT \
+ CONCAT4E(rfbTranslateWithSingleTable,24,to,BPP)
+#define rfbTranslateWithSingleTableINto24 \
+ CONCAT4E(rfbTranslateWithSingleTable,BPP,to,24)
+#define rfbTranslateWithRGBTables24toOUT \
+ CONCAT4E(rfbTranslateWithRGBTables,24,to,BPP)
+#define rfbTranslateWithRGBTablesINto24 \
+ CONCAT4E(rfbTranslateWithRGBTables,BPP,to,24)
+
+/*
+ * rfbTranslateWithSingleTableINtoOUT translates a rectangle of pixel data
+ * using a single lookup table.
+ */
+
+static void
+rfbTranslateWithSingleTable24toOUT (char *table, rfbPixelFormat *in,
+ rfbPixelFormat *out,
+ char *iptr, char *optr,
+ int bytesBetweenInputLines,
+ int width, int height)
+{
+ CARD8 *ip = (CARD8 *)iptr;
+ OUT_T *op = (OUT_T *)optr;
+ int ipextra = bytesBetweenInputLines - width*3;
+ OUT_T *opLineEnd;
+ OUT_T *t = (OUT_T *)table;
+ int shift = rfbEndianTest?0:8;
+
+ while (height > 0) {
+ opLineEnd = op + width;
+
+ while (op < opLineEnd) {
+ *(op++) = t[((*(CARD32 *)ip)>>shift)&0x00ffffff];
+ ip+=3;
+ }
+
+ ip += ipextra;
+ height--;
+ }
+}
+
+
+/*
+ * rfbTranslateWithRGBTablesINtoOUT translates a rectangle of pixel data
+ * using three separate lookup tables for the red, green and blue values.
+ */
+
+static void
+rfbTranslateWithRGBTables24toOUT (char *table, rfbPixelFormat *in,
+ rfbPixelFormat *out,
+ char *iptr, char *optr,
+ int bytesBetweenInputLines,
+ int width, int height)
+{
+ CARD8 *ip = (CARD8 *)iptr;
+ OUT_T *op = (OUT_T *)optr;
+ int ipextra = bytesBetweenInputLines - width*3;
+ OUT_T *opLineEnd;
+ OUT_T *redTable = (OUT_T *)table;
+ OUT_T *greenTable = redTable + in->redMax + 1;
+ OUT_T *blueTable = greenTable + in->greenMax + 1;
+ CARD32 inValue;
+ int shift = rfbEndianTest?0:8;
+
+ while (height > 0) {
+ opLineEnd = &op[width];
+
+ while (op < opLineEnd) {
+ inValue = ((*(CARD32 *)ip)>>shift)&0x00ffffff;
+ *(op++) = (redTable[(inValue >> in->redShift) & in->redMax] |
+ greenTable[(inValue >> in->greenShift) & in->greenMax] |
+ blueTable[(inValue >> in->blueShift) & in->blueMax]);
+ ip+=3;
+ }
+ ip += ipextra;
+ height--;
+ }
+}
+
+/*
+ * rfbTranslateWithSingleTableINto24 translates a rectangle of pixel data
+ * using a single lookup table.
+ */
+
+static void
+rfbTranslateWithSingleTableINto24 (char *table, rfbPixelFormat *in,
+ rfbPixelFormat *out,
+ char *iptr, char *optr,
+ int bytesBetweenInputLines,
+ int width, int height)
+{
+ IN_T *ip = (IN_T *)iptr;
+ CARD8 *op = (CARD8 *)optr;
+ int ipextra = bytesBetweenInputLines / sizeof(IN_T) - width;
+ CARD8 *opLineEnd;
+ CARD8 *t = (CARD8 *)table;
+
+ while (height > 0) {
+ opLineEnd = op + width * 3;
+
+ while (op < opLineEnd) {
+ memcpy(op,&t[3*(*(ip++))],3);
+ op += 3;
+ }
+
+ ip += ipextra;
+ height--;
+ }
+}
+
+
+/*
+ * rfbTranslateWithRGBTablesINto24 translates a rectangle of pixel data
+ * using three separate lookup tables for the red, green and blue values.
+ */
+
+static void
+rfbTranslateWithRGBTablesINto24 (char *table, rfbPixelFormat *in,
+ rfbPixelFormat *out,
+ char *iptr, char *optr,
+ int bytesBetweenInputLines,
+ int width, int height)
+{
+ IN_T *ip = (IN_T *)iptr;
+ CARD8 *op = (CARD8 *)optr;
+ int ipextra = bytesBetweenInputLines / sizeof(IN_T) - width;
+ CARD8 *opLineEnd;
+ CARD8 *redTable = (CARD8 *)table;
+ CARD8 *greenTable = redTable + 3*(in->redMax + 1);
+ CARD8 *blueTable = greenTable + 3*(in->greenMax + 1);
+ CARD32 outValue;
+
+ while (height > 0) {
+ opLineEnd = op+3*width;
+
+ while (op < opLineEnd) {
+ outValue = (redTable[(*ip >> in->redShift) & in->redMax] |
+ greenTable[(*ip >> in->greenShift) & in->greenMax] |
+ blueTable[(*ip >> in->blueShift) & in->blueMax]);
+ memcpy(op,&outValue,3);
+ op += 3;
+ ip++;
+ }
+ ip += ipextra;
+ height--;
+ }
+}
+
+#undef IN_T
+#undef OUT_T
+#undef rfbTranslateWithSingleTable24toOUT
+#undef rfbTranslateWithRGBTables24toOUT
+#undef rfbTranslateWithSingleTableINto24
+#undef rfbTranslateWithRGBTablesINto24
+
+#endif
diff --git a/krfb/libvncserver/tabletranstemplate.c b/krfb/libvncserver/tabletranstemplate.c
new file mode 100644
index 00000000..0aafff0f
--- /dev/null
+++ b/krfb/libvncserver/tabletranstemplate.c
@@ -0,0 +1,117 @@
+/*
+ * tabletranstemplate.c - template for translation using lookup tables.
+ *
+ * This file shouldn't be compiled. It is included multiple times by
+ * translate.c, each time with different definitions of the macros IN and OUT.
+ *
+ * For each pair of values IN and OUT, this file defines two functions for
+ * translating a given rectangle of pixel data. One uses a single lookup
+ * table, and the other uses three separate lookup tables for the red, green
+ * and blue values.
+ *
+ * I know this code isn't nice to read because of all the macros, but
+ * efficiency is important here.
+ */
+
+/*
+ * OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
+ * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
+ * All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#if !defined(IN) || !defined(OUT)
+#error "This file shouldn't be compiled."
+#error "It is included as part of translate.c"
+#endif
+
+#define IN_T CONCAT2E(CARD,IN)
+#define OUT_T CONCAT2E(CARD,OUT)
+#define rfbTranslateWithSingleTableINtoOUT \
+ CONCAT4E(rfbTranslateWithSingleTable,IN,to,OUT)
+#define rfbTranslateWithRGBTablesINtoOUT \
+ CONCAT4E(rfbTranslateWithRGBTables,IN,to,OUT)
+
+/*
+ * rfbTranslateWithSingleTableINtoOUT translates a rectangle of pixel data
+ * using a single lookup table.
+ */
+
+static void
+rfbTranslateWithSingleTableINtoOUT (char *table, rfbPixelFormat *in,
+ rfbPixelFormat *out,
+ char *iptr, char *optr,
+ int bytesBetweenInputLines,
+ int width, int height)
+{
+ IN_T *ip = (IN_T *)iptr;
+ OUT_T *op = (OUT_T *)optr;
+ int ipextra = bytesBetweenInputLines / sizeof(IN_T) - width;
+ OUT_T *opLineEnd;
+ OUT_T *t = (OUT_T *)table;
+
+ while (height > 0) {
+ opLineEnd = op + width;
+
+ while (op < opLineEnd) {
+ *(op++) = t[*(ip++)];
+ }
+
+ ip += ipextra;
+ height--;
+ }
+}
+
+
+/*
+ * rfbTranslateWithRGBTablesINtoOUT translates a rectangle of pixel data
+ * using three separate lookup tables for the red, green and blue values.
+ */
+
+static void
+rfbTranslateWithRGBTablesINtoOUT (char *table, rfbPixelFormat *in,
+ rfbPixelFormat *out,
+ char *iptr, char *optr,
+ int bytesBetweenInputLines,
+ int width, int height)
+{
+ IN_T *ip = (IN_T *)iptr;
+ OUT_T *op = (OUT_T *)optr;
+ int ipextra = bytesBetweenInputLines / sizeof(IN_T) - width;
+ OUT_T *opLineEnd;
+ OUT_T *redTable = (OUT_T *)table;
+ OUT_T *greenTable = redTable + in->redMax + 1;
+ OUT_T *blueTable = greenTable + in->greenMax + 1;
+
+ while (height > 0) {
+ opLineEnd = &op[width];
+
+ while (op < opLineEnd) {
+ *(op++) = (redTable[(*ip >> in->redShift) & in->redMax] |
+ greenTable[(*ip >> in->greenShift) & in->greenMax] |
+ blueTable[(*ip >> in->blueShift) & in->blueMax]);
+ ip++;
+ }
+ ip += ipextra;
+ height--;
+ }
+}
+
+#undef IN_T
+#undef OUT_T
+#undef rfbTranslateWithSingleTableINtoOUT
+#undef rfbTranslateWithRGBTablesINtoOUT
diff --git a/krfb/libvncserver/tight.c b/krfb/libvncserver/tight.c
new file mode 100644
index 00000000..8b57f82a
--- /dev/null
+++ b/krfb/libvncserver/tight.c
@@ -0,0 +1,1809 @@
+/*
+ * tight.c
+ *
+ * Routines to implement Tight Encoding
+ */
+
+/*
+ * Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved.
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+/*#include <stdio.h>*/
+#include "rfb.h"
+
+#ifdef WIN32
+#define XMD_H
+#undef FAR
+#define NEEDFAR_POINTERS
+#endif
+
+#include <jpeglib.h>
+
+/* Note: The following constant should not be changed. */
+#define TIGHT_MIN_TO_COMPRESS 12
+
+/* The parameters below may be adjusted. */
+#define MIN_SPLIT_RECT_SIZE 4096
+#define MIN_SOLID_SUBRECT_SIZE 2048
+#define MAX_SPLIT_TILE_SIZE 16
+
+/* May be set to TRUE with "-lazytight" Xvnc option. */
+Bool rfbTightDisableGradient = FALSE;
+
+/* This variable is set on every rfbSendRectEncodingTight() call. */
+static Bool usePixelFormat24;
+
+
+/* Compression level stuff. The following array contains various
+ encoder parameters for each of 10 compression levels (0..9).
+ Last three parameters correspond to JPEG quality levels (0..9). */
+
+typedef struct TIGHT_CONF_s {
+ int maxRectSize, maxRectWidth;
+ int monoMinRectSize, gradientMinRectSize;
+ int idxZlibLevel, monoZlibLevel, rawZlibLevel, gradientZlibLevel;
+ int gradientThreshold, gradientThreshold24;
+ int idxMaxColorsDivisor;
+ int jpegQuality, jpegThreshold, jpegThreshold24;
+} TIGHT_CONF;
+
+static TIGHT_CONF tightConf[10] = {
+ { 512, 32, 6, 65536, 0, 0, 0, 0, 0, 0, 4, 20, 10000, 23000 },
+ { 2048, 128, 6, 65536, 1, 1, 1, 0, 0, 0, 8, 30, 8000, 18000 },
+ { 6144, 256, 8, 65536, 3, 3, 2, 0, 0, 0, 24, 40, 6500, 15000 },
+ { 10240, 1024, 12, 65536, 5, 5, 3, 0, 0, 0, 32, 50, 5000, 12000 },
+ { 16384, 2048, 12, 65536, 6, 6, 4, 0, 0, 0, 32, 55, 4000, 10000 },
+ { 32768, 2048, 12, 4096, 7, 7, 5, 4, 150, 380, 32, 60, 3000, 8000 },
+ { 65536, 2048, 16, 4096, 7, 7, 6, 4, 170, 420, 48, 65, 2000, 5000 },
+ { 65536, 2048, 16, 4096, 8, 8, 7, 5, 180, 450, 64, 70, 1000, 2500 },
+ { 65536, 2048, 32, 8192, 9, 9, 8, 6, 190, 475, 64, 75, 500, 1200 },
+ { 65536, 2048, 32, 8192, 9, 9, 9, 6, 200, 500, 96, 80, 200, 500 }
+};
+
+static int compressLevel;
+static int qualityLevel;
+
+/* Stuff dealing with palettes. */
+
+typedef struct COLOR_LIST_s {
+ struct COLOR_LIST_s *next;
+ int idx;
+ CARD32 rgb;
+} COLOR_LIST;
+
+typedef struct PALETTE_ENTRY_s {
+ COLOR_LIST *listNode;
+ int numPixels;
+} PALETTE_ENTRY;
+
+typedef struct PALETTE_s {
+ PALETTE_ENTRY entry[256];
+ COLOR_LIST *hash[256];
+ COLOR_LIST list[256];
+} PALETTE;
+
+static int paletteNumColors, paletteMaxColors;
+static CARD32 monoBackground, monoForeground;
+static PALETTE palette;
+
+/* Pointers to dynamically-allocated buffers. */
+
+static int tightBeforeBufSize = 0;
+static char *tightBeforeBuf = NULL;
+
+static int tightAfterBufSize = 0;
+static char *tightAfterBuf = NULL;
+
+static int *prevRowBuf = NULL;
+
+
+/* Prototypes for static functions. */
+
+static void FindBestSolidArea (rfbClientPtr cl, int x, int y, int w, int h,
+ CARD32 colorValue, int *w_ptr, int *h_ptr);
+static void ExtendSolidArea (rfbClientPtr cl, int x, int y, int w, int h,
+ CARD32 colorValue,
+ int *x_ptr, int *y_ptr, int *w_ptr, int *h_ptr);
+static Bool CheckSolidTile (rfbClientPtr cl, int x, int y, int w, int h,
+ CARD32 *colorPtr, Bool needSameColor);
+static Bool CheckSolidTile8 (rfbClientPtr cl, int x, int y, int w, int h,
+ CARD32 *colorPtr, Bool needSameColor);
+static Bool CheckSolidTile16 (rfbClientPtr cl, int x, int y, int w, int h,
+ CARD32 *colorPtr, Bool needSameColor);
+static Bool CheckSolidTile32 (rfbClientPtr cl, int x, int y, int w, int h,
+ CARD32 *colorPtr, Bool needSameColor);
+
+static Bool SendRectSimple (rfbClientPtr cl, int x, int y, int w, int h);
+static Bool SendSubrect (rfbClientPtr cl, int x, int y, int w, int h);
+static Bool SendTightHeader (rfbClientPtr cl, int x, int y, int w, int h);
+
+static Bool SendSolidRect (rfbClientPtr cl);
+static Bool SendMonoRect (rfbClientPtr cl, int w, int h);
+static Bool SendIndexedRect (rfbClientPtr cl, int w, int h);
+static Bool SendFullColorRect (rfbClientPtr cl, int w, int h);
+static Bool SendGradientRect (rfbClientPtr cl, int w, int h);
+
+static Bool CompressData(rfbClientPtr cl, int streamId, int dataLen,
+ int zlibLevel, int zlibStrategy);
+static Bool SendCompressedData(rfbClientPtr cl, int compressedLen);
+
+static void FillPalette8(int count);
+static void FillPalette16(int count);
+static void FillPalette32(int count);
+
+static void PaletteReset(void);
+static int PaletteInsert(CARD32 rgb, int numPixels, int bpp);
+
+static void Pack24(rfbClientPtr cl, char *buf, rfbPixelFormat *fmt, int count);
+
+static void EncodeIndexedRect16(CARD8 *buf, int count);
+static void EncodeIndexedRect32(CARD8 *buf, int count);
+
+static void EncodeMonoRect8(CARD8 *buf, int w, int h);
+static void EncodeMonoRect16(CARD8 *buf, int w, int h);
+static void EncodeMonoRect32(CARD8 *buf, int w, int h);
+
+static void FilterGradient24(rfbClientPtr cl, char *buf, rfbPixelFormat *fmt, int w, int h);
+static void FilterGradient16(rfbClientPtr cl, CARD16 *buf, rfbPixelFormat *fmt, int w, int h);
+static void FilterGradient32(rfbClientPtr cl, CARD32 *buf, rfbPixelFormat *fmt, int w, int h);
+
+static int DetectSmoothImage(rfbClientPtr cl, rfbPixelFormat *fmt, int w, int h);
+static unsigned long DetectSmoothImage24(rfbClientPtr cl, rfbPixelFormat *fmt, int w, int h);
+static unsigned long DetectSmoothImage16(rfbClientPtr cl, rfbPixelFormat *fmt, int w, int h);
+static unsigned long DetectSmoothImage32(rfbClientPtr cl, rfbPixelFormat *fmt, int w, int h);
+
+static Bool SendJpegRect(rfbClientPtr cl, int x, int y, int w, int h,
+ int quality);
+static void PrepareRowForJpeg(rfbClientPtr cl, CARD8 *dst, int x, int y, int count);
+static void PrepareRowForJpeg24(rfbClientPtr cl, CARD8 *dst, int x, int y, int count);
+static void PrepareRowForJpeg16(rfbClientPtr cl, CARD8 *dst, int x, int y, int count);
+static void PrepareRowForJpeg32(rfbClientPtr cl, CARD8 *dst, int x, int y, int count);
+
+static void JpegInitDestination(j_compress_ptr cinfo);
+static boolean JpegEmptyOutputBuffer(j_compress_ptr cinfo);
+static void JpegTermDestination(j_compress_ptr cinfo);
+static void JpegSetDstManager(j_compress_ptr cinfo);
+
+
+/*
+ * Tight encoding implementation.
+ */
+
+int
+rfbNumCodedRectsTight(cl, x, y, w, h)
+ rfbClientPtr cl;
+ int x, y, w, h;
+{
+ int maxRectSize, maxRectWidth;
+ int subrectMaxWidth, subrectMaxHeight;
+
+ /* No matter how many rectangles we will send if LastRect markers
+ are used to terminate rectangle stream. */
+ if (cl->enableLastRectEncoding && w * h >= MIN_SPLIT_RECT_SIZE)
+ return 0;
+
+ maxRectSize = tightConf[cl->tightCompressLevel].maxRectSize;
+ maxRectWidth = tightConf[cl->tightCompressLevel].maxRectWidth;
+
+ if (w > maxRectWidth || w * h > maxRectSize) {
+ subrectMaxWidth = (w > maxRectWidth) ? maxRectWidth : w;
+ subrectMaxHeight = maxRectSize / subrectMaxWidth;
+ return (((w - 1) / maxRectWidth + 1) *
+ ((h - 1) / subrectMaxHeight + 1));
+ } else {
+ return 1;
+ }
+}
+
+Bool
+rfbSendRectEncodingTight(cl, x, y, w, h)
+ rfbClientPtr cl;
+ int x, y, w, h;
+{
+ int nMaxRows;
+ CARD32 colorValue;
+ int dx, dy, dw, dh;
+ int x_best, y_best, w_best, h_best;
+ char *fbptr;
+
+ compressLevel = cl->tightCompressLevel;
+ qualityLevel = cl->tightQualityLevel;
+
+ if ( cl->format.depth == 24 && cl->format.redMax == 0xFF &&
+ cl->format.greenMax == 0xFF && cl->format.blueMax == 0xFF ) {
+ usePixelFormat24 = TRUE;
+ } else {
+ usePixelFormat24 = FALSE;
+ }
+
+ if (!cl->enableLastRectEncoding || w * h < MIN_SPLIT_RECT_SIZE)
+ return SendRectSimple(cl, x, y, w, h);
+
+ /* Make sure we can write at least one pixel into tightBeforeBuf. */
+
+ if (tightBeforeBufSize < 4) {
+ tightBeforeBufSize = 4;
+ if (tightBeforeBuf == NULL)
+ tightBeforeBuf = (char *)malloc(tightBeforeBufSize);
+ else
+ tightBeforeBuf = (char *)realloc(tightBeforeBuf,
+ tightBeforeBufSize);
+ }
+
+ /* Calculate maximum number of rows in one non-solid rectangle. */
+
+ {
+ int maxRectSize, maxRectWidth, nMaxWidth;
+
+ maxRectSize = tightConf[compressLevel].maxRectSize;
+ maxRectWidth = tightConf[compressLevel].maxRectWidth;
+ nMaxWidth = (w > maxRectWidth) ? maxRectWidth : w;
+ nMaxRows = maxRectSize / nMaxWidth;
+ }
+
+ /* Try to find large solid-color areas and send them separately. */
+
+ for (dy = y; dy < y + h; dy += MAX_SPLIT_TILE_SIZE) {
+
+ /* If a rectangle becomes too large, send its upper part now. */
+
+ if (dy - y >= nMaxRows) {
+ if (!SendRectSimple(cl, x, y, w, nMaxRows))
+ return 0;
+ y += nMaxRows;
+ h -= nMaxRows;
+ }
+
+ dh = (dy + MAX_SPLIT_TILE_SIZE <= y + h) ?
+ MAX_SPLIT_TILE_SIZE : (y + h - dy);
+
+ for (dx = x; dx < x + w; dx += MAX_SPLIT_TILE_SIZE) {
+
+ dw = (dx + MAX_SPLIT_TILE_SIZE <= x + w) ?
+ MAX_SPLIT_TILE_SIZE : (x + w - dx);
+
+ if (CheckSolidTile(cl, dx, dy, dw, dh, &colorValue, FALSE)) {
+
+ /* Get dimensions of solid-color area. */
+
+ FindBestSolidArea(cl, dx, dy, w - (dx - x), h - (dy - y),
+ colorValue, &w_best, &h_best);
+
+ /* Make sure a solid rectangle is large enough
+ (or the whole rectangle is of the same color). */
+
+ if ( w_best * h_best != w * h &&
+ w_best * h_best < MIN_SOLID_SUBRECT_SIZE )
+ continue;
+
+ /* Try to extend solid rectangle to maximum size. */
+
+ x_best = dx; y_best = dy;
+ ExtendSolidArea(cl, x, y, w, h, colorValue,
+ &x_best, &y_best, &w_best, &h_best);
+
+ /* Send rectangles at top and left to solid-color area. */
+
+ if ( y_best != y &&
+ !SendRectSimple(cl, x, y, w, y_best-y) )
+ return FALSE;
+ if ( x_best != x &&
+ !rfbSendRectEncodingTight(cl, x, y_best,
+ x_best-x, h_best) )
+ return FALSE;
+
+ /* Send solid-color rectangle. */
+
+ if (!SendTightHeader(cl, x_best, y_best, w_best, h_best))
+ return FALSE;
+
+ fbptr = (cl->screen->frameBuffer +
+ (cl->screen->paddedWidthInBytes * y_best) +
+ (x_best * (cl->screen->bitsPerPixel / 8)));
+
+ (*cl->translateFn)(cl->translateLookupTable, &cl->screen->rfbServerFormat,
+ &cl->format, fbptr, tightBeforeBuf,
+ cl->screen->paddedWidthInBytes, 1, 1);
+
+ if (!SendSolidRect(cl))
+ return FALSE;
+
+ /* Send remaining rectangles (at right and bottom). */
+
+ if ( x_best + w_best != x + w &&
+ !rfbSendRectEncodingTight(cl, x_best+w_best, y_best,
+ w-(x_best-x)-w_best, h_best) )
+ return FALSE;
+ if ( y_best + h_best != y + h &&
+ !rfbSendRectEncodingTight(cl, x, y_best+h_best,
+ w, h-(y_best-y)-h_best) )
+ return FALSE;
+
+ /* Return after all recursive calls are done. */
+
+ return TRUE;
+ }
+
+ }
+
+ }
+
+ /* No suitable solid-color rectangles found. */
+
+ return SendRectSimple(cl, x, y, w, h);
+}
+
+static void
+FindBestSolidArea(cl, x, y, w, h, colorValue, w_ptr, h_ptr)
+ rfbClientPtr cl;
+ int x, y, w, h;
+ CARD32 colorValue;
+ int *w_ptr, *h_ptr;
+{
+ int dx, dy, dw, dh;
+ int w_prev;
+ int w_best = 0, h_best = 0;
+
+ w_prev = w;
+
+ for (dy = y; dy < y + h; dy += MAX_SPLIT_TILE_SIZE) {
+
+ dh = (dy + MAX_SPLIT_TILE_SIZE <= y + h) ?
+ MAX_SPLIT_TILE_SIZE : (y + h - dy);
+ dw = (w_prev > MAX_SPLIT_TILE_SIZE) ?
+ MAX_SPLIT_TILE_SIZE : w_prev;
+
+ if (!CheckSolidTile(cl, x, dy, dw, dh, &colorValue, TRUE))
+ break;
+
+ for (dx = x + dw; dx < x + w_prev;) {
+ dw = (dx + MAX_SPLIT_TILE_SIZE <= x + w_prev) ?
+ MAX_SPLIT_TILE_SIZE : (x + w_prev - dx);
+ if (!CheckSolidTile(cl, dx, dy, dw, dh, &colorValue, TRUE))
+ break;
+ dx += dw;
+ }
+
+ w_prev = dx - x;
+ if (w_prev * (dy + dh - y) > w_best * h_best) {
+ w_best = w_prev;
+ h_best = dy + dh - y;
+ }
+ }
+
+ *w_ptr = w_best;
+ *h_ptr = h_best;
+}
+
+static void
+ExtendSolidArea(cl, x, y, w, h, colorValue, x_ptr, y_ptr, w_ptr, h_ptr)
+ rfbClientPtr cl;
+ int x, y, w, h;
+ CARD32 colorValue;
+ int *x_ptr, *y_ptr, *w_ptr, *h_ptr;
+{
+ int cx, cy;
+
+ /* Try to extend the area upwards. */
+ for ( cy = *y_ptr - 1;
+ cy >= y && CheckSolidTile(cl, *x_ptr, cy, *w_ptr, 1, &colorValue, TRUE);
+ cy-- );
+ *h_ptr += *y_ptr - (cy + 1);
+ *y_ptr = cy + 1;
+
+ /* ... downwards. */
+ for ( cy = *y_ptr + *h_ptr;
+ cy < y + h &&
+ CheckSolidTile(cl, *x_ptr, cy, *w_ptr, 1, &colorValue, TRUE);
+ cy++ );
+ *h_ptr += cy - (*y_ptr + *h_ptr);
+
+ /* ... to the left. */
+ for ( cx = *x_ptr - 1;
+ cx >= x && CheckSolidTile(cl, cx, *y_ptr, 1, *h_ptr, &colorValue, TRUE);
+ cx-- );
+ *w_ptr += *x_ptr - (cx + 1);
+ *x_ptr = cx + 1;
+
+ /* ... to the right. */
+ for ( cx = *x_ptr + *w_ptr;
+ cx < x + w &&
+ CheckSolidTile(cl, cx, *y_ptr, 1, *h_ptr, &colorValue, TRUE);
+ cx++ );
+ *w_ptr += cx - (*x_ptr + *w_ptr);
+}
+
+static Bool
+CheckSolidTile(cl, x, y, w, h, colorPtr, needSameColor)
+ rfbClientPtr cl;
+ int x, y, w, h;
+ CARD32 *colorPtr;
+ Bool needSameColor;
+{
+ switch(cl->screen->rfbServerFormat.bitsPerPixel) {
+ case 32:
+ return CheckSolidTile32(cl, x, y, w, h, colorPtr, needSameColor);
+ case 16:
+ return CheckSolidTile16(cl, x, y, w, h, colorPtr, needSameColor);
+ default:
+ return CheckSolidTile8(cl, x, y, w, h, colorPtr, needSameColor);
+ }
+}
+
+#define DEFINE_CHECK_SOLID_FUNCTION(bpp) \
+ \
+static Bool \
+CheckSolidTile##bpp(cl, x, y, w, h, colorPtr, needSameColor) \
+ rfbClientPtr cl; \
+ int x, y, w, h; \
+ CARD32 *colorPtr; \
+ Bool needSameColor; \
+{ \
+ CARD##bpp *fbptr; \
+ CARD##bpp colorValue; \
+ int dx, dy; \
+ \
+ fbptr = (CARD##bpp *) \
+ &cl->screen->frameBuffer[y * cl->screen->paddedWidthInBytes + x * (bpp/8)]; \
+ \
+ colorValue = *fbptr; \
+ if (needSameColor && (CARD32)colorValue != *colorPtr) \
+ return FALSE; \
+ \
+ for (dy = 0; dy < h; dy++) { \
+ for (dx = 0; dx < w; dx++) { \
+ if (colorValue != fbptr[dx]) \
+ return FALSE; \
+ } \
+ fbptr = (CARD##bpp *)((CARD8 *)fbptr + cl->screen->paddedWidthInBytes); \
+ } \
+ \
+ *colorPtr = (CARD32)colorValue; \
+ return TRUE; \
+}
+
+DEFINE_CHECK_SOLID_FUNCTION(8)
+DEFINE_CHECK_SOLID_FUNCTION(16)
+DEFINE_CHECK_SOLID_FUNCTION(32)
+
+static Bool
+SendRectSimple(cl, x, y, w, h)
+ rfbClientPtr cl;
+ int x, y, w, h;
+{
+ int maxBeforeSize, maxAfterSize;
+ int maxRectSize, maxRectWidth;
+ int subrectMaxWidth, subrectMaxHeight;
+ int dx, dy;
+ int rw, rh;
+
+ maxRectSize = tightConf[compressLevel].maxRectSize;
+ maxRectWidth = tightConf[compressLevel].maxRectWidth;
+
+ maxBeforeSize = maxRectSize * (cl->format.bitsPerPixel / 8);
+ maxAfterSize = maxBeforeSize + (maxBeforeSize + 99) / 100 + 12;
+
+ if (tightBeforeBufSize < maxBeforeSize) {
+ tightBeforeBufSize = maxBeforeSize;
+ if (tightBeforeBuf == NULL)
+ tightBeforeBuf = (char *)malloc(tightBeforeBufSize);
+ else
+ tightBeforeBuf = (char *)realloc(tightBeforeBuf,
+ tightBeforeBufSize);
+ }
+
+ if (tightAfterBufSize < maxAfterSize) {
+ tightAfterBufSize = maxAfterSize;
+ if (tightAfterBuf == NULL)
+ tightAfterBuf = (char *)malloc(tightAfterBufSize);
+ else
+ tightAfterBuf = (char *)realloc(tightAfterBuf,
+ tightAfterBufSize);
+ }
+
+ if (w > maxRectWidth || w * h > maxRectSize) {
+ subrectMaxWidth = (w > maxRectWidth) ? maxRectWidth : w;
+ subrectMaxHeight = maxRectSize / subrectMaxWidth;
+
+ for (dy = 0; dy < h; dy += subrectMaxHeight) {
+ for (dx = 0; dx < w; dx += maxRectWidth) {
+ rw = (dx + maxRectWidth < w) ? maxRectWidth : w - dx;
+ rh = (dy + subrectMaxHeight < h) ? subrectMaxHeight : h - dy;
+ if (!SendSubrect(cl, x+dx, y+dy, rw, rh))
+ return FALSE;
+ }
+ }
+ } else {
+ if (!SendSubrect(cl, x, y, w, h))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static Bool
+SendSubrect(cl, x, y, w, h)
+ rfbClientPtr cl;
+ int x, y, w, h;
+{
+ char *fbptr;
+ Bool success = FALSE;
+
+ /* Send pending data if there is more than 128 bytes. */
+ if (cl->ublen > 128) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ if (!SendTightHeader(cl, x, y, w, h))
+ return FALSE;
+
+ fbptr = (cl->screen->frameBuffer + (cl->screen->paddedWidthInBytes * y)
+ + (x * (cl->screen->bitsPerPixel / 8)));
+
+ (*cl->translateFn)(cl->translateLookupTable, &cl->screen->rfbServerFormat,
+ &cl->format, fbptr, tightBeforeBuf,
+ cl->screen->paddedWidthInBytes, w, h);
+
+ paletteMaxColors = w * h / tightConf[compressLevel].idxMaxColorsDivisor;
+ if ( paletteMaxColors < 2 &&
+ w * h >= tightConf[compressLevel].monoMinRectSize ) {
+ paletteMaxColors = 2;
+ }
+ switch (cl->format.bitsPerPixel) {
+ case 8:
+ FillPalette8(w * h);
+ break;
+ case 16:
+ FillPalette16(w * h);
+ break;
+ default:
+ FillPalette32(w * h);
+ }
+
+ switch (paletteNumColors) {
+ case 0:
+ /* Truecolor image */
+ if (DetectSmoothImage(cl, &cl->format, w, h)) {
+ if (qualityLevel != -1) {
+ success = SendJpegRect(cl, x, y, w, h,
+ tightConf[qualityLevel].jpegQuality);
+ } else {
+ success = SendGradientRect(cl, w, h);
+ }
+ } else {
+ success = SendFullColorRect(cl, w, h);
+ }
+ break;
+ case 1:
+ /* Solid rectangle */
+ success = SendSolidRect(cl);
+ break;
+ case 2:
+ /* Two-color rectangle */
+ success = SendMonoRect(cl, w, h);
+ break;
+ default:
+ /* Up to 256 different colors */
+ if ( paletteNumColors > 96 &&
+ qualityLevel != -1 && qualityLevel <= 3 &&
+ DetectSmoothImage(cl, &cl->format, w, h) ) {
+ success = SendJpegRect(cl, x, y, w, h,
+ tightConf[qualityLevel].jpegQuality);
+ } else {
+ success = SendIndexedRect(cl, w, h);
+ }
+ }
+ return success;
+}
+
+static Bool
+SendTightHeader(cl, x, y, w, h)
+ rfbClientPtr cl;
+ int x, y, w, h;
+{
+ rfbFramebufferUpdateRectHeader rect;
+
+ if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ rect.r.x = Swap16IfLE(x);
+ rect.r.y = Swap16IfLE(y);
+ rect.r.w = Swap16IfLE(w);
+ rect.r.h = Swap16IfLE(h);
+ rect.encoding = Swap32IfLE(rfbEncodingTight);
+
+ memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
+ sz_rfbFramebufferUpdateRectHeader);
+ cl->ublen += sz_rfbFramebufferUpdateRectHeader;
+
+ cl->rfbRectanglesSent[rfbEncodingTight]++;
+ cl->rfbBytesSent[rfbEncodingTight] += sz_rfbFramebufferUpdateRectHeader;
+
+ return TRUE;
+}
+
+/*
+ * Subencoding implementations.
+ */
+
+static Bool
+SendSolidRect(cl)
+ rfbClientPtr cl;
+{
+ int len;
+
+ if (usePixelFormat24) {
+ Pack24(cl, tightBeforeBuf, &cl->format, 1);
+ len = 3;
+ } else
+ len = cl->format.bitsPerPixel / 8;
+
+ if (cl->ublen + 1 + len > UPDATE_BUF_SIZE) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ cl->updateBuf[cl->ublen++] = (char)(rfbTightFill << 4);
+ memcpy (&cl->updateBuf[cl->ublen], tightBeforeBuf, len);
+ cl->ublen += len;
+
+ cl->rfbBytesSent[rfbEncodingTight] += len + 1;
+
+ return TRUE;
+}
+
+static Bool
+SendMonoRect(cl, w, h)
+ rfbClientPtr cl;
+ int w, h;
+{
+ int streamId = 1;
+ int paletteLen, dataLen;
+
+ if ( cl->ublen + TIGHT_MIN_TO_COMPRESS + 6 +
+ 2 * cl->format.bitsPerPixel / 8 > UPDATE_BUF_SIZE ) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ /* Prepare tight encoding header. */
+ dataLen = (w + 7) / 8;
+ dataLen *= h;
+
+ cl->updateBuf[cl->ublen++] = (streamId | rfbTightExplicitFilter) << 4;
+ cl->updateBuf[cl->ublen++] = rfbTightFilterPalette;
+ cl->updateBuf[cl->ublen++] = 1;
+
+ /* Prepare palette, convert image. */
+ switch (cl->format.bitsPerPixel) {
+
+ case 32:
+ EncodeMonoRect32((CARD8 *)tightBeforeBuf, w, h);
+
+ ((CARD32 *)tightAfterBuf)[0] = monoBackground;
+ ((CARD32 *)tightAfterBuf)[1] = monoForeground;
+ if (usePixelFormat24) {
+ Pack24(cl, tightAfterBuf, &cl->format, 2);
+ paletteLen = 6;
+ } else
+ paletteLen = 8;
+
+ memcpy(&cl->updateBuf[cl->ublen], tightAfterBuf, paletteLen);
+ cl->ublen += paletteLen;
+ cl->rfbBytesSent[rfbEncodingTight] += 3 + paletteLen;
+ break;
+
+ case 16:
+ EncodeMonoRect16((CARD8 *)tightBeforeBuf, w, h);
+
+ ((CARD16 *)tightAfterBuf)[0] = (CARD16)monoBackground;
+ ((CARD16 *)tightAfterBuf)[1] = (CARD16)monoForeground;
+
+ memcpy(&cl->updateBuf[cl->ublen], tightAfterBuf, 4);
+ cl->ublen += 4;
+ cl->rfbBytesSent[rfbEncodingTight] += 7;
+ break;
+
+ default:
+ EncodeMonoRect8((CARD8 *)tightBeforeBuf, w, h);
+
+ cl->updateBuf[cl->ublen++] = (char)monoBackground;
+ cl->updateBuf[cl->ublen++] = (char)monoForeground;
+ cl->rfbBytesSent[rfbEncodingTight] += 5;
+ }
+
+ return CompressData(cl, streamId, dataLen,
+ tightConf[compressLevel].monoZlibLevel,
+ Z_DEFAULT_STRATEGY);
+}
+
+static Bool
+SendIndexedRect(cl, w, h)
+ rfbClientPtr cl;
+ int w, h;
+{
+ int streamId = 2;
+ int i, entryLen;
+
+ if ( cl->ublen + TIGHT_MIN_TO_COMPRESS + 6 +
+ paletteNumColors * cl->format.bitsPerPixel / 8 >
+ UPDATE_BUF_SIZE ) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ /* Prepare tight encoding header. */
+ cl->updateBuf[cl->ublen++] = (streamId | rfbTightExplicitFilter) << 4;
+ cl->updateBuf[cl->ublen++] = rfbTightFilterPalette;
+ cl->updateBuf[cl->ublen++] = (char)(paletteNumColors - 1);
+
+ /* Prepare palette, convert image. */
+ switch (cl->format.bitsPerPixel) {
+
+ case 32:
+ EncodeIndexedRect32((CARD8 *)tightBeforeBuf, w * h);
+
+ for (i = 0; i < paletteNumColors; i++) {
+ ((CARD32 *)tightAfterBuf)[i] =
+ palette.entry[i].listNode->rgb;
+ }
+ if (usePixelFormat24) {
+ Pack24(cl, tightAfterBuf, &cl->format, paletteNumColors);
+ entryLen = 3;
+ } else
+ entryLen = 4;
+
+ memcpy(&cl->updateBuf[cl->ublen], tightAfterBuf, paletteNumColors * entryLen);
+ cl->ublen += paletteNumColors * entryLen;
+ cl->rfbBytesSent[rfbEncodingTight] += 3 + paletteNumColors * entryLen;
+ break;
+
+ case 16:
+ EncodeIndexedRect16((CARD8 *)tightBeforeBuf, w * h);
+
+ for (i = 0; i < paletteNumColors; i++) {
+ ((CARD16 *)tightAfterBuf)[i] =
+ (CARD16)palette.entry[i].listNode->rgb;
+ }
+
+ memcpy(&cl->updateBuf[cl->ublen], tightAfterBuf, paletteNumColors * 2);
+ cl->ublen += paletteNumColors * 2;
+ cl->rfbBytesSent[rfbEncodingTight] += 3 + paletteNumColors * 2;
+ break;
+
+ default:
+ return FALSE; /* Should never happen. */
+ }
+
+ return CompressData(cl, streamId, w * h,
+ tightConf[compressLevel].idxZlibLevel,
+ Z_DEFAULT_STRATEGY);
+}
+
+static Bool
+SendFullColorRect(cl, w, h)
+ rfbClientPtr cl;
+ int w, h;
+{
+ int streamId = 0;
+ int len;
+
+ if (cl->ublen + TIGHT_MIN_TO_COMPRESS + 1 > UPDATE_BUF_SIZE) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ cl->updateBuf[cl->ublen++] = 0x00; /* stream id = 0, no flushing, no filter */
+ cl->rfbBytesSent[rfbEncodingTight]++;
+
+ if (usePixelFormat24) {
+ Pack24(cl, tightBeforeBuf, &cl->format, w * h);
+ len = 3;
+ } else
+ len = cl->format.bitsPerPixel / 8;
+
+ return CompressData(cl, streamId, w * h * len,
+ tightConf[compressLevel].rawZlibLevel,
+ Z_DEFAULT_STRATEGY);
+}
+
+static Bool
+SendGradientRect(cl, w, h)
+ rfbClientPtr cl;
+ int w, h;
+{
+ int streamId = 3;
+ int len;
+
+ if (cl->format.bitsPerPixel == 8)
+ return SendFullColorRect(cl, w, h);
+
+ if (cl->ublen + TIGHT_MIN_TO_COMPRESS + 2 > UPDATE_BUF_SIZE) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ if (prevRowBuf == NULL)
+ prevRowBuf = (int *)malloc(2048 * 3 * sizeof(int));
+
+ cl->updateBuf[cl->ublen++] = (streamId | rfbTightExplicitFilter) << 4;
+ cl->updateBuf[cl->ublen++] = rfbTightFilterGradient;
+ cl->rfbBytesSent[rfbEncodingTight] += 2;
+
+ if (usePixelFormat24) {
+ FilterGradient24(cl, tightBeforeBuf, &cl->format, w, h);
+ len = 3;
+ } else if (cl->format.bitsPerPixel == 32) {
+ FilterGradient32(cl, (CARD32 *)tightBeforeBuf, &cl->format, w, h);
+ len = 4;
+ } else {
+ FilterGradient16(cl, (CARD16 *)tightBeforeBuf, &cl->format, w, h);
+ len = 2;
+ }
+
+ return CompressData(cl, streamId, w * h * len,
+ tightConf[compressLevel].gradientZlibLevel,
+ Z_FILTERED);
+}
+
+static Bool
+CompressData(cl, streamId, dataLen, zlibLevel, zlibStrategy)
+ rfbClientPtr cl;
+ int streamId, dataLen, zlibLevel, zlibStrategy;
+{
+ z_streamp pz;
+ int err;
+
+ if (dataLen < TIGHT_MIN_TO_COMPRESS) {
+ memcpy(&cl->updateBuf[cl->ublen], tightBeforeBuf, dataLen);
+ cl->ublen += dataLen;
+ cl->rfbBytesSent[rfbEncodingTight] += dataLen;
+ return TRUE;
+ }
+
+ pz = &cl->zsStruct[streamId];
+
+ /* Initialize compression stream if needed. */
+ if (!cl->zsActive[streamId]) {
+ pz->zalloc = Z_NULL;
+ pz->zfree = Z_NULL;
+ pz->opaque = Z_NULL;
+
+ err = deflateInit2 (pz, zlibLevel, Z_DEFLATED, MAX_WBITS,
+ MAX_MEM_LEVEL, zlibStrategy);
+ if (err != Z_OK)
+ return FALSE;
+
+ cl->zsActive[streamId] = TRUE;
+ cl->zsLevel[streamId] = zlibLevel;
+ }
+
+ /* Prepare buffer pointers. */
+ pz->next_in = (Bytef *)tightBeforeBuf;
+ pz->avail_in = dataLen;
+ pz->next_out = (Bytef *)tightAfterBuf;
+ pz->avail_out = tightAfterBufSize;
+
+ /* Change compression parameters if needed. */
+ if (zlibLevel != cl->zsLevel[streamId]) {
+ if (deflateParams (pz, zlibLevel, zlibStrategy) != Z_OK) {
+ return FALSE;
+ }
+ cl->zsLevel[streamId] = zlibLevel;
+ }
+
+ /* Actual compression. */
+ if ( deflate (pz, Z_SYNC_FLUSH) != Z_OK ||
+ pz->avail_in != 0 || pz->avail_out == 0 ) {
+ return FALSE;
+ }
+
+ return SendCompressedData(cl, tightAfterBufSize - pz->avail_out);
+}
+
+static Bool SendCompressedData(cl, compressedLen)
+ rfbClientPtr cl;
+ int compressedLen;
+{
+ int i, portionLen;
+
+ cl->updateBuf[cl->ublen++] = compressedLen & 0x7F;
+ cl->rfbBytesSent[rfbEncodingTight]++;
+ if (compressedLen > 0x7F) {
+ cl->updateBuf[cl->ublen-1] |= 0x80;
+ cl->updateBuf[cl->ublen++] = compressedLen >> 7 & 0x7F;
+ cl->rfbBytesSent[rfbEncodingTight]++;
+ if (compressedLen > 0x3FFF) {
+ cl->updateBuf[cl->ublen-1] |= 0x80;
+ cl->updateBuf[cl->ublen++] = compressedLen >> 14 & 0xFF;
+ cl->rfbBytesSent[rfbEncodingTight]++;
+ }
+ }
+
+ portionLen = UPDATE_BUF_SIZE;
+ for (i = 0; i < compressedLen; i += portionLen) {
+ if (i + portionLen > compressedLen) {
+ portionLen = compressedLen - i;
+ }
+ if (cl->ublen + portionLen > UPDATE_BUF_SIZE) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+ memcpy(&cl->updateBuf[cl->ublen], &tightAfterBuf[i], portionLen);
+ cl->ublen += portionLen;
+ }
+ portionLen = UPDATE_BUF_SIZE;
+ cl->rfbBytesSent[rfbEncodingTight] += compressedLen;
+ return TRUE;
+}
+
+/*
+ * Code to determine how many different colors used in rectangle.
+ */
+
+static void
+FillPalette8(count)
+ int count;
+{
+ CARD8 *data = (CARD8 *)tightBeforeBuf;
+ CARD8 c0, c1;
+ int i, n0, n1;
+
+ paletteNumColors = 0;
+
+ c0 = data[0];
+ for (i = 1; i < count && data[i] == c0; i++);
+ if (i == count) {
+ paletteNumColors = 1;
+ return; /* Solid rectangle */
+ }
+
+ if (paletteMaxColors < 2)
+ return;
+
+ n0 = i;
+ c1 = data[i];
+ n1 = 0;
+ for (i++; i < count; i++) {
+ if (data[i] == c0) {
+ n0++;
+ } else if (data[i] == c1) {
+ n1++;
+ } else
+ break;
+ }
+ if (i == count) {
+ if (n0 > n1) {
+ monoBackground = (CARD32)c0;
+ monoForeground = (CARD32)c1;
+ } else {
+ monoBackground = (CARD32)c1;
+ monoForeground = (CARD32)c0;
+ }
+ paletteNumColors = 2; /* Two colors */
+ }
+}
+
+#define DEFINE_FILL_PALETTE_FUNCTION(bpp) \
+ \
+static void \
+FillPalette##bpp(count) \
+ int count; \
+{ \
+ CARD##bpp *data = (CARD##bpp *)tightBeforeBuf; \
+ CARD##bpp c0, c1, ci; \
+ int i, n0, n1, ni; \
+ \
+ c0 = data[0]; \
+ for (i = 1; i < count && data[i] == c0; i++); \
+ if (i >= count) { \
+ paletteNumColors = 1; /* Solid rectangle */ \
+ return; \
+ } \
+ \
+ if (paletteMaxColors < 2) { \
+ paletteNumColors = 0; /* Full-color encoding preferred */ \
+ return; \
+ } \
+ \
+ n0 = i; \
+ c1 = data[i]; \
+ n1 = 0; \
+ for (i++; i < count; i++) { \
+ ci = data[i]; \
+ if (ci == c0) { \
+ n0++; \
+ } else if (ci == c1) { \
+ n1++; \
+ } else \
+ break; \
+ } \
+ if (i >= count) { \
+ if (n0 > n1) { \
+ monoBackground = (CARD32)c0; \
+ monoForeground = (CARD32)c1; \
+ } else { \
+ monoBackground = (CARD32)c1; \
+ monoForeground = (CARD32)c0; \
+ } \
+ paletteNumColors = 2; /* Two colors */ \
+ return; \
+ } \
+ \
+ PaletteReset(); \
+ PaletteInsert (c0, (CARD32)n0, bpp); \
+ PaletteInsert (c1, (CARD32)n1, bpp); \
+ \
+ ni = 1; \
+ for (i++; i < count; i++) { \
+ if (data[i] == ci) { \
+ ni++; \
+ } else { \
+ if (!PaletteInsert (ci, (CARD32)ni, bpp)) \
+ return; \
+ ci = data[i]; \
+ ni = 1; \
+ } \
+ } \
+ PaletteInsert (ci, (CARD32)ni, bpp); \
+}
+
+DEFINE_FILL_PALETTE_FUNCTION(16)
+DEFINE_FILL_PALETTE_FUNCTION(32)
+
+
+/*
+ * Functions to operate with palette structures.
+ */
+
+#define HASH_FUNC16(rgb) ((int)(((rgb >> 8) + rgb) & 0xFF))
+#define HASH_FUNC32(rgb) ((int)(((rgb >> 16) + (rgb >> 8)) & 0xFF))
+
+static void
+PaletteReset(void)
+{
+ paletteNumColors = 0;
+ memset(palette.hash, 0, 256 * sizeof(COLOR_LIST *));
+}
+
+static int
+PaletteInsert(rgb, numPixels, bpp)
+ CARD32 rgb;
+ int numPixels;
+ int bpp;
+{
+ COLOR_LIST *pnode;
+ COLOR_LIST *prev_pnode = NULL;
+ int hash_key, idx, new_idx, count;
+
+ hash_key = (bpp == 16) ? HASH_FUNC16(rgb) : HASH_FUNC32(rgb);
+
+ pnode = palette.hash[hash_key];
+
+ while (pnode != NULL) {
+ if (pnode->rgb == rgb) {
+ /* Such palette entry already exists. */
+ new_idx = idx = pnode->idx;
+ count = palette.entry[idx].numPixels + numPixels;
+ if (new_idx && palette.entry[new_idx-1].numPixels < count) {
+ do {
+ palette.entry[new_idx] = palette.entry[new_idx-1];
+ palette.entry[new_idx].listNode->idx = new_idx;
+ new_idx--;
+ }
+ while (new_idx && palette.entry[new_idx-1].numPixels < count);
+ palette.entry[new_idx].listNode = pnode;
+ pnode->idx = new_idx;
+ }
+ palette.entry[new_idx].numPixels = count;
+ return paletteNumColors;
+ }
+ prev_pnode = pnode;
+ pnode = pnode->next;
+ }
+
+ /* Check if palette is full. */
+ if (paletteNumColors == 256 || paletteNumColors == paletteMaxColors) {
+ paletteNumColors = 0;
+ return 0;
+ }
+
+ /* Move palette entries with lesser pixel counts. */
+ for ( idx = paletteNumColors;
+ idx > 0 && palette.entry[idx-1].numPixels < numPixels;
+ idx-- ) {
+ palette.entry[idx] = palette.entry[idx-1];
+ palette.entry[idx].listNode->idx = idx;
+ }
+
+ /* Add new palette entry into the freed slot. */
+ pnode = &palette.list[paletteNumColors];
+ if (prev_pnode != NULL) {
+ prev_pnode->next = pnode;
+ } else {
+ palette.hash[hash_key] = pnode;
+ }
+ pnode->next = NULL;
+ pnode->idx = idx;
+ pnode->rgb = rgb;
+ palette.entry[idx].listNode = pnode;
+ palette.entry[idx].numPixels = numPixels;
+
+ return (++paletteNumColors);
+}
+
+
+/*
+ * Converting 32-bit color samples into 24-bit colors.
+ * Should be called only when redMax, greenMax and blueMax are 255.
+ * Color components assumed to be byte-aligned.
+ */
+
+static void Pack24(cl, buf, fmt, count)
+ rfbClientPtr cl;
+ char *buf;
+ rfbPixelFormat *fmt;
+ int count;
+{
+ CARD32 *buf32;
+ CARD32 pix;
+ int r_shift, g_shift, b_shift;
+
+ buf32 = (CARD32 *)buf;
+
+ if (!cl->screen->rfbServerFormat.bigEndian == !fmt->bigEndian) {
+ r_shift = fmt->redShift;
+ g_shift = fmt->greenShift;
+ b_shift = fmt->blueShift;
+ } else {
+ r_shift = 24 - fmt->redShift;
+ g_shift = 24 - fmt->greenShift;
+ b_shift = 24 - fmt->blueShift;
+ }
+
+ while (count--) {
+ pix = *buf32++;
+ *buf++ = (char)(pix >> r_shift);
+ *buf++ = (char)(pix >> g_shift);
+ *buf++ = (char)(pix >> b_shift);
+ }
+}
+
+
+/*
+ * Converting truecolor samples into palette indices.
+ */
+
+#define DEFINE_IDX_ENCODE_FUNCTION(bpp) \
+ \
+static void \
+EncodeIndexedRect##bpp(buf, count) \
+ CARD8 *buf; \
+ int count; \
+{ \
+ COLOR_LIST *pnode; \
+ CARD##bpp *src; \
+ CARD##bpp rgb; \
+ int rep = 0; \
+ \
+ src = (CARD##bpp *) buf; \
+ \
+ while (count--) { \
+ rgb = *src++; \
+ while (count && *src == rgb) { \
+ rep++, src++, count--; \
+ } \
+ pnode = palette.hash[HASH_FUNC##bpp(rgb)]; \
+ while (pnode != NULL) { \
+ if ((CARD##bpp)pnode->rgb == rgb) { \
+ *buf++ = (CARD8)pnode->idx; \
+ while (rep) { \
+ *buf++ = (CARD8)pnode->idx; \
+ rep--; \
+ } \
+ break; \
+ } \
+ pnode = pnode->next; \
+ } \
+ } \
+}
+
+DEFINE_IDX_ENCODE_FUNCTION(16)
+DEFINE_IDX_ENCODE_FUNCTION(32)
+
+#define DEFINE_MONO_ENCODE_FUNCTION(bpp) \
+ \
+static void \
+EncodeMonoRect##bpp(buf, w, h) \
+ CARD8 *buf; \
+ int w, h; \
+{ \
+ CARD##bpp *ptr; \
+ CARD##bpp bg; \
+ unsigned int value, mask; \
+ int aligned_width; \
+ int x, y, bg_bits; \
+ \
+ ptr = (CARD##bpp *) buf; \
+ bg = (CARD##bpp) monoBackground; \
+ aligned_width = w - w % 8; \
+ \
+ for (y = 0; y < h; y++) { \
+ for (x = 0; x < aligned_width; x += 8) { \
+ for (bg_bits = 0; bg_bits < 8; bg_bits++) { \
+ if (*ptr++ != bg) \
+ break; \
+ } \
+ if (bg_bits == 8) { \
+ *buf++ = 0; \
+ continue; \
+ } \
+ mask = 0x80 >> bg_bits; \
+ value = mask; \
+ for (bg_bits++; bg_bits < 8; bg_bits++) { \
+ mask >>= 1; \
+ if (*ptr++ != bg) { \
+ value |= mask; \
+ } \
+ } \
+ *buf++ = (CARD8)value; \
+ } \
+ \
+ mask = 0x80; \
+ value = 0; \
+ if (x >= w) \
+ continue; \
+ \
+ for (; x < w; x++) { \
+ if (*ptr++ != bg) { \
+ value |= mask; \
+ } \
+ mask >>= 1; \
+ } \
+ *buf++ = (CARD8)value; \
+ } \
+}
+
+DEFINE_MONO_ENCODE_FUNCTION(8)
+DEFINE_MONO_ENCODE_FUNCTION(16)
+DEFINE_MONO_ENCODE_FUNCTION(32)
+
+
+/*
+ * ``Gradient'' filter for 24-bit color samples.
+ * Should be called only when redMax, greenMax and blueMax are 255.
+ * Color components assumed to be byte-aligned.
+ */
+
+static void
+FilterGradient24(cl, buf, fmt, w, h)
+ rfbClientPtr cl;
+ char *buf;
+ rfbPixelFormat *fmt;
+ int w, h;
+{
+ CARD32 *buf32;
+ CARD32 pix32;
+ int *prevRowPtr;
+ int shiftBits[3];
+ int pixHere[3], pixUpper[3], pixLeft[3], pixUpperLeft[3];
+ int prediction;
+ int x, y, c;
+
+ buf32 = (CARD32 *)buf;
+ memset (prevRowBuf, 0, w * 3 * sizeof(int));
+
+ if (!cl->screen->rfbServerFormat.bigEndian == !fmt->bigEndian) {
+ shiftBits[0] = fmt->redShift;
+ shiftBits[1] = fmt->greenShift;
+ shiftBits[2] = fmt->blueShift;
+ } else {
+ shiftBits[0] = 24 - fmt->redShift;
+ shiftBits[1] = 24 - fmt->greenShift;
+ shiftBits[2] = 24 - fmt->blueShift;
+ }
+
+ for (y = 0; y < h; y++) {
+ for (c = 0; c < 3; c++) {
+ pixUpper[c] = 0;
+ pixHere[c] = 0;
+ }
+ prevRowPtr = prevRowBuf;
+ for (x = 0; x < w; x++) {
+ pix32 = *buf32++;
+ for (c = 0; c < 3; c++) {
+ pixUpperLeft[c] = pixUpper[c];
+ pixLeft[c] = pixHere[c];
+ pixUpper[c] = *prevRowPtr;
+ pixHere[c] = (int)(pix32 >> shiftBits[c] & 0xFF);
+ *prevRowPtr++ = pixHere[c];
+
+ prediction = pixLeft[c] + pixUpper[c] - pixUpperLeft[c];
+ if (prediction < 0) {
+ prediction = 0;
+ } else if (prediction > 0xFF) {
+ prediction = 0xFF;
+ }
+ *buf++ = (char)(pixHere[c] - prediction);
+ }
+ }
+ }
+}
+
+
+/*
+ * ``Gradient'' filter for other color depths.
+ */
+
+#define DEFINE_GRADIENT_FILTER_FUNCTION(bpp) \
+ \
+static void \
+FilterGradient##bpp(cl, buf, fmt, w, h) \
+ rfbClientPtr cl; \
+ CARD##bpp *buf; \
+ rfbPixelFormat *fmt; \
+ int w, h; \
+{ \
+ CARD##bpp pix, diff; \
+ Bool endianMismatch; \
+ int *prevRowPtr; \
+ int maxColor[3], shiftBits[3]; \
+ int pixHere[3], pixUpper[3], pixLeft[3], pixUpperLeft[3]; \
+ int prediction; \
+ int x, y, c; \
+ \
+ memset (prevRowBuf, 0, w * 3 * sizeof(int)); \
+ \
+ endianMismatch = (!cl->screen->rfbServerFormat.bigEndian != !fmt->bigEndian); \
+ \
+ maxColor[0] = fmt->redMax; \
+ maxColor[1] = fmt->greenMax; \
+ maxColor[2] = fmt->blueMax; \
+ shiftBits[0] = fmt->redShift; \
+ shiftBits[1] = fmt->greenShift; \
+ shiftBits[2] = fmt->blueShift; \
+ \
+ for (y = 0; y < h; y++) { \
+ for (c = 0; c < 3; c++) { \
+ pixUpper[c] = 0; \
+ pixHere[c] = 0; \
+ } \
+ prevRowPtr = prevRowBuf; \
+ for (x = 0; x < w; x++) { \
+ pix = *buf; \
+ if (endianMismatch) { \
+ pix = Swap##bpp(pix); \
+ } \
+ diff = 0; \
+ for (c = 0; c < 3; c++) { \
+ pixUpperLeft[c] = pixUpper[c]; \
+ pixLeft[c] = pixHere[c]; \
+ pixUpper[c] = *prevRowPtr; \
+ pixHere[c] = (int)(pix >> shiftBits[c] & maxColor[c]); \
+ *prevRowPtr++ = pixHere[c]; \
+ \
+ prediction = pixLeft[c] + pixUpper[c] - pixUpperLeft[c]; \
+ if (prediction < 0) { \
+ prediction = 0; \
+ } else if (prediction > maxColor[c]) { \
+ prediction = maxColor[c]; \
+ } \
+ diff |= ((pixHere[c] - prediction) & maxColor[c]) \
+ << shiftBits[c]; \
+ } \
+ if (endianMismatch) { \
+ diff = Swap##bpp(diff); \
+ } \
+ *buf++ = diff; \
+ } \
+ } \
+}
+
+DEFINE_GRADIENT_FILTER_FUNCTION(16)
+DEFINE_GRADIENT_FILTER_FUNCTION(32)
+
+
+/*
+ * Code to guess if given rectangle is suitable for smooth image
+ * compression (by applying "gradient" filter or JPEG coder).
+ */
+
+#define JPEG_MIN_RECT_SIZE 4096
+
+#define DETECT_SUBROW_WIDTH 7
+#define DETECT_MIN_WIDTH 8
+#define DETECT_MIN_HEIGHT 8
+
+static int
+DetectSmoothImage (cl, fmt, w, h)
+ rfbClientPtr cl;
+ rfbPixelFormat *fmt;
+ int w, h;
+{
+ long avgError;
+
+ if ( cl->screen->rfbServerFormat.bitsPerPixel == 8 || fmt->bitsPerPixel == 8 ||
+ w < DETECT_MIN_WIDTH || h < DETECT_MIN_HEIGHT ) {
+ return 0;
+ }
+
+ if (qualityLevel != -1) {
+ if (w * h < JPEG_MIN_RECT_SIZE) {
+ return 0;
+ }
+ } else {
+ if ( rfbTightDisableGradient ||
+ w * h < tightConf[compressLevel].gradientMinRectSize ) {
+ return 0;
+ }
+ }
+
+ if (fmt->bitsPerPixel == 32) {
+ if (usePixelFormat24) {
+ avgError = DetectSmoothImage24(cl, fmt, w, h);
+ if (qualityLevel != -1) {
+ return (avgError < tightConf[qualityLevel].jpegThreshold24);
+ }
+ return (avgError < tightConf[compressLevel].gradientThreshold24);
+ } else {
+ avgError = DetectSmoothImage32(cl, fmt, w, h);
+ }
+ } else {
+ avgError = DetectSmoothImage16(cl, fmt, w, h);
+ }
+ if (qualityLevel != -1) {
+ return (avgError < tightConf[qualityLevel].jpegThreshold);
+ }
+ return (avgError < tightConf[compressLevel].gradientThreshold);
+}
+
+static unsigned long
+DetectSmoothImage24 (cl, fmt, w, h)
+ rfbClientPtr cl;
+ rfbPixelFormat *fmt;
+ int w, h;
+{
+ int off;
+ int x, y, d, dx, c;
+ int diffStat[256];
+ int pixelCount = 0;
+ int pix, left[3];
+ unsigned long avgError;
+
+ /* If client is big-endian, color samples begin from the second
+ byte (offset 1) of a 32-bit pixel value. */
+ off = (fmt->bigEndian != 0);
+
+ memset(diffStat, 0, 256*sizeof(int));
+
+ y = 0, x = 0;
+ while (y < h && x < w) {
+ for (d = 0; d < h - y && d < w - x - DETECT_SUBROW_WIDTH; d++) {
+ for (c = 0; c < 3; c++) {
+ left[c] = (int)tightBeforeBuf[((y+d)*w+x+d)*4+off+c] & 0xFF;
+ }
+ for (dx = 1; dx <= DETECT_SUBROW_WIDTH; dx++) {
+ for (c = 0; c < 3; c++) {
+ pix = (int)tightBeforeBuf[((y+d)*w+x+d+dx)*4+off+c] & 0xFF;
+ diffStat[abs(pix - left[c])]++;
+ left[c] = pix;
+ }
+ pixelCount++;
+ }
+ }
+ if (w > h) {
+ x += h;
+ y = 0;
+ } else {
+ x = 0;
+ y += w;
+ }
+ }
+
+ if (diffStat[0] * 33 / pixelCount >= 95)
+ return 0;
+
+ avgError = 0;
+ for (c = 1; c < 8; c++) {
+ avgError += (unsigned long)diffStat[c] * (unsigned long)(c * c);
+ if (diffStat[c] == 0 || diffStat[c] > diffStat[c-1] * 2)
+ return 0;
+ }
+ for (; c < 256; c++) {
+ avgError += (unsigned long)diffStat[c] * (unsigned long)(c * c);
+ }
+ avgError /= (pixelCount * 3 - diffStat[0]);
+
+ return avgError;
+}
+
+#define DEFINE_DETECT_FUNCTION(bpp) \
+ \
+static unsigned long \
+DetectSmoothImage##bpp (cl, fmt, w, h) \
+ rfbClientPtr cl; \
+ rfbPixelFormat *fmt; \
+ int w, h; \
+{ \
+ Bool endianMismatch; \
+ CARD##bpp pix; \
+ int maxColor[3], shiftBits[3]; \
+ int x, y, d, dx, c; \
+ int diffStat[256]; \
+ int pixelCount = 0; \
+ int sample, sum, left[3]; \
+ unsigned long avgError; \
+ \
+ endianMismatch = (!cl->screen->rfbServerFormat.bigEndian != !fmt->bigEndian); \
+ \
+ maxColor[0] = fmt->redMax; \
+ maxColor[1] = fmt->greenMax; \
+ maxColor[2] = fmt->blueMax; \
+ shiftBits[0] = fmt->redShift; \
+ shiftBits[1] = fmt->greenShift; \
+ shiftBits[2] = fmt->blueShift; \
+ \
+ memset(diffStat, 0, 256*sizeof(int)); \
+ \
+ y = 0, x = 0; \
+ while (y < h && x < w) { \
+ for (d = 0; d < h - y && d < w - x - DETECT_SUBROW_WIDTH; d++) { \
+ pix = ((CARD##bpp *)tightBeforeBuf)[(y+d)*w+x+d]; \
+ if (endianMismatch) { \
+ pix = Swap##bpp(pix); \
+ } \
+ for (c = 0; c < 3; c++) { \
+ left[c] = (int)(pix >> shiftBits[c] & maxColor[c]); \
+ } \
+ for (dx = 1; dx <= DETECT_SUBROW_WIDTH; dx++) { \
+ pix = ((CARD##bpp *)tightBeforeBuf)[(y+d)*w+x+d+dx]; \
+ if (endianMismatch) { \
+ pix = Swap##bpp(pix); \
+ } \
+ sum = 0; \
+ for (c = 0; c < 3; c++) { \
+ sample = (int)(pix >> shiftBits[c] & maxColor[c]); \
+ sum += abs(sample - left[c]); \
+ left[c] = sample; \
+ } \
+ if (sum > 255) \
+ sum = 255; \
+ diffStat[sum]++; \
+ pixelCount++; \
+ } \
+ } \
+ if (w > h) { \
+ x += h; \
+ y = 0; \
+ } else { \
+ x = 0; \
+ y += w; \
+ } \
+ } \
+ \
+ if ((diffStat[0] + diffStat[1]) * 100 / pixelCount >= 90) \
+ return 0; \
+ \
+ avgError = 0; \
+ for (c = 1; c < 8; c++) { \
+ avgError += (unsigned long)diffStat[c] * (unsigned long)(c * c); \
+ if (diffStat[c] == 0 || diffStat[c] > diffStat[c-1] * 2) \
+ return 0; \
+ } \
+ for (; c < 256; c++) { \
+ avgError += (unsigned long)diffStat[c] * (unsigned long)(c * c); \
+ } \
+ avgError /= (pixelCount - diffStat[0]); \
+ \
+ return avgError; \
+}
+
+DEFINE_DETECT_FUNCTION(16)
+DEFINE_DETECT_FUNCTION(32)
+
+
+/*
+ * JPEG compression stuff.
+ */
+
+static struct jpeg_destination_mgr jpegDstManager;
+static Bool jpegError;
+static int jpegDstDataLen;
+
+static Bool
+SendJpegRect(cl, x, y, w, h, quality)
+ rfbClientPtr cl;
+ int x, y, w, h;
+ int quality;
+{
+ struct jpeg_compress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+ CARD8 *srcBuf;
+ JSAMPROW rowPointer[1];
+ int dy;
+
+ if (cl->screen->rfbServerFormat.bitsPerPixel == 8)
+ return SendFullColorRect(cl, w, h);
+
+ srcBuf = (CARD8 *)malloc(w * 3);
+ if (srcBuf == NULL) {
+ return SendFullColorRect(cl, w, h);
+ }
+ rowPointer[0] = srcBuf;
+
+ cinfo.err = jpeg_std_error(&jerr);
+ jpeg_create_compress(&cinfo);
+
+ cinfo.image_width = w;
+ cinfo.image_height = h;
+ cinfo.input_components = 3;
+ cinfo.in_color_space = JCS_RGB;
+
+ jpeg_set_defaults(&cinfo);
+ jpeg_set_quality(&cinfo, quality, TRUE);
+
+ JpegSetDstManager (&cinfo);
+
+ jpeg_start_compress(&cinfo, TRUE);
+
+ for (dy = 0; dy < h; dy++) {
+ PrepareRowForJpeg(cl, srcBuf, x, y + dy, w);
+ jpeg_write_scanlines(&cinfo, rowPointer, 1);
+ if (jpegError)
+ break;
+ }
+
+ if (!jpegError)
+ jpeg_finish_compress(&cinfo);
+
+ jpeg_destroy_compress(&cinfo);
+ free(srcBuf);
+
+ if (jpegError)
+ return SendFullColorRect(cl, w, h);
+
+ if (cl->ublen + TIGHT_MIN_TO_COMPRESS + 1 > UPDATE_BUF_SIZE) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ cl->updateBuf[cl->ublen++] = (char)(rfbTightJpeg << 4);
+ cl->rfbBytesSent[rfbEncodingTight]++;
+
+ return SendCompressedData(cl, jpegDstDataLen);
+}
+
+static void
+PrepareRowForJpeg(cl, dst, x, y, count)
+ rfbClientPtr cl;
+ CARD8 *dst;
+ int x, y, count;
+{
+ if (cl->screen->rfbServerFormat.bitsPerPixel == 32) {
+ if ( cl->screen->rfbServerFormat.redMax == 0xFF &&
+ cl->screen->rfbServerFormat.greenMax == 0xFF &&
+ cl->screen->rfbServerFormat.blueMax == 0xFF ) {
+ PrepareRowForJpeg24(cl, dst, x, y, count);
+ } else {
+ PrepareRowForJpeg32(cl, dst, x, y, count);
+ }
+ } else {
+ /* 16 bpp assumed. */
+ PrepareRowForJpeg16(cl, dst, x, y, count);
+ }
+}
+
+static void
+PrepareRowForJpeg24(cl, dst, x, y, count)
+ rfbClientPtr cl;
+ CARD8 *dst;
+ int x, y, count;
+{
+ CARD32 *fbptr;
+ CARD32 pix;
+
+ fbptr = (CARD32 *)
+ &cl->screen->frameBuffer[y * cl->screen->paddedWidthInBytes + x * 4];
+
+ while (count--) {
+ pix = *fbptr++;
+ *dst++ = (CARD8)(pix >> cl->screen->rfbServerFormat.redShift);
+ *dst++ = (CARD8)(pix >> cl->screen->rfbServerFormat.greenShift);
+ *dst++ = (CARD8)(pix >> cl->screen->rfbServerFormat.blueShift);
+ }
+}
+
+#define DEFINE_JPEG_GET_ROW_FUNCTION(bpp) \
+ \
+static void \
+PrepareRowForJpeg##bpp(cl, dst, x, y, count) \
+ rfbClientPtr cl; \
+ CARD8 *dst; \
+ int x, y, count; \
+{ \
+ CARD##bpp *fbptr; \
+ CARD##bpp pix; \
+ int inRed, inGreen, inBlue; \
+ \
+ fbptr = (CARD##bpp *) \
+ &cl->screen->frameBuffer[y * cl->screen->paddedWidthInBytes + \
+ x * (bpp / 8)]; \
+ \
+ while (count--) { \
+ pix = *fbptr++; \
+ \
+ inRed = (int) \
+ (pix >> cl->screen->rfbServerFormat.redShift & cl->screen->rfbServerFormat.redMax); \
+ inGreen = (int) \
+ (pix >> cl->screen->rfbServerFormat.greenShift & cl->screen->rfbServerFormat.greenMax); \
+ inBlue = (int) \
+ (pix >> cl->screen->rfbServerFormat.blueShift & cl->screen->rfbServerFormat.blueMax); \
+ \
+ *dst++ = (CARD8)((inRed * 255 + cl->screen->rfbServerFormat.redMax / 2) / \
+ cl->screen->rfbServerFormat.redMax); \
+ *dst++ = (CARD8)((inGreen * 255 + cl->screen->rfbServerFormat.greenMax / 2) / \
+ cl->screen->rfbServerFormat.greenMax); \
+ *dst++ = (CARD8)((inBlue * 255 + cl->screen->rfbServerFormat.blueMax / 2) / \
+ cl->screen->rfbServerFormat.blueMax); \
+ } \
+}
+
+DEFINE_JPEG_GET_ROW_FUNCTION(16)
+DEFINE_JPEG_GET_ROW_FUNCTION(32)
+
+/*
+ * Destination manager implementation for JPEG library.
+ */
+
+static void
+JpegInitDestination(j_compress_ptr cinfo)
+{
+ jpegError = FALSE;
+ jpegDstManager.next_output_byte = (JOCTET *)tightAfterBuf;
+ jpegDstManager.free_in_buffer = (size_t)tightAfterBufSize;
+}
+
+static boolean
+JpegEmptyOutputBuffer(j_compress_ptr cinfo)
+{
+ jpegError = TRUE;
+ jpegDstManager.next_output_byte = (JOCTET *)tightAfterBuf;
+ jpegDstManager.free_in_buffer = (size_t)tightAfterBufSize;
+
+ return TRUE;
+}
+
+static void
+JpegTermDestination(j_compress_ptr cinfo)
+{
+ jpegDstDataLen = tightAfterBufSize - jpegDstManager.free_in_buffer;
+}
+
+static void
+JpegSetDstManager(j_compress_ptr cinfo)
+{
+ jpegDstManager.init_destination = JpegInitDestination;
+ jpegDstManager.empty_output_buffer = JpegEmptyOutputBuffer;
+ jpegDstManager.term_destination = JpegTermDestination;
+ cinfo->dest = &jpegDstManager;
+}
+
diff --git a/krfb/libvncserver/translate.c b/krfb/libvncserver/translate.c
new file mode 100644
index 00000000..d6021d57
--- /dev/null
+++ b/krfb/libvncserver/translate.c
@@ -0,0 +1,484 @@
+/*
+ * translate.c - translate between different pixel formats
+ */
+
+/*
+ * OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
+ * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
+ * All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "rfb.h"
+#include "sraRegion.h"
+
+static void PrintPixelFormat(rfbPixelFormat *pf);
+static Bool rfbSetClientColourMapBGR233(rfbClientPtr cl);
+
+Bool rfbEconomicTranslate = FALSE;
+
+/*
+ * Some standard pixel formats.
+ */
+
+static const rfbPixelFormat BGR233Format = {
+ 8, 8, 0, 1, 7, 7, 3, 0, 3, 6, 0, 0
+};
+
+
+/*
+ * Macro to compare pixel formats.
+ */
+
+#define PF_EQ(x,y) \
+ ((x.bitsPerPixel == y.bitsPerPixel) && \
+ (x.depth == y.depth) && \
+ ((x.bigEndian == y.bigEndian) || (x.bitsPerPixel == 8)) && \
+ (x.trueColour == y.trueColour) && \
+ (!x.trueColour || ((x.redMax == y.redMax) && \
+ (x.greenMax == y.greenMax) && \
+ (x.blueMax == y.blueMax) && \
+ (x.redShift == y.redShift) && \
+ (x.greenShift == y.greenShift) && \
+ (x.blueShift == y.blueShift))))
+
+#define CONCAT2(a,b) a##b
+#define CONCAT2E(a,b) CONCAT2(a,b)
+#define CONCAT4(a,b,c,d) a##b##c##d
+#define CONCAT4E(a,b,c,d) CONCAT4(a,b,c,d)
+
+#undef OUT
+#undef IN
+
+#define OUT 8
+#include "tableinitcmtemplate.c"
+#include "tableinittctemplate.c"
+#define IN 8
+#include "tabletranstemplate.c"
+#undef IN
+#define IN 16
+#include "tabletranstemplate.c"
+#undef IN
+#define IN 32
+#include "tabletranstemplate.c"
+#undef IN
+#undef OUT
+
+#define OUT 16
+#include "tableinitcmtemplate.c"
+#include "tableinittctemplate.c"
+#define IN 8
+#include "tabletranstemplate.c"
+#undef IN
+#define IN 16
+#include "tabletranstemplate.c"
+#undef IN
+#define IN 32
+#include "tabletranstemplate.c"
+#undef IN
+#undef OUT
+
+#define OUT 32
+#include "tableinitcmtemplate.c"
+#include "tableinittctemplate.c"
+#define IN 8
+#include "tabletranstemplate.c"
+#undef IN
+#define IN 16
+#include "tabletranstemplate.c"
+#undef IN
+#define IN 32
+#include "tabletranstemplate.c"
+#undef IN
+#undef OUT
+
+#ifdef ALLOW24BPP
+#define COUNT_OFFSETS 4
+#define BPP2OFFSET(bpp) ((bpp)/8-1)
+#include "tableinit24.c"
+#define BPP 8
+#include "tabletrans24template.c"
+#undef BPP
+#define BPP 16
+#include "tabletrans24template.c"
+#undef BPP
+#define BPP 24
+#include "tabletrans24template.c"
+#undef BPP
+#define BPP 32
+#include "tabletrans24template.c"
+#undef BPP
+#else
+#define COUNT_OFFSETS 3
+#define BPP2OFFSET(bpp) ((int)(bpp)/16)
+#endif
+
+typedef void (*rfbInitCMTableFnType)(char **table, rfbPixelFormat *in,
+ rfbPixelFormat *out,rfbColourMap* cm);
+typedef void (*rfbInitTableFnType)(char **table, rfbPixelFormat *in,
+ rfbPixelFormat *out);
+
+rfbInitCMTableFnType rfbInitColourMapSingleTableFns[COUNT_OFFSETS] = {
+ rfbInitColourMapSingleTable8,
+ rfbInitColourMapSingleTable16,
+#ifdef ALLOW24BPP
+ rfbInitColourMapSingleTable24,
+#endif
+ rfbInitColourMapSingleTable32
+};
+
+rfbInitTableFnType rfbInitTrueColourSingleTableFns[COUNT_OFFSETS] = {
+ rfbInitTrueColourSingleTable8,
+ rfbInitTrueColourSingleTable16,
+#ifdef ALLOW24BPP
+ rfbInitTrueColourSingleTable24,
+#endif
+ rfbInitTrueColourSingleTable32
+};
+
+rfbInitTableFnType rfbInitTrueColourRGBTablesFns[COUNT_OFFSETS] = {
+ rfbInitTrueColourRGBTables8,
+ rfbInitTrueColourRGBTables16,
+#ifdef ALLOW24BPP
+ rfbInitTrueColourRGBTables24,
+#endif
+ rfbInitTrueColourRGBTables32
+};
+
+rfbTranslateFnType rfbTranslateWithSingleTableFns[COUNT_OFFSETS][COUNT_OFFSETS] = {
+ { rfbTranslateWithSingleTable8to8,
+ rfbTranslateWithSingleTable8to16,
+#ifdef ALLOW24BPP
+ rfbTranslateWithSingleTable8to24,
+#endif
+ rfbTranslateWithSingleTable8to32 },
+ { rfbTranslateWithSingleTable16to8,
+ rfbTranslateWithSingleTable16to16,
+#ifdef ALLOW24BPP
+ rfbTranslateWithSingleTable16to24,
+#endif
+ rfbTranslateWithSingleTable16to32 },
+#ifdef ALLOW24BPP
+ { rfbTranslateWithSingleTable24to8,
+ rfbTranslateWithSingleTable24to16,
+ rfbTranslateWithSingleTable24to24,
+ rfbTranslateWithSingleTable24to32 },
+#endif
+ { rfbTranslateWithSingleTable32to8,
+ rfbTranslateWithSingleTable32to16,
+#ifdef ALLOW24BPP
+ rfbTranslateWithSingleTable32to24,
+#endif
+ rfbTranslateWithSingleTable32to32 }
+};
+
+rfbTranslateFnType rfbTranslateWithRGBTablesFns[COUNT_OFFSETS][COUNT_OFFSETS] = {
+ { rfbTranslateWithRGBTables8to8,
+ rfbTranslateWithRGBTables8to16,
+#ifdef ALLOW24BPP
+ rfbTranslateWithRGBTables8to24,
+#endif
+ rfbTranslateWithRGBTables8to32 },
+ { rfbTranslateWithRGBTables16to8,
+ rfbTranslateWithRGBTables16to16,
+#ifdef ALLOW24BPP
+ rfbTranslateWithRGBTables16to24,
+#endif
+ rfbTranslateWithRGBTables16to32 },
+#ifdef ALLOW24BPP
+ { rfbTranslateWithRGBTables24to8,
+ rfbTranslateWithRGBTables24to16,
+ rfbTranslateWithRGBTables24to24,
+ rfbTranslateWithRGBTables24to32 },
+#endif
+ { rfbTranslateWithRGBTables32to8,
+ rfbTranslateWithRGBTables32to16,
+#ifdef ALLOW24BPP
+ rfbTranslateWithRGBTables32to24,
+#endif
+ rfbTranslateWithRGBTables32to32 }
+};
+
+
+
+/*
+ * rfbTranslateNone is used when no translation is required.
+ */
+
+void
+rfbTranslateNone(char *table, rfbPixelFormat *in, rfbPixelFormat *out,
+ char *iptr, char *optr, int bytesBetweenInputLines,
+ int width, int height)
+{
+ int bytesPerOutputLine = width * (out->bitsPerPixel / 8);
+
+ while (height > 0) {
+ memcpy(optr, iptr, bytesPerOutputLine);
+ iptr += bytesBetweenInputLines;
+ optr += bytesPerOutputLine;
+ height--;
+ }
+}
+
+
+/*
+ * rfbSetTranslateFunction sets the translation function.
+ */
+
+Bool
+rfbSetTranslateFunction(cl)
+ rfbClientPtr cl;
+{
+ rfbLog("Pixel format for client %s:\n",cl->host);
+ PrintPixelFormat(&cl->format);
+
+ /*
+ * Check that bits per pixel values are valid
+ */
+
+ if ((cl->screen->rfbServerFormat.bitsPerPixel != 8) &&
+ (cl->screen->rfbServerFormat.bitsPerPixel != 16) &&
+#ifdef ALLOW24BPP
+ (cl->screen->rfbServerFormat.bitsPerPixel != 24) &&
+#endif
+ (cl->screen->rfbServerFormat.bitsPerPixel != 32))
+ {
+ rfbLog("%s: server bits per pixel not 8, 16 or 32 (is %d)\n",
+ "rfbSetTranslateFunction",
+ cl->screen->rfbServerFormat.bitsPerPixel);
+ rfbCloseClient(cl);
+ return FALSE;
+ }
+
+ if ((cl->format.bitsPerPixel != 8) &&
+ (cl->format.bitsPerPixel != 16) &&
+#ifdef ALLOW24BPP
+ (cl->format.bitsPerPixel != 24) &&
+#endif
+ (cl->format.bitsPerPixel != 32))
+ {
+ rfbLog("%s: client bits per pixel not 8, 16 or 32\n",
+ "rfbSetTranslateFunction");
+ rfbCloseClient(cl);
+ return FALSE;
+ }
+
+ if (!cl->format.trueColour && (cl->format.bitsPerPixel != 8)) {
+ rfbLog("rfbSetTranslateFunction: client has colour map "
+ "but %d-bit - can only cope with 8-bit colour maps\n",
+ cl->format.bitsPerPixel);
+ rfbCloseClient(cl);
+ return FALSE;
+ }
+
+ /*
+ * bpp is valid, now work out how to translate
+ */
+
+ if (!cl->format.trueColour) {
+ /*
+ * truecolour -> colour map
+ *
+ * Set client's colour map to BGR233, then effectively it's
+ * truecolour as well
+ */
+
+ if (!rfbSetClientColourMapBGR233(cl))
+ return FALSE;
+
+ cl->format = BGR233Format;
+ }
+
+ /* truecolour -> truecolour */
+
+ if (PF_EQ(cl->format,cl->screen->rfbServerFormat)) {
+
+ /* client & server the same */
+
+ rfbLog("no translation needed\n");
+ cl->translateFn = rfbTranslateNone;
+ return TRUE;
+ }
+
+ if ((cl->screen->rfbServerFormat.bitsPerPixel < 16) ||
+ ((!cl->screen->rfbServerFormat.trueColour || !rfbEconomicTranslate) &&
+ (cl->screen->rfbServerFormat.bitsPerPixel == 16))) {
+
+ /* we can use a single lookup table for <= 16 bpp */
+
+ cl->translateFn = rfbTranslateWithSingleTableFns
+ [BPP2OFFSET(cl->screen->rfbServerFormat.bitsPerPixel)]
+ [BPP2OFFSET(cl->format.bitsPerPixel)];
+
+ if(cl->screen->rfbServerFormat.trueColour)
+ (*rfbInitTrueColourSingleTableFns
+ [BPP2OFFSET(cl->format.bitsPerPixel)]) (&cl->translateLookupTable,
+ &(cl->screen->rfbServerFormat), &cl->format);
+ else
+ (*rfbInitColourMapSingleTableFns
+ [BPP2OFFSET(cl->format.bitsPerPixel)]) (&cl->translateLookupTable,
+ &(cl->screen->rfbServerFormat), &cl->format,&cl->screen->colourMap);
+
+ } else {
+
+ /* otherwise we use three separate tables for red, green and blue */
+
+ cl->translateFn = rfbTranslateWithRGBTablesFns
+ [BPP2OFFSET(cl->screen->rfbServerFormat.bitsPerPixel)]
+ [BPP2OFFSET(cl->format.bitsPerPixel)];
+
+ (*rfbInitTrueColourRGBTablesFns
+ [BPP2OFFSET(cl->format.bitsPerPixel)]) (&cl->translateLookupTable,
+ &(cl->screen->rfbServerFormat), &cl->format);
+ }
+
+ return TRUE;
+}
+
+
+
+/*
+ * rfbSetClientColourMapBGR233 sets the client's colour map so that it's
+ * just like an 8-bit BGR233 true colour client.
+ */
+
+static Bool
+rfbSetClientColourMapBGR233(cl)
+ rfbClientPtr cl;
+{
+ char buf[sz_rfbSetColourMapEntriesMsg + 256 * 3 * 2];
+ rfbSetColourMapEntriesMsg *scme = (rfbSetColourMapEntriesMsg *)buf;
+ CARD16 *rgb = (CARD16 *)(&buf[sz_rfbSetColourMapEntriesMsg]);
+ int i, len;
+ int r, g, b;
+
+ if (cl->format.bitsPerPixel != 8 ) {
+ rfbLog("%s: client not 8 bits per pixel\n",
+ "rfbSetClientColourMapBGR233");
+ rfbCloseClient(cl);
+ return FALSE;
+ }
+
+ scme->type = rfbSetColourMapEntries;
+
+ scme->firstColour = Swap16IfLE(0);
+ scme->nColours = Swap16IfLE(256);
+
+ len = sz_rfbSetColourMapEntriesMsg;
+
+ i = 0;
+
+ for (b = 0; b < 4; b++) {
+ for (g = 0; g < 8; g++) {
+ for (r = 0; r < 8; r++) {
+ rgb[i++] = Swap16IfLE(r * 65535 / 7);
+ rgb[i++] = Swap16IfLE(g * 65535 / 7);
+ rgb[i++] = Swap16IfLE(b * 65535 / 3);
+ }
+ }
+ }
+
+ len += 256 * 3 * 2;
+
+ if (WriteExact(cl, buf, len) < 0) {
+ rfbLogPerror("rfbSetClientColourMapBGR233: write");
+ rfbCloseClient(cl);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/* this function is not called very often, so it needn't be
+ efficient. */
+
+/*
+ * rfbSetClientColourMap is called to set the client's colour map. If the
+ * client is a true colour client, we simply update our own translation table
+ * and mark the whole screen as having been modified.
+ */
+
+Bool
+rfbSetClientColourMap(cl, firstColour, nColours)
+ rfbClientPtr cl;
+ int firstColour;
+ int nColours;
+{
+ if (cl->screen->rfbServerFormat.trueColour || !cl->readyForSetColourMapEntries) {
+ return TRUE;
+ }
+
+ if (nColours == 0) {
+ nColours = cl->screen->colourMap.count;
+ }
+
+ if (cl->format.trueColour) {
+ (*rfbInitColourMapSingleTableFns
+ [BPP2OFFSET(cl->format.bitsPerPixel)]) (&cl->translateLookupTable,
+ &cl->screen->rfbServerFormat, &cl->format,&cl->screen->colourMap);
+
+ sraRgnDestroy(cl->modifiedRegion);
+ cl->modifiedRegion =
+ sraRgnCreateRect(0,0,cl->screen->width,cl->screen->height);
+
+ return TRUE;
+ }
+
+ return rfbSendSetColourMapEntries(cl, firstColour, nColours);
+}
+
+
+/*
+ * rfbSetClientColourMaps sets the colour map for each RFB client.
+ */
+
+void
+rfbSetClientColourMaps(rfbScreen, firstColour, nColours)
+ rfbScreenInfoPtr rfbScreen;
+ int firstColour;
+ int nColours;
+{
+ rfbClientIteratorPtr i;
+ rfbClientPtr cl;
+
+ i = rfbGetClientIterator(rfbScreen);
+ while((cl = rfbClientIteratorNext(i)))
+ rfbSetClientColourMap(cl, firstColour, nColours);
+ rfbReleaseClientIterator(i);
+}
+
+static void
+PrintPixelFormat(pf)
+ rfbPixelFormat *pf;
+{
+ if (pf->bitsPerPixel == 1) {
+ rfbLog(" 1 bpp, %s sig bit in each byte is leftmost on the screen.\n",
+ (pf->bigEndian ? "most" : "least"));
+ } else {
+ rfbLog(" %d bpp, depth %d%s\n",pf->bitsPerPixel,pf->depth,
+ ((pf->bitsPerPixel == 8) ? ""
+ : (pf->bigEndian ? ", big endian" : ", little endian")));
+ if (pf->trueColour) {
+ rfbLog(" true colour: max r %d g %d b %d, shift r %d g %d b %d\n",
+ pf->redMax, pf->greenMax, pf->blueMax,
+ pf->redShift, pf->greenShift, pf->blueShift);
+ } else {
+ rfbLog(" uses a colour map (not true colour).\n");
+ }
+ }
+}
diff --git a/krfb/libvncserver/vncauth.c b/krfb/libvncserver/vncauth.c
new file mode 100644
index 00000000..ef27e356
--- /dev/null
+++ b/krfb/libvncserver/vncauth.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+/*
+ * vncauth.c - Functions for VNC password management and authentication.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <time.h>
+#ifdef WIN32
+#define srandom srand
+#define random rand
+#else
+#include <sys/time.h>
+#endif
+#include "rfb.h"
+#include "d3des.h"
+
+
+/*
+ * We use a fixed key to store passwords, since we assume that our local
+ * file system is secure but nonetheless don't want to store passwords
+ * as plaintext.
+ */
+
+unsigned char fixedkey[8] = {23,82,107,6,35,78,88,7};
+
+
+/*
+ * Encrypt a password and store it in a file. Returns 0 if successful,
+ * 1 if the file could not be written.
+ */
+
+int
+vncEncryptAndStorePasswd(char *passwd, char *fname)
+{
+ FILE *fp;
+ unsigned int i;
+ unsigned char encryptedPasswd[8];
+
+ if ((fp = fopen(fname,"w")) == NULL) return 1;
+
+ /* windows security sux */
+#ifndef WIN32
+ chmod(fname, S_IRUSR|S_IWUSR);
+#endif
+
+ /* pad password with nulls */
+
+ for (i = 0; i < 8; i++) {
+ if (i < strlen(passwd)) {
+ encryptedPasswd[i] = passwd[i];
+ } else {
+ encryptedPasswd[i] = 0;
+ }
+ }
+
+ /* Do encryption in-place - this way we overwrite our copy of the plaintext
+ password */
+
+ deskey(fixedkey, EN0);
+ des(encryptedPasswd, encryptedPasswd);
+
+ for (i = 0; i < 8; i++) {
+ putc(encryptedPasswd[i], fp);
+ }
+
+ fclose(fp);
+ return 0;
+}
+
+
+/*
+ * Decrypt a password from a file. Returns a pointer to a newly allocated
+ * string containing the password or a null pointer if the password could
+ * not be retrieved for some reason.
+ */
+
+char *
+vncDecryptPasswdFromFile(char *fname)
+{
+ FILE *fp;
+ int i, ch;
+ unsigned char *passwd = (unsigned char *)malloc(9);
+
+ if ((fp = fopen(fname,"r")) == NULL) return NULL;
+
+ for (i = 0; i < 8; i++) {
+ ch = getc(fp);
+ if (ch == EOF) {
+ fclose(fp);
+ return NULL;
+ }
+ passwd[i] = ch;
+ }
+
+ fclose(fp);
+
+ deskey(fixedkey, DE1);
+ des(passwd, passwd);
+
+ passwd[8] = 0;
+
+ return (char *)passwd;
+}
+
+
+/*
+ * Generate CHALLENGESIZE random bytes for use in challenge-response
+ * authentication.
+ */
+
+void
+vncRandomBytes(unsigned char *bytes)
+{
+ int i;
+ unsigned int seed = (unsigned int) time(0);
+
+ srandom(seed);
+ for (i = 0; i < CHALLENGESIZE; i++) {
+ bytes[i] = (unsigned char)(random() & 255);
+ }
+}
+
+
+/*
+ * Encrypt CHALLENGESIZE bytes in memory using a password.
+ */
+
+void
+vncEncryptBytes(unsigned char *bytes, char *passwd)
+{
+ unsigned char key[8];
+ unsigned int i;
+
+ /* key is simply password padded with nulls */
+
+ for (i = 0; i < 8; i++) {
+ if (i < strlen(passwd)) {
+ key[i] = passwd[i];
+ } else {
+ key[i] = 0;
+ }
+ }
+
+ deskey(key, EN0);
+
+ for (i = 0; i < CHALLENGESIZE; i += 8) {
+ des(bytes+i, bytes+i);
+ }
+}
diff --git a/krfb/libvncserver/vncev.c b/krfb/libvncserver/vncev.c
new file mode 100644
index 00000000..ba00f9c8
--- /dev/null
+++ b/krfb/libvncserver/vncev.c
@@ -0,0 +1,119 @@
+/* This program is a simple server to show events coming from the client */
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include "rfb.h"
+#include "default8x16.h"
+
+char f[640*480];
+char* keys[0x400];
+
+int hex2number(unsigned char c)
+{
+ if(c>'f') return(-1);
+ else if(c>'F')
+ return(10+c-'a');
+ else if(c>'9')
+ return(10+c-'A');
+ else
+ return(c-'0');
+}
+
+void read_keys()
+{
+ int i,j,k;
+ char buffer[1024];
+ FILE* keysyms=fopen("keysym.h","r");
+
+ memset(keys,0,0x400*sizeof(char*));
+
+ if(!keysyms)
+ return;
+
+ while(!feof(keysyms)) {
+ fgets(buffer,1024,keysyms);
+ if(!strncmp(buffer,"#define XK_",strlen("#define XK_"))) {
+ for(i=strlen("#define XK_");buffer[i] && buffer[i]!=' '
+ && buffer[i]!='\t';i++);
+ if(buffer[i]==0) /* don't support wrapped lines */
+ continue;
+ buffer[i]=0;
+ for(i++;buffer[i] && buffer[i]!='0';i++);
+ if(buffer[i]==0 || buffer[i+1]!='x') continue;
+ for(j=0,i+=2;(k=hex2number(buffer[i]))>=0;i++)
+ j=j*16+k;
+ if(keys[j&0x3ff]) {
+ char* x=malloc(1+strlen(keys[j&0x3ff])+1+strlen(buffer+strlen("#define ")));
+ strcpy(x,keys[j&0x3ff]);
+ strcat(x,",");
+ strcat(x,buffer+strlen("#define "));
+ free(keys[j&0x3ff]);
+ keys[j&0x3ff]=x;
+ } else
+ keys[j&0x3ff] = strdup(buffer+strlen("#define "));
+ }
+
+ }
+ fclose(keysyms);
+}
+
+int lineHeight=16,lineY=480-16;
+void output(rfbScreenInfoPtr s,char* line)
+{
+ rfbDoCopyRect(s,0,0,640,480-lineHeight,0,-lineHeight);
+ rfbDrawString(s,&default8x16Font,10,lineY,line,0x01);
+ fprintf(stderr,"%s\n",line);
+}
+
+void dokey(Bool down,KeySym k,rfbClientPtr cl)
+{
+ char buffer[1024];
+
+ sprintf(buffer,"%s: %s (0x%x)",
+ down?"down":"up",keys[k&0x3ff]?keys[k&0x3ff]:"",k);
+ output(cl->screen,buffer);
+}
+
+void doptr(int buttonMask,int x,int y,rfbClientPtr cl)
+{
+ char buffer[1024];
+ if(buttonMask) {
+ sprintf(buffer,"Ptr: mouse button mask 0x%x at %d,%d",buttonMask,x,y);
+ output(cl->screen,buffer);
+ }
+
+}
+
+void newclient(rfbClientPtr cl)
+{
+ char buffer[1024];
+ struct sockaddr_in addr;
+ int len=sizeof(addr),ip;
+
+ getpeername(cl->sock,&addr,&len);
+ ip=ntohl(addr.sin_addr.s_addr);
+ sprintf(buffer,"Client connected from ip %d.%d.%d.%d",
+ (ip>>24)&0xff,(ip>>16)&0xff,(ip>>8)&0xff,ip&0xff);
+ output(cl->screen,buffer);
+}
+
+int main(int argc,char** argv)
+{
+ rfbScreenInfoPtr s=rfbGetScreen(&argc,argv,640,480,8,1,1);
+ s->colourMap.is16=FALSE;
+ s->colourMap.count=2;
+ s->colourMap.data.bytes="\xd0\xd0\xd0\x30\x01\xe0";
+ s->rfbServerFormat.trueColour=FALSE;
+ s->frameBuffer=f;
+ s->kbdAddEvent=dokey;
+ s->ptrAddEvent=doptr;
+ s->newClientHook=newclient;
+
+ memset(f,0,640*480);
+ read_keys();
+ rfbInitServer(s);
+
+ while(1) {
+ rfbProcessEvents(s,999999);
+ }
+}
diff --git a/krfb/libvncserver/x11vnc.c b/krfb/libvncserver/x11vnc.c
new file mode 100644
index 00000000..4e298f4a
--- /dev/null
+++ b/krfb/libvncserver/x11vnc.c
@@ -0,0 +1,578 @@
+/* This file (x11vnc.c) is part of LibVNCServer.
+ It is a small clone of x0rfbserver by HexoNet, demonstrating the
+ capabilities of LibVNCServer.
+*/
+
+#include <X11/Xlib.h>
+#include <X11/keysym.h>
+#include <X11/extensions/XTest.h>
+#ifndef NO_SHM
+#include <X11/extensions/XShm.h>
+#include <sys/shm.h>
+#endif
+#define KEYSYM_H
+#undef Bool
+#define KeySym RFBKeySym
+#include "rfb.h"
+
+Display *dpy = 0;
+int window;
+int c=0,blockLength = 32;
+int tileX=0,tileY=0,tileWidth=32,tileHeight=32*2,dontTile=TRUE;
+Bool gotInput = FALSE;
+Bool viewOnly = FALSE;
+Bool sharedMode = FALSE;
+
+Bool disconnectAfterFirstClient = TRUE;
+
+/* keyboard handling */
+#define KBDDEBUG
+
+char modifiers[0x100];
+KeyCode keycodes[0x100],leftShiftCode,rightShiftCode,altGrCode;
+
+void init_keycodes()
+{
+ KeySym key,*keymap;
+ int i,j,minkey,maxkey,syms_per_keycode;
+
+ memset(modifiers,-1,sizeof(modifiers));
+
+ XDisplayKeycodes(dpy,&minkey,&maxkey);
+ keymap=XGetKeyboardMapping(dpy,minkey,(maxkey - minkey + 1),&syms_per_keycode);
+
+#ifdef KBDDEBUG
+ fprintf(stderr,"minkey=%d, maxkey=%d, syms_per_keycode=%d\n",
+ minkey,maxkey,syms_per_keycode);
+#endif
+ for (i = minkey; i <= maxkey; i++)
+ for(j=0;j<syms_per_keycode;j++) {
+ key=keymap[(i-minkey)*syms_per_keycode+j];
+#ifdef KBDDEBUG
+ fprintf(stderr,"keymap(i=0x%x,j=%d)==0x%lx\n",i,j,key);
+#endif
+ if(key>=' ' && key<0x100 && i==XKeysymToKeycode(dpy,key)) {
+ keycodes[key]=i;
+ modifiers[key]=j;
+#ifdef KBDDEBUG
+ fprintf(stderr,"key 0x%lx (%c): keycode=0x%x, modifier=%d\n",
+ key,(char)key,i,j);
+#endif
+ }
+ }
+
+ leftShiftCode=XKeysymToKeycode(dpy,XK_Shift_L);
+ rightShiftCode=XKeysymToKeycode(dpy,XK_Shift_R);
+ altGrCode=XKeysymToKeycode(dpy,XK_Mode_switch);
+
+#ifdef KBDDEBUG
+ fprintf(stderr,"leftShift=0x%x, rightShift=0x%x, altGr=0x%x\n",
+ leftShiftCode,rightShiftCode,altGrCode);
+#endif
+
+ XFree ((char *) keymap);
+}
+
+static Bool shutDownServer=0;
+
+/* the hooks */
+
+void clientGone(rfbClientPtr cl)
+{
+ shutDownServer=-1;
+}
+
+enum rfbNewClientAction newClient(rfbClientPtr cl)
+{
+ if(disconnectAfterFirstClient)
+ cl->clientGoneHook = clientGone;
+ if(viewOnly)
+ cl->clientData = (void*)-1;
+ else
+ cl->clientData = (void*)0;
+ return(RFB_CLIENT_ACCEPT);
+}
+
+#define LEFTSHIFT 1
+#define RIGHTSHIFT 2
+#define ALTGR 4
+char ModifierState = 0;
+
+/* this function adjusts the modifiers according to mod (as from modifiers) and ModifierState */
+
+void tweakModifiers(char mod,Bool down)
+{
+ Bool isShift=ModifierState&(LEFTSHIFT|RIGHTSHIFT);
+#ifdef KBDDEBUG
+ fprintf(stderr,"tweakModifiers: 0x%x %s\n",
+ mod,down?"down":"up");
+#endif
+ if(mod<0) return;
+ if(isShift && mod!=1) {
+ if(ModifierState&LEFTSHIFT)
+ XTestFakeKeyEvent(dpy,leftShiftCode,!down,CurrentTime);
+ if(ModifierState&RIGHTSHIFT)
+ XTestFakeKeyEvent(dpy,rightShiftCode,!down,CurrentTime);
+ }
+ if(!isShift && mod==1)
+ XTestFakeKeyEvent(dpy,leftShiftCode,down,CurrentTime);
+
+ if(ModifierState&ALTGR && mod!=2)
+ XTestFakeKeyEvent(dpy,altGrCode,!down,CurrentTime);
+ if(!(ModifierState&ALTGR) && mod==2)
+ XTestFakeKeyEvent(dpy,altGrCode,down,CurrentTime);
+}
+
+void keyboard(Bool down,KeySym keySym,rfbClientPtr cl)
+{
+ if(((int)cl->clientData)==-1) return; /* viewOnly */
+
+#define ADJUSTMOD(sym,state) \
+ if(keySym==sym) { if(down) ModifierState|=state; else ModifierState&=~state; }
+
+ ADJUSTMOD(XK_Shift_L,LEFTSHIFT)
+ ADJUSTMOD(XK_Shift_R,RIGHTSHIFT)
+ ADJUSTMOD(XK_Mode_switch,ALTGR)
+
+#ifdef KBDDEBUG
+ fprintf(stderr,"keyboard: down=%s, keySym=0x%lx (%s), ModState=0x%x\n",
+ down?"down":"up",keySym,XKeysymToString(keySym),ModifierState);
+#endif
+
+ if(keySym>=' ' && keySym<0x100) {
+ KeyCode k;
+ if(down)
+ tweakModifiers(modifiers[keySym],True);
+ //tweakModifiers(modifiers[keySym],down);
+ //k = XKeysymToKeycode( dpy,keySym );
+ k = keycodes[keySym];
+ if(k!=NoSymbol) {
+ XTestFakeKeyEvent(dpy,k,down,CurrentTime);
+ gotInput = TRUE;
+ }
+ if(down)
+ tweakModifiers(modifiers[keySym],False);
+ gotInput = TRUE;
+ } else {
+ KeyCode k = XKeysymToKeycode( dpy,keySym );
+ if(k!=NoSymbol) {
+ XTestFakeKeyEvent(dpy,k,down,CurrentTime);
+ gotInput = TRUE;
+ }
+ }
+}
+
+int oldButtonMask = 0;
+
+void mouse(int buttonMask,int x,int y,rfbClientPtr cl)
+{
+ int i=0;
+
+ if(((int)cl->clientData)==-1) return; /* viewOnly */
+
+ XTestFakeMotionEvent(dpy,0,x,y,CurrentTime );
+ while(i<5) {
+ if ((oldButtonMask&(1<<i))!=(buttonMask&(1<<i)))
+ XTestFakeButtonEvent(dpy,i+1,(buttonMask&(1<<i))?True:False,CurrentTime);
+ i++;
+ }
+ oldButtonMask = buttonMask;
+ //fprintf(stderr,"-");
+ gotInput = TRUE;
+}
+
+/* the X11 interaction */
+
+#ifndef NO_SHM
+Bool useSHM = TRUE;
+XShmSegmentInfo shminfo;
+#else
+Bool useSHM = FALSE;
+#endif
+
+void getImage(int bpp,Display *dpy,int xscreen,XImage **i,int x,int y,int width,int height)
+{
+ if(width<=0) width=DisplayWidth(dpy,xscreen);
+ if(height<=0) height=DisplayHeight(dpy,xscreen);
+ if(useSHM && bpp>0) {
+ static Bool firstTime = TRUE;
+ if(firstTime) {
+ firstTime = FALSE;
+ *i = XShmCreateImage(dpy,
+ DefaultVisual( dpy, xscreen ),
+ bpp,
+ ZPixmap,
+ NULL,
+ &shminfo,
+ width,height);
+
+ if(*i == 0) {
+ useSHM = FALSE;
+ getImage(bpp,dpy,xscreen,i,x,y,width,height);
+ return;
+ }
+
+ shminfo.shmid = shmget( IPC_PRIVATE,
+ (*i)->bytes_per_line * (*i)->height,
+ IPC_CREAT | 0777 );
+ shminfo.shmaddr = (*i)->data = (char *) shmat( shminfo.shmid, 0, 0 );
+ shminfo.readOnly = False;
+ XShmAttach( dpy, &shminfo );
+ }
+
+ if(x==0 && y==0 && width==DisplayWidth(dpy,xscreen) && height==DisplayHeight(dpy,xscreen))
+ XShmGetImage(dpy,window,*i,0,0,AllPlanes);
+ else
+ XGetSubImage(dpy,window,x,y,width,height,AllPlanes,ZPixmap,*i,0,0);
+ } else {
+ *i = XGetImage(dpy,window,x,y,width,height,AllPlanes,ZPixmap );
+ }
+}
+
+void checkForImageUpdates(rfbScreenInfoPtr s,char *b,int rowstride,int x,int y,int width,int height)
+{
+ Bool changed;
+ int i,j,k,l1,l2,x1,y1;
+ int bpp=s->bitsPerPixel/8;
+
+ for(j=0;j<height;j+=blockLength)
+ for(i=0;i<width;i+=blockLength) {
+ y1=j+blockLength; if(y1>height) y1=height;
+ x1=i+blockLength; if(x1>width) x1=width;
+ y1*=rowstride;
+ x1*=bpp;
+ changed=FALSE;
+ for(l1=j*rowstride,l2=(j+y)*s->paddedWidthInBytes+x*bpp;l1<y1;l1+=rowstride,l2+=s->paddedWidthInBytes)
+ for(k=i*bpp;k<x1;k++)
+ if(s->frameBuffer[l2+k]!=b[l1+k]) {
+ // fprintf(stderr,"changed: %d, %d\n",k,l);
+ changed=TRUE;
+ goto changed_p;
+ }
+ if(changed) {
+ changed_p:
+ for(l1+=i*bpp,l2+=i*bpp;l1<y1;l1+=rowstride,l2+=s->paddedWidthInBytes)
+ memcpy(/*b+l,*/s->frameBuffer+l2,b+l1,x1-i*bpp);
+ rfbMarkRectAsModified(s,x+i,y+j,x+i+blockLength,y+j+blockLength);
+ }
+ }
+}
+
+int probeX=0,probeY=0;
+
+void probeScreen(rfbScreenInfoPtr s,int xscreen)
+{
+ int i,j,/*pixel,i1,*/j1,
+ bpp=s->rfbServerFormat.bitsPerPixel/8,/*mask=(1<<bpp)-1,*/
+ rstride=s->paddedWidthInBytes;
+ XImage* im;
+ //fprintf(stderr,"/%d,%d",probeX,probeY);
+#if 0
+ probeX++;
+ if(probeX>=tileWidth) {
+ probeX=0;
+ probeY++;
+ if(probeY>=tileHeight)
+ probeY=0;
+ }
+#else
+ probeX=(rand()%tileWidth);
+ probeY=(rand()%tileHeight);
+#endif
+
+ for(j=probeY;j<s->height;j+=tileHeight)
+ for(i=0/*probeX*/;i<s->width;i+=tileWidth) {
+ im=XGetImage(dpy,window,i,j,tileWidth/*1*/,1,AllPlanes,ZPixmap);
+ /* for(i1=0;i1<bpp && im->data[i1]==(s->frameBuffer+i*bpp+j*rstride)[i1];i1++);
+ if(i1<bpp) { */
+ if(memcmp(im->data,s->frameBuffer+i*bpp+j*rstride,tileWidth*bpp)) {
+ /* do update */
+ int x=i/*-probeX*/,w=(x+tileWidth>s->width)?s->width-x:tileWidth,
+ y=j-probeY,h=(y+tileHeight>s->height)?s->height-y:tileHeight;
+
+ XDestroyImage(im);
+ //getImage(bpp,dpy,xscreen,&im,x,y,w,h);
+ //fprintf(stderr,"GetImage(%d,%d,%d,%d)",x,y,w,h);
+ im = XGetImage(dpy,window,x,y,w,h,AllPlanes,ZPixmap );
+ for(j1=0;j1<h;j1++)
+ memcpy(s->frameBuffer+x*bpp+(y+j1)*rstride,
+ im->data+j1*im->bytes_per_line,bpp*w);
+ //checkForImageUpdates(s,im->data,rstride,x,y,w,h);
+ //if(0 && !useSHM)
+ XDestroyImage(im);
+ //memcpy(s->frameBuffer+i*bpp+j*rstride,&pixel,bpp);
+ rfbMarkRectAsModified(s,x,y,x+w,y+h);
+ //fprintf(stderr,"%d:%d:%x\n",i,j,pixel);
+ //fprintf(stderr,"*");
+ } else
+ XDestroyImage(im);
+ }
+}
+
+#define LOCAL_CONTROL
+
+#ifdef LOCAL_CONTROL
+#include "1instance.c"
+#endif
+
+/* the main program */
+
+int main(int argc,char** argv)
+{
+ //Screen *sc;
+ //Colormap cm;
+ XImage *framebufferImage;
+ char *backupImage;
+ int xscreen,i;
+ rfbScreenInfoPtr screen;
+ int maxMsecsToConnect = 5000; /* a maximum of 5 seconds to connect */
+ int updateCounter; /* about every 50 ms a screen update should be made. */
+
+#ifdef LOCAL_CONTROL
+ char message[1024];
+ single_instance_struct single_instance = { "/tmp/x11vnc_control" };
+
+ open_control_file(&single_instance);
+#endif
+
+ for(i=argc-1;i>0;i--)
+#ifdef LOCAL_CONTROL
+ if(i<argc-1 && !strcmp(argv[i],"-toggleviewonly")) {
+ snprintf(message, sizeof(message), "t%s",argv[i+1]);
+ send_message(&single_instance,message);
+ exit(0);
+ } else if(!strcmp(argv[i],"-listclients")) {
+ fprintf(stderr,"list clients\n");
+ send_message(&single_instance,"l");
+ exit(0);
+ } else
+#ifdef BACKCHANNEL
+ if(i<argc-1 && !strcmp(argv[i],"-backchannel")) {
+ snprintf(message, sizeof(message), "b%s",argv[i+1]);
+ send_message(&single_instance,message);
+ exit(0);
+ } else
+#endif
+#endif
+ if(i<argc-1 && strcmp(argv[i],"-display")==0) {
+ fprintf(stderr,"Using display %s\n",argv[i+1]);
+ dpy = XOpenDisplay(argv[i+1]);
+ if(dpy==0) {
+ fprintf(stderr,"Couldn't connect to display \"%s\".\n",argv[i+1]);
+ exit(1);
+ }
+ } else if(i<argc-1 && strcmp(argv[i],"-wait4client")==0) {
+ maxMsecsToConnect = atoi(argv[i+1]);
+ } else if(i<argc-1 && strcmp(argv[i],"-update")==0) {
+ updateCounter = atoi(argv[i+1]);
+ } else if(strcmp(argv[i],"-noshm")==0) {
+ useSHM = FALSE;
+ } else if(strcmp(argv[i],"-runforever")==0) {
+ disconnectAfterFirstClient = FALSE;
+ } else if(strcmp(argv[i],"-tile")==0) {
+ dontTile=FALSE;
+ } else if(strcmp(argv[i],"-viewonly")==0) {
+ viewOnly=TRUE;
+ } else if(strcmp(argv[i],"-shared")==0) {
+ sharedMode=TRUE;
+ }
+
+ updateCounter = dontTile?20:1;
+
+ if(dpy==0)
+ dpy = XOpenDisplay("");
+ if(dpy==0) {
+ fprintf(stderr,"Couldn't open display!\n");
+ exit(2);
+ }
+
+ xscreen = DefaultScreen(dpy);
+ window = RootWindow(dpy,xscreen);
+ //XTestGrabControl(dpy,True);
+
+ init_keycodes();
+
+ getImage(0,dpy,xscreen,&framebufferImage,0,0,-1,-1);
+
+ screen = rfbGetScreen(&argc,argv,framebufferImage->width,
+ framebufferImage->height,
+ framebufferImage->bits_per_pixel,
+ 8,
+ framebufferImage->bits_per_pixel/8);
+
+ screen->paddedWidthInBytes = framebufferImage->bytes_per_line;
+
+ screen->rfbServerFormat.bitsPerPixel = framebufferImage->bits_per_pixel;
+ screen->rfbServerFormat.depth = framebufferImage->depth;
+ //rfbEndianTest = framebufferImage->bitmap_bit_order != MSBFirst;
+ screen->rfbServerFormat.trueColour = TRUE;
+
+ if ( screen->rfbServerFormat.bitsPerPixel == 8 ) {
+ if(CellsOfScreen(ScreenOfDisplay(dpy,xscreen))) {
+ XColor color[256];
+ int i;
+ screen->colourMap.count = 256;
+ screen->rfbServerFormat.trueColour = FALSE;
+ screen->colourMap.is16 = TRUE;
+ for(i=0;i<256;i++)
+ color[i].pixel=i;
+ XQueryColors(dpy,DefaultColormap(dpy,xscreen),color,256);
+ screen->colourMap.data.shorts = (short*)malloc(3*sizeof(short)*screen->colourMap.count);
+ for(i=0;i<screen->colourMap.count;i++) {
+ screen->colourMap.data.shorts[i*3+0] = color[i].red;
+ screen->colourMap.data.shorts[i*3+1] = color[i].green;
+ screen->colourMap.data.shorts[i*3+2] = color[i].blue;
+ }
+ } else {
+ screen->rfbServerFormat.redShift = 0;
+ screen->rfbServerFormat.greenShift = 2;
+ screen->rfbServerFormat.blueShift = 5;
+ screen->rfbServerFormat.redMax = 3;
+ screen->rfbServerFormat.greenMax = 7;
+ screen->rfbServerFormat.blueMax = 3;
+ }
+ } else {
+ screen->rfbServerFormat.redShift = 0;
+ if ( framebufferImage->red_mask )
+ while ( ! ( framebufferImage->red_mask & (1 << screen->rfbServerFormat.redShift) ) )
+ screen->rfbServerFormat.redShift++;
+ screen->rfbServerFormat.greenShift = 0;
+ if ( framebufferImage->green_mask )
+ while ( ! ( framebufferImage->green_mask & (1 << screen->rfbServerFormat.greenShift) ) )
+ screen->rfbServerFormat.greenShift++;
+ screen->rfbServerFormat.blueShift = 0;
+ if ( framebufferImage->blue_mask )
+ while ( ! ( framebufferImage->blue_mask & (1 << screen->rfbServerFormat.blueShift) ) )
+ screen->rfbServerFormat.blueShift++;
+ screen->rfbServerFormat.redMax = framebufferImage->red_mask >> screen->rfbServerFormat.redShift;
+ screen->rfbServerFormat.greenMax = framebufferImage->green_mask >> screen->rfbServerFormat.greenShift;
+ screen->rfbServerFormat.blueMax = framebufferImage->blue_mask >> screen->rfbServerFormat.blueShift;
+ }
+
+ backupImage = malloc(screen->height*screen->paddedWidthInBytes);
+ memcpy(backupImage,framebufferImage->data,screen->height*screen->paddedWidthInBytes);
+
+ screen->frameBuffer = backupImage;
+ screen->cursor = 0;
+ screen->newClientHook = newClient;
+
+ screen->kbdAddEvent = keyboard;
+ screen->ptrAddEvent = mouse;
+
+ if(sharedMode) {
+ screen->rfbAlwaysShared = TRUE;
+ }
+
+ screen->rfbDeferUpdateTime = 1;
+ updateCounter /= screen->rfbDeferUpdateTime;
+
+ rfbInitServer(screen);
+
+ c=0;
+ while(1) {
+ if(screen->rfbClientHead)
+ maxMsecsToConnect = 1<<16;
+ else {
+ maxMsecsToConnect -= screen->rfbDeferUpdateTime;
+ if(maxMsecsToConnect<0) {
+ fprintf(stderr,"Maximum time to connect reached. Exiting.\n");
+ XTestDiscard(dpy);
+ exit(2);
+ }
+ }
+
+#ifdef LOCAL_CONTROL
+ if(get_next_message(message,1024,&single_instance,50)) {
+ if(message[0]=='l' && message[1]==0) {
+ rfbClientPtr cl;
+ int i;
+ for(i=0,cl=screen->rfbClientHead;cl;cl=cl->next,i++)
+ fprintf(stderr,"%02d: %s\n",i,cl->host);
+ } else if(message[0]=='t') {
+ rfbClientPtr cl;
+ for(cl=screen->rfbClientHead;cl;cl=cl->next)
+ if(!strcmp(message+1,cl->host)) {
+ cl->clientData=(void*)((cl->clientData==0)?-1:0);
+ break;
+ }
+ }
+#ifdef BACKCHANNEL
+ else if(message[0]=='b')
+ rfbSendBackChannel(screen,message+1,strlen(message+1));
+#endif
+ }
+#endif
+
+ rfbProcessEvents(screen,-1);
+ if(shutDownServer) {
+ free(backupImage);
+ rfbScreenCleanup(screen);
+ XFree(dpy);
+#ifndef NO_SHM
+ XShmDetach(dpy,framebufferImage);
+#endif
+ exit(0);
+ }
+
+ if(dontTile) {
+ if(gotInput) {
+ gotInput = FALSE;
+ c=updateCounter;
+ } else if(screen->rfbClientHead && c++>updateCounter) {
+ c=0;
+ //fprintf(stderr,"*");
+ if(!useSHM)
+ framebufferImage->f.destroy_image(framebufferImage);
+ if(dontTile) {
+ getImage(screen->rfbServerFormat.bitsPerPixel,dpy,xscreen,&framebufferImage,0,0,screen->width,screen->height);
+ checkForImageUpdates(screen,framebufferImage->data,framebufferImage->bytes_per_line,
+ 0,0,screen->width,screen->height);
+ } else {
+ /* old tile code. Eventually to be removed (TODO) */
+ char isRightEdge = tileX+tileWidth>=screen->width;
+ char isLowerEdge = tileY+tileHeight>=screen->height;
+ getImage(screen->rfbServerFormat.bitsPerPixel,dpy,xscreen,&framebufferImage,tileX,tileY,
+ isRightEdge?screen->width-tileX:tileWidth,
+ isLowerEdge?screen->height-tileY:tileHeight);
+ checkForImageUpdates(screen,framebufferImage->data,framebufferImage->bytes_per_line,
+ tileX,tileY,
+ isRightEdge?screen->width-tileX:tileWidth,
+ isLowerEdge?screen->height-tileY:tileHeight);
+ if(isRightEdge) {
+ tileX=0;
+ if(isLowerEdge)
+ tileY=0;
+ else
+ tileY+=tileHeight;
+ } else
+ tileX+=tileWidth;
+ }
+ }
+ } else if(c++>updateCounter) {
+ c=0;
+ probeScreen(screen,xscreen);
+ }
+
+#ifdef WRITE_SNAPS
+ {
+ int i,j,r,g,b;
+ FILE* f=fopen("test.pnm","wb");
+ fprintf(f,"P6\n%d %d\n255\n",screen->width,screen->height);
+ for(j=0;j<screen->height;j++)
+ for(i=0;i<screen->width;i++) {
+ //r=screen->frameBuffer[j*screen->paddedWidthInBytes+i*2];
+ r=framebufferImage->data[j*screen->paddedWidthInBytes+i*2];
+ fputc(((r>>screen->rfbServerFormat.redShift)&screen->rfbServerFormat.redMax)*255/screen->rfbServerFormat.redMax,f);
+ fputc(((r>>screen->rfbServerFormat.greenShift)&screen->rfbServerFormat.greenMax)*255/screen->rfbServerFormat.greenMax,f);
+ fputc(((r>>screen->rfbServerFormat.blueShift)&screen->rfbServerFormat.blueMax)*255/screen->rfbServerFormat.blueMax,f);
+ }
+ fclose(f);
+ }
+#endif
+ }
+#ifndef NO_SHM
+ //XShmDetach(dpy,framebufferImage);
+#endif
+
+ return(0);
+}
diff --git a/krfb/libvncserver/zippy.c b/krfb/libvncserver/zippy.c
new file mode 100644
index 00000000..2f35059d
--- /dev/null
+++ b/krfb/libvncserver/zippy.c
@@ -0,0 +1,182 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <rfb.h>
+#include <keysym.h>
+#include "radon.h"
+
+int maxx=400, maxy=400, bpp=4;
+/* odd maxx doesn't work (vncviewer bug) */
+
+/* Here we create a structure so that every client has it's own pointer */
+
+/* turns the framebuffer black */
+void blank_framebuffer(char* frame_buffer, int x1, int y1, int x2, int y2);
+/* displays a red bar, a green bar, and a blue bar */
+void draw_primary_colors (char* frame_buffer, int x1, int y1, int x2, int y2);
+void linecount (char* frame_buffer);
+/* handles mouse events */
+void on_mouse_event (int buttonMask,int x,int y,rfbClientPtr cl);
+/* handles keyboard events */
+void on_key_press (Bool down,KeySym key,rfbClientPtr cl);
+
+int main (int argc, char **argv)
+{
+ int i;
+ rfbScreenInfoPtr server;
+
+ rfbProcessSizeArguments(&maxx,&maxy,&bpp,&argc,argv);
+
+ server = rfbGetScreen (&argc, argv, maxx, maxy, 8, 3, bpp);
+ server->desktopName = "Zippy das wundersquirrel\'s VNC server";
+ server->frameBuffer = (char*)malloc(maxx*maxy*bpp);
+ server->rfbAlwaysShared = TRUE;
+ server->kbdAddEvent = on_key_press;
+ server->ptrAddEvent = on_mouse_event;
+
+ rfbInitServer (server);
+
+ blank_framebuffer(server->frameBuffer, 0, 0, maxx, maxy);
+ rfbRunEventLoop (server, -1, FALSE);
+ free(server->frameBuffer);
+ rfbScreenCleanup (server);
+ return 0;
+}
+
+void blank_framebuffer(char* frame_buffer, int x1, int y1, int x2, int y2)
+{
+ int i;
+ for (i=0; i < maxx * maxy * bpp; i++) frame_buffer[i]=(char) 0;
+}
+
+void draw_primary_colors (char* frame_buffer, int x1, int y1, int x2, int y2)
+{
+ int i, j, current_pixel;
+ for (i=y1; i < y2; i++){
+ for (j=x1; j < x2; j++) {
+ current_pixel = (i*x2 + j) * bpp;
+ if (i < y2 ) {
+ frame_buffer[current_pixel+0] = (char) 128;
+ frame_buffer[current_pixel+1] = (char) 0;
+ frame_buffer[current_pixel+2] = (char) 0;
+ }
+ if (i < y2/3*2) {
+ frame_buffer[current_pixel+0] = (char) 0;
+ frame_buffer[current_pixel+1] = (char) 128;
+ frame_buffer[current_pixel+2] = (char) 0;
+ }
+ if (i < y2/3) {
+ frame_buffer[current_pixel+0] = (char) 0;
+ frame_buffer[current_pixel+1] = (char) 0;
+ frame_buffer[current_pixel+2] = (char) 128;
+ }
+ }
+ }
+ }
+
+/* Dscho's versions (slower, but works for bpp != 3 or 4) */
+void draw_primary_colours_generic(rfbScreenInfoPtr s,int x1,int y1,int x2,int y2)
+{
+ rfbPixelFormat f=s->rfbServerFormat;
+ int i,j;
+ for(j=y1;j<y2;j++)
+ for(i=x1;i<x2;i++)
+ if(j<y1*2/3+y2/3)
+ rfbDrawPixel(s,i,j,f.redMax<<f.redShift);
+ else if(j<y1/3+y2*2/3)
+ rfbDrawPixel(s,i,j,f.greenMax<<f.greenShift);
+ else
+ rfbDrawPixel(s,i,j,f.blueMax<<f.blueShift);
+}
+
+void draw_primary_colours_generic_fast(rfbScreenInfoPtr s,int x1,int y1,int x2,int y2)
+{
+ rfbPixelFormat f=s->rfbServerFormat;
+ int i,j,y3=(y1*2+y2)/3,y4=(y1+y2*2)/3;
+ /* draw first pixel */
+ rfbDrawPixel(s,x1,y1,f.redMax<<f.redShift);
+ rfbDrawPixel(s,x1,y3,f.greenMax<<f.greenShift);
+ rfbDrawPixel(s,x1,y4,f.blueMax<<f.blueShift);
+ /* then copy stripes */
+ for(j=0;j<y2-y4;j++)
+ for(i=x1;i<x2;i++) {
+#define ADDR(x,y) s->frameBuffer+(x)*bpp+(y)*s->paddedWidthInBytes
+ memcpy(ADDR(i,j+y1),ADDR(x1,y1),bpp);
+ memcpy(ADDR(i,j+y3),ADDR(x1,y3),bpp);
+ memcpy(ADDR(i,j+y4),ADDR(x1,y4),bpp);
+ }
+}
+
+void draw_primary_colours_generic_ultrafast(rfbScreenInfoPtr s,int x1,int y1,int x2,int y2)
+{
+ rfbPixelFormat f=s->rfbServerFormat;
+ int i,j,y3=(y1*2+y2)/3,y4=(y1+y2*2)/3;
+ /* fill rectangles */
+ rfbFillRect(s,x1,y1,x2,y3,f.redMax<<f.redShift);
+ rfbFillRect(s,x1,y3,x2,y4,f.greenMax<<f.greenShift);
+ rfbFillRect(s,x1,y4,x2,y2,f.blueMax<<f.blueShift);
+}
+
+void linecount (char* frame_buffer)
+{
+ int i,j,k, current_pixel;
+ for (i=maxy-4; i>maxy-20; i-=4)
+ for (j=0; j<4; j++) for (k=0; k < maxx; k++) {
+ current_pixel = (i*j*maxx + k) * bpp;
+ if (i%2 == 0) {
+ frame_buffer[current_pixel+0] = (char) 0;
+ frame_buffer[current_pixel+1] = (char) 0;
+ frame_buffer[current_pixel+2] = (char) 128;
+ }
+
+ if (i%2 == 1) {
+ frame_buffer[current_pixel+0] = (char) 128;
+ frame_buffer[current_pixel+1] = (char) 0;
+ frame_buffer[current_pixel+2] = (char) 0;
+ }
+ }
+
+}
+
+
+void on_key_press (Bool down,KeySym key,rfbClientPtr cl)
+{
+ if (down) //or else the action occurs on both the press and depress
+ switch (key) {
+
+ case XK_b:
+ case XK_B:
+ rfbUndrawCursor(cl->screen);
+ blank_framebuffer(cl->screen->frameBuffer, 0, 0, maxx, maxy);
+ rfbDrawString(cl->screen,&radonFont,20,maxy-20,"Hello, World!",0xffffff);
+ rfbMarkRectAsModified(cl->screen,0, 0,maxx,maxy);
+ fprintf (stderr, "Framebuffer blanked\n");
+ break;
+ case XK_p:
+ case XK_P:
+ rfbUndrawCursor(cl->screen);
+ /* draw_primary_colors (cl->screen->frameBuffer, 0, 0, maxx, maxy); */
+ draw_primary_colours_generic_ultrafast (cl->screen, 0, 0, maxx, maxy);
+ rfbMarkRectAsModified(cl->screen,0, 0,maxx,maxy);
+ fprintf (stderr, "Primary colors displayed\n");
+ break;
+ case XK_Q:
+ case XK_q:
+ fprintf (stderr, "Exiting now\n");
+ exit(0);
+ case XK_C:
+ case XK_c:
+ rfbUndrawCursor(cl->screen);
+ rfbDrawString(cl->screen,&radonFont,20,100,"Hello, World!",0xffffff);
+ rfbMarkRectAsModified(cl->screen,0, 0,maxx,maxy);
+ break;
+ default:
+ fprintf (stderr, "The %c key was pressed\n", (char) key);
+ }
+}
+
+
+void on_mouse_event (int buttonMask,int x,int y,rfbClientPtr cl)
+{
+ printf("buttonMask: %i\n"
+ "x: %i\n" "y: %i\n", buttonMask, x, y);
+}
diff --git a/krfb/libvncserver/zlib.c b/krfb/libvncserver/zlib.c
new file mode 100644
index 00000000..1eac366d
--- /dev/null
+++ b/krfb/libvncserver/zlib.c
@@ -0,0 +1,304 @@
+/*
+ * zlib.c
+ *
+ * Routines to implement zlib based encoding (deflate).
+ */
+
+/*
+ * Copyright (C) 2000 Tridia Corporation. All Rights Reserved.
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ *
+ * For the latest source code, please check:
+ *
+ * http://www.developVNC.org/
+ *
+ * or send email to feedback@developvnc.org.
+ */
+
+#include <stdio.h>
+#include "rfb.h"
+
+/*
+ * zlibBeforeBuf contains pixel data in the client's format.
+ * zlibAfterBuf contains the zlib (deflated) encoding version.
+ * If the zlib compressed/encoded version is
+ * larger than the raw data or if it exceeds zlibAfterBufSize then
+ * raw encoding is used instead.
+ */
+
+static int zlibBeforeBufSize = 0;
+static char *zlibBeforeBuf = NULL;
+
+static int zlibAfterBufSize = 0;
+static char *zlibAfterBuf = NULL;
+static int zlibAfterBufLen;
+
+/*
+ * rfbSendOneRectEncodingZlib - send a given rectangle using one Zlib
+ * rectangle encoding.
+ */
+
+Bool
+rfbSendOneRectEncodingZlib(cl, x, y, w, h)
+ rfbClientPtr cl;
+ int x, y, w, h;
+{
+ rfbFramebufferUpdateRectHeader rect;
+ rfbZlibHeader hdr;
+ int deflateResult;
+ int previousOut;
+ int i;
+ char *fbptr = (cl->screen->frameBuffer + (cl->screen->paddedWidthInBytes * y)
+ + (x * (cl->screen->bitsPerPixel / 8)));
+
+ int maxRawSize;
+ int maxCompSize;
+
+ maxRawSize = (cl->screen->width * cl->screen->height
+ * (cl->format.bitsPerPixel / 8));
+
+ if (zlibBeforeBufSize < maxRawSize) {
+ zlibBeforeBufSize = maxRawSize;
+ if (zlibBeforeBuf == NULL)
+ zlibBeforeBuf = (char *)malloc(zlibBeforeBufSize);
+ else
+ zlibBeforeBuf = (char *)realloc(zlibBeforeBuf, zlibBeforeBufSize);
+ }
+
+ /* zlib compression is not useful for very small data sets.
+ * So, we just send these raw without any compression.
+ */
+ if (( w * h * (cl->screen->bitsPerPixel / 8)) <
+ VNC_ENCODE_ZLIB_MIN_COMP_SIZE ) {
+
+ int result;
+
+ /* The translation function (used also by the in raw encoding)
+ * requires 4/2/1 byte alignment in the output buffer (which is
+ * updateBuf for the raw encoding) based on the bitsPerPixel of
+ * the viewer/client. This prevents SIGBUS errors on some
+ * architectures like SPARC, PARISC...
+ */
+ if (( cl->format.bitsPerPixel > 8 ) &&
+ ( cl->ublen % ( cl->format.bitsPerPixel / 8 )) != 0 ) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ result = rfbSendRectEncodingRaw(cl, x, y, w, h);
+
+ return result;
+
+ }
+
+ /*
+ * zlib requires output buffer to be slightly larger than the input
+ * buffer, in the worst case.
+ */
+ maxCompSize = maxRawSize + (( maxRawSize + 99 ) / 100 ) + 12;
+
+ if (zlibAfterBufSize < maxCompSize) {
+ zlibAfterBufSize = maxCompSize;
+ if (zlibAfterBuf == NULL)
+ zlibAfterBuf = (char *)malloc(zlibAfterBufSize);
+ else
+ zlibAfterBuf = (char *)realloc(zlibAfterBuf, zlibAfterBufSize);
+ }
+
+ /*
+ * Convert pixel data to client format.
+ */
+ (*cl->translateFn)(cl->translateLookupTable, &cl->screen->rfbServerFormat,
+ &cl->format, fbptr, zlibBeforeBuf,
+ cl->screen->paddedWidthInBytes, w, h);
+
+ cl->compStream.next_in = ( Bytef * )zlibBeforeBuf;
+ cl->compStream.avail_in = w * h * (cl->format.bitsPerPixel / 8);
+ cl->compStream.next_out = ( Bytef * )zlibAfterBuf;
+ cl->compStream.avail_out = maxCompSize;
+ cl->compStream.data_type = Z_BINARY;
+
+ /* Initialize the deflation state. */
+ if ( cl->compStreamInited == FALSE ) {
+
+ cl->compStream.total_in = 0;
+ cl->compStream.total_out = 0;
+ cl->compStream.zalloc = Z_NULL;
+ cl->compStream.zfree = Z_NULL;
+ cl->compStream.opaque = Z_NULL;
+
+ deflateInit2( &(cl->compStream),
+ cl->zlibCompressLevel,
+ Z_DEFLATED,
+ MAX_WBITS,
+ MAX_MEM_LEVEL,
+ Z_DEFAULT_STRATEGY );
+ /* deflateInit( &(cl->compStream), Z_BEST_COMPRESSION ); */
+ /* deflateInit( &(cl->compStream), Z_BEST_SPEED ); */
+ cl->compStreamInited = TRUE;
+
+ }
+
+ previousOut = cl->compStream.total_out;
+
+ /* Perform the compression here. */
+ deflateResult = deflate( &(cl->compStream), Z_SYNC_FLUSH );
+
+ /* Find the total size of the resulting compressed data. */
+ zlibAfterBufLen = cl->compStream.total_out - previousOut;
+
+ if ( deflateResult != Z_OK ) {
+ rfbLog("zlib deflation error: %s\n", cl->compStream.msg);
+ return FALSE;
+ }
+
+ /* Note that it is not possible to switch zlib parameters based on
+ * the results of the compression pass. The reason is
+ * that we rely on the compressor and decompressor states being
+ * in sync. Compressing and then discarding the results would
+ * cause lose of synchronization.
+ */
+
+ /* Update statics */
+ cl->rfbRectanglesSent[rfbEncodingZlib]++;
+ cl->rfbBytesSent[rfbEncodingZlib] += (sz_rfbFramebufferUpdateRectHeader
+ + sz_rfbZlibHeader + zlibAfterBufLen);
+
+ if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbZlibHeader
+ > UPDATE_BUF_SIZE)
+ {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ rect.r.x = Swap16IfLE(x);
+ rect.r.y = Swap16IfLE(y);
+ rect.r.w = Swap16IfLE(w);
+ rect.r.h = Swap16IfLE(h);
+ rect.encoding = Swap32IfLE(rfbEncodingZlib);
+
+ memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
+ sz_rfbFramebufferUpdateRectHeader);
+ cl->ublen += sz_rfbFramebufferUpdateRectHeader;
+
+ hdr.nBytes = Swap32IfLE(zlibAfterBufLen);
+
+ memcpy(&cl->updateBuf[cl->ublen], (char *)&hdr, sz_rfbZlibHeader);
+ cl->ublen += sz_rfbZlibHeader;
+
+ for (i = 0; i < zlibAfterBufLen;) {
+
+ int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen;
+
+ if (i + bytesToCopy > zlibAfterBufLen) {
+ bytesToCopy = zlibAfterBufLen - i;
+ }
+
+ memcpy(&cl->updateBuf[cl->ublen], &zlibAfterBuf[i], bytesToCopy);
+
+ cl->ublen += bytesToCopy;
+ i += bytesToCopy;
+
+ if (cl->ublen == UPDATE_BUF_SIZE) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+
+}
+
+
+/*
+ * rfbSendRectEncodingZlib - send a given rectangle using one or more
+ * Zlib encoding rectangles.
+ */
+
+Bool
+rfbSendRectEncodingZlib(cl, x, y, w, h)
+ rfbClientPtr cl;
+ int x, y, w, h;
+{
+ int maxLines;
+ int linesRemaining;
+ rfbRectangle partialRect;
+
+ partialRect.x = x;
+ partialRect.y = y;
+ partialRect.w = w;
+ partialRect.h = h;
+
+ /* Determine maximum pixel/scan lines allowed per rectangle. */
+ maxLines = ( ZLIB_MAX_SIZE(w) / w );
+
+ /* Initialize number of scan lines left to do. */
+ linesRemaining = h;
+
+ /* Loop until all work is done. */
+ while ( linesRemaining > 0 ) {
+
+ int linesToComp;
+
+ if ( maxLines < linesRemaining )
+ linesToComp = maxLines;
+ else
+ linesToComp = linesRemaining;
+
+ partialRect.h = linesToComp;
+
+ /* Encode (compress) and send the next rectangle. */
+ if ( ! rfbSendOneRectEncodingZlib( cl,
+ partialRect.x,
+ partialRect.y,
+ partialRect.w,
+ partialRect.h )) {
+
+ return FALSE;
+ }
+
+ /* Technically, flushing the buffer here is not extrememly
+ * efficient. However, this improves the overall throughput
+ * of the system over very slow networks. By flushing
+ * the buffer with every maximum size zlib rectangle, we
+ * improve the pipelining usage of the server CPU, network,
+ * and viewer CPU components. Insuring that these components
+ * are working in parallel actually improves the performance
+ * seen by the user.
+ * Since, zlib is most useful for slow networks, this flush
+ * is appropriate for the desired behavior of the zlib encoding.
+ */
+ if (( cl->ublen > 0 ) &&
+ ( linesToComp == maxLines )) {
+ if (!rfbSendUpdateBuf(cl)) {
+
+ return FALSE;
+ }
+ }
+
+ /* Update remaining and incremental rectangle location. */
+ linesRemaining -= linesToComp;
+ partialRect.y += linesToComp;
+
+ }
+
+ return TRUE;
+
+}
+
+