]> source.dussan.org Git - tigervnc.git/commitdiff
- moved Xvnc sources to unix/xserver/hw/vnc directory to affect current X tree
authorAdam Tkac <atkac@redhat.com>
Fri, 21 Mar 2008 18:56:48 +0000 (18:56 +0000)
committerAdam Tkac <atkac@redhat.com>
Fri, 21 Mar 2008 18:56:48 +0000 (18:56 +0000)
- replaced unix/xc.patch by unix/xserver.patch
- completely deleted unneded unix/xc subtree (sources are in unix/xserver/hw/vnc)

git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/branches/1.5-xserver@2439 3789f03b-4d11-0410-bbf8-ca57d06f2519

29 files changed:
unix/xc.patch [deleted file]
unix/xc/config/cf/host.def [deleted file]
unix/xc/config/cf/vnc.def [deleted file]
unix/xc/programs/Xserver/Xvnc.man [deleted file]
unix/xc/programs/Xserver/vnc/Imakefile [deleted file]
unix/xc/programs/Xserver/vnc/RegionHelper.h [deleted file]
unix/xc/programs/Xserver/vnc/XserverDesktop.cc [deleted file]
unix/xc/programs/Xserver/vnc/XserverDesktop.h [deleted file]
unix/xc/programs/Xserver/vnc/Xvnc/Imakefile [deleted file]
unix/xc/programs/Xserver/vnc/Xvnc/buildtime.c [deleted file]
unix/xc/programs/Xserver/vnc/Xvnc/xvnc.cc [deleted file]
unix/xc/programs/Xserver/vnc/module/Imakefile [deleted file]
unix/xc/programs/Xserver/vnc/vncExtInit.cc [deleted file]
unix/xc/programs/Xserver/vnc/vncExtInit.h [deleted file]
unix/xc/programs/Xserver/vnc/vncHooks.cc [deleted file]
unix/xc/programs/Xserver/vnc/vncHooks.h [deleted file]
unix/xc/programs/Xserver/vnc/xf86vncModule.cc [deleted file]
unix/xserver.patch [new file with mode: 0644]
unix/xserver/hw/vnc/RegionHelper.h [new file with mode: 0644]
unix/xserver/hw/vnc/XserverDesktop.cc [new file with mode: 0644]
unix/xserver/hw/vnc/XserverDesktop.h [new file with mode: 0644]
unix/xserver/hw/vnc/Xvnc.man [new file with mode: 0644]
unix/xserver/hw/vnc/buildtime.c [new file with mode: 0644]
unix/xserver/hw/vnc/vncExtInit.cc [new file with mode: 0644]
unix/xserver/hw/vnc/vncExtInit.h [new file with mode: 0644]
unix/xserver/hw/vnc/vncHooks.cc [new file with mode: 0644]
unix/xserver/hw/vnc/vncHooks.h [new file with mode: 0644]
unix/xserver/hw/vnc/xf86vncModule.cc [new file with mode: 0644]
unix/xserver/hw/vnc/xvnc.cc [new file with mode: 0644]

diff --git a/unix/xc.patch b/unix/xc.patch
deleted file mode 100644 (file)
index a5927b9..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-diff -bcr xc.org/programs/Xserver/Imakefile xc/programs/Xserver/Imakefile
-*** xc.org/programs/Xserver/Imakefile  2004-12-15 20:22:53.000000000 +0100
---- xc/programs/Xserver/Imakefile      2005-02-14 14:23:21.000000000 +0100
-***************
-*** 128,134 ****
-         LIBREGEX = RegexLibrary
-  
-  #if DoLoadableServer
-!     LIBCWRAPPER = os/libcwrapper.o
-  #endif
-  
-  #if BuildXprint
---- 128,134 ----
-         LIBREGEX = RegexLibrary
-  
-  #if DoLoadableServer
-!     LIBCWRAPPER = os/libcwrapper.o os/libos.a
-  #endif
-  
-  #if BuildXprint
-***************
-*** 414,419 ****
---- 414,430 ----
-  #define ServerToInstall Xsun
-  #endif
-  #endif /* XsunServer */
-+ XCOMM
-+ XCOMM X VNC server
-+ XCOMM
-+ FBSUBDIR = fb
-+ XVNCDDXDIR = vnc/Xvnc
-+ XVNCDIRS = $(STDDIRS) $(FBSUBDIR) miext/damage $(XVNCDDXDIR) $(DEPDIRS)
-+ XVNCLIBS = PreFbLibs vnc/Xvnc/LibraryTargetName(xvnc) FbPostFbLibs
-+ XVNCOBJS = $(XVNCDDXDIR)/stubs.o $(XVNCDDXDIR)/miinitext.o
-+ XVNCSYSLIBS = $(FONTLIBS) $(SYSLIBS)
-+ ServerTarget(Xvnc,$(XVNCDIRS),$(XVNCOBJS), \
-+      $(LIBCWRAPPER) $(XVNCLIBS) $(LOADABLEEXTS),$(XVNCSYSLIBS))
-  
-  
-  #if defined(Xsun24Server) && Xsun24Server
-diff -bcr xc.org/programs/Xserver/mi/miinitext.c xc/programs/Xserver/mi/miinitext.c
-*** xc.org/programs/Xserver/mi/miinitext.c     2004-12-13 06:48:41.000000000 +0100
---- xc/programs/Xserver/mi/miinitext.c 2005-02-11 16:47:34.000000000 +0100
-***************
-*** 286,291 ****
---- 286,294 ----
-  #ifdef MITMISC
-  extern void MITMiscExtensionInit(INITARGS);
-  #endif
-+ #ifdef VNCEXT
-+ extern void vncExtensionInit(INITARGS);
-+ #endif
-  #ifdef XIDLE
-  extern void XIdleExtensionInit(INITARGS);
-  #endif
-***************
-*** 587,592 ****
---- 590,598 ----
-  #ifdef MITMISC
-      if (!noMITMiscExtension) MITMiscExtensionInit();
-  #endif
-+ #ifdef VNCEXT
-+     vncExtensionInit();
-+ #endif
-  #ifdef XIDLE
-      if (!noXIdleExtension) XIdleExtensionInit();
-  #endif
diff --git a/unix/xc/config/cf/host.def b/unix/xc/config/cf/host.def
deleted file mode 100644 (file)
index 2de89af..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <vnc.def>
diff --git a/unix/xc/config/cf/vnc.def b/unix/xc/config/cf/vnc.def
deleted file mode 100644 (file)
index b7660a5..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-#define BuildServersOnly YES
-#define BuildFonts NO
-#define BuildClients NO
-#define BuildDocs NO
-#define BuildPexExt NO
-#define BuildNls NO
-#define BuildXIE NO
-#define BuildGlxExt YES
-#define GlxBuiltInXMesa YES
-#define XnestServer YES
-#define XF86Server NO
-#define XprtServer NO
-#define BuildXFree86ConfigTools NO
-
-#ifdef SunArchitecture
-#define ProjectRoot /usr/openwin
-#define HasGcc3 YES
-#endif
-
-#define HasFreetype2 NO
-#define BuildVNCExt YES
-#define VNCExtDefines -DVNCEXT
-#define SiteExtensionDefines VNCExtDefines
-#define SiteExtensionDirs vnc
-
-#define VncUnixDir $(TOP)/..
-#define VncCommonDir VncUnixDir/../common
-#define VncExtLibs VncCommonDir/rfb/librfb.a \
-                   VncCommonDir/Xregion/libXregion.a \
-                   VncCommonDir/network/libnetwork.a \
-                   VncCommonDir/rdr/librdr.a \
-                   VncCommonDir/jpeg/build/libjpeg.a
-
-#define SiteExtensionLibs vnc/LibraryTargetName(vnc) VncExtLibs
-
-#define        ServerTarget(server,subdirs,objects,libs,syslibs)               @@\
-CCLINK = $(CXXENVSETUP) $(CXX) @@\
-ServerTargetWithFlags(server,subdirs,objects,libs,syslibs,$(_NOOP_))
diff --git a/unix/xc/programs/Xserver/Xvnc.man b/unix/xc/programs/Xserver/Xvnc.man
deleted file mode 100644 (file)
index 94a2786..0000000
+++ /dev/null
@@ -1,284 +0,0 @@
-.TH Xvnc 1 "17 Apr 2006" "TightVNC" "Virtual Network Computing"
-.SH NAME
-Xvnc \- the X VNC server 
-.SH SYNOPSIS
-.B Xvnc
-.RI [ options ] 
-.RI : display#
-.SH DESCRIPTION
-.B Xvnc
-is the X VNC (Virtual Network Computing) server.  It is based on a standard X
-server, but it has a "virtual" screen rather than a physical one.  X
-applications display themselves on it as if it were a normal X display, but
-they can only be accessed via a VNC viewer - see \fBvncviewer\fP(1).
-
-So Xvnc is really two servers in one. To the applications it is an X server,
-and to the remote VNC users it is a VNC server. By convention we have arranged
-that the VNC server display number will be the same as the X server display
-number, which means you can use eg. snoopy:2 to refer to display 2 on machine
-"snoopy" in both the X world and the VNC world.
-
-The best way of starting \fBXvnc\fP is via the \fBvncserver\fP script.  This
-sets up the environment appropriately and runs some X applications to get you
-going.  See the manual page for \fBvncserver\fP(1) for more information.
-
-.SH OPTIONS
-.B Xvnc
-takes lots of options - running \fBXvnc -help\fP gives a list.  Many of these
-are standard X server options, which are described in the \fBXserver\fP(1)
-manual page.  In addition to options which can only be set via the
-command-line, there are also "parameters" which can be set both via the
-command-line and through the \fBvncconfig\fP(1) program.
-
-.TP
-.B \-geometry \fIwidth\fPx\fIheight\fP
-Specify the size of the desktop to be created. Default is 1024x768.
-
-.TP
-.B \-depth \fIdepth\fP
-Specify the pixel depth in bits of the desktop to be created. Default is 16,
-other possible values are 8, 15, and 24 - anything else is likely to cause
-strange behaviour by applications.
-
-.TP
-.B \-pixelformat \fIformat\fP
-Specify pixel format for server to use (BGRnnn or RGBnnn).  The default for
-depth 8 is BGR233 (meaning the most significant two bits represent blue, the
-next three green, and the least significant three represent red), the default
-for depth 16 is RGB565 and for depth 24 is RGB888.
-
-.TP
-.B \-cc 3
-As an alternative to the default TrueColor visual, this allows you to run an
-Xvnc server with a PseudoColor visual (i.e. one which uses a color map or
-palette), which can be useful for running some old X applications which only
-work on such a display.  Values other than 3 (PseudoColor) and 4 (TrueColor)
-for the \-cc option may result in strange behaviour, and PseudoColor desktops
-must be 8 bits deep (i.e. \fB-depth 8\fP).
-
-.TP
-.B \-inetd 
-This significantly changes Xvnc's behaviour so that it can be launched from
-inetd.  See the section below on usage with inetd.
-
-.TP
-.B \-help
-List all the options and parameters
-
-.SH PARAMETERS
-VNC parameters can be set both via the command-line and through the
-\fBvncconfig\fP(1) program, and with a VNC-enabled XFree86 server via Options
-entries in the XF86Config file.
-
-Parameters can be turned on with -\fIparam\fP or off with
--\fIparam\fP=0.  Parameters which take a value can be specified as
--\fIparam\fP \fIvalue\fP.  Other valid forms are \fIparam\fP\fB=\fP\fIvalue\fP
--\fIparam\fP=\fIvalue\fP --\fIparam\fP=\fIvalue\fP.  Parameter names are
-case-insensitive.
-
-.TP
-.B \-desktop \fIdesktop-name\fP
-Each desktop has a name which may be displayed by the viewer. It defaults to
-"x11".
-
-.TP
-.B \-rfbport \fIport\fP
-Specifies the TCP port on which Xvnc listens for connections from viewers (the
-protocol used in VNC is called RFB - "remote framebuffer").  The default is
-5900 plus the display number.
-
-.TP
-.B \-rfbwait \fItime\fP, \-ClientWaitTimeMillis \fItime\fP
-
-Time in milliseconds to wait for a viewer which is blocking Xvnc.  This is
-necessary because Xvnc is single-threaded and sometimes blocks until the viewer
-has finished sending or receiving a message - note that this does not mean an
-update will be aborted after this time.  Default is 20000 (20 seconds).
-
-.TP
-.B \-httpd \fIdirectory\fP
-Run a mini-HTTP server which serves files from the given directory.  Normally
-the directory will contain the classes for the Java viewer.  In addition, files
-with a .vnc extension will have certain substitutions made so that a single
-installation of the Java VNC viewer can be served by separate instances of
-Xvnc.
-
-.TP
-.B \-httpPort \fIport\fP
-Specifies the port on which the mini-HTTP server runs.  Default is 5800 plus
-the display number.
-
-.TP
-.B \-rfbauth \fIpasswd-file\fP, \-PasswordFile \fIpasswd-file\fP
-Specifies the file containing the password used to authenticate viewers.  The
-file is accessed each time a connection comes in, so it can be changed on the
-fly via \fBvncpasswd\fP(1).
-
-.TP
-.B \-deferUpdate \fItime\fP
-Xvnc uses a "deferred update" mechanism which enhances performance in many
-cases. After any change to the framebuffer, Xvnc waits for this number of
-milliseconds (default 40) before sending an update to any waiting clients. This
-means that more changes tend to get coalesced together in a single
-update. Setting it to 0 results in the same behaviour as earlier versions of
-Xvnc, where the first change to the framebuffer causes an immediate update to
-any waiting clients.
-
-.TP
-.B \-SendCutText
-Send clipboard changes to clients (default is on).  Note that you must also run
-\fBvncconfig\fP(1) to get the clipboard to work.
-
-.TP
-.B \-AcceptCutText
-Accept clipboard updates from clients (default is on).  Note that you must also
-run \fBvncconfig\fP(1) to get the clipboard to work.
-
-.TP
-.B \-AcceptPointerEvents
-Accept pointer press and release events from clients (default is on).
-
-.TP
-.B \-AcceptKeyEvents
-Accept key press and release events from clients (default is on).
-
-.TP
-.B \-DisconnectClients
-Disconnect existing clients if an incoming connection is non-shared (default is
-on). If \fBDisconnectClients\fP is false, then a new non-shared connection will
-be refused while there is a client active.  When combined with
-\fBNeverShared\fP this means only one client is allowed at a time.
-
-.TP
-.B \-NeverShared
-Never treat incoming connections as shared, regardless of the client-specified
-setting (default is off).
-
-.TP
-.B \-AlwaysShared
-Always treat incoming connections as shared, regardless of the client-specified
-setting (default is off).
-
-.TP
-.B \-Protocol3.3
-Always use protocol version 3.3 for backwards compatibility with badly-behaved
-clients (default is off).
-
-.TP
-.B \-CompareFB
-Perform pixel comparison on framebuffer to reduce unnecessary updates (default
-is on).
-
-.TP
-.B \-SecurityTypes \fIsec-types\fP
-Specify which security schemes to use separated by commas.  At present only
-"None" and "VncAuth" are supported.  The default is "VncAuth" - note that if
-you want a server which does not require a password, you must set this
-parameter to "None".
-
-.TP
-.B \-IdleTimeout \fIseconds\fP
-The number of seconds after which an idle VNC connection will be dropped
-(default is 0, which means that idle connections will never be dropped).
-
-.TP
-.B \-QueryConnect
-Prompts the user of the desktop to explicitly accept or reject incoming
-connections.  This is most useful when using the vnc.so module or
-\fBx0vncserver\fP(1) program to access an existing X desktop via VNC.
-
-The \fBvncconfig\fP(1) program must be running on the desktop in order for
-QueryConnect to be supported by the \fBvnc.so\fP(1) module or
-\fBXvnc\fP(1) program.  The \fBx0vncserver\fP(1) program does not require
-\fBvncconfig\fP(1) to be running.
-
-.TP
-.B \-localhost
-Only allow connections from the same machine. Useful if you use SSH and want to
-stop non-SSH connections from any other hosts. See the guide to using VNC with
-SSH on the web site.
-
-.TP
-.B \-log \fIlogname\fP:\fIdest\fP:\fIlevel\fP
-Configures the debug log settings.  \fIdest\fP can currently be \fBstderr\fP or
-\fBstdout\fP, and \fIlevel\fP is between 0 and 100, 100 meaning most verbose
-output.  \fIlogname\fP is usually \fB*\fP meaning all, but you can target a
-specific source file if you know the name of its "LogWriter".  Default is
-\fB*:stderr:30\fP.
-
-.TP
-.B \-RemapKeys \fImapping
-Sets up a keyboard mapping.
-.I mapping
-is a comma-separated string of character mappings, each of the form
-.IR char -> char ,
-or
-.IR char <> char ,
-where
-.I char
-is a hexadecimal keysym. For example, to exchange the " and @ symbols you would specify the following:
-.IP "" 10
-RemapKeys=0x22<>0x40
-
-.SH USAGE WITH INETD
-By configuring the \fBinetd\fP(1) service appropriately, Xvnc can be launched
-on demand when a connection comes in, rather than having to be started
-manually.  When given the \fB-inetd\fP option, instead of listening for TCP
-connections on a given port it uses its standard input and standard output.
-There are two modes controlled by the wait/nowait entry in the inetd.conf file.
-
-In the nowait mode, Xvnc uses its standard input and output directly as the
-connection to a viewer.  It never has a listening socket, so cannot accept
-further connections from viewers (it can however connect out to listening
-viewers by use of the vncconfig program).  Further viewer connections to the
-same TCP port result in inetd spawning off a new Xvnc to deal with each
-connection.  When the connection to the viewer dies, the Xvnc and any
-associated X clients die.  This behaviour is most useful when combined with the
-XDMCP options -query and -once.  An typical example in inetd.conf might be (all
-on one line):
-
-5950   stream   tcp nowait nobody  /usr/local/bin/Xvnc Xvnc -inetd -query
-localhost -once securitytypes=none
-
-In this example a viewer connection to :50 will result in a new Xvnc for that
-connection which should display the standard XDM login screen on that machine.
-Because the user needs to login via XDM, it is usually OK to accept connections
-without a VNC password in this case.
-
-In the wait mode, when the first connection comes in, inetd gives the listening
-socket to Xvnc.  This means that for a given TCP port, there is only ever one
-Xvnc at a time.  Further viewer connections to the same port are accepted by
-the same Xvnc in the normal way.  Even when the original connection is broken,
-the Xvnc will continue to run.  If this is used with the XDMCP options -query
-and -once, the Xvnc and associated X clients will die when the user logs out of
-the X session in the normal way.  It is important to use a VNC password in this
-case.  A typical entry in inetd.conf might be:
-
-5951   stream   tcp wait   james     /usr/local/bin/Xvnc Xvnc -inetd -query localhost -once passwordFile=/home/james/.vnc/passwd
-
-In fact typically, you would have one entry for each user who uses VNC
-regularly, each of whom has their own dedicated TCP port which they use.  In
-this example, when user "james" connects to :51, he enters his VNC password,
-then gets the XDM login screen where he logs in in the normal way.  However,
-unlike the previous example, if he disconnects, the session remains persistent,
-and when he reconnects he will get the same session back again.  When he logs
-out of the X session, the Xvnc will die, but of course a new one will be
-created automatically the next time he connects.
-
-.SH SEE ALSO
-.BR vncconfig (1),
-.BR vncpasswd (1),
-.BR vncserver (1),
-.BR vncviewer (1),
-.BR Xserver (1),
-.BR inetd (1)
-.br
-http://www.tightvnc.com
-
-.SH AUTHOR
-Tristan Richardson, RealVNC Ltd.
-
-VNC was originally developed by the RealVNC team while at Olivetti
-Research Ltd / AT&T Laboratories Cambridge.  TightVNC additions were
-implemented by Constantin Kaplinsky. Many other people participated in
-development, testing and support.
diff --git a/unix/xc/programs/Xserver/vnc/Imakefile b/unix/xc/programs/Xserver/vnc/Imakefile
deleted file mode 100644 (file)
index d260759..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-XCOMM CDEBUGFLAGS = -g
-XCOMM CXXDEBUGFLAGS = -g
-
-   VNCUNIXDIR = VncUnixDir
- VNCCOMMONDIR = VncCommonDir
-   VNCINCLUDE = -I$(VNCCOMMONDIR) -I$(VNCUNIXDIR)/vncconfig
-
-#define CplusplusSource
-
-#if DoLoadableServer
-#define IHaveSubdirs
-#endif
-
-#include <Server.tmpl>
-
-#if DoLoadableServer
-       MODULE_SUBDIRS = module
-#endif
-         SRCS = vncExtInit.cc vncHooks.cc XserverDesktop.cc
-         OBJS = vncExtInit.o vncHooks.o XserverDesktop.o
-     INCLUDES = -I../include -I$(EXTINCSRC) -I$(XINCLUDESRC) -I$(FONTINCSRC) \
-                -I../render $(VNCINCLUDE)
-#if defined(XFree86Version) && XFree86Version >= 4000
-   VNCDEFINES = -DGC_HAS_COMPOSITE_CLIP
-#endif
-#if defined(ProjectX) && (ProjectX >= 604)
-   VNCDEFINES = -DGC_HAS_COMPOSITE_CLIP
-#endif
-      DEFINES = $(STD_DEFINES) $(VNCDEFINES) -UXFree86LOADER
-
-#define IHaveSubdirs
-SUBDIRS = Xvnc $(MODULE_SUBDIRS)
-
-NormalLibraryTarget(vnc,$(OBJS))
-LintLibraryTarget(vnc,$(SRCS))
-NormalLintTarget($(SRCS))
-
-NormalLibraryObjectRule()
-NormalCplusplusObjectRule()
-
-
-MakeSubdirs($(SUBDIRS))
-DependSubdirs($(SUBDIRS))
-
-DependTarget()
diff --git a/unix/xc/programs/Xserver/vnc/RegionHelper.h b/unix/xc/programs/Xserver/vnc/RegionHelper.h
deleted file mode 100644 (file)
index 61dc89f..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd.  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.
- */
-#ifndef __REGIONHELPER_H__
-#define __REGIONHELPER_H__
-
-// RegionHelper is a class which helps in using X server regions by
-// automatically freeing them in the destructor.  It also fixes a problem with
-// REGION_INIT when given an empty rectangle.
-
-// REGION_NULL was introduced in the Xorg tree as the way to initialise an
-// empty region.  If it's not already defined do it the old way.  Note that the
-// old way causes a segfault in the new tree...
-#ifndef REGION_NULL
-#define REGION_NULL(pScreen,pReg) REGION_INIT(pScreen,pReg,NullBox,0)
-#endif
-
-class RegionHelper {
-public:
-
-  // constructor from a single rect
-  RegionHelper(ScreenPtr pScreen_, BoxPtr rect, int size)
-    : pScreen(pScreen_), reg(0)
-  {
-    init(rect, size);
-  }
-
-  // constructor from an existing X server region
-  RegionHelper(ScreenPtr pScreen_, RegionPtr pRegion)
-    : pScreen(pScreen_), reg(&regRec)
-  {
-    REGION_NULL(pScreen, reg);
-    REGION_COPY(pScreen, reg, pRegion);
-  }
-
-  // constructor from an array of rectangles
-  RegionHelper(ScreenPtr pScreen_, int nrects, xRectanglePtr rects,
-               int ctype=CT_NONE)
-    : pScreen(pScreen_)
-  {
-    reg = RECTS_TO_REGION(pScreen, nrects, rects, ctype);
-  }
-
-  // constructor for calling init() later
-  RegionHelper(ScreenPtr pScreen_) : pScreen(pScreen_), reg(0) {
-  }
-
-  void init(BoxPtr rect, int size) {
-    reg = &regRec;
-    if (!rect || (rect && (rect->x2 == rect->x1 || rect->y2 == rect->y1))) {
-      REGION_NULL(pScreen, reg);
-    } else {
-      REGION_INIT(pScreen, reg, rect, size);
-    }
-  }
-
-  // destructor frees as appropriate
-  ~RegionHelper() {
-    if (reg == &regRec) {
-      REGION_UNINIT(pScreen, reg);
-    } else if (reg) {
-      REGION_DESTROY(pScreen, reg);
-    }
-  }
-  ScreenPtr pScreen;
-  RegionRec regRec;
-  RegionPtr reg;
-};
-
-#endif
diff --git a/unix/xc/programs/Xserver/vnc/XserverDesktop.cc b/unix/xc/programs/Xserver/vnc/XserverDesktop.cc
deleted file mode 100644 (file)
index 9e5ea0f..0000000
+++ /dev/null
@@ -1,1147 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd.  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.
- */
-//
-// XserverDesktop.cxx
-//
-
-#include <stdio.h>
-#include <strings.h>
-#include <unistd.h>
-#include <pwd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/utsname.h>
-#include <network/TcpSocket.h>
-#include <rfb/Exception.h>
-#include <rfb/VNCServerST.h>
-#include <rfb/HTTPServer.h>
-#include <rfb/LogWriter.h>
-#include <rfb/Configuration.h>
-#include "XserverDesktop.h"
-#include "vncExtInit.h"
-
-extern "C" {
-#define public c_public
-#define class c_class
-
-  // windowTable is in globals.h in XFree 4, but not in XFree 3 unfortunately
-extern WindowPtr *WindowTable;
-extern char *display;
-
-#include "inputstr.h"
-#include "servermd.h"
-#include "colormapst.h"
-#include "resource.h"
-#include "cursorstr.h"
-#include "windowstr.h"
-#define XK_CYRILLIC
-#include "keysym.h"
-#undef public
-#undef class
-}
-
-using namespace rfb;
-using namespace network;
-
-static LogWriter vlog("XserverDesktop");
-
-rfb::IntParameter deferUpdateTime("DeferUpdate",
-                                  "Time in milliseconds to defer updates",40);
-
-rfb::BoolParameter alwaysSetDeferUpdateTimer("AlwaysSetDeferUpdateTimer",
-                  "Always reset the defer update timer on every change",false);
-
-IntParameter queryConnectTimeout("QueryConnectTimeout",
-                                 "Number of seconds to show the Accept Connection dialog before "
-                                 "rejecting the connection",
-                                 10);
-
-static KeyCode KeysymToKeycode(KeySymsPtr keymap, KeySym ks, int* col);
-
-static rdr::U8 reverseBits[] = {
-  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
-};
-
-
-class FileHTTPServer : public rfb::HTTPServer {
-public:
-  FileHTTPServer(XserverDesktop* d) : desktop(d) {}
-  virtual ~FileHTTPServer() {}
-
-  virtual rdr::InStream* getFile(const char* name, const char** contentType,
-                                 int* contentLength, time_t* lastModified)
-  {
-    if (name[0] != '/' || strstr(name, "..") != 0) {
-      vlog.info("http request was for invalid file name");
-      return 0;
-    }
-
-    if (strcmp(name, "/") == 0) name = "/index.vnc";
-
-    CharArray httpDirStr(httpDir.getData());
-    CharArray fname(strlen(httpDirStr.buf)+strlen(name)+1);
-    sprintf(fname.buf, "%s%s", httpDirStr.buf, name);
-    int fd = open(fname.buf, O_RDONLY);
-    if (fd < 0) return 0;
-    rdr::InStream* is = new rdr::FdInStream(fd, -1, 0, true);
-    *contentType = guessContentType(name, *contentType);
-    if (strlen(name) > 4 && strcasecmp(&name[strlen(name)-4], ".vnc") == 0) {
-      is = new rdr::SubstitutingInStream(is, desktop, 20);
-      *contentType = "text/html";
-    } else {
-      struct stat st;
-      if (fstat(fd, &st) == 0) {
-        *contentLength = st.st_size;
-        *lastModified = st.st_mtime;
-      }
-    }
-    return is;
-  }
-
-  XserverDesktop* desktop;
-};
-
-
-XserverDesktop::XserverDesktop(ScreenPtr pScreen_,
-                               network::TcpListener* listener_,
-                               network::TcpListener* httpListener_,
-                               const char* name, void* fbptr)
-  : pScreen(pScreen_), deferredUpdateTimer(0), dummyTimer(0),
-    server(0), httpServer(0),
-    listener(listener_), httpListener(httpListener_),
-    cmap(0), deferredUpdateTimerSet(false),
-    grabbing(false), ignoreHooks_(false), directFbptr(fbptr != 0),
-    oldButtonMask(0),
-    queryConnectId(0)
-{
-  int i;
-  format.depth = pScreen->rootDepth;
-  for (i = 0; i < screenInfo.numPixmapFormats; i++) {
-    if (screenInfo.formats[i].depth == format.depth) {
-      format.bpp = screenInfo.formats[i].bitsPerPixel;
-      break;
-    }
-  }
-  if (i == screenInfo.numPixmapFormats) {
-    fprintf(stderr,"no pixmap format for root depth???\n");
-    abort();
-  }
-  format.bigEndian = (screenInfo.imageByteOrder == MSBFirst);
-
-  VisualPtr vis;
-  for (i = 0; i < pScreen->numVisuals; i++) {
-    if (pScreen->visuals[i].vid == pScreen->rootVisual) {
-      vis = &pScreen->visuals[i];
-      break;
-    }
-  }
-  if (i == pScreen->numVisuals) {
-    fprintf(stderr,"no visual rec for root visual???\n");
-    abort();
-  }
-  format.trueColour = (vis->c_class == TrueColor);
-  if (!format.trueColour && format.bpp != 8)
-    throw rfb::Exception("X server uses unsupported visual");
-  format.redShift   = ffs(vis->redMask) - 1;
-  format.greenShift = ffs(vis->greenMask) - 1;
-  format.blueShift  = ffs(vis->blueMask) - 1;
-  format.redMax     = vis->redMask   >> format.redShift;
-  format.greenMax   = vis->greenMask >> format.greenShift;
-  format.blueMax    = vis->blueMask  >> format.blueShift;
-
-  width_ = pScreen->width;
-  height_ = pScreen->height;
-  if (fbptr)
-    data = (rdr::U8*)fbptr;
-  else
-    data = new rdr::U8[pScreen->width * pScreen->height * (format.bpp/8)];
-  colourmap = this;
-
-  serverReset(pScreen);
-
-  server = new VNCServerST(name, this);
-  server->setPixelBuffer(this);
-  server->setQueryConnectionHandler(this);
-
-  if (httpListener)
-    httpServer = new FileHTTPServer(this);
-}
-
-XserverDesktop::~XserverDesktop()
-{
-  if (!directFbptr)
-    delete [] data;
-  TimerFree(deferredUpdateTimer);
-  TimerFree(dummyTimer);
-  delete httpServer;
-  delete server;
-}
-
-void XserverDesktop::serverReset(ScreenPtr pScreen_)
-{
-  pScreen = pScreen_;
-  XID* ids = new XID[pScreen->maxInstalledCmaps];
-  int nmaps = (*pScreen->ListInstalledColormaps)(pScreen, ids);
-  cmap = (ColormapPtr)LookupIDByType(ids[0], RT_COLORMAP);
-  delete [] ids;
-}
-
-char* XserverDesktop::substitute(const char* varName)
-{
-  if (strcmp(varName, "$$") == 0) {
-    return rfb::strDup("$");
-  }
-  if (strcmp(varName, "$PORT") == 0) {
-    char* str = new char[10];
-    sprintf(str, "%d", listener ? listener->getMyPort() : 0);
-    return str;
-  }
-  if (strcmp(varName, "$WIDTH") == 0) {
-    char* str = new char[10];
-    sprintf(str, "%d", width());
-    return str;
-  }
-  if (strcmp(varName, "$HEIGHT") == 0) {
-    char* str = new char[10];
-    sprintf(str, "%d", height());
-    return str;
-  }
-  if (strcmp(varName, "$APPLETWIDTH") == 0) {
-    char* str = new char[10];
-    sprintf(str, "%d", width());
-    return str;
-  }
-  if (strcmp(varName, "$APPLETHEIGHT") == 0) {
-    char* str = new char[10];
-    sprintf(str, "%d", height() + 32);
-    return str;
-  }
-  if (strcmp(varName, "$DESKTOP") == 0) {
-    return rfb::strDup(server->getName());
-  }
-  if (strcmp(varName, "$DISPLAY") == 0) {
-    struct utsname uts;
-    uname(&uts);
-    char* str = new char[256];
-    strncat(str, uts.nodename, 240);
-    strcat(str, ":");
-    strncat(str, display, 10);
-    return str;
-  }
-  if (strcmp(varName, "$USER") == 0) {
-    struct passwd* user = getpwuid(getuid());
-    return rfb::strDup(user ? user->pw_name : "?");
-  }
-  return 0;
-}
-
-rfb::VNCServerST::queryResult
-XserverDesktop::queryConnection(network::Socket* sock,
-                                const char* userName,
-                                char** reason) {
-  if (queryConnectId) {
-    *reason = strDup("Another connection is currently being queried.");
-    return rfb::VNCServerST::REJECT;
-  }
-  queryConnectAddress.replaceBuf(sock->getPeerAddress());
-  if (!userName)
-    userName = "(anonymous)";
-  queryConnectUsername.replaceBuf(strDup(userName));
-  queryConnectId = sock;
-  vncQueryConnect(this, sock);
-  return rfb::VNCServerST::PENDING;
-}
-
-
-void XserverDesktop::setColormap(ColormapPtr cmap_)
-{
-  if (cmap != cmap_) {
-    cmap = cmap_;
-    setColourMapEntries(0, 0);
-  }
-}
-
-void XserverDesktop::setColourMapEntries(ColormapPtr pColormap, int ndef,
-                                         xColorItem* pdef)
-{
-  if (cmap != pColormap || ndef <= 0) return;
-
-  int first = pdef[0].pixel;
-  int n = 1;
-
-  for (int i = 1; i < ndef; i++) {
-    if (first + n == pdef[i].pixel) {
-      n++;
-    } else {
-      setColourMapEntries(first, n);
-      first = pdef[i].pixel;
-      n = 1;
-    }
-  }
-  setColourMapEntries(first, n);
-}
-
-void XserverDesktop::setColourMapEntries(int firstColour, int nColours)
-{
-  try {
-    server->setColourMapEntries(firstColour, nColours);
-  } catch (rdr::Exception& e) {
-    vlog.error("XserverDesktop::setColourMapEntries: %s",e.str());
-  }
-}
-
-void XserverDesktop::bell()
-{
-  server->bell();
-}
-
-void XserverDesktop::serverCutText(const char* str, int len)
-{
-  try {
-    server->serverCutText(str, len);
-  } catch (rdr::Exception& e) {
-    vlog.error("XserverDesktop::serverCutText: %s",e.str());
-  }
-}
-
-void XserverDesktop::setCursor(CursorPtr cursor)
-{
-  try {
-    int w = cursor->bits->width;
-    int h = cursor->bits->height;
-    rdr::U8* cursorData = new rdr::U8[w * h * (getPF().bpp / 8)];
-
-    xColorItem fg, bg;
-    fg.red   = cursor->foreRed;
-    fg.green = cursor->foreGreen;
-    fg.blue  = cursor->foreBlue;
-    FakeAllocColor(cmap, &fg);
-    bg.red   = cursor->backRed;
-    bg.green = cursor->backGreen;
-    bg.blue  = cursor->backBlue;
-    FakeAllocColor(cmap, &bg);
-    FakeFreeColor(cmap, fg.pixel);
-    FakeFreeColor(cmap, bg.pixel);
-
-    int xMaskBytesPerRow = BitmapBytePad(w);
-
-    for (int y = 0; y < h; y++) {
-      for (int x = 0; x < w; x++) {
-        int byte = y * xMaskBytesPerRow + x / 8;
-#if (BITMAP_BIT_ORDER == MSBFirst)
-        int bit = 7 - x % 8;
-#else
-        int bit = x % 8;
-#endif
-        switch (getPF().bpp) {
-        case 8:
-          ((rdr::U8*)cursorData)[y * w + x]
-            = (cursor->bits->source[byte] & (1 << bit)) ? fg.pixel : bg.pixel;
-          break;
-        case 16:
-          ((rdr::U16*)cursorData)[y * w + x]
-            = (cursor->bits->source[byte] & (1 << bit)) ? fg.pixel : bg.pixel;
-          break;
-        case 32:
-          ((rdr::U32*)cursorData)[y * w + x]
-            = (cursor->bits->source[byte] & (1 << bit)) ? fg.pixel : bg.pixel;
-          break;
-        }
-      }
-    }
-
-    int rfbMaskBytesPerRow = (w + 7) / 8;
-
-    rdr::U8* cursorMask = new rdr::U8[rfbMaskBytesPerRow * h];
-
-    for (int j = 0; j < h; j++) {
-      for (int i = 0; i < rfbMaskBytesPerRow; i++)
-#if (BITMAP_BIT_ORDER == MSBFirst)
-        cursorMask[j * rfbMaskBytesPerRow + i]
-          = cursor->bits->mask[j * xMaskBytesPerRow + i];
-#else
-        cursorMask[j * rfbMaskBytesPerRow + i]
-          = reverseBits[cursor->bits->mask[j * xMaskBytesPerRow + i]];
-#endif
-    }
-
-    server->setCursor(cursor->bits->width, cursor->bits->height,
-                      Point(cursor->bits->xhot, cursor->bits->yhot),
-                      cursorData, cursorMask);
-    server->tryUpdate();
-    delete [] cursorData;
-    delete [] cursorMask;
-  } catch (rdr::Exception& e) {
-    vlog.error("XserverDesktop::setCursor: %s",e.str());
-  }
-}
-
-static void printRegion(RegionPtr reg)
-{
-  int nrects = REGION_NUM_RECTS(reg);
-
-  fprintf(stderr,"Region num rects %2d extents %3d,%3d %3dx%3d\n",nrects,
-          (REGION_EXTENTS(pScreen,reg))->x1,
-          (REGION_EXTENTS(pScreen,reg))->y1,
-          (REGION_EXTENTS(pScreen,reg))->x2-(REGION_EXTENTS(pScreen,reg))->x1,
-          (REGION_EXTENTS(pScreen,reg))->y2-(REGION_EXTENTS(pScreen,reg))->y1);
-
-  for (int i = 0; i < nrects; i++) {
-    fprintf(stderr,"    rect %3d,%3d %3dx%3d\n",
-            REGION_RECTS(reg)[i].x1,
-            REGION_RECTS(reg)[i].y1,
-            REGION_RECTS(reg)[i].x2-REGION_RECTS(reg)[i].x1,
-            REGION_RECTS(reg)[i].y2-REGION_RECTS(reg)[i].y1);
-  }
-}
-
-CARD32 XserverDesktop::deferredUpdateTimerCallback(OsTimerPtr timer,
-                                                   CARD32 now, pointer arg)
-{
-  XserverDesktop* desktop = (XserverDesktop*)arg;
-  desktop->deferredUpdateTimerSet = false;
-  try {
-    desktop->server->tryUpdate();
-  } catch (rdr::Exception& e) {
-    vlog.error("XserverDesktop::deferredUpdateTimerCallback: %s",e.str());
-  }
-  return 0;
-}
-
-void XserverDesktop::deferUpdate()
-{
-  if (deferUpdateTime != 0) {
-    if (!deferredUpdateTimerSet || alwaysSetDeferUpdateTimer) {
-      deferredUpdateTimerSet = true;
-      deferredUpdateTimer = TimerSet(deferredUpdateTimer, 0,
-                                     deferUpdateTime,
-                                     deferredUpdateTimerCallback, this);
-    }
-  } else {
-    server->tryUpdate();
-  }
-}
-
-void XserverDesktop::add_changed(RegionPtr reg)
-{
-  if (ignoreHooks_) return;
-  if (grabbing) return;
-  try {
-    rfb::Region rfbReg;
-    rfbReg.setExtentsAndOrderedRects((ShortRect*)REGION_EXTENTS(pScreen, reg),
-                                     REGION_NUM_RECTS(reg),
-                                     (ShortRect*)REGION_RECTS(reg));
-    server->add_changed(rfbReg);
-    deferUpdate();
-  } catch (rdr::Exception& e) {
-    vlog.error("XserverDesktop::add_changed: %s",e.str());
-  }
-}
-
-void XserverDesktop::add_copied(RegionPtr dst, int dx, int dy)
-{
-  if (ignoreHooks_) return;
-  if (grabbing) return;
-  try {
-    rfb::Region rfbReg;
-    rfbReg.setExtentsAndOrderedRects((ShortRect*)REGION_EXTENTS(pScreen, dst),
-                                     REGION_NUM_RECTS(dst),
-                                     (ShortRect*)REGION_RECTS(dst));
-    server->add_copied(rfbReg, rfb::Point(dx, dy));
-    deferUpdate();
-  } catch (rdr::Exception& e) {
-    vlog.error("XserverDesktop::add_copied: %s",e.str());
-  }
-}
-
-void XserverDesktop::positionCursor()
-{
-  if (!cursorPos.equals(oldCursorPos)) {
-    oldCursorPos = cursorPos;
-    (*pScreen->SetCursorPosition) (pScreen, cursorPos.x, cursorPos.y, FALSE);
-    server->setCursorPos(cursorPos);
-    server->tryUpdate();
-  }
-}
-
-void XserverDesktop::blockHandler(fd_set* fds)
-{
-  try {
-    ScreenPtr screenWithCursor = GetCurrentRootWindow()->drawable.pScreen;
-    if (screenWithCursor == pScreen) {
-      int x, y;
-      GetSpritePosition(&x, &y);
-      if (x != cursorPos.x || y != cursorPos.y) {
-        cursorPos = oldCursorPos = Point(x, y);
-        server->setCursorPos(cursorPos);
-        server->tryUpdate();
-      }
-    }
-
-    if (listener)
-      FD_SET(listener->getFd(), fds);
-    if (httpListener)
-      FD_SET(httpListener->getFd(), fds);
-
-    std::list<Socket*> sockets;
-    server->getSockets(&sockets);
-    std::list<Socket*>::iterator i;
-    for (i = sockets.begin(); i != sockets.end(); i++) {
-      int fd = (*i)->getFd();
-      if ((*i)->isShutdown()) {
-        vlog.debug("client gone, sock %d",fd);
-        server->removeSocket(*i);
-        vncClientGone(fd);
-        delete (*i);
-      } else {
-        FD_SET(fd, fds);
-      }
-    }
-    if (httpServer) {
-      httpServer->getSockets(&sockets);
-      for (i = sockets.begin(); i != sockets.end(); i++) {
-        int fd = (*i)->getFd();
-        if ((*i)->isShutdown()) {
-          vlog.debug("http client gone, sock %d",fd);
-          httpServer->removeSocket(*i);
-          delete (*i);
-        } else {
-          FD_SET(fd, fds);
-        }
-      }
-    }
-  } catch (rdr::Exception& e) {
-    vlog.error("XserverDesktop::blockHandler: %s",e.str());
-  }
-}
-
-static CARD32 dummyTimerCallback(OsTimerPtr timer, CARD32 now, pointer arg) {
-  return 0;
-}
-
-void XserverDesktop::wakeupHandler(fd_set* fds, int nfds)
-{
-  try {
-    if (nfds >= 1) {
-
-      if (listener) {
-        if (FD_ISSET(listener->getFd(), fds)) {
-          FD_CLR(listener->getFd(), fds);
-          Socket* sock = listener->accept();
-          server->addSocket(sock);
-          vlog.debug("new client, sock %d",sock->getFd());
-        }
-      }
-
-      if (httpListener) {
-        if (FD_ISSET(httpListener->getFd(), fds)) {
-          FD_CLR(httpListener->getFd(), fds);
-          Socket* sock = httpListener->accept();
-          httpServer->addSocket(sock);
-          vlog.debug("new http client, sock %d",sock->getFd());
-        }
-      }
-
-      std::list<Socket*> sockets;
-      server->getSockets(&sockets);
-      std::list<Socket*>::iterator i;
-      for (i = sockets.begin(); i != sockets.end(); i++) {
-        int fd = (*i)->getFd();
-        if (FD_ISSET(fd, fds)) {
-          FD_CLR(fd, fds);
-          server->processSocketEvent(*i);
-        }
-      }
-
-      if (httpServer) {
-        httpServer->getSockets(&sockets);
-        for (i = sockets.begin(); i != sockets.end(); i++) {
-          int fd = (*i)->getFd();
-          if (FD_ISSET(fd, fds)) {
-            FD_CLR(fd, fds);
-            httpServer->processSocketEvent(*i);
-          }
-        }
-      }
-
-      positionCursor();
-    }
-
-    int timeout = server->checkTimeouts();
-    if (timeout > 0) {
-      // set a dummy timer just so we are guaranteed be called again next time.
-      dummyTimer = TimerSet(dummyTimer, 0, timeout,
-                            dummyTimerCallback, 0);
-    }
-
-  } catch (rdr::Exception& e) {
-    vlog.error("XserverDesktop::wakeupHandler: %s",e.str());
-  }
-}
-
-void XserverDesktop::addClient(Socket* sock, bool reverse)
-{
-  vlog.debug("new client, sock %d reverse %d",sock->getFd(),reverse);
-  server->addSocket(sock, reverse);
-}
-
-void XserverDesktop::disconnectClients()
-{
-  vlog.debug("disconnecting all clients");
-  return server->closeClients("Disconnection from server end");
-}
-
-
-int XserverDesktop::getQueryTimeout(void* opaqueId,
-                                    const char** address,
-                                    const char** username)
-{
-  if (opaqueId && queryConnectId == opaqueId) {
-    vlog.info("address=%s, username=%s, timeout=%d",
-              queryConnectAddress.buf, queryConnectUsername.buf,
-              (int)queryConnectTimeout);
-    if (address) *address = queryConnectAddress.buf;
-    if (username) *username = queryConnectUsername.buf;
-    return queryConnectTimeout;
-  }
-  return 0;
-}
-
-void XserverDesktop::approveConnection(void* opaqueId, bool accept,
-                                       const char* rejectMsg)
-{
-  if (queryConnectId == opaqueId) {
-    server->approveConnection((network::Socket*)opaqueId, accept, rejectMsg);
-    queryConnectId = 0;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////
-//
-// SDesktop callbacks
-
-
-void XserverDesktop::pointerEvent(const Point& pos, int buttonMask)
-{
-  xEvent ev;
-  DevicePtr dev = LookupPointerDevice();
-
-  // SetCursorPosition seems to be very expensive (at least on XFree86 3.3.6
-  // for S3), so we delay calling it until positionCursor() is called at the
-  // end of processing a load of RFB.
-  //(*pScreen->SetCursorPosition) (pScreen, pos.x, pos.y, FALSE);
-
-  NewCurrentScreen(pScreen, pos.x, pos.y);
-
-  ev.u.u.type = MotionNotify;
-  ev.u.u.detail = 0;
-  ev.u.keyButtonPointer.rootX = pos.x;
-  ev.u.keyButtonPointer.rootY = pos.y;
-  ev.u.keyButtonPointer.time = GetTimeInMillis();
-
-  if (!pos.equals(cursorPos))
-    (*dev->processInputProc)(&ev, (DeviceIntPtr)dev, 1);
-
-  for (int i = 0; i < 5; i++) {
-    if ((buttonMask ^ oldButtonMask) & (1<<i)) {
-      // Do not use the pointer mapping. Treat VNC buttons as logical
-      // buttons.
-      ev.u.u.detail = i + 1;
-      ev.u.u.type = (buttonMask & (1<<i)) ? ButtonPress : ButtonRelease;
-      (*dev->processInputProc)(&ev, (DeviceIntPtr)dev, 1);
-    }
-  }
-
-  cursorPos = pos;
-  oldButtonMask = buttonMask;
-}
-
-void XserverDesktop::clientCutText(const char* str, int len)
-{
-  vncClientCutText(str, len);
-}
-
-void XserverDesktop::grabRegion(const rfb::Region& region)
-{
-  if (directFbptr) return;
-  if (!pScreen->GetImage) {
-    vlog.error("VNC error: pScreen->GetImage == 0");
-    return;
-  }
-
-  grabbing = true;
-
-  int bytesPerPixel = format.bpp/8;
-  int bytesPerRow = pScreen->width * bytesPerPixel;
-
-  std::vector<rfb::Rect> rects;
-  std::vector<rfb::Rect>::iterator i;
-  region.get_rects(&rects);
-  for (i = rects.begin(); i != rects.end(); i++) {
-    for (int y = i->tl.y; y < i->br.y; y++) {
-      (*pScreen->GetImage) ((DrawablePtr)WindowTable[pScreen->myNum],
-                            i->tl.x, y, i->width(), 1,
-                            ZPixmap, (unsigned long)~0L,
-                            ((char*)data
-                             + y * bytesPerRow + i->tl.x * bytesPerPixel));
-    }
-  }
-  grabbing = false;
-}
-
-void XserverDesktop::lookup(int index, int* r, int* g, int* b)
-{
-  if ((cmap->c_class | DynamicClass) == DirectColor) {
-    VisualPtr v = cmap->pVisual;
-    *r = cmap->red  [(index & v->redMask  ) >> v->offsetRed  ].co.local.red;
-    *g = cmap->green[(index & v->greenMask) >> v->offsetGreen].co.local.green;
-    *b = cmap->blue [(index & v->blueMask ) >> v->offsetBlue ].co.local.blue;
-  } else {
-    EntryPtr pent;
-    pent = (EntryPtr)&cmap->red[index];
-    if (pent->fShared) {
-      *r = pent->co.shco.red->color;
-      *g = pent->co.shco.green->color;
-      *b = pent->co.shco.blue->color;
-    } else {
-      *r = pent->co.local.red;
-      *g = pent->co.local.green;
-      *b = pent->co.local.blue;
-    }
-  }
-}
-
-//
-// Keyboard handling
-//
-
-#define IS_PRESSED(keyc, keycode) \
-  ((keyc)->down[(keycode) >> 3] & (1 << ((keycode) & 7)))
-
-// ModifierState is a class which helps simplify generating a "fake" press
-// or release of shift, ctrl, alt, etc.  An instance of the class is created
-// for every modifier which may need to be pressed or released.  Then either
-// press() or release() may be called to make sure that the corresponding keys
-// are in the right state.  The destructor of the class automatically reverts
-// to the previous state.  Each modifier may have multiple keys associated with
-// it, so in the case of a fake release, this may involve releasing more than
-// one key.
-
-class ModifierState {
-public:
-  ModifierState(DeviceIntPtr dev_, int modIndex_)
-    : dev(dev_), modIndex(modIndex_), nKeys(0), keys(0), pressed(false)
-  {
-  }
-  ~ModifierState() {
-    for (int i = 0; i < nKeys; i++)
-      generateXKeyEvent(keys[i], !pressed);
-    delete [] keys;
-  }
-  void press() {
-    KeyClassPtr keyc = dev->key;
-    if (!(keyc->state & (1<<modIndex))) {
-      tempKeyEvent(keyc->modifierKeyMap[modIndex * keyc->maxKeysPerModifier],
-                   true);
-      pressed = true;
-    }
-  }
-  void release() {
-    KeyClassPtr keyc = dev->key;
-    if (keyc->state & (1<<modIndex)) {
-      for (int k = 0; k < keyc->maxKeysPerModifier; k++) {
-        int keycode
-          = keyc->modifierKeyMap[modIndex * keyc->maxKeysPerModifier + k];
-        if (keycode && IS_PRESSED(keyc, keycode))
-          tempKeyEvent(keycode, false);
-      }
-    }
-  }
-private:
-  void tempKeyEvent(int keycode, bool down) {
-    if (keycode) {
-      if (!keys) keys = new int[dev->key->maxKeysPerModifier];
-      keys[nKeys++] = keycode;
-      generateXKeyEvent(keycode, down);
-    }
-  }
-  void generateXKeyEvent(int keycode, bool down) {
-    xEvent ev;
-    ev.u.u.type = down ? KeyPress : KeyRelease;
-    ev.u.u.detail = keycode;
-    ev.u.keyButtonPointer.time = GetTimeInMillis();
-    (*dev->c_public.processInputProc)(&ev, dev, 1);
-    vlog.debug("fake keycode %d %s", keycode, down ? "down" : "up");
-  }
-  DeviceIntPtr dev;
-  int modIndex;
-  int nKeys;
-  int* keys;
-  bool pressed;
-};
-
-
-// altKeysym is a table of alternative keysyms which have the same meaning.
-
-struct altKeysym_t {
-  KeySym a, b;
-};
-
-altKeysym_t altKeysym[] = {
-  { XK_Shift_L,        XK_Shift_R },
-  { XK_Control_L,      XK_Control_R },
-  { XK_Meta_L,         XK_Meta_R },
-  { XK_Alt_L,          XK_Alt_R },
-  { XK_Super_L,        XK_Super_R },
-  { XK_Hyper_L,        XK_Hyper_R },
-  { XK_KP_Space,       XK_space },
-  { XK_KP_Tab,         XK_Tab },
-  { XK_KP_Enter,       XK_Return },
-  { XK_KP_F1,          XK_F1 },
-  { XK_KP_F2,          XK_F2 },
-  { XK_KP_F3,          XK_F3 },
-  { XK_KP_F4,          XK_F4 },
-  { XK_KP_Home,        XK_Home },
-  { XK_KP_Left,        XK_Left },
-  { XK_KP_Up,          XK_Up },
-  { XK_KP_Right,       XK_Right },
-  { XK_KP_Down,        XK_Down },
-  { XK_KP_Page_Up,     XK_Page_Up },
-  { XK_KP_Page_Down,   XK_Page_Down },
-  { XK_KP_End,         XK_End },
-  { XK_KP_Begin,       XK_Begin },
-  { XK_KP_Insert,      XK_Insert },
-  { XK_KP_Delete,      XK_Delete },
-  { XK_KP_Equal,       XK_equal },
-  { XK_KP_Multiply,    XK_asterisk },
-  { XK_KP_Add,         XK_plus },
-  { XK_KP_Separator,   XK_comma },
-  { XK_KP_Subtract,    XK_minus },
-  { XK_KP_Decimal,     XK_period },
-  { XK_KP_Divide,      XK_slash },
-  { XK_KP_0,           XK_0 },
-  { XK_KP_1,           XK_1 },
-  { XK_KP_2,           XK_2 },
-  { XK_KP_3,           XK_3 },
-  { XK_KP_4,           XK_4 },
-  { XK_KP_5,           XK_5 },
-  { XK_KP_6,           XK_6 },
-  { XK_KP_7,           XK_7 },
-  { XK_KP_8,           XK_8 },
-  { XK_KP_9,           XK_9 },
-};
-
-// keyEvent() - work out the best keycode corresponding to the keysym sent by
-// the viewer.  This is non-trivial because we can't assume much about the
-// local keyboard layout.  We must also find out which column of the keyboard
-// mapping the keysym is in, and alter the shift state appropriately.  Column 0
-// means both shift and "mode_switch" (AltGr) must be released, column 1 means
-// shift must be pressed and mode_switch released, column 2 means shift must be
-// released and mode_switch pressed, and column 3 means both shift and
-// mode_switch must be pressed.
-
-void XserverDesktop::keyEvent(rdr::U32 keysym, bool down)
-{
-  if (keysym == XK_Caps_Lock) {
-    vlog.debug("Ignoring caps lock");
-    return;
-  }
-  DeviceIntPtr dev = (DeviceIntPtr)LookupKeyboardDevice();
-  KeyClassPtr keyc = dev->key;
-  KeySymsPtr keymap = &keyc->curKeySyms;
-
-  // find which modifier Mode_switch is on.
-  int modeSwitchMapIndex = 0;
-  for (int i = 3; i < 8; i++) {
-    for (int k = 0; k < keyc->maxKeysPerModifier; k++) {
-      int keycode = keyc->modifierKeyMap[i * keyc->maxKeysPerModifier + k];
-      for (int j = 0; j < keymap->mapWidth; j++) {
-        if (keycode != 0 &&
-            keymap->map[(keycode - keymap->minKeyCode)
-                        * keymap->mapWidth + j] == XK_Mode_switch)
-        {
-          modeSwitchMapIndex = i;
-          break;
-        }
-      }
-    }
-  }
-
-  int col = 0;
-  if (keyc->state & (1<<ShiftMapIndex)) col |= 1;
-  if (modeSwitchMapIndex && (keyc->state & (1<<modeSwitchMapIndex))) col |= 2;
-
-  int kc = KeysymToKeycode(keymap, keysym, &col);
-
-  // Sort out the "shifted Tab" mess.  If we are sent a shifted Tab, generate a
-  // local shifted Tab regardless of what the "shifted Tab" keysym is on the
-  // local keyboard (it might be Tab, ISO_Left_Tab or HP's private BackTab
-  // keysym, and quite possibly some others too).  We never get ISO_Left_Tab
-  // here because it's already been translated in VNCSConnectionST.
-  if (keysym == XK_Tab && (keyc->state & (1<<ShiftMapIndex)))
-    col |= 1;
-
-  if (kc == 0) {
-    // Not a direct match in the local keyboard mapping.  Check for alternative
-    // keysyms with the same meaning.
-    for (int i = 0; i < sizeof(altKeysym) / sizeof(altKeysym_t); i++) {
-      if (keysym == altKeysym[i].a)
-        kc = KeysymToKeycode(keymap, altKeysym[i].b, &col);
-      else if (keysym == altKeysym[i].b)
-        kc = KeysymToKeycode(keymap, altKeysym[i].a, &col);
-      if (kc) break;
-    }
-  }
-
-  if (kc == 0) {
-    // Last resort - dynamically add a new key to the keyboard mapping.
-    for (kc = keymap->maxKeyCode; kc >= keymap->minKeyCode; kc--) {
-      if (!keymap->map[(kc - keymap->minKeyCode) * keymap->mapWidth]) {
-        keymap->map[(kc - keymap->minKeyCode) * keymap->mapWidth] = keysym;
-        col = 0;
-        SendMappingNotify(MappingKeyboard, kc, 1, serverClient);
-        vlog.info("Added unknown keysym 0x%x to keycode %d",keysym,kc);
-        break;
-      }
-    }
-    if (kc < keymap->minKeyCode) {
-      vlog.info("Keyboard mapping full - ignoring unknown keysym 0x%x",keysym);
-      return;
-    }
-  }
-
-  // See if it's a modifier key.  If so, then don't do any auto-repeat, because
-  // the X server will translate each press into a release followed by a press.
-  for (int i = 0; i < 8; i++) {
-    for (int k = 0; k < keyc->maxKeysPerModifier; k++) {
-      if (kc == keyc->modifierKeyMap[i * keyc->maxKeysPerModifier + k] &&
-          IS_PRESSED(keyc,kc) && down)
-        return;
-    }
-  }
-
-  ModifierState shift(dev, ShiftMapIndex);
-  ModifierState modeSwitch(dev, modeSwitchMapIndex);
-  if (down) {
-    if (col & 1)
-      shift.press();
-    else
-      shift.release();
-    if (modeSwitchMapIndex) {
-      if (col & 2)
-        modeSwitch.press();
-      else
-        modeSwitch.release();
-    }
-  }
-  vlog.debug("keycode %d %s", kc, down ? "down" : "up");
-  xEvent ev;
-  ev.u.u.type = down ? KeyPress : KeyRelease;
-  ev.u.u.detail = kc;
-  ev.u.keyButtonPointer.time = GetTimeInMillis();
-  (*dev->c_public.processInputProc)(&ev, dev, 1);
-}
-
-
-void XConvertCase(KeySym sym, KeySym *lower, KeySym *upper)
-{
-    *lower = sym;
-    *upper = sym;
-    switch(sym >> 8) {
-    case 0: /* Latin 1 */
-       if ((sym >= XK_A) && (sym <= XK_Z))
-           *lower += (XK_a - XK_A);
-       else if ((sym >= XK_a) && (sym <= XK_z))
-           *upper -= (XK_a - XK_A);
-       else if ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))
-           *lower += (XK_agrave - XK_Agrave);
-       else if ((sym >= XK_agrave) && (sym <= XK_odiaeresis))
-           *upper -= (XK_agrave - XK_Agrave);
-       else if ((sym >= XK_Ooblique) && (sym <= XK_Thorn))
-           *lower += (XK_oslash - XK_Ooblique);
-       else if ((sym >= XK_oslash) && (sym <= XK_thorn))
-           *upper -= (XK_oslash - XK_Ooblique);
-       break;
-    case 1: /* Latin 2 */
-       /* Assume the KeySym is a legal value (ignore discontinuities) */
-       if (sym == XK_Aogonek)
-           *lower = XK_aogonek;
-       else if (sym >= XK_Lstroke && sym <= XK_Sacute)
-           *lower += (XK_lstroke - XK_Lstroke);
-       else if (sym >= XK_Scaron && sym <= XK_Zacute)
-           *lower += (XK_scaron - XK_Scaron);
-       else if (sym >= XK_Zcaron && sym <= XK_Zabovedot)
-           *lower += (XK_zcaron - XK_Zcaron);
-       else if (sym == XK_aogonek)
-           *upper = XK_Aogonek;
-       else if (sym >= XK_lstroke && sym <= XK_sacute)
-           *upper -= (XK_lstroke - XK_Lstroke);
-       else if (sym >= XK_scaron && sym <= XK_zacute)
-           *upper -= (XK_scaron - XK_Scaron);
-       else if (sym >= XK_zcaron && sym <= XK_zabovedot)
-           *upper -= (XK_zcaron - XK_Zcaron);
-       else if (sym >= XK_Racute && sym <= XK_Tcedilla)
-           *lower += (XK_racute - XK_Racute);
-       else if (sym >= XK_racute && sym <= XK_tcedilla)
-           *upper -= (XK_racute - XK_Racute);
-       break;
-    case 2: /* Latin 3 */
-       /* Assume the KeySym is a legal value (ignore discontinuities) */
-       if (sym >= XK_Hstroke && sym <= XK_Hcircumflex)
-           *lower += (XK_hstroke - XK_Hstroke);
-       else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex)
-           *lower += (XK_gbreve - XK_Gbreve);
-       else if (sym >= XK_hstroke && sym <= XK_hcircumflex)
-           *upper -= (XK_hstroke - XK_Hstroke);
-       else if (sym >= XK_gbreve && sym <= XK_jcircumflex)
-           *upper -= (XK_gbreve - XK_Gbreve);
-       else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex)
-           *lower += (XK_cabovedot - XK_Cabovedot);
-       else if (sym >= XK_cabovedot && sym <= XK_scircumflex)
-           *upper -= (XK_cabovedot - XK_Cabovedot);
-       break;
-    case 3: /* Latin 4 */
-       /* Assume the KeySym is a legal value (ignore discontinuities) */
-       if (sym >= XK_Rcedilla && sym <= XK_Tslash)
-           *lower += (XK_rcedilla - XK_Rcedilla);
-       else if (sym >= XK_rcedilla && sym <= XK_tslash)
-           *upper -= (XK_rcedilla - XK_Rcedilla);
-       else if (sym == XK_ENG)
-           *lower = XK_eng;
-       else if (sym == XK_eng)
-           *upper = XK_ENG;
-       else if (sym >= XK_Amacron && sym <= XK_Umacron)
-           *lower += (XK_amacron - XK_Amacron);
-       else if (sym >= XK_amacron && sym <= XK_umacron)
-           *upper -= (XK_amacron - XK_Amacron);
-       break;
-    case 6: /* Cyrillic */
-       /* Assume the KeySym is a legal value (ignore discontinuities) */
-       if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE)
-           *lower -= (XK_Serbian_DJE - XK_Serbian_dje);
-       else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze)
-           *upper += (XK_Serbian_DJE - XK_Serbian_dje);
-       else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN)
-           *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu);
-       else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign)
-           *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu);
-        break;
-    case 7: /* Greek */
-       /* Assume the KeySym is a legal value (ignore discontinuities) */
-       if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent)
-           *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
-       else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent &&
-                sym != XK_Greek_iotaaccentdieresis &&
-                sym != XK_Greek_upsilonaccentdieresis)
-           *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
-       else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA)
-           *lower += (XK_Greek_alpha - XK_Greek_ALPHA);
-       else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega &&
-                sym != XK_Greek_finalsmallsigma)
-           *upper -= (XK_Greek_alpha - XK_Greek_ALPHA);
-        break;
-    }
-}
-
-static KeySym KeyCodetoKeySym(KeySymsPtr keymap, int keycode, int col)
-{
-  register int per = keymap->mapWidth;
-  register KeySym *syms;
-  KeySym lsym, usym;
-
-  if ((col < 0) || ((col >= per) && (col > 3)) ||
-      (keycode < keymap->minKeyCode) || (keycode > keymap->maxKeyCode))
-    return NoSymbol;
-
-  syms = &keymap->map[(keycode - keymap->minKeyCode) * per];
-  if (col < 4) {
-    if (col > 1) {
-      while ((per > 2) && (syms[per - 1] == NoSymbol))
-        per--;
-      if (per < 3)
-        col -= 2;
-    }
-    if ((per <= (col|1)) || (syms[col|1] == NoSymbol)) {
-      XConvertCase(syms[col&~1], &lsym, &usym);
-      if (!(col & 1))
-        return lsym;
-      // I'm commenting out this logic because it's incorrect even though it
-      // was copied from the Xlib sources.  The X protocol book quite clearly
-      // states that where a group consists of element 1 being a non-alphabetic
-      // keysym and element 2 being NoSymbol that you treat the second element
-      // as being the same as the first.  This also tallies with the behaviour
-      // produced by the installed Xlib on my linux box (I believe this is
-      // because it uses some XKB code rather than the original Xlib code -
-      // compare XKBBind.c with KeyBind.c in lib/X11).
-      // else if (usym == lsym)
-      //   return NoSymbol;
-      else
-        return usym;
-    }
-  }
-  return syms[col];
-}
-
-// KeysymToKeycode() - find the keycode and column corresponding to the given
-// keysym.  The value of col passed in should be the column determined from the
-// current shift state.  If the keysym can be found in that column we prefer
-// that to finding it in a different column (which would require fake events to
-// alter the shift state).
-
-static KeyCode KeysymToKeycode(KeySymsPtr keymap, KeySym ks, int* col)
-{
-  register int i, j;
-
-  j = *col;
-  for (i = keymap->minKeyCode; i <= keymap->maxKeyCode; i++) {
-    if (KeyCodetoKeySym(keymap, i, j) == ks)
-      return i;
-  }
-
-  for (j = 0; j < keymap->mapWidth; j++) {
-    for (i = keymap->minKeyCode; i <= keymap->maxKeyCode; i++) {
-      if (KeyCodetoKeySym(keymap, i, j) == ks) {
-        *col = j;
-        return i;
-      }
-    }
-  }
-  return 0;
-}
diff --git a/unix/xc/programs/Xserver/vnc/XserverDesktop.h b/unix/xc/programs/Xserver/vnc/XserverDesktop.h
deleted file mode 100644 (file)
index 880acc2..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd.  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.
- */
-//
-// XserverDesktop.h
-//
-
-#ifndef __XSERVERDESKTOP_H__
-#define __XSERVERDESKTOP_H__
-
-#include <rfb/SDesktop.h>
-#include <rfb/HTTPServer.h>
-#include <rfb/PixelBuffer.h>
-#include <rfb/Configuration.h>
-#include <rfb/VNCServerST.h>
-#include <rdr/SubstitutingInStream.h>
-
-extern "C" {
-#define class c_class;
-#include <scrnintstr.h>
-#include <os.h>
-#undef class
-}
-
-namespace rfb {
-  class VNCServerST;
-}
-
-namespace network { class TcpListener; class Socket; }
-
-class XserverDesktop : public rfb::SDesktop, public rfb::FullFramePixelBuffer,
-                       public rfb::ColourMap, public rdr::Substitutor,
-                       public rfb::VNCServerST::QueryConnectionHandler {
-public:
-
-  XserverDesktop(ScreenPtr pScreen, network::TcpListener* listener,
-                 network::TcpListener* httpListener_,
-                 const char* name, void* fbptr);
-  virtual ~XserverDesktop();
-
-  // methods called from X server code
-  void serverReset(ScreenPtr pScreen);
-  void setColormap(ColormapPtr cmap);
-  void setColourMapEntries(ColormapPtr pColormap, int ndef, xColorItem* pdef);
-  void bell();
-  void serverCutText(const char* str, int len);
-  void setCursor(CursorPtr cursor);
-  void add_changed(RegionPtr reg);
-  void add_copied(RegionPtr dst, int dx, int dy);
-  void positionCursor();
-  void ignoreHooks(bool b) { ignoreHooks_ = b; }
-  void blockHandler(fd_set* fds);
-  void wakeupHandler(fd_set* fds, int nfds);
-  void addClient(network::Socket* sock, bool reverse);
-  void disconnectClients();
-
-  // QueryConnect methods called from X server code
-  // getQueryTimeout()
-  //   Returns the timeout associated with a particular
-  //   connection, identified by an opaque Id passed to the
-  //   X code earlier.  Also optionally gets the address and
-  //   name associated with that connection.
-  //   Returns zero if the Id is not recognised.
-  int getQueryTimeout(void* opaqueId,
-                      const char** address=0,
-                      const char** username=0);
-
-  // approveConnection()
-  //   Used by X server code to supply the result of a query.
-  void approveConnection(void* opaqueId, bool accept,
-                         const char* rejectMsg=0);
-
-  // rfb::SDesktop callbacks
-  virtual void pointerEvent(const rfb::Point& pos, int buttonMask);
-  virtual void keyEvent(rdr::U32 key, bool down);
-  virtual void clientCutText(const char* str, int len);
-  virtual rfb::Point getFbSize() { return rfb::Point(width(), height()); }
-
-  // rfb::PixelBuffer callbacks
-  virtual void grabRegion(const rfb::Region& r);
-
-  // rfb::ColourMap callbacks
-  virtual void lookup(int index, int* r, int* g, int* b);
-
-  // rdr::Substitutor callback
-  virtual char* substitute(const char* varName);
-
-  // rfb::VNCServerST::QueryConnectionHandler callback
-  virtual rfb::VNCServerST::queryResult queryConnection(network::Socket* sock,
-                                                        const char* userName,
-                                                        char** reason);
-
-private:
-  void setColourMapEntries(int firstColour, int nColours);
-  static CARD32 deferredUpdateTimerCallback(OsTimerPtr timer, CARD32 now,
-                                            pointer arg);
-  void deferUpdate();
-  ScreenPtr pScreen;
-  OsTimerPtr deferredUpdateTimer, dummyTimer;
-  rfb::VNCServerST* server;
-  rfb::HTTPServer* httpServer;
-  network::TcpListener* listener;
-  network::TcpListener* httpListener;
-  ColormapPtr cmap;
-  bool deferredUpdateTimerSet;
-  bool grabbing;
-  bool ignoreHooks_;
-  bool directFbptr;
-  int oldButtonMask;
-  rfb::Point cursorPos, oldCursorPos;
-
-  void* queryConnectId;
-  rfb::CharArray queryConnectAddress;
-  rfb::CharArray queryConnectUsername;
-};
-#endif
diff --git a/unix/xc/programs/Xserver/vnc/Xvnc/Imakefile b/unix/xc/programs/Xserver/vnc/Xvnc/Imakefile
deleted file mode 100644 (file)
index 57db671..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-
- VNCCOMMONDIR = VncCommonDir
-   VNCINCLUDE = -I$(VNCCOMMONDIR)
-      VNCLIBS = VncExtLibs
-
-#if defined(XFree86Version) && XFree86Version < 4000
-   VNCDEFINES = -DNO_INIT_BACKING_STORE
-#endif
-
-#define CplusplusSource
-
-#include <Server.tmpl>
-
-#if HasShm
-SHMDEF = -DHAS_SHM
-#endif
-
-XCOMM add more architectures here as we discover them
-#if defined(HPArchitecture) || \
-    (defined(SparcArchitecture) && !defined(LynxOSArchitecture)) || \
-    SystemV4 || \
-    defined(OSF1Architecture) || \
-    defined(i386BsdArchitecture) || \
-    defined(LinuxArchitecture) || \
-    defined(DarwinArchitecture)
-MMAPDEF = -DHAS_MMAP
-#endif
-
-#ifdef XVendorString
-VENDORSTRING = XVendorString
-#else
-VENDORSTRING = "unknown"
-#endif
-
-#ifdef XVendorRelease
-VENDORRELEASE = XVendorRelease
-#else
-VENDORRELEASE = 0
-#endif
-
-   VENDOR_STRING = -DVENDOR_STRING=\"$(VENDORSTRING)\"
-   VENDOR_RELEASE = -DVENDOR_RELEASE="$(VENDORRELEASE)"
-
-#ifdef OS2Architecture
-SRCS1 = os2_stubs.c
-OBJS1 = os2_stubs.o
-#endif
-
-FBINCLUDE = -I../../fb
-
-SRCSA =        xvnc.cc stubs.c $(SRCS1) miinitext.c $(SRCS2)
-
-OBJSA =        xvnc.o stubs.o $(OBJS1) miinitext.o $(OBJS2)
-
-INCLUDES = -I. -I.. -I$(XBUILDINCDIR) -I$(FONTINCSRC) \
-           $(FBINCLUDE) -I../../mfb -I../../mi -I../../include -I../../os  \
-           -I$(EXTINCSRC) -I$(XINCLUDESRC)  -I$(SERVERSRC)/render $(VNCINCLUDE)
-
-DEFINES = $(OS_DEFINES) $(SHMDEF) $(MMAPDEF) $(FB_DEFINES) \
-          $(VENDOR_STRING) $(VENDOR_RELEASE) $(STD_DEFINES) ServerOSDefines \
-          $(VNCDEFINES) -UXFree86LOADER
-
-#if defined(XFree86Version) || defined(XorgVersion)
-/* 
- * Make sure XINPUT, XF86VidTune, etc arent defined for the miinitext.o 
- * used by Xvnc 
- */
-EXT_DEFINES = ExtensionDefines -UXF86VIDMODE -UXFreeXDGA -UXF86MISC -UXF86DRI
-#endif
-
-
-SRCS = $(SRCSA) $(SRCSB) $(SRCSC)
-OBJS = $(OBJSA) $(OBJSB) $(OBJSC)
-
-NormalLibraryObjectRule()
-NormalLibraryTarget(xvnc,$(OBJS) buildtime.o)
-
-#ifdef OS2Architecture
-LinkSourceFile(os2_stubs.c,../xfree86/os-support/os2)
-SpecialCObjectRule(os2_stubs,$(ICONFIGFILES),-DOS2NULLSELECT)
-#endif
-
-#ifdef HasGcc
-NO_OPERATOR_NAMES = -fno-operator-names
-#endif
-LinkSourceFile(stubs.c,../../Xi)
-SpecialCplusplusObjectRule(xvnc,$(ICONFIGFILES) xvnc,$(EXT_DEFINES) $(NO_OPERATOR_NAMES))
-
-LinkSourceFile(miinitext.c,$(SERVERSRC)/mi)
-SpecialCObjectRule(miinitext,$(ICONFIGFILES),$(EXT_DEFINES) $(PAN_DEFINES) -DNO_MODULE_EXTS $(EXT_MODULE_DEFINES) -UXFree86LOADER)
-
-/* InstallManPage(Xvfb,$(MANDIR)) */
-DependTarget()
-
-buildtime.o: $(OBJS) ../LibraryTargetName(vnc) $(VNCLIBS)
diff --git a/unix/xc/programs/Xserver/vnc/Xvnc/buildtime.c b/unix/xc/programs/Xserver/vnc/Xvnc/buildtime.c
deleted file mode 100644 (file)
index 3f4c369..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd.  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.
- */
-char buildtime[] = __DATE__ " " __TIME__;
diff --git a/unix/xc/programs/Xserver/vnc/Xvnc/xvnc.cc b/unix/xc/programs/Xserver/vnc/Xvnc/xvnc.cc
deleted file mode 100644 (file)
index 5daf663..0000000
+++ /dev/null
@@ -1,1472 +0,0 @@
-/* Copyright (c) 1993  X Consortium
-   Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
-
-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.
-
-*/
-
-#include <rfb/Configuration.h>
-#include <rfb/Logger_stdio.h>
-#include <rfb/LogWriter.h>
-#include <network/TcpSocket.h>
-#include "vncExtInit.h"
-
-extern "C" {
-#define class c_class
-#define public c_public
-#define xor c_xor
-#define and c_and
-#ifdef WIN32
-#include <X11/Xwinsock.h>
-#endif
-#include <stdio.h>
-#include "X11/X.h"
-#define NEED_EVENTS
-#include "X11/Xproto.h"
-#include "X11/Xos.h"
-#include "scrnintstr.h"
-#include "servermd.h"
-#include "fb.h"
-#include "mi.h"
-#include "mibstore.h"
-#include "colormapst.h"
-#include "gcstruct.h"
-#include "input.h"
-#include "mipointer.h"
-#define new New
-#include "micmap.h"
-#undef new
-#include <sys/types.h>
-#ifdef HAS_MMAP
-#include <sys/mman.h>
-#ifndef MAP_FILE
-#define MAP_FILE 0
-#endif
-#endif /* HAS_MMAP */
-#include <sys/stat.h>
-#include <errno.h>
-#ifndef WIN32
-#include <sys/param.h>
-#endif
-#include <X11/XWDFile.h>
-#ifdef HAS_SHM
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#endif /* HAS_SHM */
-#include "dix.h"
-#include "miline.h"
-#include "inputstr.h"
-#include "keysym.h"
-  extern int defaultColorVisualClass;
-  extern char buildtime[];
-#undef class
-#undef public
-#undef xor
-#undef and
-}
-
-#define XVNCVERSION "TightVNC 1.5 series"
-#define XVNCCOPYRIGHT ("Copyright (C) 2002-2005 RealVNC Ltd.\n" \
-                      "Copyright (C) 2000-2006 Constantin Kaplinsky\n" \
-                      "Copyright (C) 2004-2006 Peter Astrand, Cendio AB\n" \
-                       "See http://www.tightvnc.com for information on TightVNC.\n")
-
-
-extern char *display;
-extern int monitorResolution;
-
-#define VFB_DEFAULT_WIDTH  1024
-#define VFB_DEFAULT_HEIGHT 768
-#define VFB_DEFAULT_DEPTH  16
-#define VFB_DEFAULT_WHITEPIXEL 0xffff
-#define VFB_DEFAULT_BLACKPIXEL 0
-#define VFB_DEFAULT_LINEBIAS 0
-#define XWD_WINDOW_NAME_LEN 60
-
-typedef struct
-{
-    int scrnum;
-    int width;
-    int paddedBytesWidth;
-    int paddedWidth;
-    int height;
-    int depth;
-    int bitsPerPixel;
-    int sizeInBytes;
-    int ncolors;
-    char *pfbMemory;
-    XWDColor *pXWDCmap;
-    XWDFileHeader *pXWDHeader;
-    Pixel blackPixel;
-    Pixel whitePixel;
-    unsigned int lineBias;
-    CloseScreenProcPtr closeScreen;
-
-#ifdef HAS_MMAP
-    int mmap_fd;
-    char mmap_file[MAXPATHLEN];
-#endif
-
-#ifdef HAS_SHM
-    int shmid;
-#endif
-
-    Bool pixelFormatDefined;
-    Bool rgbNotBgr;
-    int redBits, greenBits, blueBits;
-
-} vfbScreenInfo, *vfbScreenInfoPtr;
-
-static int vfbNumScreens;
-static vfbScreenInfo vfbScreens[MAXSCREENS];
-static Bool vfbPixmapDepths[33];
-#ifdef HAS_MMAP
-static char *pfbdir = NULL;
-#endif
-typedef enum { NORMAL_MEMORY_FB, SHARED_MEMORY_FB, MMAPPED_FILE_FB } fbMemType;
-static fbMemType fbmemtype = NORMAL_MEMORY_FB;
-static char needswap = 0;
-static int lastScreen = -1;
-static Bool Render = TRUE;
-
-static bool displaySpecified = false;
-static bool wellKnownSocketsCreated = false;
-static char displayNumStr[16];
-
-#define swapcopy16(_dst, _src) \
-    if (needswap) { CARD16 _s = _src; cpswaps(_s, _dst); } \
-    else _dst = _src;
-
-#define swapcopy32(_dst, _src) \
-    if (needswap) { CARD32 _s = _src; cpswapl(_s, _dst); } \
-    else _dst = _src;
-
-
-static void
-vfbInitializePixmapDepths(void)
-{
-    int i;
-    vfbPixmapDepths[1] = TRUE; /* always need bitmaps */
-    for (i = 2; i <= 32; i++)
-       vfbPixmapDepths[i] = FALSE;
-}
-
-static void
-vfbInitializeDefaultScreens(void)
-{
-    int i;
-
-    for (i = 0; i < MAXSCREENS; i++)
-    {
-       vfbScreens[i].scrnum = i;
-       vfbScreens[i].width  = VFB_DEFAULT_WIDTH;
-       vfbScreens[i].height = VFB_DEFAULT_HEIGHT;
-       vfbScreens[i].depth  = VFB_DEFAULT_DEPTH;
-       vfbScreens[i].blackPixel = VFB_DEFAULT_BLACKPIXEL;
-       vfbScreens[i].whitePixel = VFB_DEFAULT_WHITEPIXEL;
-       vfbScreens[i].lineBias = VFB_DEFAULT_LINEBIAS;
-       vfbScreens[i].pixelFormatDefined = FALSE;
-       vfbScreens[i].pfbMemory = NULL;
-    }
-    vfbNumScreens = 1;
-}
-
-static int
-vfbBitsPerPixel(int depth)
-{
-    if (depth == 1) return 1;
-    else if (depth <= 8) return 8;
-    else if (depth <= 16) return 16;
-    else return 32;
-}
-
-
-extern "C" {
-
-  void ddxGiveUp()
-  {
-    int i;
-
-    /* clean up the framebuffers */
-
-    switch (fbmemtype)
-    {
-#ifdef HAS_MMAP
-    case MMAPPED_FILE_FB: 
-       for (i = 0; i < vfbNumScreens; i++)
-       {
-           if (-1 == unlink(vfbScreens[i].mmap_file))
-           {
-               perror("unlink");
-               ErrorF("unlink %s failed, errno %d",
-                      vfbScreens[i].mmap_file, errno);
-           }
-       }
-       break;
-#else /* HAS_MMAP */
-    case MMAPPED_FILE_FB:
-        break;
-#endif /* HAS_MMAP */
-       
-#ifdef HAS_SHM
-    case SHARED_MEMORY_FB:
-       for (i = 0; i < vfbNumScreens; i++)
-       {
-           if (-1 == shmdt((char *)vfbScreens[i].pXWDHeader))
-           {
-               perror("shmdt");
-               ErrorF("shmdt failed, errno %d", errno);
-           }
-       }
-       break;
-#else /* HAS_SHM */
-    case SHARED_MEMORY_FB:
-        break;
-#endif /* HAS_SHM */
-       
-    case NORMAL_MEMORY_FB:
-       for (i = 0; i < vfbNumScreens; i++)
-       {
-           Xfree(vfbScreens[i].pXWDHeader);
-       }
-       break;
-    }
-}
-
-void
-AbortDDX()
-{
-    ddxGiveUp();
-}
-
-#ifdef __DARWIN__
-void
-DarwinHandleGUI(int argc, char *argv[])
-{
-}
-
-void GlxExtensionInit();
-void GlxWrapInitVisuals(void *procPtr);
-
-void
-DarwinGlxExtensionInit()
-{
-    GlxExtensionInit();
-}
-
-void
-DarwinGlxWrapInitVisuals(
-    void *procPtr)
-{
-    GlxWrapInitVisuals(procPtr);
-}
-#endif
-
-void
-OsVendorInit()
-{
-}
-
-void
-OsVendorFatalError()
-{
-}
-
-void ddxBeforeReset(void)
-{
-    return;
-}
-
-void 
-ddxUseMsg()
-{
-    ErrorF("\nXvnc %s - built %s\n%s", XVNCVERSION, buildtime, XVNCCOPYRIGHT);
-    ErrorF("Underlying X server release %d, %s\n\n", VENDOR_RELEASE,
-           VENDOR_STRING);
-    ErrorF("-screen scrn WxHxD     set screen's width, height, depth\n");
-    ErrorF("-pixdepths list-of-int support given pixmap depths\n");
-#ifdef RENDER
-    ErrorF("+/-render             turn on/off RENDER extension support"
-          "(default on)\n");
-#endif
-    ErrorF("-linebias n            adjust thin line pixelization\n");
-    ErrorF("-blackpixel n          pixel value for black\n");
-    ErrorF("-whitepixel n          pixel value for white\n");
-
-#ifdef HAS_MMAP
-    ErrorF("-fbdir directory       put framebuffers in mmap'ed files in directory\n");
-#endif
-
-#ifdef HAS_SHM
-    ErrorF("-shmem                 put framebuffers in shared memory\n");
-#endif
-
-    ErrorF("-geometry WxH          set screen 0's width, height\n");
-    ErrorF("-depth D               set screen 0's depth\n");
-    ErrorF("-pixelformat fmt       set pixel format (rgbNNN or bgrNNN)\n");
-    ErrorF("-inetd                 has been launched from inetd\n");
-    ErrorF("\nVNC parameters:\n");
-
-    fprintf(stderr,"\n"
-            "Parameters can be turned on with -<param> or off with -<param>=0\n"
-            "Parameters which take a value can be specified as "
-            "-<param> <value>\n"
-            "Other valid forms are <param>=<value> -<param>=<value> "
-            "--<param>=<value>\n"
-            "Parameter names are case-insensitive.  The parameters are:\n\n");
-    rfb::Configuration::listParams(79, 14);
-  }
-}
-
-/* ddxInitGlobals - called by |InitGlobals| from os/util.c */
-void ddxInitGlobals(void)
-{
-}
-
-static 
-bool displayNumFree(int num)
-{
-    try {
-       network::TcpListener l(6000+num);
-    } catch (rdr::Exception& e) {
-       return false;
-    }
-    char file[256];
-    sprintf(file, "/tmp/.X%d-lock", num);
-    if (access(file, F_OK) == 0) return false;
-    sprintf(file, "/tmp/.X11-unix/X%d", num);
-    if (access(file, F_OK) == 0) return false;
-    sprintf(file, "/usr/spool/sockets/X11/%d", num);
-    if (access(file, F_OK) == 0) return false;
-    return true;
-}
-
-int 
-ddxProcessArgument(int argc, char *argv[], int i)
-{
-    static Bool firstTime = TRUE;
-
-    if (firstTime)
-    {
-       vfbInitializeDefaultScreens();
-       vfbInitializePixmapDepths();
-       firstTime = FALSE;
-       rfb::initStdIOLoggers();
-       rfb::LogWriter::setLogParams("*:stderr:30");
-    }
-
-    if (argv[i][0] ==  ':')
-       displaySpecified = true;
-
-    if (strcmp (argv[i], "-screen") == 0)      /* -screen n WxHxD */
-    {
-       int screenNum;
-       if (i + 2 >= argc) UseMsg();
-       screenNum = atoi(argv[i+1]);
-       if (screenNum < 0 || screenNum >= MAXSCREENS)
-       {
-           ErrorF("Invalid screen number %d\n", screenNum);
-           UseMsg();
-       }
-       if (3 != sscanf(argv[i+2], "%dx%dx%d",
-                       &vfbScreens[screenNum].width,
-                       &vfbScreens[screenNum].height,
-                       &vfbScreens[screenNum].depth))
-       {
-           ErrorF("Invalid screen configuration %s\n", argv[i+2]);
-           UseMsg();
-       }
-
-       if (screenNum >= vfbNumScreens)
-           vfbNumScreens = screenNum + 1;
-       lastScreen = screenNum;
-       return 3;
-    }
-
-    if (strcmp (argv[i], "-pixdepths") == 0)   /* -pixdepths list-of-depth */
-    {
-       int depth, ret = 1;
-
-       if (++i >= argc) UseMsg();
-       while ((i < argc) && (depth = atoi(argv[i++])) != 0)
-       {
-           if (depth < 0 || depth > 32)
-           {
-               ErrorF("Invalid pixmap depth %d\n", depth);
-               UseMsg();
-           }
-           vfbPixmapDepths[depth] = TRUE;
-           ret++;
-       }
-       return ret;
-    }
-    
-    if (strcmp (argv[i], "+render") == 0)      /* +render */
-    {
-       Render = TRUE;
-       return 1;
-    }
-  
-    if (strcmp (argv[i], "-render") == 0)      /* -render */
-    {
-       Render = FALSE;
-       return 1;
-    }
-
-    if (strcmp (argv[i], "-blackpixel") == 0)  /* -blackpixel n */
-    {
-       Pixel pix;
-       if (++i >= argc) UseMsg();
-       pix = atoi(argv[i]);
-       if (-1 == lastScreen)
-       {
-           int i;
-           for (i = 0; i < MAXSCREENS; i++)
-           {
-               vfbScreens[i].blackPixel = pix;
-           }
-       }
-       else
-       {
-           vfbScreens[lastScreen].blackPixel = pix;
-       }
-       return 2;
-    }
-
-    if (strcmp (argv[i], "-whitepixel") == 0)  /* -whitepixel n */
-    {
-       Pixel pix;
-       if (++i >= argc) UseMsg();
-       pix = atoi(argv[i]);
-       if (-1 == lastScreen)
-       {
-           int i;
-           for (i = 0; i < MAXSCREENS; i++)
-           {
-               vfbScreens[i].whitePixel = pix;
-           }
-       }
-       else
-       {
-           vfbScreens[lastScreen].whitePixel = pix;
-       }
-       return 2;
-    }
-    
-    if (strcmp (argv[i], "-linebias") == 0)    /* -linebias n */
-    {
-       unsigned int linebias;
-       if (++i >= argc) UseMsg();
-       linebias = atoi(argv[i]);
-       if (-1 == lastScreen)
-       {
-           int i;
-           for (i = 0; i < MAXSCREENS; i++)
-           {
-               vfbScreens[i].lineBias = linebias;
-           }
-       }
-       else
-       {
-           vfbScreens[lastScreen].lineBias = linebias;
-       }
-       return 2;
-    }
-
-#ifdef HAS_MMAP
-    if (strcmp (argv[i], "-fbdir") == 0)       /* -fbdir directory */
-    {
-       if (++i >= argc) UseMsg();
-       pfbdir = argv[i];
-       fbmemtype = MMAPPED_FILE_FB;
-       return 2;
-    }
-#endif /* HAS_MMAP */
-
-#ifdef HAS_SHM
-    if (strcmp (argv[i], "-shmem") == 0)       /* -shmem */
-    {
-       fbmemtype = SHARED_MEMORY_FB;
-       return 1;
-    }
-#endif
-    
-    if (strcmp(argv[i], "-geometry") == 0)
-    {
-       if (++i >= argc) UseMsg();
-       if (sscanf(argv[i],"%dx%d",&vfbScreens[0].width,
-                  &vfbScreens[0].height) != 2) {
-           ErrorF("Invalid geometry %s\n", argv[i]);
-           UseMsg();
-       }
-       return 2;
-    }
-    
-    if (strcmp(argv[i], "-depth") == 0)
-    {
-       if (++i >= argc) UseMsg();
-       vfbScreens[0].depth = atoi(argv[i]);
-       return 2;
-    }
-
-    if (strcmp(argv[i], "-pixelformat") == 0)
-    {
-       char rgbbgr[4];
-       int bits1, bits2, bits3;
-       if (++i >= argc) UseMsg();
-       if (sscanf(argv[i], "%3s%1d%1d%1d", rgbbgr,&bits1,&bits2,&bits3) < 4) {
-           ErrorF("Invalid pixel format %s\n", argv[i]);
-           UseMsg();
-       }
-
-#define SET_PIXEL_FORMAT(vfbScreen)                     \
-    (vfbScreen).pixelFormatDefined = TRUE;              \
-    (vfbScreen).depth = bits1 + bits2 + bits3;          \
-    (vfbScreen).greenBits = bits2;                      \
-    if (strcasecmp(rgbbgr, "bgr") == 0) {               \
-        (vfbScreen).rgbNotBgr = FALSE;                  \
-        (vfbScreen).redBits = bits3;                    \
-        (vfbScreen).blueBits = bits1;                   \
-    } else if (strcasecmp(rgbbgr, "rgb") == 0) {        \
-        (vfbScreen).rgbNotBgr = TRUE;                   \
-        (vfbScreen).redBits = bits1;                    \
-        (vfbScreen).blueBits = bits3;                   \
-    } else {                                            \
-        ErrorF("Invalid pixel format %s\n", argv[i]);   \
-        UseMsg();                                       \
-    }
-
-       if (-1 == lastScreen)
-       {
-           int i;
-           for (i = 0; i < MAXSCREENS; i++)
-           {
-               SET_PIXEL_FORMAT(vfbScreens[i]);
-           }
-       }
-       else
-       {
-           SET_PIXEL_FORMAT(vfbScreens[lastScreen]);
-       }
-
-       return 2;
-    }
-
-    if (strcmp(argv[i], "-inetd") == 0)
-    {
-       dup2(0,3);
-       vncInetdSock = 3;
-       close(2);
-       
-       if (!displaySpecified) {
-           int port = network::TcpSocket::getSockPort(vncInetdSock);
-           int displayNum = port - 5900;
-           if (displayNum < 0 || displayNum > 99 || !displayNumFree(displayNum)) {
-               for (displayNum = 1; displayNum < 100; displayNum++)
-                   if (displayNumFree(displayNum)) break;
-               
-               if (displayNum == 100)
-                   FatalError("Xvnc error: no free display number for -inetd");
-           }
-           
-           display = displayNumStr;
-           sprintf(displayNumStr, "%d", displayNum);
-       }
-       
-       return 1;
-    }
-    
-    if (rfb::Configuration::setParam(argv[i]))
-       return 1;
-    
-    if (argv[i][0] == '-' && i+1 < argc) {
-       if (rfb::Configuration::setParam(&argv[i][1], argv[i+1]))
-           return 2;
-    }
-    
-    return 0;
-}
-
-#ifdef DDXTIME /* from ServerOSDefines */
-CARD32
-GetTimeInMillis()
-{
-    struct timeval  tp;
-
-    X_GETTIMEOFDAY(&tp);
-    return(tp.tv_sec * 1000) + (tp.tv_usec / 1000);
-}
-#endif
-
-static ColormapPtr InstalledMaps[MAXSCREENS];
-
-static int 
-vfbListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps)
-{
-    /* By the time we are processing requests, we can guarantee that there
-     * is always a colormap installed */
-    *pmaps = InstalledMaps[pScreen->myNum]->mid;
-    return (1);
-}
-
-
-static void 
-vfbInstallColormap(ColormapPtr pmap)
-{
-    int index = pmap->pScreen->myNum;
-    ColormapPtr oldpmap = InstalledMaps[index];
-
-    if (pmap != oldpmap)
-    {
-       int entries;
-       XWDFileHeader *pXWDHeader;
-       XWDColor *pXWDCmap;
-       VisualPtr pVisual;
-       Pixel *     ppix;
-       xrgb *      prgb;
-       xColorItem *defs;
-       int i;
-
-       if(oldpmap != (ColormapPtr)None)
-           WalkTree(pmap->pScreen, TellLostMap, (char *)&oldpmap->mid);
-       /* Install pmap */
-       InstalledMaps[index] = pmap;
-       WalkTree(pmap->pScreen, TellGainedMap, (char *)&pmap->mid);
-
-       entries = pmap->pVisual->ColormapEntries;
-       pXWDHeader = vfbScreens[pmap->pScreen->myNum].pXWDHeader;
-       pXWDCmap = vfbScreens[pmap->pScreen->myNum].pXWDCmap;
-       pVisual = pmap->pVisual;
-
-       swapcopy32(pXWDHeader->visual_class, pVisual->c_class);
-       swapcopy32(pXWDHeader->red_mask, pVisual->redMask);
-       swapcopy32(pXWDHeader->green_mask, pVisual->greenMask);
-       swapcopy32(pXWDHeader->blue_mask, pVisual->blueMask);
-       swapcopy32(pXWDHeader->bits_per_rgb, pVisual->bitsPerRGBValue);
-       swapcopy32(pXWDHeader->colormap_entries, pVisual->ColormapEntries);
-
-       ppix = (Pixel *)ALLOCATE_LOCAL(entries * sizeof(Pixel));
-       prgb = (xrgb *)ALLOCATE_LOCAL(entries * sizeof(xrgb));
-       defs = (xColorItem *)ALLOCATE_LOCAL(entries * sizeof(xColorItem));
-
-       for (i = 0; i < entries; i++)  ppix[i] = i;
-       /* XXX truecolor */
-       QueryColors(pmap, entries, ppix, prgb);
-
-       for (i = 0; i < entries; i++) { /* convert xrgbs to xColorItems */
-           defs[i].pixel = ppix[i] & 0xff; /* change pixel to index */
-           defs[i].red = prgb[i].red;
-           defs[i].green = prgb[i].green;
-           defs[i].blue = prgb[i].blue;
-           defs[i].flags =  DoRed|DoGreen|DoBlue;
-       }
-       (*pmap->pScreen->StoreColors)(pmap, entries, defs);
-       
-       DEALLOCATE_LOCAL(ppix);
-       DEALLOCATE_LOCAL(prgb);
-       DEALLOCATE_LOCAL(defs);
-    }
-}
-
-static void
-vfbUninstallColormap(ColormapPtr pmap)
-{
-    ColormapPtr curpmap = InstalledMaps[pmap->pScreen->myNum];
-
-    if(pmap == curpmap)
-    {
-       if (pmap->mid != pmap->pScreen->defColormap)
-       {
-           curpmap = (ColormapPtr) LookupIDByType(pmap->pScreen->defColormap,
-                                                  RT_COLORMAP);
-           (*pmap->pScreen->InstallColormap)(curpmap);
-       }
-    }
-}
-
-static void
-vfbStoreColors(ColormapPtr pmap, int ndef, xColorItem *pdefs)
-{
-    XWDColor *pXWDCmap;
-    int i;
-
-    if (pmap != InstalledMaps[pmap->pScreen->myNum])
-    {
-       return;
-    }
-
-    pXWDCmap = vfbScreens[pmap->pScreen->myNum].pXWDCmap;
-
-    if ((pmap->pVisual->c_class | DynamicClass) == DirectColor)
-    {
-       return;
-    }
-
-    for (i = 0; i < ndef; i++)
-    {
-       if (pdefs[i].flags & DoRed)
-       {
-           swapcopy16(pXWDCmap[pdefs[i].pixel].red, pdefs[i].red);
-       }
-       if (pdefs[i].flags & DoGreen)
-       {
-           swapcopy16(pXWDCmap[pdefs[i].pixel].green, pdefs[i].green);
-       }
-       if (pdefs[i].flags & DoBlue)
-       {
-           swapcopy16(pXWDCmap[pdefs[i].pixel].blue, pdefs[i].blue);
-       }
-    }
-}
-
-static Bool
-vfbSaveScreen(ScreenPtr pScreen, int on)
-{
-    return TRUE;
-}
-
-#ifdef HAS_MMAP
-
-/* this flushes any changes to the screens out to the mmapped file */
-static void
-vfbBlockHandler(pointer blockData, OSTimePtr pTimeout, pointer pReadmask)
-{
-    int i;
-
-    for (i = 0; i < vfbNumScreens; i++)
-    {
-#ifdef MS_ASYNC
-       if (-1 == msync((caddr_t)vfbScreens[i].pXWDHeader,
-                       (size_t)vfbScreens[i].sizeInBytes, MS_ASYNC))
-#else
-       /* silly NetBSD and who else? */
-       if (-1 == msync((caddr_t)vfbScreens[i].pXWDHeader,
-                       (size_t)vfbScreens[i].sizeInBytes))
-#endif
-       {
-           perror("msync");
-           ErrorF("msync failed, errno %d", errno);
-       }
-    }
-}
-
-
-static void
-vfbWakeupHandler(pointer blockData, int result, pointer pReadmask)
-{
-}
-
-
-static void
-vfbAllocateMmappedFramebuffer(vfbScreenInfoPtr pvfb)
-{
-#define DUMMY_BUFFER_SIZE 65536
-    char dummyBuffer[DUMMY_BUFFER_SIZE];
-    int currentFileSize, writeThisTime;
-
-    sprintf(pvfb->mmap_file, "%s/Xvfb_screen%d", pfbdir, pvfb->scrnum);
-    if (-1 == (pvfb->mmap_fd = open(pvfb->mmap_file, O_CREAT|O_RDWR, 0666)))
-    {
-       perror("open");
-       ErrorF("open %s failed, errno %d", pvfb->mmap_file, errno);
-       return;
-    }
-
-    /* Extend the file to be the proper size */
-
-    bzero(dummyBuffer, DUMMY_BUFFER_SIZE);
-    for (currentFileSize = 0;
-        currentFileSize < pvfb->sizeInBytes;
-        currentFileSize += writeThisTime)
-    {
-       writeThisTime = min(DUMMY_BUFFER_SIZE,
-                           pvfb->sizeInBytes - currentFileSize);
-       if (-1 == write(pvfb->mmap_fd, dummyBuffer, writeThisTime))
-       {
-           perror("write");
-           ErrorF("write %s failed, errno %d", pvfb->mmap_file, errno);
-           return;
-       }
-    }
-
-    /* try to mmap the file */
-
-    pvfb->pXWDHeader = (XWDFileHeader *)mmap((caddr_t)NULL, pvfb->sizeInBytes,
-                                   PROT_READ|PROT_WRITE,
-                                   MAP_FILE|MAP_SHARED,
-                                   pvfb->mmap_fd, 0);
-    if (-1 == (long)pvfb->pXWDHeader)
-    {
-       perror("mmap");
-       ErrorF("mmap %s failed, errno %d", pvfb->mmap_file, errno);
-       pvfb->pXWDHeader = NULL;
-       return;
-    }
-
-    if (!RegisterBlockAndWakeupHandlers(vfbBlockHandler, vfbWakeupHandler,
-                                       NULL))
-    {
-       pvfb->pXWDHeader = NULL;
-    }
-}
-#endif /* HAS_MMAP */
-
-
-#ifdef HAS_SHM
-static void
-vfbAllocateSharedMemoryFramebuffer(vfbScreenInfoPtr pvfb)
-{
-    /* create the shared memory segment */
-
-    pvfb->shmid = shmget(IPC_PRIVATE, pvfb->sizeInBytes, IPC_CREAT|0777);
-    if (pvfb->shmid < 0)
-    {
-       perror("shmget");
-       ErrorF("shmget %d bytes failed, errno %d", pvfb->sizeInBytes, errno);
-       return;
-    }
-
-    /* try to attach it */
-
-    pvfb->pXWDHeader = (XWDFileHeader *)shmat(pvfb->shmid, 0, 0);
-    if (-1 == (long)pvfb->pXWDHeader)
-    {
-       perror("shmat");
-       ErrorF("shmat failed, errno %d", errno);
-       pvfb->pXWDHeader = NULL; 
-       return;
-    }
-
-    ErrorF("screen %d shmid %d\n", pvfb->scrnum, pvfb->shmid);
-}
-#endif /* HAS_SHM */
-
-
-static char *
-vfbAllocateFramebufferMemory(vfbScreenInfoPtr pvfb)
-{
-    if (pvfb->pfbMemory) return pvfb->pfbMemory; /* already done */
-
-    pvfb->sizeInBytes = pvfb->paddedBytesWidth * pvfb->height;
-
-    /* Calculate how many entries in colormap.  This is rather bogus, because
-     * the visuals haven't even been set up yet, but we need to know because we
-     * have to allocate space in the file for the colormap.  The number 10
-     * below comes from the MAX_PSEUDO_DEPTH define in cfbcmap.c.
-     */
-
-    if (pvfb->depth <= 10)
-    { /* single index colormaps */
-       pvfb->ncolors = 1 << pvfb->depth;
-    }
-    else
-    { /* decomposed colormaps */
-       int nplanes_per_color_component = pvfb->depth / 3;
-       if (pvfb->depth % 3) nplanes_per_color_component++;
-       pvfb->ncolors = 1 << nplanes_per_color_component;
-    }
-
-    /* add extra bytes for XWDFileHeader, window name, and colormap */
-
-    pvfb->sizeInBytes += SIZEOF(XWDheader) + XWD_WINDOW_NAME_LEN +
-                   pvfb->ncolors * SIZEOF(XWDColor);
-
-    pvfb->pXWDHeader = NULL; 
-    switch (fbmemtype)
-    {
-#ifdef HAS_MMAP
-    case MMAPPED_FILE_FB:  vfbAllocateMmappedFramebuffer(pvfb); break;
-#else
-    case MMAPPED_FILE_FB: break;
-#endif
-
-#ifdef HAS_SHM
-    case SHARED_MEMORY_FB: vfbAllocateSharedMemoryFramebuffer(pvfb); break;
-#else
-    case SHARED_MEMORY_FB: break;
-#endif
-
-    case NORMAL_MEMORY_FB:
-       pvfb->pXWDHeader = (XWDFileHeader *)Xalloc(pvfb->sizeInBytes);
-       break;
-    }
-
-    if (pvfb->pXWDHeader)
-    {
-       pvfb->pXWDCmap = (XWDColor *)((char *)pvfb->pXWDHeader
-                               + SIZEOF(XWDheader) + XWD_WINDOW_NAME_LEN);
-       pvfb->pfbMemory = (char *)(pvfb->pXWDCmap + pvfb->ncolors);
-
-       return pvfb->pfbMemory;
-    }
-    else
-       return NULL;
-}
-
-static void
-vfbWriteXWDFileHeader(ScreenPtr pScreen)
-{
-    vfbScreenInfoPtr pvfb = &vfbScreens[pScreen->myNum];
-    XWDFileHeader *pXWDHeader = pvfb->pXWDHeader;
-    char hostname[XWD_WINDOW_NAME_LEN];
-    unsigned long swaptest = 1;
-    int i;
-
-    needswap = *(char *) &swaptest;
-
-    pXWDHeader->header_size = (char *)pvfb->pXWDCmap - (char *)pvfb->pXWDHeader;
-    pXWDHeader->file_version = XWD_FILE_VERSION;
-
-    pXWDHeader->pixmap_format = ZPixmap;
-    pXWDHeader->pixmap_depth = pvfb->depth;
-    pXWDHeader->pixmap_height = pXWDHeader->window_height = pvfb->height;
-    pXWDHeader->xoffset = 0;
-    pXWDHeader->byte_order = IMAGE_BYTE_ORDER;
-    pXWDHeader->bitmap_bit_order = BITMAP_BIT_ORDER;
-#ifndef INTERNAL_VS_EXTERNAL_PADDING
-    pXWDHeader->pixmap_width = pXWDHeader->window_width = pvfb->width;
-    pXWDHeader->bitmap_unit = BITMAP_SCANLINE_UNIT;
-    pXWDHeader->bitmap_pad = BITMAP_SCANLINE_PAD;
-#else
-    pXWDHeader->pixmap_width = pXWDHeader->window_width = pvfb->paddedWidth;
-    pXWDHeader->bitmap_unit = BITMAP_SCANLINE_UNIT_PROTO;
-    pXWDHeader->bitmap_pad = BITMAP_SCANLINE_PAD_PROTO;
-#endif
-    pXWDHeader->bits_per_pixel = pvfb->bitsPerPixel;
-    pXWDHeader->bytes_per_line = pvfb->paddedBytesWidth;
-    pXWDHeader->ncolors = pvfb->ncolors;
-
-    /* visual related fields are written when colormap is installed */
-
-    pXWDHeader->window_x = pXWDHeader->window_y = 0;
-    pXWDHeader->window_bdrwidth = 0;
-
-    /* write xwd "window" name: Xvfb hostname:server.screen */
-
-    if (-1 == gethostname(hostname, sizeof(hostname)))
-       hostname[0] = 0;
-    else
-       hostname[XWD_WINDOW_NAME_LEN-1] = 0;
-    sprintf((char *)(pXWDHeader+1), "Xvfb %s:%s.%d", hostname, display,
-           pScreen->myNum);
-
-    /* write colormap pixel slot values */
-
-    for (i = 0; i < pvfb->ncolors; i++)
-    {
-       pvfb->pXWDCmap[i].pixel = i;
-    }
-
-    /* byte swap to most significant byte first */
-
-    if (needswap)
-    {
-       SwapLongs((CARD32 *)pXWDHeader, SIZEOF(XWDheader)/4);
-       for (i = 0; i < pvfb->ncolors; i++)
-       {
-           register char n;
-           swapl(&pvfb->pXWDCmap[i].pixel, n);
-       }
-    }
-}
-
-
-static Bool
-vfbCursorOffScreen (ScreenPtr *ppScreen, int *x, int *y)
-{
-    return FALSE;
-}
-
-static void
-vfbCrossScreen (ScreenPtr pScreen, Bool entering)
-{
-}
-
-static Bool vfbRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) {
-    return TRUE;
-}
-
-static Bool vfbUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) {
-    return TRUE;
-}
-
-static void vfbSetCursor(ScreenPtr pScreen, CursorPtr pCursor, int x, int y) 
-{
-}
-
-static void vfbMoveCursor(ScreenPtr pScreen, int x, int y) 
-{
-}
-
-static miPointerSpriteFuncRec vfbPointerSpriteFuncs = {
-    vfbRealizeCursor,
-    vfbUnrealizeCursor,
-    vfbSetCursor,
-    vfbMoveCursor
-};
-
-static miPointerScreenFuncRec vfbPointerCursorFuncs = {
-    vfbCursorOffScreen,
-    vfbCrossScreen,
-    miPointerWarpCursor
-};
-
-static Bool
-vfbCloseScreen(int index, ScreenPtr pScreen)
-{
-    vfbScreenInfoPtr pvfb = &vfbScreens[index];
-    int i;
-    pScreen->CloseScreen = pvfb->closeScreen;
-
-    /*
-     * XXX probably lots of stuff to clean.  For now,
-     * clear InstalledMaps[] so that server reset works correctly.
-     */
-    for (i = 0; i < MAXSCREENS; i++)
-       InstalledMaps[i] = NULL;
-
-    return pScreen->CloseScreen(index, pScreen);
-}
-
-static Bool
-vfbScreenInit(int index, ScreenPtr pScreen, int argc, char **argv)
-{
-    vfbScreenInfoPtr pvfb = &vfbScreens[index];
-    int dpi = 100;
-    int ret;
-    char *pbits;
-
-    if (monitorResolution) dpi = monitorResolution;
-
-    pvfb->paddedBytesWidth = PixmapBytePad(pvfb->width, pvfb->depth);
-    pvfb->bitsPerPixel = vfbBitsPerPixel(pvfb->depth);
-    pvfb->paddedWidth = pvfb->paddedBytesWidth * 8 / pvfb->bitsPerPixel;
-    pbits = vfbAllocateFramebufferMemory(pvfb);
-    if (!pbits) return FALSE;
-    vncFbptr[index] = pbits;
-
-    defaultColorVisualClass
-       = (pvfb->bitsPerPixel > 8) ? TrueColor : PseudoColor;
-
-    ret = fbScreenInit(pScreen, pbits, pvfb->width, pvfb->height,
-                      dpi, dpi, pvfb->paddedWidth, pvfb->bitsPerPixel);
-  
-#ifdef RENDER
-    if (ret && Render) 
-       fbPictureInit (pScreen, 0, 0);
-#endif
-
-    if (!ret) return FALSE;
-
-    /* miInitializeBackingStore(pScreen); */
-
-    /*
-     * Circumvent the backing store that was just initialised.  This amounts
-     * to a truely bizarre way of initialising SaveDoomedAreas and friends.
-     */
-
-    pScreen->InstallColormap = vfbInstallColormap;
-    pScreen->UninstallColormap = vfbUninstallColormap;
-    pScreen->ListInstalledColormaps = vfbListInstalledColormaps;
-
-    pScreen->SaveScreen = vfbSaveScreen;
-    pScreen->StoreColors = vfbStoreColors;
-    
-    miPointerInitialize(pScreen, &vfbPointerSpriteFuncs, &vfbPointerCursorFuncs,
-                       FALSE);
-    
-    vfbWriteXWDFileHeader(pScreen);
-
-    pScreen->blackPixel = pvfb->blackPixel;
-    pScreen->whitePixel = pvfb->whitePixel;
-
-    if (!pvfb->pixelFormatDefined && pvfb->depth == 16) {
-       pvfb->pixelFormatDefined = TRUE;
-       pvfb->rgbNotBgr = TRUE;
-       pvfb->blueBits = pvfb->redBits = 5;
-       pvfb->greenBits = 6;
-    }
-    
-    if (pvfb->pixelFormatDefined) {
-       VisualPtr vis = pScreen->visuals;
-       for (int i = 0; i < pScreen->numVisuals; i++) {
-           if (pvfb->rgbNotBgr) {
-               vis->offsetBlue = 0;
-               vis->blueMask = (1 << pvfb->blueBits) - 1;
-               vis->offsetGreen = pvfb->blueBits;
-               vis->greenMask = ((1 << pvfb->greenBits) - 1) << vis->offsetGreen;
-               vis->offsetRed = vis->offsetGreen + pvfb->greenBits;
-               vis->redMask = ((1 << pvfb->redBits) - 1) << vis->offsetRed;
-           } else {
-               vis->offsetRed = 0;
-               vis->redMask = (1 << pvfb->redBits) - 1;
-               vis->offsetGreen = pvfb->redBits;
-               vis->greenMask = ((1 << pvfb->greenBits) - 1) << vis->offsetGreen;
-               vis->offsetBlue = vis->offsetGreen + pvfb->greenBits;
-               vis->blueMask = ((1 << pvfb->blueBits) - 1) << vis->offsetBlue;
-           }
-           vis++;
-       }
-    }
-    
-    ret = fbCreateDefColormap(pScreen);
-
-    miSetZeroLineBias(pScreen, pvfb->lineBias);
-
-    pvfb->closeScreen = pScreen->CloseScreen;
-    pScreen->CloseScreen = vfbCloseScreen;
-
-#ifndef NO_INIT_BACKING_STORE
-  miInitializeBackingStore(pScreen);
-  pScreen->backingStoreSupport = Always;
-#endif
-
-  return ret;
-
-} /* end vfbScreenInit */
-
-
-static void vfbClientStateChange(CallbackListPtr*, pointer, pointer) {
-  dispatchException &= ~DE_RESET;
-}
-
-void
-InitOutput(ScreenInfo *screenInfo, int argc, char **argv)
-{
-  ErrorF("\nXvnc %s - built %s\n%s", XVNCVERSION, buildtime, XVNCCOPYRIGHT);
-  ErrorF("Underlying X server release %d, %s\n\n", VENDOR_RELEASE,
-         VENDOR_STRING);
-    int i;
-    int NumFormats = 0;
-
-    /* initialize pixmap formats */
-
-    /* must have a pixmap depth to match every screen depth */
-    for (i = 0; i < vfbNumScreens; i++)
-    {
-       vfbPixmapDepths[vfbScreens[i].depth] = TRUE;
-    }
-
-    /* RENDER needs a good set of pixmaps. */
-    if (Render) {
-       vfbPixmapDepths[1] = TRUE;
-       vfbPixmapDepths[4] = TRUE;
-       vfbPixmapDepths[8] = TRUE;
-/*     vfbPixmapDepths[15] = TRUE; */
-       vfbPixmapDepths[16] = TRUE;
-       vfbPixmapDepths[24] = TRUE;
-       vfbPixmapDepths[32] = TRUE;
-    }
-
-    for (i = 1; i <= 32; i++)
-    {
-       if (vfbPixmapDepths[i])
-       {
-           if (NumFormats >= MAXFORMATS)
-               FatalError ("MAXFORMATS is too small for this server\n");
-           screenInfo->formats[NumFormats].depth = i;
-           screenInfo->formats[NumFormats].bitsPerPixel = vfbBitsPerPixel(i);
-           screenInfo->formats[NumFormats].scanlinePad = BITMAP_SCANLINE_PAD;
-           NumFormats++;
-       }
-    }
-
-    screenInfo->imageByteOrder = IMAGE_BYTE_ORDER;
-    screenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
-    screenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
-    screenInfo->bitmapBitOrder = BITMAP_BIT_ORDER;
-    screenInfo->numPixmapFormats = NumFormats;
-
-    /* initialize screens */
-
-    for (i = 0; i < vfbNumScreens; i++)
-    {
-       if (-1 == AddScreen(vfbScreenInit, argc, argv))
-       {
-           FatalError("Couldn't add screen %d", i);
-       }
-    }
-
-    if (!AddCallback(&ClientStateCallback, vfbClientStateChange, 0)) {
-       FatalError("AddCallback failed\n");
-    }
-} /* end InitOutput */
-
-#ifdef DPMSExtension
-extern "C" {
-#if NeedFunctionPrototypes
-  void DPMSSet(CARD16 level)
-#else
-    void DPMSSet(level)
-    CARD16 level;
-#endif
-  {
-    return;
-  }
-
-  Bool DPMSSupported()
-  {
-    return FALSE;
-  }
-}
-#endif
-
-/* this is just to get the server to link on AIX */
-#ifdef AIXV3
-int SelectWaitTime = 10000; /* usec */
-#endif
-
-Bool LegalModifier(unsigned int key, DevicePtr pDev)
-{
-  return TRUE;
-}
-
-void ProcessInputEvents()
-{
-  mieqProcessInputEvents();
-  miPointerUpdate();
-}
-
-/* Fairly standard US PC Keyboard */
-
-#define VFB_MIN_KEY 8
-#define VFB_MAX_KEY 255
-#define VFB_MAP_LEN (VFB_MAX_KEY - VFB_MIN_KEY + 1)
-#define KEYSYMS_PER_KEY 2
-KeySym keyboardMap[VFB_MAP_LEN * KEYSYMS_PER_KEY] = {
-  NoSymbol, NoSymbol,
-  XK_Escape, NoSymbol,
-  XK_1, XK_exclam,
-  XK_2, XK_at,
-  XK_3, XK_numbersign,
-  XK_4, XK_dollar,
-  XK_5, XK_percent,
-  XK_6, XK_asciicircum,
-  XK_7, XK_ampersand,
-  XK_8, XK_asterisk,
-  XK_9, XK_parenleft,
-  XK_0, XK_parenright,
-  XK_minus, XK_underscore,
-  XK_equal, XK_plus,
-  XK_BackSpace, NoSymbol,
-  XK_Tab, NoSymbol,
-  XK_q, XK_Q,
-  XK_w, XK_W,
-  XK_e, XK_E,
-  XK_r, XK_R,
-  XK_t, XK_T,
-  XK_y, XK_Y,
-  XK_u, XK_U,
-  XK_i, XK_I,
-  XK_o, XK_O,
-  XK_p, XK_P,
-  XK_bracketleft, XK_braceleft,
-  XK_bracketright, XK_braceright,
-  XK_Return, NoSymbol,
-  XK_Control_L, NoSymbol,
-  XK_a, XK_A,
-  XK_s, XK_S,
-  XK_d, XK_D,
-  XK_f, XK_F,
-  XK_g, XK_G,
-  XK_h, XK_H,
-  XK_j, XK_J,
-  XK_k, XK_K,
-  XK_l, XK_L,
-  XK_semicolon, XK_colon,
-  XK_apostrophe, XK_quotedbl,
-  XK_grave, XK_asciitilde,
-  XK_Shift_L, NoSymbol,
-  XK_backslash, XK_bar,
-  XK_z, XK_Z,
-  XK_x, XK_X,
-  XK_c, XK_C,
-  XK_v, XK_V,
-  XK_b, XK_B,
-  XK_n, XK_N,
-  XK_m, XK_M,
-  XK_comma, XK_less,
-  XK_period, XK_greater,
-  XK_slash, XK_question,
-  XK_Shift_R, NoSymbol,
-  XK_KP_Multiply, NoSymbol,
-  XK_Alt_L, XK_Meta_L,
-  XK_space, NoSymbol,
-  /*XK_Caps_Lock*/ NoSymbol, NoSymbol,
-  XK_F1, NoSymbol,
-  XK_F2, NoSymbol,
-  XK_F3, NoSymbol,
-  XK_F4, NoSymbol,
-  XK_F5, NoSymbol,
-  XK_F6, NoSymbol,
-  XK_F7, NoSymbol,
-  XK_F8, NoSymbol,
-  XK_F9, NoSymbol,
-  XK_F10, NoSymbol,
-  XK_Num_Lock, XK_Pointer_EnableKeys,
-  XK_Scroll_Lock, NoSymbol,
-  XK_KP_Home, XK_KP_7,
-  XK_KP_Up, XK_KP_8,
-  XK_KP_Prior, XK_KP_9,
-  XK_KP_Subtract, NoSymbol,
-  XK_KP_Left, XK_KP_4,
-  XK_KP_Begin, XK_KP_5,
-  XK_KP_Right, XK_KP_6,
-  XK_KP_Add, NoSymbol,
-  XK_KP_End, XK_KP_1,
-  XK_KP_Down, XK_KP_2,
-  XK_KP_Next, XK_KP_3,
-  XK_KP_Insert, XK_KP_0,
-  XK_KP_Delete, XK_KP_Decimal,
-  NoSymbol, NoSymbol,
-  NoSymbol, NoSymbol,
-  NoSymbol, NoSymbol,
-  XK_F11, NoSymbol,
-  XK_F12, NoSymbol,
-  XK_Home, NoSymbol,
-  XK_Up, NoSymbol,
-  XK_Prior, NoSymbol,
-  XK_Left, NoSymbol,
-  NoSymbol, NoSymbol,
-  XK_Right, NoSymbol,
-  XK_End, NoSymbol,
-  XK_Down, NoSymbol,
-  XK_Next, NoSymbol,
-  XK_Insert, NoSymbol,
-  XK_Delete, NoSymbol,
-  XK_KP_Enter, NoSymbol,
-  XK_Control_R, NoSymbol,
-  XK_Pause, XK_Break,
-  XK_Print, XK_Execute,
-  XK_KP_Divide, NoSymbol,
-  XK_Alt_R, XK_Meta_R,
-};
-
-static Bool GetMappings(KeySymsPtr pKeySyms, CARD8 *pModMap)
-{
-  int i;
-
-  for (i = 0; i < MAP_LENGTH; i++)
-    pModMap[i] = NoSymbol;
-
-  for (i = 0; i < VFB_MAP_LEN; i++) {
-    if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Caps_Lock)
-      pModMap[i + VFB_MIN_KEY] = LockMask;
-    else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_L ||
-             keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_R)
-      pModMap[i + VFB_MIN_KEY] = ShiftMask;
-    else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_L ||
-             keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_R) {
-      pModMap[i + VFB_MIN_KEY] = ControlMask;
-    }
-    else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_L ||
-             keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_R)
-      pModMap[i + VFB_MIN_KEY] = Mod1Mask;
-  }
-
-  pKeySyms->minKeyCode = VFB_MIN_KEY;
-  pKeySyms->maxKeyCode = VFB_MAX_KEY;
-  pKeySyms->mapWidth = KEYSYMS_PER_KEY;
-  pKeySyms->map = keyboardMap;
-
-  return TRUE;
-}
-
-static void vfbBell(int percent, DeviceIntPtr device, pointer ctrl, int class_)
-{
-  if (percent > 0)
-    vncBell();
-}
-
-static int vfbKeybdProc(DeviceIntPtr pDevice, int onoff)
-{
-  KeySymsRec           keySyms;
-  CARD8                modMap[MAP_LENGTH];
-  DevicePtr pDev = (DevicePtr)pDevice;
-
-  switch (onoff)
-  {
-  case DEVICE_INIT: 
-    GetMappings(&keySyms, modMap);
-    InitKeyboardDeviceStruct(pDev, &keySyms, modMap,
-                             (BellProcPtr)vfbBell, (KbdCtrlProcPtr)NoopDDA);
-    break;
-  case DEVICE_ON: 
-    pDev->on = TRUE;
-    break;
-  case DEVICE_OFF: 
-    pDev->on = FALSE;
-    break;
-  case DEVICE_CLOSE:
-    break;
-  }
-  return Success;
-}
-
-static int vfbMouseProc(DeviceIntPtr pDevice, int onoff)
-{
-  BYTE map[6];
-  DevicePtr pDev = (DevicePtr)pDevice;
-
-  switch (onoff)
-  {
-  case DEVICE_INIT:
-    map[1] = 1;
-    map[2] = 2;
-    map[3] = 3;
-    map[4] = 4;
-    map[5] = 5;
-    InitPointerDeviceStruct(pDev, map, 5, miPointerGetMotionEvents,
-                            (PtrCtrlProcPtr)NoopDDA, miPointerGetMotionBufferSize());
-    break;
-
-  case DEVICE_ON:
-    pDev->on = TRUE;
-    break;
-
-  case DEVICE_OFF:
-    pDev->on = FALSE;
-    break;
-
-  case DEVICE_CLOSE:
-    break;
-  }
-  return Success;
-}
-
-// InitInput is called after InitExtensions, so we're guaranteed that
-// vncExtensionInit() has already been called.
-
-void InitInput(int argc, char *argv[])
-{
-  DeviceIntPtr p, k;
-  p = AddInputDevice(vfbMouseProc, TRUE);
-  k = AddInputDevice(vfbKeybdProc, TRUE);
-  RegisterPointerDevice(p);
-  RegisterKeyboardDevice(k);
-  miRegisterPointerDevice(screenInfo.screens[0], p);
-  (void)mieqInit ((DevicePtr)k, (DevicePtr)p);
-}
diff --git a/unix/xc/programs/Xserver/vnc/module/Imakefile b/unix/xc/programs/Xserver/vnc/module/Imakefile
deleted file mode 100644 (file)
index d2d34ed..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-
-   VNCUNIXDIR = VncUnixDir
- VNCCOMMONDIR = VncCommonDir
-      VNCLIBS = VncExtLibs
-   VNCINCLUDE = -I$(VNCCOMMONDIR) -I$(VNCUNIXDIR)/vncconfig
-
-#define CplusplusSource
-
-#define IHaveModules
-#include <Server.tmpl>
-
-    SRCS = vncExtInit.cc vncHooks.cc xf86vncModule.cc XserverDesktop.cc
-    OBJS = vncExtInit.o vncHooks.o xf86vncModule.o XserverDesktop.o
-INCLUDES = -I.. -I../../include -I$(EXTINCSRC) -I$(XINCLUDESRC) \
-           -I$(FONTINCSRC) -I$(XF86COMSRC) \
-           -I../../render $(VNCINCLUDE)
- DEFINES = $(STD_DEFINES) -DGC_HAS_COMPOSITE_CLIP -DXFree86LOADER
-
-LinkSourceFile(vncExtInit.cc,..)
-LinkSourceFile(vncHooks.cc,..)
-LinkSourceFile(xf86vncModule.cc,..)
-LinkSourceFile(XserverDesktop.cc,..)
-
-ModuleObjectRule()
-/*
- LibraryModuleTarget(vnc,$(OBJS) $(VNCLIBS))
- InstallLibraryModule(vnc,$(MODULEDIR),extensions)
-*/
-
-/* *** The imake rules don't define a ModuleCplusplusObjectRule so
-       for now we just assume that NormalCplusplusObjectRule will
-       do the job.
-   NB: If we don't do this then make will assume CC is the C++ compiler!
-*/
-NormalCplusplusObjectRule()
-
-/*
- * CplusplusDynamicModuleTarget - build a module to be dynamically loaded
- */
-#ifndef CplusplusDynamicModuleTarget
-#define CplusplusDynamicModuleTarget(module,modlist)                   @@\
-AllTarget(module)                                                      @@\
-                                                                       @@\
-module: modlist                                                                @@\
-       RemoveFile($@)                                                  @@\
-       $(CXX) -o $@ $(SHLIBLDFLAGS) modlist                            @@\
-                                                                       @@\
-clean::                                                                        @@\
-       RemoveFile(module)
-#endif /* CplusplusDynamicModuleTarget */
-
-
-
-CplusplusDynamicModuleTarget(vnc.so,$(OBJS) $(VNCLIBS))
-InstallDynamicModule(vnc.so,$(MODULEDIR),extensions)
-
-DependTarget()
-
-/*
- InstallDriverSDKLibraryModule(vnc,$(DRIVERSDKMODULEDIR),extensions)
-*/
diff --git a/unix/xc/programs/Xserver/vnc/vncExtInit.cc b/unix/xc/programs/Xserver/vnc/vncExtInit.cc
deleted file mode 100644 (file)
index 9cf9d21..0000000
+++ /dev/null
@@ -1,866 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd.  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>
-
-extern "C" {
-#define class c_class
-#define NEED_EVENTS
-#include "X.h"
-#include "Xproto.h"
-#include "misc.h"
-#include "os.h"
-#include "dixstruct.h"
-#include "extnsionst.h"
-#include "scrnintstr.h"
-#include "selection.h"
-#define _VNCEXT_SERVER_
-#define _VNCEXT_PROTO_
-#include "vncExt.h"
-#undef class
-#undef xalloc
-}
-
-#include <rfb/Configuration.h>
-#include <rfb/Logger_stdio.h>
-#include <rfb/LogWriter.h>
-#include <rfb/util.h>
-#include <rfb/ServerCore.h>
-#include <rfb/SSecurityFactoryStandard.h>
-#include <rdr/HexOutStream.h>
-#include <rfb/LogWriter.h>
-#undef max
-#undef min
-#include <network/TcpSocket.h>
-
-#include "XserverDesktop.h"
-#include "vncHooks.h"
-#include "vncExtInit.h"
-
-extern "C" {
-
-  extern void vncExtensionInit();
-  static void vncResetProc(ExtensionEntry* extEntry);
-  static void vncBlockHandler(pointer data, OSTimePtr t, pointer readmask);
-  static void vncWakeupHandler(pointer data, int nfds, pointer readmask);
-  static void vncClientStateChange(CallbackListPtr*, pointer, pointer);
-  static void SendSelectionChangeEvent(Atom selection);
-  static int ProcVncExtDispatch(ClientPtr client);
-  static int SProcVncExtDispatch(ClientPtr client);
-
-  extern char *display;
-
-  extern Selection *CurrentSelections;
-  extern int NumCurrentSelections;
-}
-
-using namespace rfb;
-
-static rfb::LogWriter vlog("vncext");
-
-static unsigned long vncExtGeneration = 0;
-static bool initialised = false;
-static XserverDesktop* desktop[MAXSCREENS] = { 0, };
-void* vncFbptr[MAXSCREENS] = { 0, };
-
-static char* clientCutText = 0;
-static int clientCutTextLen = 0;
-
-static XserverDesktop* queryConnectDesktop = 0;
-static void* queryConnectId = 0;
-static int queryConnectTimeout = 0;
-static OsTimerPtr queryConnectTimer = 0;
-
-static struct VncInputSelect* vncInputSelectHead = 0;
-struct VncInputSelect {
-  VncInputSelect(ClientPtr c, Window w, int m) : client(c), window(w), mask(m)
-  {
-    next = vncInputSelectHead;
-    vncInputSelectHead = this;
-  }
-  ClientPtr client;
-  Window window;
-  int mask;
-  VncInputSelect* next;
-};
-
-static int nPrevSelections = 0;
-static TimeStamp* prevSelectionTimes = 0;
-
-static int vncErrorBase = 0;
-static int vncEventBase = 0;
-static char* vncPasswdFile = 0;
-int vncInetdSock = -1;
-
-rfb::AliasParameter rfbauth("rfbauth", "Alias for PasswordFile",
-                            &SSecurityFactoryStandard::vncAuthPasswdFile);
-rfb::StringParameter httpDir("httpd",
-                             "Directory containing files to serve via HTTP",
-                             "");
-rfb::IntParameter httpPort("httpPort", "TCP port to listen for HTTP",0);
-rfb::AliasParameter rfbwait("rfbwait", "Alias for ClientWaitTimeMillis",
-                            &rfb::Server::clientWaitTimeMillis);
-rfb::IntParameter rfbport("rfbport", "TCP port to listen for RFB protocol",0);
-rfb::StringParameter desktopName("desktop", "Name of VNC desktop","x11");
-rfb::BoolParameter localhostOnly("localhost",
-                                 "Only allow connections from localhost",
-                                 false);
-
-void vncExtensionInit()
-{
-  if (vncExtGeneration == serverGeneration) {
-    vlog.error("vncExtensionInit: called twice in same generation?");
-    return;
-  }
-  vncExtGeneration = serverGeneration;
-
-  ExtensionEntry* extEntry
-    = AddExtension(VNCEXTNAME, VncExtNumberEvents, VncExtNumberErrors,
-                   ProcVncExtDispatch, SProcVncExtDispatch, vncResetProc,
-                   StandardMinorOpcode);
-  if (!extEntry) {
-    ErrorF("vncExtInit: AddExtension failed\n");
-    return;
-  }
-
-  vncErrorBase = extEntry->errorBase;
-  vncEventBase = extEntry->eventBase;
-
-  vlog.info("VNC extension running!");
-
-  if (!AddCallback(&ClientStateCallback, vncClientStateChange, 0)) {
-    FatalError("AddCallback failed\n");
-  }
-
-  try {
-    if (!initialised) {
-      rfb::initStdIOLoggers();
-      initialised = true;
-    }
-
-    for (int scr = 0; scr < screenInfo.numScreens; scr++) {
-
-      if (!desktop[scr]) {
-        network::TcpListener* listener = 0;
-        network::TcpListener* httpListener = 0;
-        if (scr == 0 && vncInetdSock != -1) {
-          if (network::TcpSocket::isSocket(vncInetdSock) &&
-              !network::TcpSocket::isConnected(vncInetdSock))
-          {
-            listener = new network::TcpListener(0, 0, vncInetdSock, true);
-            vlog.info("inetd wait");
-          }
-        } else {
-          int port = rfbport;
-          if (port == 0) port = 5900 + atoi(display);
-          port += 1000 * scr;
-          listener = new network::TcpListener(port, localhostOnly);
-          vlog.info("Listening for VNC connections on port %d",port);
-          CharArray httpDirStr(httpDir.getData());
-          if (httpDirStr.buf[0]) {
-            port = httpPort;
-            if (port == 0) port = 5800 + atoi(display);
-            port += 1000 * scr;
-            httpListener = new network::TcpListener(port, localhostOnly);
-            vlog.info("Listening for HTTP connections on port %d",port);
-          }
-        }
-
-        CharArray desktopNameStr(desktopName.getData());
-        desktop[scr] = new XserverDesktop(screenInfo.screens[scr], listener,
-                                          httpListener,
-                                          desktopNameStr.buf,
-                                          vncFbptr[scr]);
-        vlog.info("created VNC server for screen %d", scr);
-
-        if (scr == 0 && vncInetdSock != -1 && !listener) {
-          network::Socket* sock = new network::TcpSocket(vncInetdSock);
-          desktop[scr]->addClient(sock, false);
-          vlog.info("added inetd sock");
-        }
-
-      } else {
-        desktop[scr]->serverReset(screenInfo.screens[scr]);
-      }
-
-      vncHooksInit(screenInfo.screens[scr], desktop[scr]);
-    }
-
-    RegisterBlockAndWakeupHandlers(vncBlockHandler, vncWakeupHandler, 0);
-
-  } catch (rdr::Exception& e) {
-    vlog.error("vncExtInit: %s",e.str());
-  }
-}
-
-static void vncResetProc(ExtensionEntry* extEntry)
-{
-}
-
-//
-// vncBlockHandler - called just before the X server goes into select().  Call
-// on to the block handler for each desktop.  Then check whether any of the
-// selections have changed, and if so, notify any interested X clients.
-//
-
-static void vncBlockHandler(pointer data, OSTimePtr timeout, pointer readmask)
-{
-  fd_set* fds = (fd_set*)readmask;
-
-  for (int scr = 0; scr < screenInfo.numScreens; scr++) {
-    if (desktop[scr]) {
-      desktop[scr]->blockHandler(fds);
-    }
-  }
-
-  if (nPrevSelections != NumCurrentSelections) {
-    prevSelectionTimes
-      = (TimeStamp*)xnfrealloc(prevSelectionTimes,
-                               NumCurrentSelections * sizeof(TimeStamp));
-    for (int i = nPrevSelections; i < NumCurrentSelections; i++) {
-      prevSelectionTimes[i].months = 0;
-      prevSelectionTimes[i].milliseconds = 0;
-    }
-    nPrevSelections = NumCurrentSelections;
-  }
-  for (int i = 0; i < NumCurrentSelections; i++) {
-    if (CurrentSelections[i].lastTimeChanged.months
-        != prevSelectionTimes[i].months ||
-        CurrentSelections[i].lastTimeChanged.milliseconds
-        != prevSelectionTimes[i].milliseconds)
-    {
-      SendSelectionChangeEvent(CurrentSelections[i].selection);
-      prevSelectionTimes[i] = CurrentSelections[i].lastTimeChanged;
-    }
-  }
-}
-
-static void vncWakeupHandler(pointer data, int nfds, pointer readmask)
-{
-  fd_set* fds = (fd_set*)readmask;
-
-  for (int scr = 0; scr < screenInfo.numScreens; scr++) {
-    if (desktop[scr]) {
-      desktop[scr]->wakeupHandler(fds, nfds);
-    }
-  }
-}
-
-static void vncClientStateChange(CallbackListPtr*, pointer, pointer p)
-{
-  ClientPtr client = ((NewClientInfoRec*)p)->client;
-  if (client->clientState == ClientStateGone) {
-    VncInputSelect** nextPtr = &vncInputSelectHead;
-    for (VncInputSelect* cur = vncInputSelectHead; cur; cur = *nextPtr) {
-      if (cur->client == client) {
-        *nextPtr = cur->next;
-        delete cur;
-        continue;
-      }
-      nextPtr = &cur->next;
-    }
-  }
-}
-
-void vncBell()
-{
-  for (int scr = 0; scr < screenInfo.numScreens; scr++) {
-    if (desktop[scr]) {
-      desktop[scr]->bell();
-    }
-  }
-}
-
-void vncClientGone(int fd)
-{
-  if (fd == vncInetdSock) {
-    fprintf(stderr,"inetdSock client gone\n");
-    GiveUp(0);
-  }
-}
-
-void vncClientCutText(const char* str, int len)
-{
-  delete [] clientCutText;
-  clientCutText = new char[len];
-  memcpy(clientCutText, str, len);
-  clientCutTextLen = len;
-  xVncExtClientCutTextNotifyEvent ev;
-  ev.type = vncEventBase + VncExtClientCutTextNotify;
-  for (VncInputSelect* cur = vncInputSelectHead; cur; cur = cur->next) {
-    if (cur->mask & VncExtClientCutTextMask) {
-      ev.sequenceNumber = cur->client->sequence;
-      ev.window = cur->window;
-      ev.time = GetTimeInMillis();
-      if (cur->client->swapped) {
-        int n;
-        swaps(&ev.sequenceNumber, n);
-        swapl(&ev.window, n);
-        swapl(&ev.time, n);
-      }
-      WriteToClient(cur->client, sizeof(xVncExtClientCutTextNotifyEvent),
-                    (char *)&ev);
-    }
-  }
-}
-
-
-static CARD32 queryConnectTimerCallback(OsTimerPtr timer,
-                                        CARD32 now, pointer arg)
-{
-  if (queryConnectTimeout)
-    queryConnectDesktop->approveConnection(queryConnectId, false, "The attempt to prompt the user to accept the connection failed");
-  // Re-notify clients, causing them to discover that we're done
-  vncQueryConnect(queryConnectDesktop, queryConnectId);
-  return 0;
-}
-
-void vncQueryConnect(XserverDesktop* desktop, void* opaqueId)
-{
-  // Only one query can be processed at any one time
-  if (queryConnectTimeout && ((desktop != queryConnectDesktop) ||
-                              (opaqueId != queryConnectId))) {
-    desktop->approveConnection(opaqueId, false,
-                               "Another connection is currently being queried.");
-    return;
-  }
-
-  // Get the query timeout.  If it's zero, there is no query.
-  queryConnectTimeout = desktop->getQueryTimeout(opaqueId);
-  queryConnectId = queryConnectTimeout ? opaqueId : 0;
-  queryConnectDesktop = queryConnectTimeout ? desktop : 0;
-
-  // Notify clients
-  bool notified = false;
-  xVncExtQueryConnectNotifyEvent ev;
-  ev.type = vncEventBase + VncExtQueryConnectNotify;
-  for (VncInputSelect* cur = vncInputSelectHead; cur; cur = cur->next) {
-    if (cur->mask & VncExtQueryConnectMask) {
-      ev.sequenceNumber = cur->client->sequence;
-      ev.window = cur->window;
-      if (cur->client->swapped) {
-        int n;
-        swaps(&ev.sequenceNumber, n);
-        swapl(&ev.window, n);
-      }
-      WriteToClient(cur->client, sizeof(xVncExtQueryConnectNotifyEvent),
-                    (char *)&ev);
-      notified = true;
-    }
-  }
-
-  // If we're being asked to query a connection (rather than to cancel
-  //   a query), and haven't been able to notify clients then reject it.
-  if (queryConnectTimeout && !notified) {
-    queryConnectTimeout = 0;
-    queryConnectId = 0;
-    queryConnectDesktop = 0;
-    desktop->approveConnection(opaqueId, false,
-                               "Unable to query the local user to accept the connection.");
-    return;
-  }    
-
-  // Set a timer so that if no-one ever responds, we will eventually 
-  //   reject the connection
-  //   NB: We don't set a timer if sock is null, since that indicates
-  //       that pending queries should be cancelled.
-  if (queryConnectDesktop)
-    queryConnectTimer = TimerSet(queryConnectTimer, 0,
-                                 queryConnectTimeout*2000,
-                                 queryConnectTimerCallback, 0);
-  else
-    TimerCancel(queryConnectTimer);
-}
-
-static void SendSelectionChangeEvent(Atom selection)
-{
-  xVncExtSelectionChangeNotifyEvent ev;
-  ev.type = vncEventBase + VncExtSelectionChangeNotify;
-  for (VncInputSelect* cur = vncInputSelectHead; cur; cur = cur->next) {
-    if (cur->mask & VncExtSelectionChangeMask) {
-      ev.sequenceNumber = cur->client->sequence;
-      ev.window = cur->window;
-      ev.selection = selection;
-      if (cur->client->swapped) {
-        int n;
-        swaps(&ev.sequenceNumber, n);
-        swapl(&ev.window, n);
-        swapl(&ev.selection, n);
-      }
-      WriteToClient(cur->client, sizeof(xVncExtSelectionChangeNotifyEvent),
-                    (char *)&ev);
-    }
-  }
-}
-
-static int ProcVncExtSetParam(ClientPtr client)
-{
-  REQUEST(xVncExtSetParamReq);
-  REQUEST_FIXED_SIZE(xVncExtSetParamReq, stuff->paramLen);
-  CharArray param(stuff->paramLen+1);
-  strncpy(param.buf, (char*)&stuff[1], stuff->paramLen);
-  param.buf[stuff->paramLen] = 0;
-
-  xVncExtSetParamReply rep;
-  int n;
-  rep.type = X_Reply;
-  rep.length = 0;
-  rep.sequenceNumber = client->sequence;
-  rep.success = rfb::Configuration::setParam(param.buf);
-  if (client->swapped) {
-    swaps(&rep.sequenceNumber, n);
-    swapl(&rep.length, n);
-  }
-  WriteToClient(client, sizeof(xVncExtSetParamReply), (char *)&rep);
-  return (client->noClientException);
-}
-
-static int SProcVncExtSetParam(ClientPtr client)
-{
-  register char n;
-  REQUEST(xVncExtSetParamReq);
-  swaps(&stuff->length, n);
-  REQUEST_AT_LEAST_SIZE(xVncExtSetParamReq);
-  return ProcVncExtSetParam(client);
-}
-
-static int ProcVncExtGetParam(ClientPtr client)
-{
-  REQUEST(xVncExtGetParamReq);
-  REQUEST_FIXED_SIZE(xVncExtGetParamReq, stuff->paramLen);
-  CharArray param(stuff->paramLen+1);
-  strncpy(param.buf, (char*)&stuff[1], stuff->paramLen);
-  param.buf[stuff->paramLen] = 0;
-
-  xVncExtGetParamReply rep;
-  int n;
-  rep.type = X_Reply;
-  rep.sequenceNumber = client->sequence;
-  rep.success = 0;
-  int len = 0;
-  char* value = 0;
-  rfb::VoidParameter* p = rfb::Configuration::getParam(param.buf);
-  // Hack to avoid exposing password!
-  if (strcasecmp(param.buf, "Password") == 0)
-    p = 0;
-  if (p) {
-    value = p->getValueStr();
-    rep.success = 1;
-    len = value ? strlen(value) : 0;
-  }
-  rep.length = (len + 3) >> 2;
-  rep.valueLen = len;
-  if (client->swapped) {
-    swaps(&rep.sequenceNumber, n);
-    swapl(&rep.length, n);
-    swaps(&rep.valueLen, n);
-  }
-  WriteToClient(client, sizeof(xVncExtGetParamReply), (char *)&rep);
-  if (value)
-    WriteToClient(client, len, value);
-  delete [] value;
-  return (client->noClientException);
-}
-
-static int SProcVncExtGetParam(ClientPtr client)
-{
-  register char n;
-  REQUEST(xVncExtGetParamReq);
-  swaps(&stuff->length, n);
-  REQUEST_AT_LEAST_SIZE(xVncExtGetParamReq);
-  return ProcVncExtGetParam(client);
-}
-
-static int ProcVncExtGetParamDesc(ClientPtr client)
-{
-  REQUEST(xVncExtGetParamDescReq);
-  REQUEST_FIXED_SIZE(xVncExtGetParamDescReq, stuff->paramLen);
-  CharArray param(stuff->paramLen+1);
-  strncpy(param.buf, (char*)&stuff[1], stuff->paramLen);
-  param.buf[stuff->paramLen] = 0;
-
-  xVncExtGetParamDescReply rep;
-  int n;
-  rep.type = X_Reply;
-  rep.sequenceNumber = client->sequence;
-  rep.success = 0;
-  int len = 0;
-  const char* desc = 0;
-  rfb::VoidParameter* p = rfb::Configuration::getParam(param.buf);
-  if (p) {
-    desc = p->getDescription();
-    rep.success = 1;
-    len = desc ? strlen(desc) : 0;
-  }
-  rep.length = (len + 3) >> 2;
-  rep.descLen = len;
-  if (client->swapped) {
-    swaps(&rep.sequenceNumber, n);
-    swapl(&rep.length, n);
-    swaps(&rep.descLen, n);
-  }
-  WriteToClient(client, sizeof(xVncExtGetParamDescReply), (char *)&rep);
-  if (desc)
-    WriteToClient(client, len, (char*)desc);
-  return (client->noClientException);
-}
-
-static int SProcVncExtGetParamDesc(ClientPtr client)
-{
-  register char n;
-  REQUEST(xVncExtGetParamDescReq);
-  swaps(&stuff->length, n);
-  REQUEST_AT_LEAST_SIZE(xVncExtGetParamDescReq);
-  return ProcVncExtGetParamDesc(client);
-}
-
-static int ProcVncExtListParams(ClientPtr client)
-{
-  REQUEST(xVncExtListParamsReq);
-  REQUEST_SIZE_MATCH(xVncExtListParamsReq);
-
-  xVncExtListParamsReply rep;
-  int n;
-  rep.type = X_Reply;
-  rep.sequenceNumber = client->sequence;
-
-  int nParams = 0;
-  int len = 0;
-  for (ParameterIterator i(Configuration::global()); i.param; i.next()) {
-    int l = strlen(i.param->getName());
-    if (l <= 255) {
-      nParams++;
-      len += l + 1;
-    }
-  }
-  rep.length = (len + 3) >> 2;
-  rep.nParams = nParams;
-  if (client->swapped) {
-    swaps(&rep.sequenceNumber, n);
-    swapl(&rep.length, n);
-    swaps(&rep.nParams, n);
-  }
-  WriteToClient(client, sizeof(xVncExtListParamsReply), (char *)&rep);
-  rdr::U8* data = new rdr::U8[len];
-  rdr::U8* ptr = data;
-  for (ParameterIterator i(Configuration::global()); i.param; i.next()) {
-    int l = strlen(i.param->getName());
-    if (l <= 255) {
-      *ptr++ = l;
-      memcpy(ptr, i.param->getName(), l);
-      ptr += l;
-    }
-  }
-  WriteToClient(client, len, (char*)data);
-  delete [] data;
-  return (client->noClientException);
-}
-
-static int SProcVncExtListParams(ClientPtr client)
-{
-  register char n;
-  REQUEST(xVncExtListParamsReq);
-  swaps(&stuff->length, n);
-  REQUEST_SIZE_MATCH(xVncExtListParamsReq);
-  return ProcVncExtListParams(client);
-}
-
-static int ProcVncExtSetServerCutText(ClientPtr client)
-{
-  REQUEST(xVncExtSetServerCutTextReq);
-  REQUEST_FIXED_SIZE(xVncExtSetServerCutTextReq, stuff->textLen);
-  char* str = new char[stuff->textLen+1];
-  strncpy(str, (char*)&stuff[1], stuff->textLen);
-  str[stuff->textLen] = 0;
-  for (int scr = 0; scr < screenInfo.numScreens; scr++) {
-    if (desktop[scr]) {
-      desktop[scr]->serverCutText(str, stuff->textLen);
-    }
-  }
-  delete [] str;
-  return (client->noClientException);
-}
-
-static int SProcVncExtSetServerCutText(ClientPtr client)
-{
-  register char n;
-  REQUEST(xVncExtSetServerCutTextReq);
-  swaps(&stuff->length, n);
-  REQUEST_AT_LEAST_SIZE(xVncExtSetServerCutTextReq);
-  swapl(&stuff->textLen, n);
-  return ProcVncExtSetServerCutText(client);
-}
-
-static int ProcVncExtGetClientCutText(ClientPtr client)
-{
-  REQUEST(xVncExtGetClientCutTextReq);
-  REQUEST_SIZE_MATCH(xVncExtGetClientCutTextReq);
-
-  xVncExtGetClientCutTextReply rep;
-  int n;
-  rep.type = X_Reply;
-  rep.length = (clientCutTextLen + 3) >> 2;
-  rep.sequenceNumber = client->sequence;
-  rep.textLen = clientCutTextLen;
-  if (client->swapped) {
-    swaps(&rep.sequenceNumber, n);
-    swapl(&rep.length, n);
-    swapl(&rep.textLen, n);
-  }
-  WriteToClient(client, sizeof(xVncExtGetClientCutTextReply), (char *)&rep);
-  if (clientCutText)
-    WriteToClient(client, clientCutTextLen, clientCutText);
-  return (client->noClientException);
-}
-
-static int SProcVncExtGetClientCutText(ClientPtr client)
-{
-  register char n;
-  REQUEST(xVncExtGetClientCutTextReq);
-  swaps(&stuff->length, n);
-  REQUEST_SIZE_MATCH(xVncExtGetClientCutTextReq);
-  return ProcVncExtGetClientCutText(client);
-}
-
-static int ProcVncExtSelectInput(ClientPtr client)
-{
-  REQUEST(xVncExtSelectInputReq);
-  REQUEST_SIZE_MATCH(xVncExtSelectInputReq);
-  VncInputSelect** nextPtr = &vncInputSelectHead;
-  VncInputSelect* cur;
-  for (cur = vncInputSelectHead; cur; cur = *nextPtr) {
-    if (cur->client == client && cur->window == stuff->window) {
-      cur->mask = stuff->mask;
-      if (!cur->mask) {
-        *nextPtr = cur->next;
-        delete cur;
-      }
-      break;
-    }
-    nextPtr = &cur->next;
-  }
-  if (!cur) {
-    cur = new VncInputSelect(client, stuff->window, stuff->mask);
-  }
-  return (client->noClientException);
-}
-
-static int SProcVncExtSelectInput(ClientPtr client)
-{
-  register char n;
-  REQUEST(xVncExtSelectInputReq);
-  swaps(&stuff->length, n);
-  REQUEST_SIZE_MATCH(xVncExtSelectInputReq);
-  swapl(&stuff->window, n);
-  swapl(&stuff->mask, n);
-  return ProcVncExtSelectInput(client);
-}
-
-static int ProcVncExtConnect(ClientPtr client)
-{
-  REQUEST(xVncExtConnectReq);
-  REQUEST_FIXED_SIZE(xVncExtConnectReq, stuff->strLen);
-  CharArray str(stuff->strLen+1);
-  strncpy(str.buf, (char*)&stuff[1], stuff->strLen);
-  str.buf[stuff->strLen] = 0;
-
-  xVncExtConnectReply rep;
-  rep.success = 0;
-  if (desktop[0]) {
-    if (stuff->strLen == 0) {
-      try {
-        desktop[0]->disconnectClients();
-        rep.success = 1;
-      } catch (rdr::Exception& e) {
-        vlog.error("Disconnecting all clients: %s",e.str());
-      }
-    } else {
-      int port = 5500;
-      for (int i = 0; i < stuff->strLen; i++) {
-        if (str.buf[i] == ':') {
-          port = atoi(&str.buf[i+1]);
-          str.buf[i] = 0;
-          break;
-        }
-      }
-
-      try {
-        network::Socket* sock = new network::TcpSocket(str.buf, port);
-        desktop[0]->addClient(sock, true);
-       rep.success = 1;
-      } catch (rdr::Exception& e) {
-        vlog.error("Reverse connection: %s",e.str());
-      }
-    }
-  }
-
-  rep.type = X_Reply;
-  rep.length = 0;
-  rep.sequenceNumber = client->sequence;
-  if (client->swapped) {
-    int n;
-    swaps(&rep.sequenceNumber, n);
-    swapl(&rep.length, n);
-  }
-  WriteToClient(client, sizeof(xVncExtConnectReply), (char *)&rep);
-  return (client->noClientException);
-}
-
-static int SProcVncExtConnect(ClientPtr client)
-{
-  register char n;
-  REQUEST(xVncExtConnectReq);
-  swaps(&stuff->length, n);
-  REQUEST_AT_LEAST_SIZE(xVncExtConnectReq);
-  return ProcVncExtConnect(client);
-}
-
-
-static int ProcVncExtGetQueryConnect(ClientPtr client)
-{
-  REQUEST(xVncExtGetQueryConnectReq);
-  REQUEST_SIZE_MATCH(xVncExtGetQueryConnectReq);
-
-  const char *qcAddress=0, *qcUsername=0;
-  int qcTimeout;
-  if (queryConnectDesktop)
-    qcTimeout = queryConnectDesktop->getQueryTimeout(queryConnectId,
-                                                     &qcAddress, &qcUsername);
-  else
-    qcTimeout = 0;
-
-  xVncExtGetQueryConnectReply rep;
-  int n;
-  rep.type = X_Reply;
-  rep.sequenceNumber = client->sequence;
-  rep.timeout = qcTimeout;
-  rep.addrLen = qcTimeout ? strlen(qcAddress) : 0;
-  rep.userLen = qcTimeout ? strlen(qcUsername) : 0;
-  rep.opaqueId = (CARD32)queryConnectId;
-  rep.length = (rep.userLen + rep.addrLen + 3) >> 2;
-  if (client->swapped) {
-    swaps(&rep.sequenceNumber, n);
-    swapl(&rep.userLen, n);
-    swapl(&rep.addrLen, n);
-    swapl(&rep.timeout, n);
-    swapl(&rep.opaqueId, n);
-  }
-  WriteToClient(client, sizeof(xVncExtGetQueryConnectReply), (char *)&rep);
-  if (qcTimeout)
-    WriteToClient(client, strlen(qcAddress), (char*)qcAddress);
-  if (qcTimeout)
-    WriteToClient(client, strlen(qcUsername), (char*)qcUsername);
-  return (client->noClientException);
-}
-
-static int SProcVncExtGetQueryConnect(ClientPtr client)
-{
-  register char n;
-  REQUEST(xVncExtGetQueryConnectReq);
-  swaps(&stuff->length, n);
-  REQUEST_SIZE_MATCH(xVncExtGetQueryConnectReq);
-  return ProcVncExtGetQueryConnect(client);
-}
-
-
-static int ProcVncExtApproveConnect(ClientPtr client)
-{
-  REQUEST(xVncExtApproveConnectReq);
-  REQUEST_SIZE_MATCH(xVncExtApproveConnectReq);
-  if (queryConnectId == (void*)stuff->opaqueId) {
-    for (int scr = 0; scr < screenInfo.numScreens; scr++) {
-      if (desktop[scr]) {
-        desktop[scr]->approveConnection(queryConnectId, stuff->approve,
-                                        "Connection rejected by local user");
-      }
-    }
-    // Inform other clients of the event and tidy up
-    vncQueryConnect(queryConnectDesktop, queryConnectId);
-  }
-  return (client->noClientException);
-}
-
-static int SProcVncExtApproveConnect(ClientPtr client)
-{
-  register char n;
-  REQUEST(xVncExtApproveConnectReq);
-  swaps(&stuff->length, n);
-  swapl(&stuff->opaqueId, n);
-  REQUEST_SIZE_MATCH(xVncExtApproveConnectReq);
-  return ProcVncExtApproveConnect(client);
-}
-
-
-static int ProcVncExtDispatch(ClientPtr client)
-{
-  REQUEST(xReq);
-  switch (stuff->data) {
-  case X_VncExtSetParam:
-    return ProcVncExtSetParam(client);
-  case X_VncExtGetParam:
-    return ProcVncExtGetParam(client);
-  case X_VncExtGetParamDesc:
-    return ProcVncExtGetParamDesc(client);
-  case X_VncExtListParams:
-    return ProcVncExtListParams(client);
-  case X_VncExtSetServerCutText:
-    return ProcVncExtSetServerCutText(client);
-  case X_VncExtGetClientCutText:
-    return ProcVncExtGetClientCutText(client);
-  case X_VncExtSelectInput:
-    return ProcVncExtSelectInput(client);
-  case X_VncExtConnect:
-    return ProcVncExtConnect(client);
-  case X_VncExtGetQueryConnect:
-    return ProcVncExtGetQueryConnect(client);
-  case X_VncExtApproveConnect:
-    return ProcVncExtApproveConnect(client);
-  default:
-    return BadRequest;
-  }
-}
-
-static int SProcVncExtDispatch(ClientPtr client)
-{
-  REQUEST(xReq);
-  switch (stuff->data) {
-  case X_VncExtSetParam:
-    return SProcVncExtSetParam(client);
-  case X_VncExtGetParam:
-    return SProcVncExtGetParam(client);
-  case X_VncExtGetParamDesc:
-    return SProcVncExtGetParamDesc(client);
-  case X_VncExtListParams:
-    return SProcVncExtListParams(client);
-  case X_VncExtSetServerCutText:
-    return SProcVncExtSetServerCutText(client);
-  case X_VncExtGetClientCutText:
-    return SProcVncExtGetClientCutText(client);
-  case X_VncExtSelectInput:
-    return SProcVncExtSelectInput(client);
-  case X_VncExtConnect:
-    return SProcVncExtConnect(client);
-  case X_VncExtGetQueryConnect:
-    return SProcVncExtGetQueryConnect(client);
-  case X_VncExtApproveConnect:
-    return SProcVncExtApproveConnect(client);
-  default:
-    return BadRequest;
-  }
-}
-
diff --git a/unix/xc/programs/Xserver/vnc/vncExtInit.h b/unix/xc/programs/Xserver/vnc/vncExtInit.h
deleted file mode 100644 (file)
index 45453e1..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd.  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.
- */
-#ifndef __VNCEXTINIT_H__
-#define __VNCEXTINIT_H__
-
-#include <rfb/Configuration.h>
-#include "XserverDesktop.h"
-
-extern void vncClientCutText(const char* str, int len);
-extern void vncQueryConnect(XserverDesktop* desktop, void* opaqueId);
-extern void vncClientGone(int fd);
-extern void vncBell();
-extern void* vncFbptr[];
-extern int vncInetdSock;
-extern rfb::StringParameter httpDir;
-
-#endif
diff --git a/unix/xc/programs/Xserver/vnc/vncHooks.cc b/unix/xc/programs/Xserver/vnc/vncHooks.cc
deleted file mode 100644 (file)
index ce8e7f0..0000000
+++ /dev/null
@@ -1,1533 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd.  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 "XserverDesktop.h"
-#include "vncHooks.h"
-
-extern "C" {
-#define class c_class
-#define private c_private
-#include "scrnintstr.h"
-#include "windowstr.h"
-#include "gcstruct.h"
-#include "regionstr.h"
-#include "dixfontstr.h"
-#include "colormapst.h"
-#ifdef RENDER
-#include "picturestr.h"
-#endif
-
-#ifdef GC_HAS_COMPOSITE_CLIP
-#define COMPOSITE_CLIP(gc) ((gc)->pCompositeClip)
-#else
-#include "mfb.h"
-#define COMPOSITE_CLIP(gc) \
-  (((mfbPrivGCPtr)((gc)->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip)
-#endif
-
-#undef class
-#undef private
-}
-
-#include "RegionHelper.h"
-
-#define DBGPRINT(x) //(fprintf x)
-
-// MAX_RECTS_PER_OP is the maximum number of rectangles we generate from
-// operations like Polylines and PolySegment.  If the operation is more complex
-// than this, we simply use the bounding box.  Ideally it would be a
-// command-line option, but that would involve an extra malloc each time, so we
-// fix it here.
-#define MAX_RECTS_PER_OP 5
-
-static unsigned long vncHooksGeneration = 0;
-
-// vncHooksScreenRec and vncHooksGCRec contain pointers to the original
-// functions which we "wrap" in order to hook the screen changes.  The screen
-// functions are each wrapped individually, while the GC "funcs" and "ops" are
-// wrapped as a unit.
-
-typedef struct {
-  XserverDesktop* desktop;
-
-  CloseScreenProcPtr           CloseScreen;
-  CreateGCProcPtr              CreateGC;
-  PaintWindowBackgroundProcPtr PaintWindowBackground;
-  PaintWindowBorderProcPtr     PaintWindowBorder;
-  CopyWindowProcPtr            CopyWindow;
-  ClearToBackgroundProcPtr     ClearToBackground;
-  RestoreAreasProcPtr          RestoreAreas;
-  InstallColormapProcPtr       InstallColormap;
-  StoreColorsProcPtr           StoreColors;
-  DisplayCursorProcPtr         DisplayCursor;
-  ScreenBlockHandlerProcPtr    BlockHandler;
-#ifdef RENDER
-  CompositeProcPtr             Composite;
-#endif
-} vncHooksScreenRec, *vncHooksScreenPtr;
-
-typedef struct {
-    GCFuncs *wrappedFuncs;
-    GCOps *wrappedOps;
-} vncHooksGCRec, *vncHooksGCPtr;
-
-static int vncHooksScreenIndex;
-static int vncHooksGCIndex;
-
-
-// screen functions
-
-static Bool vncHooksCloseScreen(int i, ScreenPtr pScreen);
-static Bool vncHooksCreateGC(GCPtr pGC);
-static void vncHooksPaintWindowBackground(WindowPtr pWin, RegionPtr pRegion,
-                                          int what);
-static void vncHooksPaintWindowBorder(WindowPtr pWin, RegionPtr pRegion,
-                                      int what);
-static void vncHooksCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
-                               RegionPtr pOldRegion);
-static void vncHooksClearToBackground(WindowPtr pWin, int x, int y, int w,
-                                      int h, Bool generateExposures);
-static RegionPtr vncHooksRestoreAreas(WindowPtr pWin, RegionPtr prgnExposed);
-static void vncHooksInstallColormap(ColormapPtr pColormap);
-static void vncHooksStoreColors(ColormapPtr pColormap, int ndef,
-                                xColorItem* pdef);
-static Bool vncHooksDisplayCursor(ScreenPtr pScreen, CursorPtr cursor);
-static void vncHooksBlockHandler(int i, pointer blockData, pointer pTimeout,
-                                 pointer pReadmask);
-#ifdef RENDER
-static void vncHooksComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, 
-                             PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, 
-                             INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height);
-#endif
-
-// GC "funcs"
-
-static void vncHooksValidateGC(GCPtr pGC, unsigned long changes,
-                               DrawablePtr pDrawable);
-static void vncHooksChangeGC(GCPtr pGC, unsigned long mask);
-static void vncHooksCopyGC(GCPtr src, unsigned long mask, GCPtr dst);
-static void vncHooksDestroyGC(GCPtr pGC);
-static void vncHooksChangeClip(GCPtr pGC, int type, pointer pValue,int nrects);
-static void vncHooksDestroyClip(GCPtr pGC);
-static void vncHooksCopyClip(GCPtr dst, GCPtr src);
-
-static GCFuncs vncHooksGCFuncs = {
-  vncHooksValidateGC, vncHooksChangeGC, vncHooksCopyGC, vncHooksDestroyGC,
-  vncHooksChangeClip, vncHooksDestroyClip, vncHooksCopyClip,
-};
-
-// GC "ops"
-
-static void vncHooksFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nInit,
-                              DDXPointPtr pptInit, int *pwidthInit,
-                              int fSorted);
-static void vncHooksSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *psrc,
-                             DDXPointPtr ppt, int *pwidth, int nspans,
-                             int fSorted);
-static void vncHooksPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth,
-                             int x, int y, int w, int h, int leftPad,
-                             int format, char *pBits);
-static RegionPtr vncHooksCopyArea(DrawablePtr pSrc, DrawablePtr pDst,
-                                  GCPtr pGC, int srcx, int srcy, int w, int h,
-                                  int dstx, int dsty);
-static RegionPtr vncHooksCopyPlane(DrawablePtr pSrc, DrawablePtr pDst,
-                                   GCPtr pGC, int srcx, int srcy, int w, int h,
-                                   int dstx, int dsty, unsigned long plane);
-static void vncHooksPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode,
-                              int npt, xPoint *pts);
-static void vncHooksPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode,
-                              int npt, DDXPointPtr ppts);
-static void vncHooksPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg,
-                                xSegment *segs);
-static void vncHooksPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects,
-                                  xRectangle *rects);
-static void vncHooksPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs,
-                            xArc *arcs);
-static void vncHooksFillPolygon(DrawablePtr pDrawable, GCPtr pGC, int shape,
-                                int mode, int count, DDXPointPtr pts);
-static void vncHooksPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrects,
-                                 xRectangle *rects);
-static void vncHooksPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs,
-                                xArc *arcs);
-static int vncHooksPolyText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
-                             int count, char *chars);
-static int vncHooksPolyText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
-                              int count, unsigned short *chars);
-static void vncHooksImageText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
-                               int count, char *chars);
-static void vncHooksImageText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
-                                int count, unsigned short *chars);
-static void vncHooksImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x,
-                                  int y, unsigned int nglyph,
-                                  CharInfoPtr *ppci, pointer pglyphBase);
-static void vncHooksPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x,
-                                 int y, unsigned int nglyph,
-                                 CharInfoPtr *ppci, pointer pglyphBase);
-static void vncHooksPushPixels(GCPtr pGC, PixmapPtr pBitMap,
-                               DrawablePtr pDrawable, int w, int h, int x,
-                               int y);
-
-static GCOps vncHooksGCOps = {
-  vncHooksFillSpans, vncHooksSetSpans, vncHooksPutImage, vncHooksCopyArea,
-  vncHooksCopyPlane, vncHooksPolyPoint, vncHooksPolylines, vncHooksPolySegment,
-  vncHooksPolyRectangle, vncHooksPolyArc, vncHooksFillPolygon,
-  vncHooksPolyFillRect, vncHooksPolyFillArc, vncHooksPolyText8,
-  vncHooksPolyText16, vncHooksImageText8, vncHooksImageText16,
-  vncHooksImageGlyphBlt, vncHooksPolyGlyphBlt, vncHooksPushPixels
-};
-
-
-
-/////////////////////////////////////////////////////////////////////////////
-// vncHooksInit() is called at initialisation time and every time the server
-// resets.  It is called once for each screen, but the indexes are only
-// allocated once for each server generation.
-
-Bool vncHooksInit(ScreenPtr pScreen, XserverDesktop* desktop)
-{
-  vncHooksScreenPtr vncHooksScreen;
-
-  if (vncHooksGeneration != serverGeneration) {
-    vncHooksGeneration = serverGeneration;
-
-    vncHooksScreenIndex = AllocateScreenPrivateIndex();
-    if (vncHooksScreenIndex < 0) {
-      ErrorF("vncHooksInit: AllocateScreenPrivateIndex failed\n");
-      return FALSE;
-    }
-
-    vncHooksGCIndex = AllocateGCPrivateIndex();
-    if (vncHooksGCIndex < 0) {
-      ErrorF("vncHooksInit: AllocateGCPrivateIndex failed\n");
-      return FALSE;
-    }
-  }
-
-  if (!AllocateGCPrivate(pScreen, vncHooksGCIndex, sizeof(vncHooksGCRec))) {
-    ErrorF("vncHooksInit: AllocateGCPrivate failed\n");
-    return FALSE;
-  }
-
-  vncHooksScreen = (vncHooksScreenPtr)xnfalloc(sizeof(vncHooksScreenRec));
-  pScreen->devPrivates[vncHooksScreenIndex].ptr = (pointer)vncHooksScreen;
-
-  vncHooksScreen->desktop = desktop;
-
-  vncHooksScreen->CloseScreen = pScreen->CloseScreen;
-  vncHooksScreen->CreateGC = pScreen->CreateGC;
-  vncHooksScreen->PaintWindowBackground = pScreen->PaintWindowBackground;
-  vncHooksScreen->PaintWindowBorder = pScreen->PaintWindowBorder;
-  vncHooksScreen->CopyWindow = pScreen->CopyWindow;
-  vncHooksScreen->ClearToBackground = pScreen->ClearToBackground;
-  vncHooksScreen->RestoreAreas = pScreen->RestoreAreas;
-  vncHooksScreen->InstallColormap = pScreen->InstallColormap;
-  vncHooksScreen->StoreColors = pScreen->StoreColors;
-  vncHooksScreen->DisplayCursor = pScreen->DisplayCursor;
-  vncHooksScreen->BlockHandler = pScreen->BlockHandler;
-#ifdef RENDER
-  PictureScreenPtr ps;
-  ps = GetPictureScreenIfSet(pScreen);
-  if (ps) {
-    vncHooksScreen->Composite = ps->Composite;
-  }
-#endif
-
-  pScreen->CloseScreen = vncHooksCloseScreen;
-  pScreen->CreateGC = vncHooksCreateGC;
-  pScreen->PaintWindowBackground = vncHooksPaintWindowBackground;
-  pScreen->PaintWindowBorder = vncHooksPaintWindowBorder;
-  pScreen->CopyWindow = vncHooksCopyWindow;
-  pScreen->ClearToBackground = vncHooksClearToBackground;
-  pScreen->RestoreAreas = vncHooksRestoreAreas;
-  pScreen->InstallColormap = vncHooksInstallColormap;
-  pScreen->StoreColors = vncHooksStoreColors;
-  pScreen->DisplayCursor = vncHooksDisplayCursor;
-  pScreen->BlockHandler = vncHooksBlockHandler;
-#ifdef RENDER
-  if (ps) {
-    ps->Composite = vncHooksComposite;
-  }
-#endif
-
-  return TRUE;
-}
-
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// screen functions
-//
-
-// SCREEN_UNWRAP and SCREEN_REWRAP unwrap and rewrap the given screen function.
-// It would be nice to do this with a C++ class, but each function is of a
-// distinct type, so it would have to use templates, and it's not worth that
-// much pain.
-
-#define SCREEN_UNWRAP(scrn,field)                                         \
-  ScreenPtr pScreen = scrn;                                               \
-  vncHooksScreenPtr vncHooksScreen                                        \
-    = ((vncHooksScreenPtr)pScreen->devPrivates[vncHooksScreenIndex].ptr); \
-  pScreen->field = vncHooksScreen->field;                                 \
-  DBGPRINT((stderr,"vncHooks" #field " called\n"));
-
-#define SCREEN_REWRAP(field) pScreen->field = vncHooks##field;
-
-
-// CloseScreen - unwrap the screen functions and call the original CloseScreen
-// function
-
-static Bool vncHooksCloseScreen(int i, ScreenPtr pScreen_)
-{
-  SCREEN_UNWRAP(pScreen_, CloseScreen);
-
-  pScreen->CreateGC = vncHooksScreen->CreateGC;
-  pScreen->PaintWindowBackground = vncHooksScreen->PaintWindowBackground;
-  pScreen->PaintWindowBorder = vncHooksScreen->PaintWindowBorder;
-  pScreen->CopyWindow = vncHooksScreen->CopyWindow;
-  pScreen->ClearToBackground = vncHooksScreen->ClearToBackground;
-  pScreen->RestoreAreas = vncHooksScreen->RestoreAreas;
-  pScreen->InstallColormap = vncHooksScreen->InstallColormap;
-  pScreen->StoreColors = vncHooksScreen->StoreColors;
-  pScreen->DisplayCursor = vncHooksScreen->DisplayCursor;
-  pScreen->BlockHandler = vncHooksScreen->BlockHandler;
-
-  xfree((pointer)vncHooksScreen);
-
-  DBGPRINT((stderr,"vncHooksCloseScreen: unwrapped screen functions\n"));
-
-  return (*pScreen->CloseScreen)(i, pScreen);
-}
-
-// CreateGC - wrap the "GC funcs"
-
-static Bool vncHooksCreateGC(GCPtr pGC)
-{
-  SCREEN_UNWRAP(pGC->pScreen, CreateGC);
-    
-  vncHooksGCPtr vncHooksGC
-    = (vncHooksGCPtr)pGC->devPrivates[vncHooksGCIndex].ptr;
-
-  Bool ret = (*pScreen->CreateGC) (pGC);
-
-  vncHooksGC->wrappedOps = 0;
-  vncHooksGC->wrappedFuncs = pGC->funcs;
-  pGC->funcs = &vncHooksGCFuncs;
-
-  SCREEN_REWRAP(CreateGC);
-
-  return ret;
-}
-
-// PaintWindowBackground - changed region is the given region
-
-static void vncHooksPaintWindowBackground(WindowPtr pWin, RegionPtr pRegion,
-                                          int what)
-{
-  SCREEN_UNWRAP(pWin->drawable.pScreen, PaintWindowBackground);
-
-  RegionHelper changed(pScreen, pRegion);
-
-  (*pScreen->PaintWindowBackground) (pWin, pRegion, what);
-
-  vncHooksScreen->desktop->add_changed(changed.reg);
-
-  SCREEN_REWRAP(PaintWindowBackground);
-}
-
-// PaintWindowBorder - changed region is the given region
-
-static void vncHooksPaintWindowBorder(WindowPtr pWin, RegionPtr pRegion,
-                                      int what)
-{
-  SCREEN_UNWRAP(pWin->drawable.pScreen, PaintWindowBorder);
-
-  RegionHelper changed(pScreen, pRegion);
-
-  (*pScreen->PaintWindowBorder) (pWin, pRegion, what);
-
-  vncHooksScreen->desktop->add_changed(changed.reg);
-
-  SCREEN_REWRAP(PaintWindowBorder);
-}
-
-// CopyWindow - destination of the copy is the old region, clipped by
-// borderClip, translated by the delta.  This call only does the copy - it
-// doesn't affect any other bits.
-
-static void vncHooksCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
-                               RegionPtr pOldRegion)
-{
-  SCREEN_UNWRAP(pWin->drawable.pScreen, CopyWindow);
-
-  RegionHelper copied(pScreen, pOldRegion);
-  int dx = pWin->drawable.x - ptOldOrg.x;
-  int dy = pWin->drawable.y - ptOldOrg.y;
-  REGION_TRANSLATE(pScreen, copied.reg, dx, dy);
-  REGION_INTERSECT(pWin->drawable.pScreen, copied.reg, copied.reg,
-                   &pWin->borderClip);
-
-  (*pScreen->CopyWindow) (pWin, ptOldOrg, pOldRegion);
-
-  vncHooksScreen->desktop->add_copied(copied.reg, dx, dy);
-
-  SCREEN_REWRAP(CopyWindow);
-}
-
-// ClearToBackground - changed region is the given rectangle, clipped by
-// clipList, but only if generateExposures is false.
-
-static void vncHooksClearToBackground(WindowPtr pWin, int x, int y, int w,
-                                      int h, Bool generateExposures)
-{
-  SCREEN_UNWRAP(pWin->drawable.pScreen, ClearToBackground);
-
-  BoxRec box;
-  box.x1 = x + pWin->drawable.x;
-  box.y1 = y + pWin->drawable.y;
-  box.x2 = w ? (box.x1 + w) : (pWin->drawable.x + pWin->drawable.width);
-  box.y2 = h ? (box.y1 + h) : (pWin->drawable.y + pWin->drawable.height);
-
-  RegionHelper changed(pScreen, &box, 0);
-
-  REGION_INTERSECT(pScreen, changed.reg, changed.reg, &pWin->clipList);
-
-  (*pScreen->ClearToBackground) (pWin, x, y, w, h, generateExposures);
-
-  if (!generateExposures) {
-    vncHooksScreen->desktop->add_changed(changed.reg);
-  }
-
-  SCREEN_REWRAP(ClearToBackground);
-}
-
-// RestoreAreas - changed region is the given region
-
-static RegionPtr vncHooksRestoreAreas(WindowPtr pWin, RegionPtr pRegion)
-{
-  SCREEN_UNWRAP(pWin->drawable.pScreen, RestoreAreas);
-
-  RegionHelper changed(pScreen, pRegion);
-
-  RegionPtr result = (*pScreen->RestoreAreas) (pWin, pRegion);
-
-  vncHooksScreen->desktop->add_changed(changed.reg);
-
-  SCREEN_REWRAP(RestoreAreas);
-
-  return result;
-}
-
-// InstallColormap - get the new colormap
-
-static void vncHooksInstallColormap(ColormapPtr pColormap)
-{
-  SCREEN_UNWRAP(pColormap->pScreen, InstallColormap);
-
-  (*pScreen->InstallColormap) (pColormap);
-
-  vncHooksScreen->desktop->setColormap(pColormap);
-
-  SCREEN_REWRAP(InstallColormap);
-}
-
-// StoreColors - get the colormap changes
-
-static void vncHooksStoreColors(ColormapPtr pColormap, int ndef,
-                                xColorItem* pdef)
-{
-  SCREEN_UNWRAP(pColormap->pScreen, StoreColors);
-
-  (*pScreen->StoreColors) (pColormap, ndef, pdef);
-
-  vncHooksScreen->desktop->setColourMapEntries(pColormap, ndef, pdef);
-
-  SCREEN_REWRAP(StoreColors);
-}
-
-// DisplayCursor - get the cursor shape
-
-static Bool vncHooksDisplayCursor(ScreenPtr pScreen_, CursorPtr cursor)
-{
-  SCREEN_UNWRAP(pScreen_, DisplayCursor);
-
-  Bool ret = (*pScreen->DisplayCursor) (pScreen, cursor);
-
-  vncHooksScreen->desktop->setCursor(cursor);
-
-  SCREEN_REWRAP(DisplayCursor);
-
-  return ret;
-}
-
-// BlockHandler - ignore any changes during the block handler - it's likely
-// these are just drawing the cursor.
-
-static void vncHooksBlockHandler(int i, pointer blockData, pointer pTimeout,
-                                 pointer pReadmask)
-{
-  SCREEN_UNWRAP(screenInfo.screens[i], BlockHandler);
-
-  vncHooksScreen->desktop->ignoreHooks(true);
-
-  (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
-
-  vncHooksScreen->desktop->ignoreHooks(false);
-
-  SCREEN_REWRAP(BlockHandler);
-}
-
-// Composite - needed for RENDER
-
-#ifdef RENDER
-void vncHooksComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, 
-                      PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, 
-                      INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
-{
-  ScreenPtr pScreen = pDst->pDrawable->pScreen;
-  vncHooksScreenPtr vncHooksScreen = ((vncHooksScreenPtr)pScreen->devPrivates[vncHooksScreenIndex].ptr); 
-  BoxRec box;
-  PictureScreenPtr ps = GetPictureScreen(pScreen);
-  rfb::Rect rect1, rect2;
-
-  rect1.setXYWH(pDst->pDrawable->x + xDst,
-               pDst->pDrawable->y + yDst,
-               width,
-               height);
-      
-  rect2 = rect1.intersect(vncHooksScreen->desktop->getRect());
-  if (!rect2.is_empty()) {
-    box.x1 = rect2.tl.x;
-    box.y1 = rect2.tl.y;
-    box.x2 = rect2.br.x;
-    box.y2 = rect2.br.y;
-    RegionHelper changed(pScreen, &box, 0);
-    vncHooksScreen->desktop->add_changed(changed.reg);
-  }
-
-  ps->Composite = vncHooksScreen->Composite;
-  (*ps->Composite)(op, pSrc, pMask, pDst, xSrc, ySrc,
-                  xMask, yMask, xDst, yDst, width, height);
-  ps->Composite = vncHooksComposite;
-}
-
-#endif /* RENDER */
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// GC "funcs"
-//
-
-// GCFuncUnwrapper is a helper class which unwraps the GC funcs and ops in its
-// constructor and rewraps them in its destructor.
-
-class GCFuncUnwrapper {
-public:
-  GCFuncUnwrapper(GCPtr pGC_) : pGC(pGC_) {
-    vncHooksGC = (vncHooksGCPtr)pGC->devPrivates[vncHooksGCIndex].ptr;
-    pGC->funcs = vncHooksGC->wrappedFuncs;
-    if (vncHooksGC->wrappedOps)
-      pGC->ops = vncHooksGC->wrappedOps;
-  }
-  ~GCFuncUnwrapper() {
-    vncHooksGC->wrappedFuncs = pGC->funcs;
-    pGC->funcs = &vncHooksGCFuncs;
-    if (vncHooksGC->wrappedOps) {
-      vncHooksGC->wrappedOps = pGC->ops;
-      pGC->ops = &vncHooksGCOps;
-    }
-  }
-  GCPtr pGC;
-  vncHooksGCPtr vncHooksGC;
-};
-
-
-// ValidateGC - wrap the "ops" if a viewable window
-
-static void vncHooksValidateGC(GCPtr pGC, unsigned long changes,
-                               DrawablePtr pDrawable)
-{
-  GCFuncUnwrapper u(pGC);
-
-  DBGPRINT((stderr,"vncHooksValidateGC called\n"));
-
-  (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable);
-    
-  u.vncHooksGC->wrappedOps = 0;
-  if (pDrawable->type == DRAWABLE_WINDOW && ((WindowPtr)pDrawable)->viewable) {
-    WindowPtr pWin = (WindowPtr)pDrawable;
-    RegionPtr pRegion = &pWin->clipList;
-
-    if (pGC->subWindowMode == IncludeInferiors)
-      pRegion = &pWin->borderClip;
-    if (REGION_NOTEMPTY(pDrawable->pScreen, pRegion)) {
-      u.vncHooksGC->wrappedOps = pGC->ops;
-      DBGPRINT((stderr,"vncHooksValidateGC: wrapped GC ops\n"));
-    }
-  }
-}
-
-// Other GC funcs - just unwrap and call on
-
-static void vncHooksChangeGC(GCPtr pGC, unsigned long mask) {
-  GCFuncUnwrapper u(pGC);
-  (*pGC->funcs->ChangeGC) (pGC, mask);
-}
-static void vncHooksCopyGC(GCPtr src, unsigned long mask, GCPtr dst) {
-  GCFuncUnwrapper u(dst);
-  (*dst->funcs->CopyGC) (src, mask, dst);
-}
-static void vncHooksDestroyGC(GCPtr pGC) {
-  GCFuncUnwrapper u(pGC);
-  (*pGC->funcs->DestroyGC) (pGC);
-}
-static void vncHooksChangeClip(GCPtr pGC, int type, pointer pValue, int nrects)
-{
-  GCFuncUnwrapper u(pGC);
-  (*pGC->funcs->ChangeClip) (pGC, type, pValue, nrects);
-}
-static void vncHooksDestroyClip(GCPtr pGC) {
-  GCFuncUnwrapper u(pGC);
-  (*pGC->funcs->DestroyClip) (pGC);
-}
-static void vncHooksCopyClip(GCPtr dst, GCPtr src) {
-  GCFuncUnwrapper u(dst);
-  (*dst->funcs->CopyClip) (dst, src);
-}
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// GC "ops"
-//
-
-// GCOpUnwrapper is a helper class which unwraps the GC funcs and ops in its
-// constructor and rewraps them in its destructor.
-
-class GCOpUnwrapper {
-public:
-  GCOpUnwrapper(DrawablePtr pDrawable, GCPtr pGC_)
-    : pGC(pGC_), pScreen(pDrawable->pScreen)
-  {
-    vncHooksGC = (vncHooksGCPtr)pGC->devPrivates[vncHooksGCIndex].ptr;
-    oldFuncs = pGC->funcs;
-    pGC->funcs = vncHooksGC->wrappedFuncs;
-    pGC->ops = vncHooksGC->wrappedOps;
-  }
-  ~GCOpUnwrapper() {
-    vncHooksGC->wrappedOps = pGC->ops;
-    pGC->funcs = oldFuncs;
-    pGC->ops = &vncHooksGCOps;
-  }
-  GCPtr pGC;
-  vncHooksGCPtr vncHooksGC;
-  GCFuncs* oldFuncs;
-  ScreenPtr pScreen;
-};
-
-#define GC_OP_UNWRAPPER(pDrawable, pGC, name)                             \
-  GCOpUnwrapper u(pDrawable, pGC);                                        \
-  ScreenPtr pScreen = (pDrawable)->pScreen;                               \
-  vncHooksScreenPtr vncHooksScreen                                        \
-    = ((vncHooksScreenPtr)pScreen->devPrivates[vncHooksScreenIndex].ptr); \
-  DBGPRINT((stderr,"vncHooks" #name " called\n"));
-
-
-// FillSpans - changed region is the whole of borderClip.  This is pessimistic,
-// but I believe this function is rarely used so it doesn't matter.
-
-static void vncHooksFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nInit,
-                              DDXPointPtr pptInit, int *pwidthInit,
-                              int fSorted)
-{
-  GC_OP_UNWRAPPER(pDrawable, pGC, FillSpans);
-
-  RegionHelper changed(pScreen, &((WindowPtr)pDrawable)->borderClip);
-
-  (*pGC->ops->FillSpans) (pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted);
-
-  vncHooksScreen->desktop->add_changed(changed.reg);
-}
-
-// SetSpans - changed region is the whole of borderClip.  This is pessimistic,
-// but I believe this function is rarely used so it doesn't matter.
-
-static void vncHooksSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *psrc,
-                             DDXPointPtr ppt, int *pwidth, int nspans,
-                             int fSorted)
-{
-  GC_OP_UNWRAPPER(pDrawable, pGC, SetSpans);
-
-  RegionHelper changed(pScreen, &((WindowPtr)pDrawable)->borderClip);
-
-  (*pGC->ops->SetSpans) (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted);
-
-  vncHooksScreen->desktop->add_changed(changed.reg);
-}
-
-// PutImage - changed region is the given rectangle, clipped by pCompositeClip
-
-static void vncHooksPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth,
-                             int x, int y, int w, int h, int leftPad,
-                             int format, char *pBits)
-{
-  GC_OP_UNWRAPPER(pDrawable, pGC, PutImage);
-
-  BoxRec box;
-  box.x1 = x + pDrawable->x;
-  box.y1 = y + pDrawable->y;
-  box.x2 = box.x1 + w;
-  box.y2 = box.y1 + h;
-
-  RegionHelper changed(pScreen, &box, 0);
-
-  REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
-  (*pGC->ops->PutImage) (pDrawable, pGC, depth, x, y, w, h, leftPad, format,
-                         pBits);
-
-  vncHooksScreen->desktop->add_changed(changed.reg);
-}
-
-// CopyArea - destination of the copy is the dest rectangle, clipped by
-// pCompositeClip.  Any parts of the destination which cannot be copied from
-// the source (could be all of it) go into the changed region.
-
-static RegionPtr vncHooksCopyArea(DrawablePtr pSrc, DrawablePtr pDst,
-                                  GCPtr pGC, int srcx, int srcy, int w, int h,
-                                  int dstx, int dsty)
-{
-  GC_OP_UNWRAPPER(pDst, pGC, CopyArea);
-
-  BoxRec box;
-  box.x1 = dstx + pDst->x;
-  box.y1 = dsty + pDst->y;
-  box.x2 = box.x1 + w;
-  box.y2 = box.y1 + h;
-
-  RegionHelper dst(pScreen, &box, 0);
-  REGION_INTERSECT(pScreen, dst.reg, dst.reg, COMPOSITE_CLIP(pGC));
-
-  RegionHelper src(pScreen);
-
-  if ((pSrc->type == DRAWABLE_WINDOW) && (pSrc->pScreen == pScreen)) {
-    box.x1 = srcx + pSrc->x;
-    box.y1 = srcy + pSrc->y;
-    box.x2 = box.x1 + w;
-    box.y2 = box.y1 + h;
-
-    src.init(&box, 0);
-    REGION_INTERSECT(pScreen, src.reg, src.reg, &((WindowPtr)pSrc)->clipList);
-    REGION_TRANSLATE(pScreen, src.reg,
-                     dstx + pDst->x - srcx - pSrc->x,
-                     dsty + pDst->y - srcy - pSrc->y);
-  } else {
-    src.init(NullBox, 0);
-  }
-
-  RegionHelper changed(pScreen, NullBox, 0);
-  REGION_SUBTRACT(pScreen, changed.reg, dst.reg, src.reg);
-  REGION_INTERSECT(pScreen, dst.reg, dst.reg, src.reg);
-
-  RegionPtr rgn = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, srcx, srcy, w, h,
-                                         dstx, dsty);
-
-  if (REGION_NOTEMPTY(pScreen, dst.reg))
-    vncHooksScreen->desktop->add_copied(dst.reg,
-                                        dstx + pDst->x - srcx - pSrc->x,
-                                        dsty + pDst->y - srcy - pSrc->y);
-
-  if (REGION_NOTEMPTY(pScreen, changed.reg))
-    vncHooksScreen->desktop->add_changed(changed.reg);
-
-  return rgn;
-}
-
-
-// CopyPlane - changed region is the destination rectangle, clipped by
-// pCompositeClip
-
-static RegionPtr vncHooksCopyPlane(DrawablePtr pSrc, DrawablePtr pDst,
-                                   GCPtr pGC, int srcx, int srcy, int w, int h,
-                                   int dstx, int dsty, unsigned long plane)
-{
-  GC_OP_UNWRAPPER(pDst, pGC, CopyPlane);
-
-  BoxRec box;
-  box.x1 = dstx + pDst->x;
-  box.y1 = dsty + pDst->y;
-  box.x2 = box.x1 + w;
-  box.y2 = box.y1 + h;
-
-  RegionHelper changed(pScreen, &box, 0);
-
-  REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
-  RegionPtr rgn = (*pGC->ops->CopyPlane) (pSrc, pDst, pGC, srcx, srcy, w, h,
-                                          dstx, dsty, plane);
-  vncHooksScreen->desktop->add_changed(changed.reg);
-
-  return rgn;
-}
-
-// PolyPoint - changed region is the bounding rect, clipped by pCompositeClip
-
-static void vncHooksPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode,
-                              int npt, xPoint *pts)
-{
-  GC_OP_UNWRAPPER(pDrawable, pGC, PolyPoint);
-
-  if (npt == 0) {
-    (*pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pts);
-    return;
-  }
-
-  int minX = pts[0].x;
-  int maxX = pts[0].x;
-  int minY = pts[0].y;
-  int maxY = pts[0].y;
-
-  if (mode == CoordModePrevious) {
-    int x = pts[0].x;
-    int y = pts[0].y;
-
-    for (int i = 1; i < npt; i++) {
-      x += pts[i].x;
-      y += pts[i].y;
-      if (x < minX) minX = x;
-      if (x > maxX) maxX = x;
-      if (y < minY) minY = y;
-      if (y > maxY) maxY = y;
-    }
-  } else {
-    for (int i = 1; i < npt; i++) {
-      if (pts[i].x < minX) minX = pts[i].x;
-      if (pts[i].x > maxX) maxX = pts[i].x;
-      if (pts[i].y < minY) minY = pts[i].y;
-      if (pts[i].y > maxY) maxY = pts[i].y;
-    }
-  }
-
-  BoxRec box;
-  box.x1 = minX + pDrawable->x;
-  box.y1 = minY + pDrawable->y;
-  box.x2 = maxX + 1 + pDrawable->x;
-  box.y2 = maxY + 1 + pDrawable->y;
-
-  RegionHelper changed(pScreen, &box, 0);
-
-  REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
-  (*pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pts);
-
-  vncHooksScreen->desktop->add_changed(changed.reg);
-}
-
-// Polylines - changed region is the union of the bounding rects of each line,
-// clipped by pCompositeClip.  If there are more than MAX_RECTS_PER_OP lines,
-// just use the bounding rect of all the lines.
-
-static void vncHooksPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode,
-                              int npt, DDXPointPtr ppts)
-{
-  GC_OP_UNWRAPPER(pDrawable, pGC, Polylines);
-
-  if (npt == 0) {
-    (*pGC->ops->Polylines) (pDrawable, pGC, mode, npt, ppts);
-    return;
-  }
-
-  int nRegRects = npt - 1;
-  xRectangle regRects[MAX_RECTS_PER_OP];
-
-  int lw = pGC->lineWidth;
-  if (lw == 0) lw = 1;
-
-  if (npt == 1)
-  {
-    // a single point
-    nRegRects = 1;
-    regRects[0].x = pDrawable->x + ppts[0].x - lw;
-    regRects[0].y = pDrawable->y + ppts[0].y - lw;
-    regRects[0].width = 2*lw;
-    regRects[0].height = 2*lw;
-  }
-  else
-  {
-    /*
-     * mitered joins can project quite a way from
-     * the line end; the 11 degree miter limit limits
-     * this extension to lw / (2 * tan(11/2)), rounded up
-     * and converted to int yields 6 * lw
-     */
-
-    int extra = lw / 2;
-    if (pGC->joinStyle == JoinMiter) {
-      extra = 6 * lw;
-    }
-
-    int prevX, prevY, curX, curY;
-    int rectX1, rectY1, rectX2, rectY2;
-    int minX, minY, maxX, maxY;
-
-    prevX = ppts[0].x + pDrawable->x;
-    prevY = ppts[0].y + pDrawable->y;
-    minX = maxX = prevX;
-    minY = maxY = prevY;
-
-    for (int i = 0; i < nRegRects; i++) {
-      if (mode == CoordModeOrigin) {
-        curX = pDrawable->x + ppts[i+1].x;
-        curY = pDrawable->y + ppts[i+1].y;
-      } else {
-        curX = prevX + ppts[i+1].x;
-        curY = prevY + ppts[i+1].y;
-      }
-
-      if (prevX > curX) {
-        rectX1 = curX - extra;
-        rectX2 = prevX + extra + 1;
-      } else {
-        rectX1 = prevX - extra;
-        rectX2 = curX + extra + 1;
-      }
-
-      if (prevY > curY) {
-        rectY1 = curY - extra;
-        rectY2 = prevY + extra + 1;
-      } else {
-        rectY1 = prevY - extra;
-        rectY2 = curY + extra + 1;
-      }
-
-      if (nRegRects <= MAX_RECTS_PER_OP) {
-        regRects[i].x = rectX1;
-        regRects[i].y = rectY1;
-        regRects[i].width = rectX2 - rectX1;
-        regRects[i].height = rectY2 - rectY1;
-      } else {
-        if (rectX1 < minX) minX = rectX1;
-        if (rectY1 < minY) minY = rectY1;
-        if (rectX2 > maxX) maxX = rectX2;
-        if (rectY2 > maxY) maxY = rectY2;
-      }
-
-      prevX = curX;
-      prevY = curY;
-    }
-
-    if (nRegRects > MAX_RECTS_PER_OP) {
-      regRects[0].x = minX;
-      regRects[0].y = minY;
-      regRects[0].width = maxX - minX;
-      regRects[0].height = maxY - minY;
-      nRegRects = 1;
-    }
-  }
-
-  RegionHelper changed(pScreen, nRegRects, regRects);
-
-  REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
-  (*pGC->ops->Polylines) (pDrawable, pGC, mode, npt, ppts);
-
-  vncHooksScreen->desktop->add_changed(changed.reg);
-}
-
-// PolySegment - changed region is the union of the bounding rects of each
-// segment, clipped by pCompositeClip.  If there are more than MAX_RECTS_PER_OP
-// segments, just use the bounding rect of all the segments.
-
-static void vncHooksPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg,
-                                xSegment *segs)
-{
-  GC_OP_UNWRAPPER(pDrawable, pGC, PolySegment);
-
-  if (nseg == 0) {
-    (*pGC->ops->PolySegment) (pDrawable, pGC, nseg, segs);
-    return;
-  }
-
-  xRectangle regRects[MAX_RECTS_PER_OP];
-  int nRegRects = nseg;
-
-  int lw = pGC->lineWidth;
-  int extra = lw / 2;
-
-  int rectX1, rectY1, rectX2, rectY2;
-  int minX, minY, maxX, maxY;
-
-  minX = maxX = segs[0].x1;
-  minY = maxY = segs[0].y1;
-
-  for (int i = 0; i < nseg; i++) {
-    if (segs[i].x1 > segs[i].x2) {
-      rectX1 = pDrawable->x + segs[i].x2 - extra;
-      rectX2 = pDrawable->x + segs[i].x1 + extra + 1;
-    } else {
-      rectX1 = pDrawable->x + segs[i].x1 - extra;
-      rectX2 = pDrawable->x + segs[i].x2 + extra + 1;
-    }
-
-    if (segs[i].y1 > segs[i].y2) {
-      rectY1 = pDrawable->y + segs[i].y2 - extra;
-      rectY2 = pDrawable->y + segs[i].y1 + extra + 1;
-    } else {
-      rectY1 = pDrawable->y + segs[i].y1 - extra;
-      rectY2 = pDrawable->y + segs[i].y2 + extra + 1;
-    }
-
-    if (nseg <= MAX_RECTS_PER_OP) {
-      regRects[i].x = rectX1;
-      regRects[i].y = rectY1;
-      regRects[i].width = rectX2 - rectX1;
-      regRects[i].height = rectY2 - rectY1;
-    } else {
-      if (rectX1 < minX) minX = rectX1;
-      if (rectY1 < minY) minY = rectY1;
-      if (rectX2 > maxX) maxX = rectX2;
-      if (rectY2 > maxY) maxY = rectY2;
-    }
-  }
-
-  if (nseg > MAX_RECTS_PER_OP) {
-    regRects[0].x = minX;
-    regRects[0].y = minY;
-    regRects[0].width = maxX - minX;
-    regRects[0].height = maxY - minY;
-    nRegRects = 1;
-  }
-
-  RegionHelper changed(pScreen, nRegRects, regRects);
-
-  REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
-  (*pGC->ops->PolySegment) (pDrawable, pGC, nseg, segs);
-
-  vncHooksScreen->desktop->add_changed(changed.reg);
-}
-
-// PolyRectangle - changed region is the union of the bounding rects around
-// each side of the outline rectangles, clipped by pCompositeClip.  If there
-// are more than MAX_RECTS_PER_OP rectangles, just use the bounding rect of all
-// the rectangles.
-
-static void vncHooksPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects,
-                                  xRectangle *rects)
-{
-  GC_OP_UNWRAPPER(pDrawable, pGC, PolyRectangle);
-
-  if (nrects == 0) {
-    (*pGC->ops->PolyRectangle) (pDrawable, pGC, nrects, rects);
-    return;
-  }
-
-  xRectangle regRects[MAX_RECTS_PER_OP*4];
-  int nRegRects = nrects * 4;
-
-  int lw = pGC->lineWidth;
-  int extra = lw / 2;
-
-  int rectX1, rectY1, rectX2, rectY2;
-  int minX, minY, maxX, maxY;
-
-  minX = maxX = rects[0].x;
-  minY = maxY = rects[0].y;
-
-  for (int i = 0; i < nrects; i++) {
-    if (nrects <= MAX_RECTS_PER_OP) {
-      regRects[i*4].x = rects[i].x - extra + pDrawable->x;
-      regRects[i*4].y = rects[i].y - extra + pDrawable->y;
-      regRects[i*4].width = rects[i].width + 1 + 2 * extra;
-      regRects[i*4].height = 1 + 2 * extra;
-
-      regRects[i*4+1].x = rects[i].x - extra + pDrawable->x;
-      regRects[i*4+1].y = rects[i].y - extra + pDrawable->y;
-      regRects[i*4+1].width = 1 + 2 * extra;
-      regRects[i*4+1].height = rects[i].height + 1 + 2 * extra;
-
-      regRects[i*4+2].x = rects[i].x + rects[i].width - extra + pDrawable->x;
-      regRects[i*4+2].y = rects[i].y - extra + pDrawable->y;
-      regRects[i*4+2].width = 1 + 2 * extra;
-      regRects[i*4+2].height = rects[i].height + 1 + 2 * extra;
-
-      regRects[i*4+3].x = rects[i].x - extra + pDrawable->x;
-      regRects[i*4+3].y = rects[i].y + rects[i].height - extra + pDrawable->y;
-      regRects[i*4+3].width = rects[i].width + 1 + 2 * extra;
-      regRects[i*4+3].height = 1 + 2 * extra;
-    } else {
-      rectX1 = pDrawable->x + rects[i].x - extra;
-      rectY1 = pDrawable->y + rects[i].y - extra;
-      rectX2 = pDrawable->x + rects[i].x + rects[i].width + extra+1;
-      rectY2 = pDrawable->y + rects[i].y + rects[i].height + extra+1;
-      if (rectX1 < minX) minX = rectX1;
-      if (rectY1 < minY) minY = rectY1;
-      if (rectX2 > maxX) maxX = rectX2;
-      if (rectY2 > maxY) maxY = rectY2;
-    }
-  }
-
-  if (nrects > MAX_RECTS_PER_OP) {
-    regRects[0].x = minX;
-    regRects[0].y = minY;
-    regRects[0].width = maxX - minX;
-    regRects[0].height = maxY - minY;
-    nRegRects = 1;
-  }
-
-  RegionHelper changed(pScreen, nRegRects, regRects);
-
-  REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
-  (*pGC->ops->PolyRectangle) (pDrawable, pGC, nrects, rects);
-
-  vncHooksScreen->desktop->add_changed(changed.reg);
-}
-
-// PolyArc - changed region is the union of bounding rects around each arc,
-// clipped by pCompositeClip.  If there are more than MAX_RECTS_PER_OP
-// arcs, just use the bounding rect of all the arcs.
-
-static void vncHooksPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs,
-                            xArc *arcs)
-{
-  GC_OP_UNWRAPPER(pDrawable, pGC, PolyArc);
-
-  if (narcs == 0) {
-    (*pGC->ops->PolyArc) (pDrawable, pGC, narcs, arcs);
-    return;
-  }
-
-  xRectangle regRects[MAX_RECTS_PER_OP];
-  int nRegRects = narcs;
-
-  int lw = pGC->lineWidth;
-  if (lw == 0) lw = 1;
-  int extra = lw / 2;
-
-  int rectX1, rectY1, rectX2, rectY2;
-  int minX, minY, maxX, maxY;
-
-  minX = maxX = arcs[0].x;
-  minY = maxY = arcs[0].y;
-
-  for (int i = 0; i < narcs; i++) {
-    if (narcs <= MAX_RECTS_PER_OP) {
-      regRects[i].x = arcs[i].x - extra + pDrawable->x;
-      regRects[i].y = arcs[i].y - extra + pDrawable->y;
-      regRects[i].width = arcs[i].width + lw;
-      regRects[i].height = arcs[i].height + lw;
-    } else {
-      rectX1 = pDrawable->x + arcs[i].x - extra;
-      rectY1 = pDrawable->y + arcs[i].y - extra;
-      rectX2 = pDrawable->x + arcs[i].x + arcs[i].width + lw;
-      rectY2 = pDrawable->y + arcs[i].y + arcs[i].height + lw;
-      if (rectX1 < minX) minX = rectX1;
-      if (rectY1 < minY) minY = rectY1;
-      if (rectX2 > maxX) maxX = rectX2;
-      if (rectY2 > maxY) maxY = rectY2;
-    }
-  }
-
-  if (narcs > MAX_RECTS_PER_OP) {
-    regRects[0].x = minX;
-    regRects[0].y = minY;
-    regRects[0].width = maxX - minX;
-    regRects[0].height = maxY - minY;
-    nRegRects = 1;
-  }
-
-  RegionHelper changed(pScreen, nRegRects, regRects);
-
-  REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
-  (*pGC->ops->PolyArc) (pDrawable, pGC, narcs, arcs);
-
-  vncHooksScreen->desktop->add_changed(changed.reg);
-}
-
-
-// FillPolygon - changed region is the bounding rect around the polygon,
-// clipped by pCompositeClip
-
-static void vncHooksFillPolygon(DrawablePtr pDrawable, GCPtr pGC, int shape,
-                                int mode, int count, DDXPointPtr pts)
-{
-  GC_OP_UNWRAPPER(pDrawable, pGC, FillPolygon);
-
-  if (count == 0) {
-    (*pGC->ops->FillPolygon) (pDrawable, pGC, shape, mode, count, pts);
-    return;
-  }
-
-  int minX = pts[0].x;
-  int maxX = pts[0].x;
-  int minY = pts[0].y;
-  int maxY = pts[0].y;
-
-  if (mode == CoordModePrevious) {
-    int x = pts[0].x;
-    int y = pts[0].y;
-
-    for (int i = 1; i < count; i++) {
-      x += pts[i].x;
-      y += pts[i].y;
-      if (x < minX) minX = x;
-      if (x > maxX) maxX = x;
-      if (y < minY) minY = y;
-      if (y > maxY) maxY = y;
-    }
-  } else {
-    for (int i = 1; i < count; i++) {
-      if (pts[i].x < minX) minX = pts[i].x;
-      if (pts[i].x > maxX) maxX = pts[i].x;
-      if (pts[i].y < minY) minY = pts[i].y;
-      if (pts[i].y > maxY) maxY = pts[i].y;
-    }
-  }
-
-  BoxRec box;
-  box.x1 = minX + pDrawable->x;
-  box.y1 = minY + pDrawable->y;
-  box.x2 = maxX + 1 + pDrawable->x;
-  box.y2 = maxY + 1 + pDrawable->y;
-
-  RegionHelper changed(pScreen, &box, 0);
-
-  REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
-  (*pGC->ops->FillPolygon) (pDrawable, pGC, shape, mode, count, pts);
-
-  vncHooksScreen->desktop->add_changed(changed.reg);
-}
-
-// PolyFillRect - changed region is the union of the rectangles, clipped by
-// pCompositeClip.  If there are more than MAX_RECTS_PER_OP rectangles, just
-// use the bounding rect of all the rectangles.
-
-static void vncHooksPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrects,
-                                 xRectangle *rects)
-{
-  GC_OP_UNWRAPPER(pDrawable, pGC, PolyFillRect);
-
-  if (nrects == 0) {
-    (*pGC->ops->PolyFillRect) (pDrawable, pGC, nrects, rects);
-    return;
-  }
-
-  xRectangle regRects[MAX_RECTS_PER_OP];
-  int nRegRects = nrects;
-  int rectX1, rectY1, rectX2, rectY2;
-  int minX, minY, maxX, maxY;
-  minX = maxX = rects[0].x;
-  minY = maxY = rects[0].y;
-
-  for (int i = 0; i < nrects; i++) {
-    if (nrects <= MAX_RECTS_PER_OP) {
-      regRects[i].x = rects[i].x + pDrawable->x;
-      regRects[i].y = rects[i].y + pDrawable->y;
-      regRects[i].width = rects[i].width;
-      regRects[i].height = rects[i].height;
-    } else {
-      rectX1 = pDrawable->x + rects[i].x;
-      rectY1 = pDrawable->y + rects[i].y;
-      rectX2 = pDrawable->x + rects[i].x + rects[i].width;
-      rectY2 = pDrawable->y + rects[i].y + rects[i].height;
-      if (rectX1 < minX) minX = rectX1;
-      if (rectY1 < minY) minY = rectY1;
-      if (rectX2 > maxX) maxX = rectX2;
-      if (rectY2 > maxY) maxY = rectY2;
-    }
-  }
-
-  if (nrects > MAX_RECTS_PER_OP) {
-    regRects[0].x = minX;
-    regRects[0].y = minY;
-    regRects[0].width = maxX - minX;
-    regRects[0].height = maxY - minY;
-    nRegRects = 1;
-  }
-
-  RegionHelper changed(pScreen, nRegRects, regRects);
-
-  REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
-  (*pGC->ops->PolyFillRect) (pDrawable, pGC, nrects, rects);
-
-  vncHooksScreen->desktop->add_changed(changed.reg);
-}
-
-// PolyFillArc - changed region is the union of bounding rects around each arc,
-// clipped by pCompositeClip.  If there are more than MAX_RECTS_PER_OP arcs,
-// just use the bounding rect of all the arcs.
-
-static void vncHooksPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs,
-                                xArc *arcs)
-{
-  GC_OP_UNWRAPPER(pDrawable, pGC, PolyFillArc);
-
-  if (narcs == 0) {
-    (*pGC->ops->PolyFillArc) (pDrawable, pGC, narcs, arcs);
-    return;
-  }
-
-  xRectangle regRects[MAX_RECTS_PER_OP];
-  int nRegRects = narcs;
-
-  int lw = pGC->lineWidth;
-  if (lw == 0) lw = 1;
-  int extra = lw / 2;
-
-  int rectX1, rectY1, rectX2, rectY2;
-  int minX, minY, maxX, maxY;
-
-  minX = maxX = arcs[0].x;
-  minY = maxY = arcs[0].y;
-
-  for (int i = 0; i < narcs; i++) {
-    if (narcs <= MAX_RECTS_PER_OP) {
-      regRects[i].x = arcs[i].x - extra + pDrawable->x;
-      regRects[i].y = arcs[i].y - extra + pDrawable->y;
-      regRects[i].width = arcs[i].width + lw;
-      regRects[i].height = arcs[i].height + lw;
-    } else {
-      rectX1 = pDrawable->x + arcs[i].x - extra;
-      rectY1 = pDrawable->y + arcs[i].y - extra;
-      rectX2 = pDrawable->x + arcs[i].x + arcs[i].width + lw;
-      rectY2 = pDrawable->y + arcs[i].y + arcs[i].height + lw;
-      if (rectX1 < minX) minX = rectX1;
-      if (rectY1 < minY) minY = rectY1;
-      if (rectX2 > maxX) maxX = rectX2;
-      if (rectY2 > maxY) maxY = rectY2;
-    }
-  }
-
-  if (narcs > MAX_RECTS_PER_OP) {
-    regRects[0].x = minX;
-    regRects[0].y = minY;
-    regRects[0].width = maxX - minX;
-    regRects[0].height = maxY - minY;
-    nRegRects = 1;
-  }
-
-  RegionHelper changed(pScreen, nRegRects, regRects);
-
-  REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
-  (*pGC->ops->PolyFillArc) (pDrawable, pGC, narcs, arcs);
-
-  vncHooksScreen->desktop->add_changed(changed.reg);
-}
-
-// GetTextBoundingRect - calculate a bounding rectangle around n chars of a
-// font.  Not particularly accurate, but good enough.
-
-static void GetTextBoundingRect(DrawablePtr pDrawable, FontPtr font, int x,
-                                int y, int nchars, BoxPtr box)
-{
-  int ascent = __rfbmax(FONTASCENT(font), FONTMAXBOUNDS(font, ascent));
-  int descent = __rfbmax(FONTDESCENT(font), FONTMAXBOUNDS(font, descent));
-  int charWidth = __rfbmax(FONTMAXBOUNDS(font,rightSideBearing),
-                           FONTMAXBOUNDS(font,characterWidth));
-
-  box->x1 = pDrawable->x + x;
-  box->y1 = pDrawable->y + y - ascent;
-  box->x2 = box->x1 + charWidth * nchars;
-  box->y2 = box->y1 + ascent + descent;
-
-  if (FONTMINBOUNDS(font,leftSideBearing) < 0)
-    box->x1 += FONTMINBOUNDS(font,leftSideBearing);
-}
-
-// PolyText8 - changed region is bounding rect around count chars, clipped by
-// pCompositeClip
-
-static int vncHooksPolyText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
-                             int count, char *chars)
-{
-  GC_OP_UNWRAPPER(pDrawable, pGC, PolyText8);
-
-  if (count == 0)
-    return (*pGC->ops->PolyText8) (pDrawable, pGC, x, y, count, chars);
-
-  BoxRec box;
-  GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box);
-
-  RegionHelper changed(pScreen, &box, 0);
-
-  REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
-  int ret = (*pGC->ops->PolyText8) (pDrawable, pGC, x, y, count, chars);
-
-  vncHooksScreen->desktop->add_changed(changed.reg);
-
-  return ret;
-}
-
-// PolyText16 - changed region is bounding rect around count chars, clipped by
-// pCompositeClip
-
-static int vncHooksPolyText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
-                              int count, unsigned short *chars)
-{
-  GC_OP_UNWRAPPER(pDrawable, pGC, PolyText16);
-
-  if (count == 0)
-    return (*pGC->ops->PolyText16) (pDrawable, pGC, x, y, count, chars);
-
-  BoxRec box;
-  GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box);
-
-  RegionHelper changed(pScreen, &box, 0);
-
-  REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
-  int ret = (*pGC->ops->PolyText16) (pDrawable, pGC, x, y, count, chars);
-
-  vncHooksScreen->desktop->add_changed(changed.reg);
-
-  return ret;
-}
-
-// ImageText8 - changed region is bounding rect around count chars, clipped by
-// pCompositeClip
-
-static void vncHooksImageText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
-                               int count, char *chars)
-{
-  GC_OP_UNWRAPPER(pDrawable, pGC, ImageText8);
-
-  if (count == 0) {
-    (*pGC->ops->ImageText8) (pDrawable, pGC, x, y, count, chars);
-    return;
-  }
-
-  BoxRec box;
-  GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box);
-
-  RegionHelper changed(pScreen, &box, 0);
-
-  REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
-  (*pGC->ops->ImageText8) (pDrawable, pGC, x, y, count, chars);
-
-  vncHooksScreen->desktop->add_changed(changed.reg);
-}
-
-// ImageText16 - changed region is bounding rect around count chars, clipped by
-// pCompositeClip
-
-static void vncHooksImageText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
-                                int count, unsigned short *chars)
-{
-  GC_OP_UNWRAPPER(pDrawable, pGC, ImageText16);
-
-  if (count == 0) {
-    (*pGC->ops->ImageText16) (pDrawable, pGC, x, y, count, chars);
-    return;
-  }
-
-  BoxRec box;
-  GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box);
-
-  RegionHelper changed(pScreen, &box, 0);
-
-  REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
-  (*pGC->ops->ImageText16) (pDrawable, pGC, x, y, count, chars);
-
-  vncHooksScreen->desktop->add_changed(changed.reg);
-}
-
-// ImageGlyphBlt - changed region is bounding rect around nglyph chars, clipped
-// by pCompositeClip
-
-static void vncHooksImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x,
-                                  int y, unsigned int nglyph,
-                                  CharInfoPtr *ppci, pointer pglyphBase)
-{
-  GC_OP_UNWRAPPER(pDrawable, pGC, ImageGlyphBlt);
-
-  if (nglyph == 0) {
-    (*pGC->ops->ImageGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci,pglyphBase);
-    return;
-  }
-
-  BoxRec box;
-  GetTextBoundingRect(pDrawable, pGC->font, x, y, nglyph, &box);
-
-  RegionHelper changed(pScreen, &box, 0);
-
-  REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
-  (*pGC->ops->ImageGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
-
-  vncHooksScreen->desktop->add_changed(changed.reg);
-}
-
-// PolyGlyphBlt - changed region is bounding rect around nglyph chars, clipped
-// by pCompositeClip
-
-static void vncHooksPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x,
-                                 int y, unsigned int nglyph,
-                                 CharInfoPtr *ppci, pointer pglyphBase)
-{
-  GC_OP_UNWRAPPER(pDrawable, pGC, PolyGlyphBlt);
-
-  if (nglyph == 0) {
-    (*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci,pglyphBase);
-    return;
-  }
-
-  BoxRec box;
-  GetTextBoundingRect(pDrawable, pGC->font, x, y, nglyph, &box);
-
-  RegionHelper changed(pScreen, &box, 0);
-
-  REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
-  (*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
-
-  vncHooksScreen->desktop->add_changed(changed.reg);
-}
-
-// PushPixels - changed region is the given rectangle, clipped by
-// pCompositeClip
-
-static void vncHooksPushPixels(GCPtr pGC, PixmapPtr pBitMap,
-                               DrawablePtr pDrawable, int w, int h, int x,
-                               int y)
-{
-  GC_OP_UNWRAPPER(pDrawable, pGC, PushPixels);
-
-  BoxRec box;
-  box.x1 = x + pDrawable->x;
-  box.y1 = y + pDrawable->y;
-  box.x2 = box.x1 + w;
-  box.y2 = box.y1 + h;
-
-  RegionHelper changed(pScreen, &box, 0);
-
-  REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
-  (*pGC->ops->PushPixels) (pGC, pBitMap, pDrawable, w, h, x, y);
-
-  vncHooksScreen->desktop->add_changed(changed.reg);
-}
diff --git a/unix/xc/programs/Xserver/vnc/vncHooks.h b/unix/xc/programs/Xserver/vnc/vncHooks.h
deleted file mode 100644 (file)
index c556ef3..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd.  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.
- */
-#ifndef __VNCHOOKS_H__
-#define __VNCHOOKS_H__
-
-extern "C" {
-#include <screenint.h>
-  extern Bool vncHooksInit(ScreenPtr pScreen, XserverDesktop* desktop);
-}
-
-#endif
diff --git a/unix/xc/programs/Xserver/vnc/xf86vncModule.cc b/unix/xc/programs/Xserver/vnc/xf86vncModule.cc
deleted file mode 100644 (file)
index ef8ea50..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd.  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.
- */
-/*  This is the xf86 module code for the vnc extension.
- */
-
-#include <rfb/Configuration.h>
-#include <rfb/Logger_stdio.h>
-#include <rfb/LogWriter.h>
-
-extern "C" {
-#define class c_class
-#define private c_private
-#define bool c_bool
-#define new c_new
-#include "xf86.h"
-#include "xf86Module.h"
-#undef class
-#undef private
-#undef bool
-#undef new
-
-using namespace rfb;
-
-extern void vncExtensionInit();
-static void vncExtensionInitWithParams(INITARGS);
-
-#ifdef XFree86LOADER
-
-static MODULESETUPPROTO(vncSetup);
-
-ExtensionModule vncExt =
-{
-    vncExtensionInitWithParams,
-    "VNC",
-    NULL,
-    NULL,
-    NULL
-};
-
-static XF86ModuleVersionInfo vncVersRec =
-{
-    "vnc",
-    "Constantin Kaplinsky",
-    MODINFOSTRING1,
-    MODINFOSTRING2,
-    XF86_VERSION_CURRENT,
-    1, 0, 0,
-    ABI_CLASS_EXTENSION,         /* needs the server extension ABI */
-    ABI_EXTENSION_VERSION,
-    MOD_CLASS_EXTENSION,
-    {0,0,0,0}
-};
-
-XF86ModuleData vncModuleData = { &vncVersRec, vncSetup, NULL };
-
-static pointer
-vncSetup(pointer module, pointer opts, int *errmaj, int *errmin) {
-    LoadExtension(&vncExt, FALSE);
-    /* Need a non-NULL return value to indicate success */
-    return (pointer)1;
-}
-
-static void vncExtensionInitWithParams(INITARGS)
-{
-  rfb::initStdIOLoggers();
-  rfb::LogWriter::setLogParams("*:stderr:30");
-
-  for (int scr = 0; scr < screenInfo.numScreens; scr++) {
-    ScrnInfoPtr pScrn = xf86Screens[scr];
-
-    for (ParameterIterator i(Configuration::global()); i.param; i.next()) {
-      char* val = xf86FindOptionValue(pScrn->options, i.param->getName());
-      if (val)
-        i.param->setParam(val);
-    }
-  }
-
-  vncExtensionInit();
-}
-
-#endif /* XFree86LOADER */
-}
diff --git a/unix/xserver.patch b/unix/xserver.patch
new file mode 100644 (file)
index 0000000..fb90c56
--- /dev/null
@@ -0,0 +1,68 @@
+diff -up os/WaitFor.c.orig xorg/os/WaitFor.c
+--- os/WaitFor.c.orig  2008-01-28 10:20:35.000000000 +0100
++++ os/WaitFor.c       2008-01-28 10:21:08.000000000 +0100
+@@ -332,13 +332,11 @@ WaitForSomething(int *pClientsReady)
+           if (XFD_ANYSET (&devicesReadable) || XFD_ANYSET (&clientsReadable))
+               break;
+-#ifdef WIN32
+           /* Windows keyboard and mouse events are added to the input queue
+              in Block- and WakupHandlers. There is no device to check if  
+              data is ready. So check here if new input is available */
+           if (*checkForInput[0] != *checkForInput[1])
+               return 0;
+-#endif
+       }
+     }
+diff -up mi/miinitext.c.orig xorg/mi/miinitext.c
+--- mi/miinitext.c.orig        2008-01-28 10:18:46.000000000 +0100
++++ mi/miinitext.c     2008-01-28 10:18:58.000000000 +0100
+@@ -289,6 +289,7 @@ extern void BigReqExtensionInit(INITARGS
+ #ifdef MITMISC
+ extern void MITMiscExtensionInit(INITARGS);
+ #endif
++extern void vncExtensionInit(INITARGS);
+ #ifdef XIDLE
+ extern void XIdleExtensionInit(INITARGS);
+ #endif
+@@ -560,6 +561,7 @@ InitExtensions(argc, argv)
+ #ifdef MITMISC
+     if (!noMITMiscExtension) MITMiscExtensionInit();
+ #endif
++    vncExtensionInit();
+ #ifdef XIDLE
+     if (!noXIdleExtension) XIdleExtensionInit();
+ #endif
+diff -up hw/Makefile.am.orig xorg/hw/Makefile.am
+--- hw/Makefile.am.orig        2008-01-28 10:18:46.000000000 +0100
++++ hw/Makefile.am     2008-01-28 10:18:58.000000000 +0100
+@@ -43,7 +43,8 @@ SUBDIRS =                    \
+       $(DMX_SUBDIRS)          \
+       $(KDRIVE_SUBDIRS)       \
+       $(XQUARTZ_SUBDIRS)      \
+-      $(XPRINT_SUBDIRS)
++      $(XPRINT_SUBDIRS)       \
++      vnc
+ DIST_SUBDIRS = dmx xfree86 vfb xnest xwin xquartz kdrive xgl xprint
+diff -up configure.ac.orig xorg/configure.ac
+--- configure.ac.orig  2008-01-28 10:18:45.000000000 +0100
++++ configure.ac       2008-01-28 10:18:58.000000000 +0100
+@@ -29,7 +29,6 @@ AC_PREREQ(2.57)
+ AC_INIT([xorg-server], 1.4.99.2, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server)
+ AC_CONFIG_SRCDIR([Makefile.am])
+ AM_INIT_AUTOMAKE([dist-bzip2 foreign])
+-AM_MAINTAINER_MODE
+ dnl this gets generated by autoheader, and thus contains all the defines.  we
+ dnl don't ever actually use it, internally.
+@@ -2173,6 +2172,7 @@ hw/dmx/input/Makefile
+ hw/dmx/glxProxy/Makefile
+ hw/dmx/Makefile
+ hw/vfb/Makefile
++hw/vnc/Makefile
+ hw/xgl/Makefile
+ hw/xgl/egl/Makefile
+ hw/xgl/egl/module/Makefile
diff --git a/unix/xserver/hw/vnc/RegionHelper.h b/unix/xserver/hw/vnc/RegionHelper.h
new file mode 100644 (file)
index 0000000..61dc89f
--- /dev/null
@@ -0,0 +1,84 @@
+/* Copyright (C) 2002-2005 RealVNC Ltd.  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.
+ */
+#ifndef __REGIONHELPER_H__
+#define __REGIONHELPER_H__
+
+// RegionHelper is a class which helps in using X server regions by
+// automatically freeing them in the destructor.  It also fixes a problem with
+// REGION_INIT when given an empty rectangle.
+
+// REGION_NULL was introduced in the Xorg tree as the way to initialise an
+// empty region.  If it's not already defined do it the old way.  Note that the
+// old way causes a segfault in the new tree...
+#ifndef REGION_NULL
+#define REGION_NULL(pScreen,pReg) REGION_INIT(pScreen,pReg,NullBox,0)
+#endif
+
+class RegionHelper {
+public:
+
+  // constructor from a single rect
+  RegionHelper(ScreenPtr pScreen_, BoxPtr rect, int size)
+    : pScreen(pScreen_), reg(0)
+  {
+    init(rect, size);
+  }
+
+  // constructor from an existing X server region
+  RegionHelper(ScreenPtr pScreen_, RegionPtr pRegion)
+    : pScreen(pScreen_), reg(&regRec)
+  {
+    REGION_NULL(pScreen, reg);
+    REGION_COPY(pScreen, reg, pRegion);
+  }
+
+  // constructor from an array of rectangles
+  RegionHelper(ScreenPtr pScreen_, int nrects, xRectanglePtr rects,
+               int ctype=CT_NONE)
+    : pScreen(pScreen_)
+  {
+    reg = RECTS_TO_REGION(pScreen, nrects, rects, ctype);
+  }
+
+  // constructor for calling init() later
+  RegionHelper(ScreenPtr pScreen_) : pScreen(pScreen_), reg(0) {
+  }
+
+  void init(BoxPtr rect, int size) {
+    reg = &regRec;
+    if (!rect || (rect && (rect->x2 == rect->x1 || rect->y2 == rect->y1))) {
+      REGION_NULL(pScreen, reg);
+    } else {
+      REGION_INIT(pScreen, reg, rect, size);
+    }
+  }
+
+  // destructor frees as appropriate
+  ~RegionHelper() {
+    if (reg == &regRec) {
+      REGION_UNINIT(pScreen, reg);
+    } else if (reg) {
+      REGION_DESTROY(pScreen, reg);
+    }
+  }
+  ScreenPtr pScreen;
+  RegionRec regRec;
+  RegionPtr reg;
+};
+
+#endif
diff --git a/unix/xserver/hw/vnc/XserverDesktop.cc b/unix/xserver/hw/vnc/XserverDesktop.cc
new file mode 100644 (file)
index 0000000..9e5ea0f
--- /dev/null
@@ -0,0 +1,1147 @@
+/* Copyright (C) 2002-2005 RealVNC Ltd.  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.
+ */
+//
+// XserverDesktop.cxx
+//
+
+#include <stdio.h>
+#include <strings.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/utsname.h>
+#include <network/TcpSocket.h>
+#include <rfb/Exception.h>
+#include <rfb/VNCServerST.h>
+#include <rfb/HTTPServer.h>
+#include <rfb/LogWriter.h>
+#include <rfb/Configuration.h>
+#include "XserverDesktop.h"
+#include "vncExtInit.h"
+
+extern "C" {
+#define public c_public
+#define class c_class
+
+  // windowTable is in globals.h in XFree 4, but not in XFree 3 unfortunately
+extern WindowPtr *WindowTable;
+extern char *display;
+
+#include "inputstr.h"
+#include "servermd.h"
+#include "colormapst.h"
+#include "resource.h"
+#include "cursorstr.h"
+#include "windowstr.h"
+#define XK_CYRILLIC
+#include "keysym.h"
+#undef public
+#undef class
+}
+
+using namespace rfb;
+using namespace network;
+
+static LogWriter vlog("XserverDesktop");
+
+rfb::IntParameter deferUpdateTime("DeferUpdate",
+                                  "Time in milliseconds to defer updates",40);
+
+rfb::BoolParameter alwaysSetDeferUpdateTimer("AlwaysSetDeferUpdateTimer",
+                  "Always reset the defer update timer on every change",false);
+
+IntParameter queryConnectTimeout("QueryConnectTimeout",
+                                 "Number of seconds to show the Accept Connection dialog before "
+                                 "rejecting the connection",
+                                 10);
+
+static KeyCode KeysymToKeycode(KeySymsPtr keymap, KeySym ks, int* col);
+
+static rdr::U8 reverseBits[] = {
+  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
+};
+
+
+class FileHTTPServer : public rfb::HTTPServer {
+public:
+  FileHTTPServer(XserverDesktop* d) : desktop(d) {}
+  virtual ~FileHTTPServer() {}
+
+  virtual rdr::InStream* getFile(const char* name, const char** contentType,
+                                 int* contentLength, time_t* lastModified)
+  {
+    if (name[0] != '/' || strstr(name, "..") != 0) {
+      vlog.info("http request was for invalid file name");
+      return 0;
+    }
+
+    if (strcmp(name, "/") == 0) name = "/index.vnc";
+
+    CharArray httpDirStr(httpDir.getData());
+    CharArray fname(strlen(httpDirStr.buf)+strlen(name)+1);
+    sprintf(fname.buf, "%s%s", httpDirStr.buf, name);
+    int fd = open(fname.buf, O_RDONLY);
+    if (fd < 0) return 0;
+    rdr::InStream* is = new rdr::FdInStream(fd, -1, 0, true);
+    *contentType = guessContentType(name, *contentType);
+    if (strlen(name) > 4 && strcasecmp(&name[strlen(name)-4], ".vnc") == 0) {
+      is = new rdr::SubstitutingInStream(is, desktop, 20);
+      *contentType = "text/html";
+    } else {
+      struct stat st;
+      if (fstat(fd, &st) == 0) {
+        *contentLength = st.st_size;
+        *lastModified = st.st_mtime;
+      }
+    }
+    return is;
+  }
+
+  XserverDesktop* desktop;
+};
+
+
+XserverDesktop::XserverDesktop(ScreenPtr pScreen_,
+                               network::TcpListener* listener_,
+                               network::TcpListener* httpListener_,
+                               const char* name, void* fbptr)
+  : pScreen(pScreen_), deferredUpdateTimer(0), dummyTimer(0),
+    server(0), httpServer(0),
+    listener(listener_), httpListener(httpListener_),
+    cmap(0), deferredUpdateTimerSet(false),
+    grabbing(false), ignoreHooks_(false), directFbptr(fbptr != 0),
+    oldButtonMask(0),
+    queryConnectId(0)
+{
+  int i;
+  format.depth = pScreen->rootDepth;
+  for (i = 0; i < screenInfo.numPixmapFormats; i++) {
+    if (screenInfo.formats[i].depth == format.depth) {
+      format.bpp = screenInfo.formats[i].bitsPerPixel;
+      break;
+    }
+  }
+  if (i == screenInfo.numPixmapFormats) {
+    fprintf(stderr,"no pixmap format for root depth???\n");
+    abort();
+  }
+  format.bigEndian = (screenInfo.imageByteOrder == MSBFirst);
+
+  VisualPtr vis;
+  for (i = 0; i < pScreen->numVisuals; i++) {
+    if (pScreen->visuals[i].vid == pScreen->rootVisual) {
+      vis = &pScreen->visuals[i];
+      break;
+    }
+  }
+  if (i == pScreen->numVisuals) {
+    fprintf(stderr,"no visual rec for root visual???\n");
+    abort();
+  }
+  format.trueColour = (vis->c_class == TrueColor);
+  if (!format.trueColour && format.bpp != 8)
+    throw rfb::Exception("X server uses unsupported visual");
+  format.redShift   = ffs(vis->redMask) - 1;
+  format.greenShift = ffs(vis->greenMask) - 1;
+  format.blueShift  = ffs(vis->blueMask) - 1;
+  format.redMax     = vis->redMask   >> format.redShift;
+  format.greenMax   = vis->greenMask >> format.greenShift;
+  format.blueMax    = vis->blueMask  >> format.blueShift;
+
+  width_ = pScreen->width;
+  height_ = pScreen->height;
+  if (fbptr)
+    data = (rdr::U8*)fbptr;
+  else
+    data = new rdr::U8[pScreen->width * pScreen->height * (format.bpp/8)];
+  colourmap = this;
+
+  serverReset(pScreen);
+
+  server = new VNCServerST(name, this);
+  server->setPixelBuffer(this);
+  server->setQueryConnectionHandler(this);
+
+  if (httpListener)
+    httpServer = new FileHTTPServer(this);
+}
+
+XserverDesktop::~XserverDesktop()
+{
+  if (!directFbptr)
+    delete [] data;
+  TimerFree(deferredUpdateTimer);
+  TimerFree(dummyTimer);
+  delete httpServer;
+  delete server;
+}
+
+void XserverDesktop::serverReset(ScreenPtr pScreen_)
+{
+  pScreen = pScreen_;
+  XID* ids = new XID[pScreen->maxInstalledCmaps];
+  int nmaps = (*pScreen->ListInstalledColormaps)(pScreen, ids);
+  cmap = (ColormapPtr)LookupIDByType(ids[0], RT_COLORMAP);
+  delete [] ids;
+}
+
+char* XserverDesktop::substitute(const char* varName)
+{
+  if (strcmp(varName, "$$") == 0) {
+    return rfb::strDup("$");
+  }
+  if (strcmp(varName, "$PORT") == 0) {
+    char* str = new char[10];
+    sprintf(str, "%d", listener ? listener->getMyPort() : 0);
+    return str;
+  }
+  if (strcmp(varName, "$WIDTH") == 0) {
+    char* str = new char[10];
+    sprintf(str, "%d", width());
+    return str;
+  }
+  if (strcmp(varName, "$HEIGHT") == 0) {
+    char* str = new char[10];
+    sprintf(str, "%d", height());
+    return str;
+  }
+  if (strcmp(varName, "$APPLETWIDTH") == 0) {
+    char* str = new char[10];
+    sprintf(str, "%d", width());
+    return str;
+  }
+  if (strcmp(varName, "$APPLETHEIGHT") == 0) {
+    char* str = new char[10];
+    sprintf(str, "%d", height() + 32);
+    return str;
+  }
+  if (strcmp(varName, "$DESKTOP") == 0) {
+    return rfb::strDup(server->getName());
+  }
+  if (strcmp(varName, "$DISPLAY") == 0) {
+    struct utsname uts;
+    uname(&uts);
+    char* str = new char[256];
+    strncat(str, uts.nodename, 240);
+    strcat(str, ":");
+    strncat(str, display, 10);
+    return str;
+  }
+  if (strcmp(varName, "$USER") == 0) {
+    struct passwd* user = getpwuid(getuid());
+    return rfb::strDup(user ? user->pw_name : "?");
+  }
+  return 0;
+}
+
+rfb::VNCServerST::queryResult
+XserverDesktop::queryConnection(network::Socket* sock,
+                                const char* userName,
+                                char** reason) {
+  if (queryConnectId) {
+    *reason = strDup("Another connection is currently being queried.");
+    return rfb::VNCServerST::REJECT;
+  }
+  queryConnectAddress.replaceBuf(sock->getPeerAddress());
+  if (!userName)
+    userName = "(anonymous)";
+  queryConnectUsername.replaceBuf(strDup(userName));
+  queryConnectId = sock;
+  vncQueryConnect(this, sock);
+  return rfb::VNCServerST::PENDING;
+}
+
+
+void XserverDesktop::setColormap(ColormapPtr cmap_)
+{
+  if (cmap != cmap_) {
+    cmap = cmap_;
+    setColourMapEntries(0, 0);
+  }
+}
+
+void XserverDesktop::setColourMapEntries(ColormapPtr pColormap, int ndef,
+                                         xColorItem* pdef)
+{
+  if (cmap != pColormap || ndef <= 0) return;
+
+  int first = pdef[0].pixel;
+  int n = 1;
+
+  for (int i = 1; i < ndef; i++) {
+    if (first + n == pdef[i].pixel) {
+      n++;
+    } else {
+      setColourMapEntries(first, n);
+      first = pdef[i].pixel;
+      n = 1;
+    }
+  }
+  setColourMapEntries(first, n);
+}
+
+void XserverDesktop::setColourMapEntries(int firstColour, int nColours)
+{
+  try {
+    server->setColourMapEntries(firstColour, nColours);
+  } catch (rdr::Exception& e) {
+    vlog.error("XserverDesktop::setColourMapEntries: %s",e.str());
+  }
+}
+
+void XserverDesktop::bell()
+{
+  server->bell();
+}
+
+void XserverDesktop::serverCutText(const char* str, int len)
+{
+  try {
+    server->serverCutText(str, len);
+  } catch (rdr::Exception& e) {
+    vlog.error("XserverDesktop::serverCutText: %s",e.str());
+  }
+}
+
+void XserverDesktop::setCursor(CursorPtr cursor)
+{
+  try {
+    int w = cursor->bits->width;
+    int h = cursor->bits->height;
+    rdr::U8* cursorData = new rdr::U8[w * h * (getPF().bpp / 8)];
+
+    xColorItem fg, bg;
+    fg.red   = cursor->foreRed;
+    fg.green = cursor->foreGreen;
+    fg.blue  = cursor->foreBlue;
+    FakeAllocColor(cmap, &fg);
+    bg.red   = cursor->backRed;
+    bg.green = cursor->backGreen;
+    bg.blue  = cursor->backBlue;
+    FakeAllocColor(cmap, &bg);
+    FakeFreeColor(cmap, fg.pixel);
+    FakeFreeColor(cmap, bg.pixel);
+
+    int xMaskBytesPerRow = BitmapBytePad(w);
+
+    for (int y = 0; y < h; y++) {
+      for (int x = 0; x < w; x++) {
+        int byte = y * xMaskBytesPerRow + x / 8;
+#if (BITMAP_BIT_ORDER == MSBFirst)
+        int bit = 7 - x % 8;
+#else
+        int bit = x % 8;
+#endif
+        switch (getPF().bpp) {
+        case 8:
+          ((rdr::U8*)cursorData)[y * w + x]
+            = (cursor->bits->source[byte] & (1 << bit)) ? fg.pixel : bg.pixel;
+          break;
+        case 16:
+          ((rdr::U16*)cursorData)[y * w + x]
+            = (cursor->bits->source[byte] & (1 << bit)) ? fg.pixel : bg.pixel;
+          break;
+        case 32:
+          ((rdr::U32*)cursorData)[y * w + x]
+            = (cursor->bits->source[byte] & (1 << bit)) ? fg.pixel : bg.pixel;
+          break;
+        }
+      }
+    }
+
+    int rfbMaskBytesPerRow = (w + 7) / 8;
+
+    rdr::U8* cursorMask = new rdr::U8[rfbMaskBytesPerRow * h];
+
+    for (int j = 0; j < h; j++) {
+      for (int i = 0; i < rfbMaskBytesPerRow; i++)
+#if (BITMAP_BIT_ORDER == MSBFirst)
+        cursorMask[j * rfbMaskBytesPerRow + i]
+          = cursor->bits->mask[j * xMaskBytesPerRow + i];
+#else
+        cursorMask[j * rfbMaskBytesPerRow + i]
+          = reverseBits[cursor->bits->mask[j * xMaskBytesPerRow + i]];
+#endif
+    }
+
+    server->setCursor(cursor->bits->width, cursor->bits->height,
+                      Point(cursor->bits->xhot, cursor->bits->yhot),
+                      cursorData, cursorMask);
+    server->tryUpdate();
+    delete [] cursorData;
+    delete [] cursorMask;
+  } catch (rdr::Exception& e) {
+    vlog.error("XserverDesktop::setCursor: %s",e.str());
+  }
+}
+
+static void printRegion(RegionPtr reg)
+{
+  int nrects = REGION_NUM_RECTS(reg);
+
+  fprintf(stderr,"Region num rects %2d extents %3d,%3d %3dx%3d\n",nrects,
+          (REGION_EXTENTS(pScreen,reg))->x1,
+          (REGION_EXTENTS(pScreen,reg))->y1,
+          (REGION_EXTENTS(pScreen,reg))->x2-(REGION_EXTENTS(pScreen,reg))->x1,
+          (REGION_EXTENTS(pScreen,reg))->y2-(REGION_EXTENTS(pScreen,reg))->y1);
+
+  for (int i = 0; i < nrects; i++) {
+    fprintf(stderr,"    rect %3d,%3d %3dx%3d\n",
+            REGION_RECTS(reg)[i].x1,
+            REGION_RECTS(reg)[i].y1,
+            REGION_RECTS(reg)[i].x2-REGION_RECTS(reg)[i].x1,
+            REGION_RECTS(reg)[i].y2-REGION_RECTS(reg)[i].y1);
+  }
+}
+
+CARD32 XserverDesktop::deferredUpdateTimerCallback(OsTimerPtr timer,
+                                                   CARD32 now, pointer arg)
+{
+  XserverDesktop* desktop = (XserverDesktop*)arg;
+  desktop->deferredUpdateTimerSet = false;
+  try {
+    desktop->server->tryUpdate();
+  } catch (rdr::Exception& e) {
+    vlog.error("XserverDesktop::deferredUpdateTimerCallback: %s",e.str());
+  }
+  return 0;
+}
+
+void XserverDesktop::deferUpdate()
+{
+  if (deferUpdateTime != 0) {
+    if (!deferredUpdateTimerSet || alwaysSetDeferUpdateTimer) {
+      deferredUpdateTimerSet = true;
+      deferredUpdateTimer = TimerSet(deferredUpdateTimer, 0,
+                                     deferUpdateTime,
+                                     deferredUpdateTimerCallback, this);
+    }
+  } else {
+    server->tryUpdate();
+  }
+}
+
+void XserverDesktop::add_changed(RegionPtr reg)
+{
+  if (ignoreHooks_) return;
+  if (grabbing) return;
+  try {
+    rfb::Region rfbReg;
+    rfbReg.setExtentsAndOrderedRects((ShortRect*)REGION_EXTENTS(pScreen, reg),
+                                     REGION_NUM_RECTS(reg),
+                                     (ShortRect*)REGION_RECTS(reg));
+    server->add_changed(rfbReg);
+    deferUpdate();
+  } catch (rdr::Exception& e) {
+    vlog.error("XserverDesktop::add_changed: %s",e.str());
+  }
+}
+
+void XserverDesktop::add_copied(RegionPtr dst, int dx, int dy)
+{
+  if (ignoreHooks_) return;
+  if (grabbing) return;
+  try {
+    rfb::Region rfbReg;
+    rfbReg.setExtentsAndOrderedRects((ShortRect*)REGION_EXTENTS(pScreen, dst),
+                                     REGION_NUM_RECTS(dst),
+                                     (ShortRect*)REGION_RECTS(dst));
+    server->add_copied(rfbReg, rfb::Point(dx, dy));
+    deferUpdate();
+  } catch (rdr::Exception& e) {
+    vlog.error("XserverDesktop::add_copied: %s",e.str());
+  }
+}
+
+void XserverDesktop::positionCursor()
+{
+  if (!cursorPos.equals(oldCursorPos)) {
+    oldCursorPos = cursorPos;
+    (*pScreen->SetCursorPosition) (pScreen, cursorPos.x, cursorPos.y, FALSE);
+    server->setCursorPos(cursorPos);
+    server->tryUpdate();
+  }
+}
+
+void XserverDesktop::blockHandler(fd_set* fds)
+{
+  try {
+    ScreenPtr screenWithCursor = GetCurrentRootWindow()->drawable.pScreen;
+    if (screenWithCursor == pScreen) {
+      int x, y;
+      GetSpritePosition(&x, &y);
+      if (x != cursorPos.x || y != cursorPos.y) {
+        cursorPos = oldCursorPos = Point(x, y);
+        server->setCursorPos(cursorPos);
+        server->tryUpdate();
+      }
+    }
+
+    if (listener)
+      FD_SET(listener->getFd(), fds);
+    if (httpListener)
+      FD_SET(httpListener->getFd(), fds);
+
+    std::list<Socket*> sockets;
+    server->getSockets(&sockets);
+    std::list<Socket*>::iterator i;
+    for (i = sockets.begin(); i != sockets.end(); i++) {
+      int fd = (*i)->getFd();
+      if ((*i)->isShutdown()) {
+        vlog.debug("client gone, sock %d",fd);
+        server->removeSocket(*i);
+        vncClientGone(fd);
+        delete (*i);
+      } else {
+        FD_SET(fd, fds);
+      }
+    }
+    if (httpServer) {
+      httpServer->getSockets(&sockets);
+      for (i = sockets.begin(); i != sockets.end(); i++) {
+        int fd = (*i)->getFd();
+        if ((*i)->isShutdown()) {
+          vlog.debug("http client gone, sock %d",fd);
+          httpServer->removeSocket(*i);
+          delete (*i);
+        } else {
+          FD_SET(fd, fds);
+        }
+      }
+    }
+  } catch (rdr::Exception& e) {
+    vlog.error("XserverDesktop::blockHandler: %s",e.str());
+  }
+}
+
+static CARD32 dummyTimerCallback(OsTimerPtr timer, CARD32 now, pointer arg) {
+  return 0;
+}
+
+void XserverDesktop::wakeupHandler(fd_set* fds, int nfds)
+{
+  try {
+    if (nfds >= 1) {
+
+      if (listener) {
+        if (FD_ISSET(listener->getFd(), fds)) {
+          FD_CLR(listener->getFd(), fds);
+          Socket* sock = listener->accept();
+          server->addSocket(sock);
+          vlog.debug("new client, sock %d",sock->getFd());
+        }
+      }
+
+      if (httpListener) {
+        if (FD_ISSET(httpListener->getFd(), fds)) {
+          FD_CLR(httpListener->getFd(), fds);
+          Socket* sock = httpListener->accept();
+          httpServer->addSocket(sock);
+          vlog.debug("new http client, sock %d",sock->getFd());
+        }
+      }
+
+      std::list<Socket*> sockets;
+      server->getSockets(&sockets);
+      std::list<Socket*>::iterator i;
+      for (i = sockets.begin(); i != sockets.end(); i++) {
+        int fd = (*i)->getFd();
+        if (FD_ISSET(fd, fds)) {
+          FD_CLR(fd, fds);
+          server->processSocketEvent(*i);
+        }
+      }
+
+      if (httpServer) {
+        httpServer->getSockets(&sockets);
+        for (i = sockets.begin(); i != sockets.end(); i++) {
+          int fd = (*i)->getFd();
+          if (FD_ISSET(fd, fds)) {
+            FD_CLR(fd, fds);
+            httpServer->processSocketEvent(*i);
+          }
+        }
+      }
+
+      positionCursor();
+    }
+
+    int timeout = server->checkTimeouts();
+    if (timeout > 0) {
+      // set a dummy timer just so we are guaranteed be called again next time.
+      dummyTimer = TimerSet(dummyTimer, 0, timeout,
+                            dummyTimerCallback, 0);
+    }
+
+  } catch (rdr::Exception& e) {
+    vlog.error("XserverDesktop::wakeupHandler: %s",e.str());
+  }
+}
+
+void XserverDesktop::addClient(Socket* sock, bool reverse)
+{
+  vlog.debug("new client, sock %d reverse %d",sock->getFd(),reverse);
+  server->addSocket(sock, reverse);
+}
+
+void XserverDesktop::disconnectClients()
+{
+  vlog.debug("disconnecting all clients");
+  return server->closeClients("Disconnection from server end");
+}
+
+
+int XserverDesktop::getQueryTimeout(void* opaqueId,
+                                    const char** address,
+                                    const char** username)
+{
+  if (opaqueId && queryConnectId == opaqueId) {
+    vlog.info("address=%s, username=%s, timeout=%d",
+              queryConnectAddress.buf, queryConnectUsername.buf,
+              (int)queryConnectTimeout);
+    if (address) *address = queryConnectAddress.buf;
+    if (username) *username = queryConnectUsername.buf;
+    return queryConnectTimeout;
+  }
+  return 0;
+}
+
+void XserverDesktop::approveConnection(void* opaqueId, bool accept,
+                                       const char* rejectMsg)
+{
+  if (queryConnectId == opaqueId) {
+    server->approveConnection((network::Socket*)opaqueId, accept, rejectMsg);
+    queryConnectId = 0;
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////
+//
+// SDesktop callbacks
+
+
+void XserverDesktop::pointerEvent(const Point& pos, int buttonMask)
+{
+  xEvent ev;
+  DevicePtr dev = LookupPointerDevice();
+
+  // SetCursorPosition seems to be very expensive (at least on XFree86 3.3.6
+  // for S3), so we delay calling it until positionCursor() is called at the
+  // end of processing a load of RFB.
+  //(*pScreen->SetCursorPosition) (pScreen, pos.x, pos.y, FALSE);
+
+  NewCurrentScreen(pScreen, pos.x, pos.y);
+
+  ev.u.u.type = MotionNotify;
+  ev.u.u.detail = 0;
+  ev.u.keyButtonPointer.rootX = pos.x;
+  ev.u.keyButtonPointer.rootY = pos.y;
+  ev.u.keyButtonPointer.time = GetTimeInMillis();
+
+  if (!pos.equals(cursorPos))
+    (*dev->processInputProc)(&ev, (DeviceIntPtr)dev, 1);
+
+  for (int i = 0; i < 5; i++) {
+    if ((buttonMask ^ oldButtonMask) & (1<<i)) {
+      // Do not use the pointer mapping. Treat VNC buttons as logical
+      // buttons.
+      ev.u.u.detail = i + 1;
+      ev.u.u.type = (buttonMask & (1<<i)) ? ButtonPress : ButtonRelease;
+      (*dev->processInputProc)(&ev, (DeviceIntPtr)dev, 1);
+    }
+  }
+
+  cursorPos = pos;
+  oldButtonMask = buttonMask;
+}
+
+void XserverDesktop::clientCutText(const char* str, int len)
+{
+  vncClientCutText(str, len);
+}
+
+void XserverDesktop::grabRegion(const rfb::Region& region)
+{
+  if (directFbptr) return;
+  if (!pScreen->GetImage) {
+    vlog.error("VNC error: pScreen->GetImage == 0");
+    return;
+  }
+
+  grabbing = true;
+
+  int bytesPerPixel = format.bpp/8;
+  int bytesPerRow = pScreen->width * bytesPerPixel;
+
+  std::vector<rfb::Rect> rects;
+  std::vector<rfb::Rect>::iterator i;
+  region.get_rects(&rects);
+  for (i = rects.begin(); i != rects.end(); i++) {
+    for (int y = i->tl.y; y < i->br.y; y++) {
+      (*pScreen->GetImage) ((DrawablePtr)WindowTable[pScreen->myNum],
+                            i->tl.x, y, i->width(), 1,
+                            ZPixmap, (unsigned long)~0L,
+                            ((char*)data
+                             + y * bytesPerRow + i->tl.x * bytesPerPixel));
+    }
+  }
+  grabbing = false;
+}
+
+void XserverDesktop::lookup(int index, int* r, int* g, int* b)
+{
+  if ((cmap->c_class | DynamicClass) == DirectColor) {
+    VisualPtr v = cmap->pVisual;
+    *r = cmap->red  [(index & v->redMask  ) >> v->offsetRed  ].co.local.red;
+    *g = cmap->green[(index & v->greenMask) >> v->offsetGreen].co.local.green;
+    *b = cmap->blue [(index & v->blueMask ) >> v->offsetBlue ].co.local.blue;
+  } else {
+    EntryPtr pent;
+    pent = (EntryPtr)&cmap->red[index];
+    if (pent->fShared) {
+      *r = pent->co.shco.red->color;
+      *g = pent->co.shco.green->color;
+      *b = pent->co.shco.blue->color;
+    } else {
+      *r = pent->co.local.red;
+      *g = pent->co.local.green;
+      *b = pent->co.local.blue;
+    }
+  }
+}
+
+//
+// Keyboard handling
+//
+
+#define IS_PRESSED(keyc, keycode) \
+  ((keyc)->down[(keycode) >> 3] & (1 << ((keycode) & 7)))
+
+// ModifierState is a class which helps simplify generating a "fake" press
+// or release of shift, ctrl, alt, etc.  An instance of the class is created
+// for every modifier which may need to be pressed or released.  Then either
+// press() or release() may be called to make sure that the corresponding keys
+// are in the right state.  The destructor of the class automatically reverts
+// to the previous state.  Each modifier may have multiple keys associated with
+// it, so in the case of a fake release, this may involve releasing more than
+// one key.
+
+class ModifierState {
+public:
+  ModifierState(DeviceIntPtr dev_, int modIndex_)
+    : dev(dev_), modIndex(modIndex_), nKeys(0), keys(0), pressed(false)
+  {
+  }
+  ~ModifierState() {
+    for (int i = 0; i < nKeys; i++)
+      generateXKeyEvent(keys[i], !pressed);
+    delete [] keys;
+  }
+  void press() {
+    KeyClassPtr keyc = dev->key;
+    if (!(keyc->state & (1<<modIndex))) {
+      tempKeyEvent(keyc->modifierKeyMap[modIndex * keyc->maxKeysPerModifier],
+                   true);
+      pressed = true;
+    }
+  }
+  void release() {
+    KeyClassPtr keyc = dev->key;
+    if (keyc->state & (1<<modIndex)) {
+      for (int k = 0; k < keyc->maxKeysPerModifier; k++) {
+        int keycode
+          = keyc->modifierKeyMap[modIndex * keyc->maxKeysPerModifier + k];
+        if (keycode && IS_PRESSED(keyc, keycode))
+          tempKeyEvent(keycode, false);
+      }
+    }
+  }
+private:
+  void tempKeyEvent(int keycode, bool down) {
+    if (keycode) {
+      if (!keys) keys = new int[dev->key->maxKeysPerModifier];
+      keys[nKeys++] = keycode;
+      generateXKeyEvent(keycode, down);
+    }
+  }
+  void generateXKeyEvent(int keycode, bool down) {
+    xEvent ev;
+    ev.u.u.type = down ? KeyPress : KeyRelease;
+    ev.u.u.detail = keycode;
+    ev.u.keyButtonPointer.time = GetTimeInMillis();
+    (*dev->c_public.processInputProc)(&ev, dev, 1);
+    vlog.debug("fake keycode %d %s", keycode, down ? "down" : "up");
+  }
+  DeviceIntPtr dev;
+  int modIndex;
+  int nKeys;
+  int* keys;
+  bool pressed;
+};
+
+
+// altKeysym is a table of alternative keysyms which have the same meaning.
+
+struct altKeysym_t {
+  KeySym a, b;
+};
+
+altKeysym_t altKeysym[] = {
+  { XK_Shift_L,        XK_Shift_R },
+  { XK_Control_L,      XK_Control_R },
+  { XK_Meta_L,         XK_Meta_R },
+  { XK_Alt_L,          XK_Alt_R },
+  { XK_Super_L,        XK_Super_R },
+  { XK_Hyper_L,        XK_Hyper_R },
+  { XK_KP_Space,       XK_space },
+  { XK_KP_Tab,         XK_Tab },
+  { XK_KP_Enter,       XK_Return },
+  { XK_KP_F1,          XK_F1 },
+  { XK_KP_F2,          XK_F2 },
+  { XK_KP_F3,          XK_F3 },
+  { XK_KP_F4,          XK_F4 },
+  { XK_KP_Home,        XK_Home },
+  { XK_KP_Left,        XK_Left },
+  { XK_KP_Up,          XK_Up },
+  { XK_KP_Right,       XK_Right },
+  { XK_KP_Down,        XK_Down },
+  { XK_KP_Page_Up,     XK_Page_Up },
+  { XK_KP_Page_Down,   XK_Page_Down },
+  { XK_KP_End,         XK_End },
+  { XK_KP_Begin,       XK_Begin },
+  { XK_KP_Insert,      XK_Insert },
+  { XK_KP_Delete,      XK_Delete },
+  { XK_KP_Equal,       XK_equal },
+  { XK_KP_Multiply,    XK_asterisk },
+  { XK_KP_Add,         XK_plus },
+  { XK_KP_Separator,   XK_comma },
+  { XK_KP_Subtract,    XK_minus },
+  { XK_KP_Decimal,     XK_period },
+  { XK_KP_Divide,      XK_slash },
+  { XK_KP_0,           XK_0 },
+  { XK_KP_1,           XK_1 },
+  { XK_KP_2,           XK_2 },
+  { XK_KP_3,           XK_3 },
+  { XK_KP_4,           XK_4 },
+  { XK_KP_5,           XK_5 },
+  { XK_KP_6,           XK_6 },
+  { XK_KP_7,           XK_7 },
+  { XK_KP_8,           XK_8 },
+  { XK_KP_9,           XK_9 },
+};
+
+// keyEvent() - work out the best keycode corresponding to the keysym sent by
+// the viewer.  This is non-trivial because we can't assume much about the
+// local keyboard layout.  We must also find out which column of the keyboard
+// mapping the keysym is in, and alter the shift state appropriately.  Column 0
+// means both shift and "mode_switch" (AltGr) must be released, column 1 means
+// shift must be pressed and mode_switch released, column 2 means shift must be
+// released and mode_switch pressed, and column 3 means both shift and
+// mode_switch must be pressed.
+
+void XserverDesktop::keyEvent(rdr::U32 keysym, bool down)
+{
+  if (keysym == XK_Caps_Lock) {
+    vlog.debug("Ignoring caps lock");
+    return;
+  }
+  DeviceIntPtr dev = (DeviceIntPtr)LookupKeyboardDevice();
+  KeyClassPtr keyc = dev->key;
+  KeySymsPtr keymap = &keyc->curKeySyms;
+
+  // find which modifier Mode_switch is on.
+  int modeSwitchMapIndex = 0;
+  for (int i = 3; i < 8; i++) {
+    for (int k = 0; k < keyc->maxKeysPerModifier; k++) {
+      int keycode = keyc->modifierKeyMap[i * keyc->maxKeysPerModifier + k];
+      for (int j = 0; j < keymap->mapWidth; j++) {
+        if (keycode != 0 &&
+            keymap->map[(keycode - keymap->minKeyCode)
+                        * keymap->mapWidth + j] == XK_Mode_switch)
+        {
+          modeSwitchMapIndex = i;
+          break;
+        }
+      }
+    }
+  }
+
+  int col = 0;
+  if (keyc->state & (1<<ShiftMapIndex)) col |= 1;
+  if (modeSwitchMapIndex && (keyc->state & (1<<modeSwitchMapIndex))) col |= 2;
+
+  int kc = KeysymToKeycode(keymap, keysym, &col);
+
+  // Sort out the "shifted Tab" mess.  If we are sent a shifted Tab, generate a
+  // local shifted Tab regardless of what the "shifted Tab" keysym is on the
+  // local keyboard (it might be Tab, ISO_Left_Tab or HP's private BackTab
+  // keysym, and quite possibly some others too).  We never get ISO_Left_Tab
+  // here because it's already been translated in VNCSConnectionST.
+  if (keysym == XK_Tab && (keyc->state & (1<<ShiftMapIndex)))
+    col |= 1;
+
+  if (kc == 0) {
+    // Not a direct match in the local keyboard mapping.  Check for alternative
+    // keysyms with the same meaning.
+    for (int i = 0; i < sizeof(altKeysym) / sizeof(altKeysym_t); i++) {
+      if (keysym == altKeysym[i].a)
+        kc = KeysymToKeycode(keymap, altKeysym[i].b, &col);
+      else if (keysym == altKeysym[i].b)
+        kc = KeysymToKeycode(keymap, altKeysym[i].a, &col);
+      if (kc) break;
+    }
+  }
+
+  if (kc == 0) {
+    // Last resort - dynamically add a new key to the keyboard mapping.
+    for (kc = keymap->maxKeyCode; kc >= keymap->minKeyCode; kc--) {
+      if (!keymap->map[(kc - keymap->minKeyCode) * keymap->mapWidth]) {
+        keymap->map[(kc - keymap->minKeyCode) * keymap->mapWidth] = keysym;
+        col = 0;
+        SendMappingNotify(MappingKeyboard, kc, 1, serverClient);
+        vlog.info("Added unknown keysym 0x%x to keycode %d",keysym,kc);
+        break;
+      }
+    }
+    if (kc < keymap->minKeyCode) {
+      vlog.info("Keyboard mapping full - ignoring unknown keysym 0x%x",keysym);
+      return;
+    }
+  }
+
+  // See if it's a modifier key.  If so, then don't do any auto-repeat, because
+  // the X server will translate each press into a release followed by a press.
+  for (int i = 0; i < 8; i++) {
+    for (int k = 0; k < keyc->maxKeysPerModifier; k++) {
+      if (kc == keyc->modifierKeyMap[i * keyc->maxKeysPerModifier + k] &&
+          IS_PRESSED(keyc,kc) && down)
+        return;
+    }
+  }
+
+  ModifierState shift(dev, ShiftMapIndex);
+  ModifierState modeSwitch(dev, modeSwitchMapIndex);
+  if (down) {
+    if (col & 1)
+      shift.press();
+    else
+      shift.release();
+    if (modeSwitchMapIndex) {
+      if (col & 2)
+        modeSwitch.press();
+      else
+        modeSwitch.release();
+    }
+  }
+  vlog.debug("keycode %d %s", kc, down ? "down" : "up");
+  xEvent ev;
+  ev.u.u.type = down ? KeyPress : KeyRelease;
+  ev.u.u.detail = kc;
+  ev.u.keyButtonPointer.time = GetTimeInMillis();
+  (*dev->c_public.processInputProc)(&ev, dev, 1);
+}
+
+
+void XConvertCase(KeySym sym, KeySym *lower, KeySym *upper)
+{
+    *lower = sym;
+    *upper = sym;
+    switch(sym >> 8) {
+    case 0: /* Latin 1 */
+       if ((sym >= XK_A) && (sym <= XK_Z))
+           *lower += (XK_a - XK_A);
+       else if ((sym >= XK_a) && (sym <= XK_z))
+           *upper -= (XK_a - XK_A);
+       else if ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))
+           *lower += (XK_agrave - XK_Agrave);
+       else if ((sym >= XK_agrave) && (sym <= XK_odiaeresis))
+           *upper -= (XK_agrave - XK_Agrave);
+       else if ((sym >= XK_Ooblique) && (sym <= XK_Thorn))
+           *lower += (XK_oslash - XK_Ooblique);
+       else if ((sym >= XK_oslash) && (sym <= XK_thorn))
+           *upper -= (XK_oslash - XK_Ooblique);
+       break;
+    case 1: /* Latin 2 */
+       /* Assume the KeySym is a legal value (ignore discontinuities) */
+       if (sym == XK_Aogonek)
+           *lower = XK_aogonek;
+       else if (sym >= XK_Lstroke && sym <= XK_Sacute)
+           *lower += (XK_lstroke - XK_Lstroke);
+       else if (sym >= XK_Scaron && sym <= XK_Zacute)
+           *lower += (XK_scaron - XK_Scaron);
+       else if (sym >= XK_Zcaron && sym <= XK_Zabovedot)
+           *lower += (XK_zcaron - XK_Zcaron);
+       else if (sym == XK_aogonek)
+           *upper = XK_Aogonek;
+       else if (sym >= XK_lstroke && sym <= XK_sacute)
+           *upper -= (XK_lstroke - XK_Lstroke);
+       else if (sym >= XK_scaron && sym <= XK_zacute)
+           *upper -= (XK_scaron - XK_Scaron);
+       else if (sym >= XK_zcaron && sym <= XK_zabovedot)
+           *upper -= (XK_zcaron - XK_Zcaron);
+       else if (sym >= XK_Racute && sym <= XK_Tcedilla)
+           *lower += (XK_racute - XK_Racute);
+       else if (sym >= XK_racute && sym <= XK_tcedilla)
+           *upper -= (XK_racute - XK_Racute);
+       break;
+    case 2: /* Latin 3 */
+       /* Assume the KeySym is a legal value (ignore discontinuities) */
+       if (sym >= XK_Hstroke && sym <= XK_Hcircumflex)
+           *lower += (XK_hstroke - XK_Hstroke);
+       else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex)
+           *lower += (XK_gbreve - XK_Gbreve);
+       else if (sym >= XK_hstroke && sym <= XK_hcircumflex)
+           *upper -= (XK_hstroke - XK_Hstroke);
+       else if (sym >= XK_gbreve && sym <= XK_jcircumflex)
+           *upper -= (XK_gbreve - XK_Gbreve);
+       else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex)
+           *lower += (XK_cabovedot - XK_Cabovedot);
+       else if (sym >= XK_cabovedot && sym <= XK_scircumflex)
+           *upper -= (XK_cabovedot - XK_Cabovedot);
+       break;
+    case 3: /* Latin 4 */
+       /* Assume the KeySym is a legal value (ignore discontinuities) */
+       if (sym >= XK_Rcedilla && sym <= XK_Tslash)
+           *lower += (XK_rcedilla - XK_Rcedilla);
+       else if (sym >= XK_rcedilla && sym <= XK_tslash)
+           *upper -= (XK_rcedilla - XK_Rcedilla);
+       else if (sym == XK_ENG)
+           *lower = XK_eng;
+       else if (sym == XK_eng)
+           *upper = XK_ENG;
+       else if (sym >= XK_Amacron && sym <= XK_Umacron)
+           *lower += (XK_amacron - XK_Amacron);
+       else if (sym >= XK_amacron && sym <= XK_umacron)
+           *upper -= (XK_amacron - XK_Amacron);
+       break;
+    case 6: /* Cyrillic */
+       /* Assume the KeySym is a legal value (ignore discontinuities) */
+       if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE)
+           *lower -= (XK_Serbian_DJE - XK_Serbian_dje);
+       else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze)
+           *upper += (XK_Serbian_DJE - XK_Serbian_dje);
+       else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN)
+           *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu);
+       else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign)
+           *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu);
+        break;
+    case 7: /* Greek */
+       /* Assume the KeySym is a legal value (ignore discontinuities) */
+       if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent)
+           *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
+       else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent &&
+                sym != XK_Greek_iotaaccentdieresis &&
+                sym != XK_Greek_upsilonaccentdieresis)
+           *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
+       else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA)
+           *lower += (XK_Greek_alpha - XK_Greek_ALPHA);
+       else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega &&
+                sym != XK_Greek_finalsmallsigma)
+           *upper -= (XK_Greek_alpha - XK_Greek_ALPHA);
+        break;
+    }
+}
+
+static KeySym KeyCodetoKeySym(KeySymsPtr keymap, int keycode, int col)
+{
+  register int per = keymap->mapWidth;
+  register KeySym *syms;
+  KeySym lsym, usym;
+
+  if ((col < 0) || ((col >= per) && (col > 3)) ||
+      (keycode < keymap->minKeyCode) || (keycode > keymap->maxKeyCode))
+    return NoSymbol;
+
+  syms = &keymap->map[(keycode - keymap->minKeyCode) * per];
+  if (col < 4) {
+    if (col > 1) {
+      while ((per > 2) && (syms[per - 1] == NoSymbol))
+        per--;
+      if (per < 3)
+        col -= 2;
+    }
+    if ((per <= (col|1)) || (syms[col|1] == NoSymbol)) {
+      XConvertCase(syms[col&~1], &lsym, &usym);
+      if (!(col & 1))
+        return lsym;
+      // I'm commenting out this logic because it's incorrect even though it
+      // was copied from the Xlib sources.  The X protocol book quite clearly
+      // states that where a group consists of element 1 being a non-alphabetic
+      // keysym and element 2 being NoSymbol that you treat the second element
+      // as being the same as the first.  This also tallies with the behaviour
+      // produced by the installed Xlib on my linux box (I believe this is
+      // because it uses some XKB code rather than the original Xlib code -
+      // compare XKBBind.c with KeyBind.c in lib/X11).
+      // else if (usym == lsym)
+      //   return NoSymbol;
+      else
+        return usym;
+    }
+  }
+  return syms[col];
+}
+
+// KeysymToKeycode() - find the keycode and column corresponding to the given
+// keysym.  The value of col passed in should be the column determined from the
+// current shift state.  If the keysym can be found in that column we prefer
+// that to finding it in a different column (which would require fake events to
+// alter the shift state).
+
+static KeyCode KeysymToKeycode(KeySymsPtr keymap, KeySym ks, int* col)
+{
+  register int i, j;
+
+  j = *col;
+  for (i = keymap->minKeyCode; i <= keymap->maxKeyCode; i++) {
+    if (KeyCodetoKeySym(keymap, i, j) == ks)
+      return i;
+  }
+
+  for (j = 0; j < keymap->mapWidth; j++) {
+    for (i = keymap->minKeyCode; i <= keymap->maxKeyCode; i++) {
+      if (KeyCodetoKeySym(keymap, i, j) == ks) {
+        *col = j;
+        return i;
+      }
+    }
+  }
+  return 0;
+}
diff --git a/unix/xserver/hw/vnc/XserverDesktop.h b/unix/xserver/hw/vnc/XserverDesktop.h
new file mode 100644 (file)
index 0000000..880acc2
--- /dev/null
@@ -0,0 +1,130 @@
+/* Copyright (C) 2002-2005 RealVNC Ltd.  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.
+ */
+//
+// XserverDesktop.h
+//
+
+#ifndef __XSERVERDESKTOP_H__
+#define __XSERVERDESKTOP_H__
+
+#include <rfb/SDesktop.h>
+#include <rfb/HTTPServer.h>
+#include <rfb/PixelBuffer.h>
+#include <rfb/Configuration.h>
+#include <rfb/VNCServerST.h>
+#include <rdr/SubstitutingInStream.h>
+
+extern "C" {
+#define class c_class;
+#include <scrnintstr.h>
+#include <os.h>
+#undef class
+}
+
+namespace rfb {
+  class VNCServerST;
+}
+
+namespace network { class TcpListener; class Socket; }
+
+class XserverDesktop : public rfb::SDesktop, public rfb::FullFramePixelBuffer,
+                       public rfb::ColourMap, public rdr::Substitutor,
+                       public rfb::VNCServerST::QueryConnectionHandler {
+public:
+
+  XserverDesktop(ScreenPtr pScreen, network::TcpListener* listener,
+                 network::TcpListener* httpListener_,
+                 const char* name, void* fbptr);
+  virtual ~XserverDesktop();
+
+  // methods called from X server code
+  void serverReset(ScreenPtr pScreen);
+  void setColormap(ColormapPtr cmap);
+  void setColourMapEntries(ColormapPtr pColormap, int ndef, xColorItem* pdef);
+  void bell();
+  void serverCutText(const char* str, int len);
+  void setCursor(CursorPtr cursor);
+  void add_changed(RegionPtr reg);
+  void add_copied(RegionPtr dst, int dx, int dy);
+  void positionCursor();
+  void ignoreHooks(bool b) { ignoreHooks_ = b; }
+  void blockHandler(fd_set* fds);
+  void wakeupHandler(fd_set* fds, int nfds);
+  void addClient(network::Socket* sock, bool reverse);
+  void disconnectClients();
+
+  // QueryConnect methods called from X server code
+  // getQueryTimeout()
+  //   Returns the timeout associated with a particular
+  //   connection, identified by an opaque Id passed to the
+  //   X code earlier.  Also optionally gets the address and
+  //   name associated with that connection.
+  //   Returns zero if the Id is not recognised.
+  int getQueryTimeout(void* opaqueId,
+                      const char** address=0,
+                      const char** username=0);
+
+  // approveConnection()
+  //   Used by X server code to supply the result of a query.
+  void approveConnection(void* opaqueId, bool accept,
+                         const char* rejectMsg=0);
+
+  // rfb::SDesktop callbacks
+  virtual void pointerEvent(const rfb::Point& pos, int buttonMask);
+  virtual void keyEvent(rdr::U32 key, bool down);
+  virtual void clientCutText(const char* str, int len);
+  virtual rfb::Point getFbSize() { return rfb::Point(width(), height()); }
+
+  // rfb::PixelBuffer callbacks
+  virtual void grabRegion(const rfb::Region& r);
+
+  // rfb::ColourMap callbacks
+  virtual void lookup(int index, int* r, int* g, int* b);
+
+  // rdr::Substitutor callback
+  virtual char* substitute(const char* varName);
+
+  // rfb::VNCServerST::QueryConnectionHandler callback
+  virtual rfb::VNCServerST::queryResult queryConnection(network::Socket* sock,
+                                                        const char* userName,
+                                                        char** reason);
+
+private:
+  void setColourMapEntries(int firstColour, int nColours);
+  static CARD32 deferredUpdateTimerCallback(OsTimerPtr timer, CARD32 now,
+                                            pointer arg);
+  void deferUpdate();
+  ScreenPtr pScreen;
+  OsTimerPtr deferredUpdateTimer, dummyTimer;
+  rfb::VNCServerST* server;
+  rfb::HTTPServer* httpServer;
+  network::TcpListener* listener;
+  network::TcpListener* httpListener;
+  ColormapPtr cmap;
+  bool deferredUpdateTimerSet;
+  bool grabbing;
+  bool ignoreHooks_;
+  bool directFbptr;
+  int oldButtonMask;
+  rfb::Point cursorPos, oldCursorPos;
+
+  void* queryConnectId;
+  rfb::CharArray queryConnectAddress;
+  rfb::CharArray queryConnectUsername;
+};
+#endif
diff --git a/unix/xserver/hw/vnc/Xvnc.man b/unix/xserver/hw/vnc/Xvnc.man
new file mode 100644 (file)
index 0000000..94a2786
--- /dev/null
@@ -0,0 +1,284 @@
+.TH Xvnc 1 "17 Apr 2006" "TightVNC" "Virtual Network Computing"
+.SH NAME
+Xvnc \- the X VNC server 
+.SH SYNOPSIS
+.B Xvnc
+.RI [ options ] 
+.RI : display#
+.SH DESCRIPTION
+.B Xvnc
+is the X VNC (Virtual Network Computing) server.  It is based on a standard X
+server, but it has a "virtual" screen rather than a physical one.  X
+applications display themselves on it as if it were a normal X display, but
+they can only be accessed via a VNC viewer - see \fBvncviewer\fP(1).
+
+So Xvnc is really two servers in one. To the applications it is an X server,
+and to the remote VNC users it is a VNC server. By convention we have arranged
+that the VNC server display number will be the same as the X server display
+number, which means you can use eg. snoopy:2 to refer to display 2 on machine
+"snoopy" in both the X world and the VNC world.
+
+The best way of starting \fBXvnc\fP is via the \fBvncserver\fP script.  This
+sets up the environment appropriately and runs some X applications to get you
+going.  See the manual page for \fBvncserver\fP(1) for more information.
+
+.SH OPTIONS
+.B Xvnc
+takes lots of options - running \fBXvnc -help\fP gives a list.  Many of these
+are standard X server options, which are described in the \fBXserver\fP(1)
+manual page.  In addition to options which can only be set via the
+command-line, there are also "parameters" which can be set both via the
+command-line and through the \fBvncconfig\fP(1) program.
+
+.TP
+.B \-geometry \fIwidth\fPx\fIheight\fP
+Specify the size of the desktop to be created. Default is 1024x768.
+
+.TP
+.B \-depth \fIdepth\fP
+Specify the pixel depth in bits of the desktop to be created. Default is 16,
+other possible values are 8, 15, and 24 - anything else is likely to cause
+strange behaviour by applications.
+
+.TP
+.B \-pixelformat \fIformat\fP
+Specify pixel format for server to use (BGRnnn or RGBnnn).  The default for
+depth 8 is BGR233 (meaning the most significant two bits represent blue, the
+next three green, and the least significant three represent red), the default
+for depth 16 is RGB565 and for depth 24 is RGB888.
+
+.TP
+.B \-cc 3
+As an alternative to the default TrueColor visual, this allows you to run an
+Xvnc server with a PseudoColor visual (i.e. one which uses a color map or
+palette), which can be useful for running some old X applications which only
+work on such a display.  Values other than 3 (PseudoColor) and 4 (TrueColor)
+for the \-cc option may result in strange behaviour, and PseudoColor desktops
+must be 8 bits deep (i.e. \fB-depth 8\fP).
+
+.TP
+.B \-inetd 
+This significantly changes Xvnc's behaviour so that it can be launched from
+inetd.  See the section below on usage with inetd.
+
+.TP
+.B \-help
+List all the options and parameters
+
+.SH PARAMETERS
+VNC parameters can be set both via the command-line and through the
+\fBvncconfig\fP(1) program, and with a VNC-enabled XFree86 server via Options
+entries in the XF86Config file.
+
+Parameters can be turned on with -\fIparam\fP or off with
+-\fIparam\fP=0.  Parameters which take a value can be specified as
+-\fIparam\fP \fIvalue\fP.  Other valid forms are \fIparam\fP\fB=\fP\fIvalue\fP
+-\fIparam\fP=\fIvalue\fP --\fIparam\fP=\fIvalue\fP.  Parameter names are
+case-insensitive.
+
+.TP
+.B \-desktop \fIdesktop-name\fP
+Each desktop has a name which may be displayed by the viewer. It defaults to
+"x11".
+
+.TP
+.B \-rfbport \fIport\fP
+Specifies the TCP port on which Xvnc listens for connections from viewers (the
+protocol used in VNC is called RFB - "remote framebuffer").  The default is
+5900 plus the display number.
+
+.TP
+.B \-rfbwait \fItime\fP, \-ClientWaitTimeMillis \fItime\fP
+
+Time in milliseconds to wait for a viewer which is blocking Xvnc.  This is
+necessary because Xvnc is single-threaded and sometimes blocks until the viewer
+has finished sending or receiving a message - note that this does not mean an
+update will be aborted after this time.  Default is 20000 (20 seconds).
+
+.TP
+.B \-httpd \fIdirectory\fP
+Run a mini-HTTP server which serves files from the given directory.  Normally
+the directory will contain the classes for the Java viewer.  In addition, files
+with a .vnc extension will have certain substitutions made so that a single
+installation of the Java VNC viewer can be served by separate instances of
+Xvnc.
+
+.TP
+.B \-httpPort \fIport\fP
+Specifies the port on which the mini-HTTP server runs.  Default is 5800 plus
+the display number.
+
+.TP
+.B \-rfbauth \fIpasswd-file\fP, \-PasswordFile \fIpasswd-file\fP
+Specifies the file containing the password used to authenticate viewers.  The
+file is accessed each time a connection comes in, so it can be changed on the
+fly via \fBvncpasswd\fP(1).
+
+.TP
+.B \-deferUpdate \fItime\fP
+Xvnc uses a "deferred update" mechanism which enhances performance in many
+cases. After any change to the framebuffer, Xvnc waits for this number of
+milliseconds (default 40) before sending an update to any waiting clients. This
+means that more changes tend to get coalesced together in a single
+update. Setting it to 0 results in the same behaviour as earlier versions of
+Xvnc, where the first change to the framebuffer causes an immediate update to
+any waiting clients.
+
+.TP
+.B \-SendCutText
+Send clipboard changes to clients (default is on).  Note that you must also run
+\fBvncconfig\fP(1) to get the clipboard to work.
+
+.TP
+.B \-AcceptCutText
+Accept clipboard updates from clients (default is on).  Note that you must also
+run \fBvncconfig\fP(1) to get the clipboard to work.
+
+.TP
+.B \-AcceptPointerEvents
+Accept pointer press and release events from clients (default is on).
+
+.TP
+.B \-AcceptKeyEvents
+Accept key press and release events from clients (default is on).
+
+.TP
+.B \-DisconnectClients
+Disconnect existing clients if an incoming connection is non-shared (default is
+on). If \fBDisconnectClients\fP is false, then a new non-shared connection will
+be refused while there is a client active.  When combined with
+\fBNeverShared\fP this means only one client is allowed at a time.
+
+.TP
+.B \-NeverShared
+Never treat incoming connections as shared, regardless of the client-specified
+setting (default is off).
+
+.TP
+.B \-AlwaysShared
+Always treat incoming connections as shared, regardless of the client-specified
+setting (default is off).
+
+.TP
+.B \-Protocol3.3
+Always use protocol version 3.3 for backwards compatibility with badly-behaved
+clients (default is off).
+
+.TP
+.B \-CompareFB
+Perform pixel comparison on framebuffer to reduce unnecessary updates (default
+is on).
+
+.TP
+.B \-SecurityTypes \fIsec-types\fP
+Specify which security schemes to use separated by commas.  At present only
+"None" and "VncAuth" are supported.  The default is "VncAuth" - note that if
+you want a server which does not require a password, you must set this
+parameter to "None".
+
+.TP
+.B \-IdleTimeout \fIseconds\fP
+The number of seconds after which an idle VNC connection will be dropped
+(default is 0, which means that idle connections will never be dropped).
+
+.TP
+.B \-QueryConnect
+Prompts the user of the desktop to explicitly accept or reject incoming
+connections.  This is most useful when using the vnc.so module or
+\fBx0vncserver\fP(1) program to access an existing X desktop via VNC.
+
+The \fBvncconfig\fP(1) program must be running on the desktop in order for
+QueryConnect to be supported by the \fBvnc.so\fP(1) module or
+\fBXvnc\fP(1) program.  The \fBx0vncserver\fP(1) program does not require
+\fBvncconfig\fP(1) to be running.
+
+.TP
+.B \-localhost
+Only allow connections from the same machine. Useful if you use SSH and want to
+stop non-SSH connections from any other hosts. See the guide to using VNC with
+SSH on the web site.
+
+.TP
+.B \-log \fIlogname\fP:\fIdest\fP:\fIlevel\fP
+Configures the debug log settings.  \fIdest\fP can currently be \fBstderr\fP or
+\fBstdout\fP, and \fIlevel\fP is between 0 and 100, 100 meaning most verbose
+output.  \fIlogname\fP is usually \fB*\fP meaning all, but you can target a
+specific source file if you know the name of its "LogWriter".  Default is
+\fB*:stderr:30\fP.
+
+.TP
+.B \-RemapKeys \fImapping
+Sets up a keyboard mapping.
+.I mapping
+is a comma-separated string of character mappings, each of the form
+.IR char -> char ,
+or
+.IR char <> char ,
+where
+.I char
+is a hexadecimal keysym. For example, to exchange the " and @ symbols you would specify the following:
+.IP "" 10
+RemapKeys=0x22<>0x40
+
+.SH USAGE WITH INETD
+By configuring the \fBinetd\fP(1) service appropriately, Xvnc can be launched
+on demand when a connection comes in, rather than having to be started
+manually.  When given the \fB-inetd\fP option, instead of listening for TCP
+connections on a given port it uses its standard input and standard output.
+There are two modes controlled by the wait/nowait entry in the inetd.conf file.
+
+In the nowait mode, Xvnc uses its standard input and output directly as the
+connection to a viewer.  It never has a listening socket, so cannot accept
+further connections from viewers (it can however connect out to listening
+viewers by use of the vncconfig program).  Further viewer connections to the
+same TCP port result in inetd spawning off a new Xvnc to deal with each
+connection.  When the connection to the viewer dies, the Xvnc and any
+associated X clients die.  This behaviour is most useful when combined with the
+XDMCP options -query and -once.  An typical example in inetd.conf might be (all
+on one line):
+
+5950   stream   tcp nowait nobody  /usr/local/bin/Xvnc Xvnc -inetd -query
+localhost -once securitytypes=none
+
+In this example a viewer connection to :50 will result in a new Xvnc for that
+connection which should display the standard XDM login screen on that machine.
+Because the user needs to login via XDM, it is usually OK to accept connections
+without a VNC password in this case.
+
+In the wait mode, when the first connection comes in, inetd gives the listening
+socket to Xvnc.  This means that for a given TCP port, there is only ever one
+Xvnc at a time.  Further viewer connections to the same port are accepted by
+the same Xvnc in the normal way.  Even when the original connection is broken,
+the Xvnc will continue to run.  If this is used with the XDMCP options -query
+and -once, the Xvnc and associated X clients will die when the user logs out of
+the X session in the normal way.  It is important to use a VNC password in this
+case.  A typical entry in inetd.conf might be:
+
+5951   stream   tcp wait   james     /usr/local/bin/Xvnc Xvnc -inetd -query localhost -once passwordFile=/home/james/.vnc/passwd
+
+In fact typically, you would have one entry for each user who uses VNC
+regularly, each of whom has their own dedicated TCP port which they use.  In
+this example, when user "james" connects to :51, he enters his VNC password,
+then gets the XDM login screen where he logs in in the normal way.  However,
+unlike the previous example, if he disconnects, the session remains persistent,
+and when he reconnects he will get the same session back again.  When he logs
+out of the X session, the Xvnc will die, but of course a new one will be
+created automatically the next time he connects.
+
+.SH SEE ALSO
+.BR vncconfig (1),
+.BR vncpasswd (1),
+.BR vncserver (1),
+.BR vncviewer (1),
+.BR Xserver (1),
+.BR inetd (1)
+.br
+http://www.tightvnc.com
+
+.SH AUTHOR
+Tristan Richardson, RealVNC Ltd.
+
+VNC was originally developed by the RealVNC team while at Olivetti
+Research Ltd / AT&T Laboratories Cambridge.  TightVNC additions were
+implemented by Constantin Kaplinsky. Many other people participated in
+development, testing and support.
diff --git a/unix/xserver/hw/vnc/buildtime.c b/unix/xserver/hw/vnc/buildtime.c
new file mode 100644 (file)
index 0000000..3f4c369
--- /dev/null
@@ -0,0 +1,18 @@
+/* Copyright (C) 2002-2005 RealVNC Ltd.  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.
+ */
+char buildtime[] = __DATE__ " " __TIME__;
diff --git a/unix/xserver/hw/vnc/vncExtInit.cc b/unix/xserver/hw/vnc/vncExtInit.cc
new file mode 100644 (file)
index 0000000..9cf9d21
--- /dev/null
@@ -0,0 +1,866 @@
+/* Copyright (C) 2002-2005 RealVNC Ltd.  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>
+
+extern "C" {
+#define class c_class
+#define NEED_EVENTS
+#include "X.h"
+#include "Xproto.h"
+#include "misc.h"
+#include "os.h"
+#include "dixstruct.h"
+#include "extnsionst.h"
+#include "scrnintstr.h"
+#include "selection.h"
+#define _VNCEXT_SERVER_
+#define _VNCEXT_PROTO_
+#include "vncExt.h"
+#undef class
+#undef xalloc
+}
+
+#include <rfb/Configuration.h>
+#include <rfb/Logger_stdio.h>
+#include <rfb/LogWriter.h>
+#include <rfb/util.h>
+#include <rfb/ServerCore.h>
+#include <rfb/SSecurityFactoryStandard.h>
+#include <rdr/HexOutStream.h>
+#include <rfb/LogWriter.h>
+#undef max
+#undef min
+#include <network/TcpSocket.h>
+
+#include "XserverDesktop.h"
+#include "vncHooks.h"
+#include "vncExtInit.h"
+
+extern "C" {
+
+  extern void vncExtensionInit();
+  static void vncResetProc(ExtensionEntry* extEntry);
+  static void vncBlockHandler(pointer data, OSTimePtr t, pointer readmask);
+  static void vncWakeupHandler(pointer data, int nfds, pointer readmask);
+  static void vncClientStateChange(CallbackListPtr*, pointer, pointer);
+  static void SendSelectionChangeEvent(Atom selection);
+  static int ProcVncExtDispatch(ClientPtr client);
+  static int SProcVncExtDispatch(ClientPtr client);
+
+  extern char *display;
+
+  extern Selection *CurrentSelections;
+  extern int NumCurrentSelections;
+}
+
+using namespace rfb;
+
+static rfb::LogWriter vlog("vncext");
+
+static unsigned long vncExtGeneration = 0;
+static bool initialised = false;
+static XserverDesktop* desktop[MAXSCREENS] = { 0, };
+void* vncFbptr[MAXSCREENS] = { 0, };
+
+static char* clientCutText = 0;
+static int clientCutTextLen = 0;
+
+static XserverDesktop* queryConnectDesktop = 0;
+static void* queryConnectId = 0;
+static int queryConnectTimeout = 0;
+static OsTimerPtr queryConnectTimer = 0;
+
+static struct VncInputSelect* vncInputSelectHead = 0;
+struct VncInputSelect {
+  VncInputSelect(ClientPtr c, Window w, int m) : client(c), window(w), mask(m)
+  {
+    next = vncInputSelectHead;
+    vncInputSelectHead = this;
+  }
+  ClientPtr client;
+  Window window;
+  int mask;
+  VncInputSelect* next;
+};
+
+static int nPrevSelections = 0;
+static TimeStamp* prevSelectionTimes = 0;
+
+static int vncErrorBase = 0;
+static int vncEventBase = 0;
+static char* vncPasswdFile = 0;
+int vncInetdSock = -1;
+
+rfb::AliasParameter rfbauth("rfbauth", "Alias for PasswordFile",
+                            &SSecurityFactoryStandard::vncAuthPasswdFile);
+rfb::StringParameter httpDir("httpd",
+                             "Directory containing files to serve via HTTP",
+                             "");
+rfb::IntParameter httpPort("httpPort", "TCP port to listen for HTTP",0);
+rfb::AliasParameter rfbwait("rfbwait", "Alias for ClientWaitTimeMillis",
+                            &rfb::Server::clientWaitTimeMillis);
+rfb::IntParameter rfbport("rfbport", "TCP port to listen for RFB protocol",0);
+rfb::StringParameter desktopName("desktop", "Name of VNC desktop","x11");
+rfb::BoolParameter localhostOnly("localhost",
+                                 "Only allow connections from localhost",
+                                 false);
+
+void vncExtensionInit()
+{
+  if (vncExtGeneration == serverGeneration) {
+    vlog.error("vncExtensionInit: called twice in same generation?");
+    return;
+  }
+  vncExtGeneration = serverGeneration;
+
+  ExtensionEntry* extEntry
+    = AddExtension(VNCEXTNAME, VncExtNumberEvents, VncExtNumberErrors,
+                   ProcVncExtDispatch, SProcVncExtDispatch, vncResetProc,
+                   StandardMinorOpcode);
+  if (!extEntry) {
+    ErrorF("vncExtInit: AddExtension failed\n");
+    return;
+  }
+
+  vncErrorBase = extEntry->errorBase;
+  vncEventBase = extEntry->eventBase;
+
+  vlog.info("VNC extension running!");
+
+  if (!AddCallback(&ClientStateCallback, vncClientStateChange, 0)) {
+    FatalError("AddCallback failed\n");
+  }
+
+  try {
+    if (!initialised) {
+      rfb::initStdIOLoggers();
+      initialised = true;
+    }
+
+    for (int scr = 0; scr < screenInfo.numScreens; scr++) {
+
+      if (!desktop[scr]) {
+        network::TcpListener* listener = 0;
+        network::TcpListener* httpListener = 0;
+        if (scr == 0 && vncInetdSock != -1) {
+          if (network::TcpSocket::isSocket(vncInetdSock) &&
+              !network::TcpSocket::isConnected(vncInetdSock))
+          {
+            listener = new network::TcpListener(0, 0, vncInetdSock, true);
+            vlog.info("inetd wait");
+          }
+        } else {
+          int port = rfbport;
+          if (port == 0) port = 5900 + atoi(display);
+          port += 1000 * scr;
+          listener = new network::TcpListener(port, localhostOnly);
+          vlog.info("Listening for VNC connections on port %d",port);
+          CharArray httpDirStr(httpDir.getData());
+          if (httpDirStr.buf[0]) {
+            port = httpPort;
+            if (port == 0) port = 5800 + atoi(display);
+            port += 1000 * scr;
+            httpListener = new network::TcpListener(port, localhostOnly);
+            vlog.info("Listening for HTTP connections on port %d",port);
+          }
+        }
+
+        CharArray desktopNameStr(desktopName.getData());
+        desktop[scr] = new XserverDesktop(screenInfo.screens[scr], listener,
+                                          httpListener,
+                                          desktopNameStr.buf,
+                                          vncFbptr[scr]);
+        vlog.info("created VNC server for screen %d", scr);
+
+        if (scr == 0 && vncInetdSock != -1 && !listener) {
+          network::Socket* sock = new network::TcpSocket(vncInetdSock);
+          desktop[scr]->addClient(sock, false);
+          vlog.info("added inetd sock");
+        }
+
+      } else {
+        desktop[scr]->serverReset(screenInfo.screens[scr]);
+      }
+
+      vncHooksInit(screenInfo.screens[scr], desktop[scr]);
+    }
+
+    RegisterBlockAndWakeupHandlers(vncBlockHandler, vncWakeupHandler, 0);
+
+  } catch (rdr::Exception& e) {
+    vlog.error("vncExtInit: %s",e.str());
+  }
+}
+
+static void vncResetProc(ExtensionEntry* extEntry)
+{
+}
+
+//
+// vncBlockHandler - called just before the X server goes into select().  Call
+// on to the block handler for each desktop.  Then check whether any of the
+// selections have changed, and if so, notify any interested X clients.
+//
+
+static void vncBlockHandler(pointer data, OSTimePtr timeout, pointer readmask)
+{
+  fd_set* fds = (fd_set*)readmask;
+
+  for (int scr = 0; scr < screenInfo.numScreens; scr++) {
+    if (desktop[scr]) {
+      desktop[scr]->blockHandler(fds);
+    }
+  }
+
+  if (nPrevSelections != NumCurrentSelections) {
+    prevSelectionTimes
+      = (TimeStamp*)xnfrealloc(prevSelectionTimes,
+                               NumCurrentSelections * sizeof(TimeStamp));
+    for (int i = nPrevSelections; i < NumCurrentSelections; i++) {
+      prevSelectionTimes[i].months = 0;
+      prevSelectionTimes[i].milliseconds = 0;
+    }
+    nPrevSelections = NumCurrentSelections;
+  }
+  for (int i = 0; i < NumCurrentSelections; i++) {
+    if (CurrentSelections[i].lastTimeChanged.months
+        != prevSelectionTimes[i].months ||
+        CurrentSelections[i].lastTimeChanged.milliseconds
+        != prevSelectionTimes[i].milliseconds)
+    {
+      SendSelectionChangeEvent(CurrentSelections[i].selection);
+      prevSelectionTimes[i] = CurrentSelections[i].lastTimeChanged;
+    }
+  }
+}
+
+static void vncWakeupHandler(pointer data, int nfds, pointer readmask)
+{
+  fd_set* fds = (fd_set*)readmask;
+
+  for (int scr = 0; scr < screenInfo.numScreens; scr++) {
+    if (desktop[scr]) {
+      desktop[scr]->wakeupHandler(fds, nfds);
+    }
+  }
+}
+
+static void vncClientStateChange(CallbackListPtr*, pointer, pointer p)
+{
+  ClientPtr client = ((NewClientInfoRec*)p)->client;
+  if (client->clientState == ClientStateGone) {
+    VncInputSelect** nextPtr = &vncInputSelectHead;
+    for (VncInputSelect* cur = vncInputSelectHead; cur; cur = *nextPtr) {
+      if (cur->client == client) {
+        *nextPtr = cur->next;
+        delete cur;
+        continue;
+      }
+      nextPtr = &cur->next;
+    }
+  }
+}
+
+void vncBell()
+{
+  for (int scr = 0; scr < screenInfo.numScreens; scr++) {
+    if (desktop[scr]) {
+      desktop[scr]->bell();
+    }
+  }
+}
+
+void vncClientGone(int fd)
+{
+  if (fd == vncInetdSock) {
+    fprintf(stderr,"inetdSock client gone\n");
+    GiveUp(0);
+  }
+}
+
+void vncClientCutText(const char* str, int len)
+{
+  delete [] clientCutText;
+  clientCutText = new char[len];
+  memcpy(clientCutText, str, len);
+  clientCutTextLen = len;
+  xVncExtClientCutTextNotifyEvent ev;
+  ev.type = vncEventBase + VncExtClientCutTextNotify;
+  for (VncInputSelect* cur = vncInputSelectHead; cur; cur = cur->next) {
+    if (cur->mask & VncExtClientCutTextMask) {
+      ev.sequenceNumber = cur->client->sequence;
+      ev.window = cur->window;
+      ev.time = GetTimeInMillis();
+      if (cur->client->swapped) {
+        int n;
+        swaps(&ev.sequenceNumber, n);
+        swapl(&ev.window, n);
+        swapl(&ev.time, n);
+      }
+      WriteToClient(cur->client, sizeof(xVncExtClientCutTextNotifyEvent),
+                    (char *)&ev);
+    }
+  }
+}
+
+
+static CARD32 queryConnectTimerCallback(OsTimerPtr timer,
+                                        CARD32 now, pointer arg)
+{
+  if (queryConnectTimeout)
+    queryConnectDesktop->approveConnection(queryConnectId, false, "The attempt to prompt the user to accept the connection failed");
+  // Re-notify clients, causing them to discover that we're done
+  vncQueryConnect(queryConnectDesktop, queryConnectId);
+  return 0;
+}
+
+void vncQueryConnect(XserverDesktop* desktop, void* opaqueId)
+{
+  // Only one query can be processed at any one time
+  if (queryConnectTimeout && ((desktop != queryConnectDesktop) ||
+                              (opaqueId != queryConnectId))) {
+    desktop->approveConnection(opaqueId, false,
+                               "Another connection is currently being queried.");
+    return;
+  }
+
+  // Get the query timeout.  If it's zero, there is no query.
+  queryConnectTimeout = desktop->getQueryTimeout(opaqueId);
+  queryConnectId = queryConnectTimeout ? opaqueId : 0;
+  queryConnectDesktop = queryConnectTimeout ? desktop : 0;
+
+  // Notify clients
+  bool notified = false;
+  xVncExtQueryConnectNotifyEvent ev;
+  ev.type = vncEventBase + VncExtQueryConnectNotify;
+  for (VncInputSelect* cur = vncInputSelectHead; cur; cur = cur->next) {
+    if (cur->mask & VncExtQueryConnectMask) {
+      ev.sequenceNumber = cur->client->sequence;
+      ev.window = cur->window;
+      if (cur->client->swapped) {
+        int n;
+        swaps(&ev.sequenceNumber, n);
+        swapl(&ev.window, n);
+      }
+      WriteToClient(cur->client, sizeof(xVncExtQueryConnectNotifyEvent),
+                    (char *)&ev);
+      notified = true;
+    }
+  }
+
+  // If we're being asked to query a connection (rather than to cancel
+  //   a query), and haven't been able to notify clients then reject it.
+  if (queryConnectTimeout && !notified) {
+    queryConnectTimeout = 0;
+    queryConnectId = 0;
+    queryConnectDesktop = 0;
+    desktop->approveConnection(opaqueId, false,
+                               "Unable to query the local user to accept the connection.");
+    return;
+  }    
+
+  // Set a timer so that if no-one ever responds, we will eventually 
+  //   reject the connection
+  //   NB: We don't set a timer if sock is null, since that indicates
+  //       that pending queries should be cancelled.
+  if (queryConnectDesktop)
+    queryConnectTimer = TimerSet(queryConnectTimer, 0,
+                                 queryConnectTimeout*2000,
+                                 queryConnectTimerCallback, 0);
+  else
+    TimerCancel(queryConnectTimer);
+}
+
+static void SendSelectionChangeEvent(Atom selection)
+{
+  xVncExtSelectionChangeNotifyEvent ev;
+  ev.type = vncEventBase + VncExtSelectionChangeNotify;
+  for (VncInputSelect* cur = vncInputSelectHead; cur; cur = cur->next) {
+    if (cur->mask & VncExtSelectionChangeMask) {
+      ev.sequenceNumber = cur->client->sequence;
+      ev.window = cur->window;
+      ev.selection = selection;
+      if (cur->client->swapped) {
+        int n;
+        swaps(&ev.sequenceNumber, n);
+        swapl(&ev.window, n);
+        swapl(&ev.selection, n);
+      }
+      WriteToClient(cur->client, sizeof(xVncExtSelectionChangeNotifyEvent),
+                    (char *)&ev);
+    }
+  }
+}
+
+static int ProcVncExtSetParam(ClientPtr client)
+{
+  REQUEST(xVncExtSetParamReq);
+  REQUEST_FIXED_SIZE(xVncExtSetParamReq, stuff->paramLen);
+  CharArray param(stuff->paramLen+1);
+  strncpy(param.buf, (char*)&stuff[1], stuff->paramLen);
+  param.buf[stuff->paramLen] = 0;
+
+  xVncExtSetParamReply rep;
+  int n;
+  rep.type = X_Reply;
+  rep.length = 0;
+  rep.sequenceNumber = client->sequence;
+  rep.success = rfb::Configuration::setParam(param.buf);
+  if (client->swapped) {
+    swaps(&rep.sequenceNumber, n);
+    swapl(&rep.length, n);
+  }
+  WriteToClient(client, sizeof(xVncExtSetParamReply), (char *)&rep);
+  return (client->noClientException);
+}
+
+static int SProcVncExtSetParam(ClientPtr client)
+{
+  register char n;
+  REQUEST(xVncExtSetParamReq);
+  swaps(&stuff->length, n);
+  REQUEST_AT_LEAST_SIZE(xVncExtSetParamReq);
+  return ProcVncExtSetParam(client);
+}
+
+static int ProcVncExtGetParam(ClientPtr client)
+{
+  REQUEST(xVncExtGetParamReq);
+  REQUEST_FIXED_SIZE(xVncExtGetParamReq, stuff->paramLen);
+  CharArray param(stuff->paramLen+1);
+  strncpy(param.buf, (char*)&stuff[1], stuff->paramLen);
+  param.buf[stuff->paramLen] = 0;
+
+  xVncExtGetParamReply rep;
+  int n;
+  rep.type = X_Reply;
+  rep.sequenceNumber = client->sequence;
+  rep.success = 0;
+  int len = 0;
+  char* value = 0;
+  rfb::VoidParameter* p = rfb::Configuration::getParam(param.buf);
+  // Hack to avoid exposing password!
+  if (strcasecmp(param.buf, "Password") == 0)
+    p = 0;
+  if (p) {
+    value = p->getValueStr();
+    rep.success = 1;
+    len = value ? strlen(value) : 0;
+  }
+  rep.length = (len + 3) >> 2;
+  rep.valueLen = len;
+  if (client->swapped) {
+    swaps(&rep.sequenceNumber, n);
+    swapl(&rep.length, n);
+    swaps(&rep.valueLen, n);
+  }
+  WriteToClient(client, sizeof(xVncExtGetParamReply), (char *)&rep);
+  if (value)
+    WriteToClient(client, len, value);
+  delete [] value;
+  return (client->noClientException);
+}
+
+static int SProcVncExtGetParam(ClientPtr client)
+{
+  register char n;
+  REQUEST(xVncExtGetParamReq);
+  swaps(&stuff->length, n);
+  REQUEST_AT_LEAST_SIZE(xVncExtGetParamReq);
+  return ProcVncExtGetParam(client);
+}
+
+static int ProcVncExtGetParamDesc(ClientPtr client)
+{
+  REQUEST(xVncExtGetParamDescReq);
+  REQUEST_FIXED_SIZE(xVncExtGetParamDescReq, stuff->paramLen);
+  CharArray param(stuff->paramLen+1);
+  strncpy(param.buf, (char*)&stuff[1], stuff->paramLen);
+  param.buf[stuff->paramLen] = 0;
+
+  xVncExtGetParamDescReply rep;
+  int n;
+  rep.type = X_Reply;
+  rep.sequenceNumber = client->sequence;
+  rep.success = 0;
+  int len = 0;
+  const char* desc = 0;
+  rfb::VoidParameter* p = rfb::Configuration::getParam(param.buf);
+  if (p) {
+    desc = p->getDescription();
+    rep.success = 1;
+    len = desc ? strlen(desc) : 0;
+  }
+  rep.length = (len + 3) >> 2;
+  rep.descLen = len;
+  if (client->swapped) {
+    swaps(&rep.sequenceNumber, n);
+    swapl(&rep.length, n);
+    swaps(&rep.descLen, n);
+  }
+  WriteToClient(client, sizeof(xVncExtGetParamDescReply), (char *)&rep);
+  if (desc)
+    WriteToClient(client, len, (char*)desc);
+  return (client->noClientException);
+}
+
+static int SProcVncExtGetParamDesc(ClientPtr client)
+{
+  register char n;
+  REQUEST(xVncExtGetParamDescReq);
+  swaps(&stuff->length, n);
+  REQUEST_AT_LEAST_SIZE(xVncExtGetParamDescReq);
+  return ProcVncExtGetParamDesc(client);
+}
+
+static int ProcVncExtListParams(ClientPtr client)
+{
+  REQUEST(xVncExtListParamsReq);
+  REQUEST_SIZE_MATCH(xVncExtListParamsReq);
+
+  xVncExtListParamsReply rep;
+  int n;
+  rep.type = X_Reply;
+  rep.sequenceNumber = client->sequence;
+
+  int nParams = 0;
+  int len = 0;
+  for (ParameterIterator i(Configuration::global()); i.param; i.next()) {
+    int l = strlen(i.param->getName());
+    if (l <= 255) {
+      nParams++;
+      len += l + 1;
+    }
+  }
+  rep.length = (len + 3) >> 2;
+  rep.nParams = nParams;
+  if (client->swapped) {
+    swaps(&rep.sequenceNumber, n);
+    swapl(&rep.length, n);
+    swaps(&rep.nParams, n);
+  }
+  WriteToClient(client, sizeof(xVncExtListParamsReply), (char *)&rep);
+  rdr::U8* data = new rdr::U8[len];
+  rdr::U8* ptr = data;
+  for (ParameterIterator i(Configuration::global()); i.param; i.next()) {
+    int l = strlen(i.param->getName());
+    if (l <= 255) {
+      *ptr++ = l;
+      memcpy(ptr, i.param->getName(), l);
+      ptr += l;
+    }
+  }
+  WriteToClient(client, len, (char*)data);
+  delete [] data;
+  return (client->noClientException);
+}
+
+static int SProcVncExtListParams(ClientPtr client)
+{
+  register char n;
+  REQUEST(xVncExtListParamsReq);
+  swaps(&stuff->length, n);
+  REQUEST_SIZE_MATCH(xVncExtListParamsReq);
+  return ProcVncExtListParams(client);
+}
+
+static int ProcVncExtSetServerCutText(ClientPtr client)
+{
+  REQUEST(xVncExtSetServerCutTextReq);
+  REQUEST_FIXED_SIZE(xVncExtSetServerCutTextReq, stuff->textLen);
+  char* str = new char[stuff->textLen+1];
+  strncpy(str, (char*)&stuff[1], stuff->textLen);
+  str[stuff->textLen] = 0;
+  for (int scr = 0; scr < screenInfo.numScreens; scr++) {
+    if (desktop[scr]) {
+      desktop[scr]->serverCutText(str, stuff->textLen);
+    }
+  }
+  delete [] str;
+  return (client->noClientException);
+}
+
+static int SProcVncExtSetServerCutText(ClientPtr client)
+{
+  register char n;
+  REQUEST(xVncExtSetServerCutTextReq);
+  swaps(&stuff->length, n);
+  REQUEST_AT_LEAST_SIZE(xVncExtSetServerCutTextReq);
+  swapl(&stuff->textLen, n);
+  return ProcVncExtSetServerCutText(client);
+}
+
+static int ProcVncExtGetClientCutText(ClientPtr client)
+{
+  REQUEST(xVncExtGetClientCutTextReq);
+  REQUEST_SIZE_MATCH(xVncExtGetClientCutTextReq);
+
+  xVncExtGetClientCutTextReply rep;
+  int n;
+  rep.type = X_Reply;
+  rep.length = (clientCutTextLen + 3) >> 2;
+  rep.sequenceNumber = client->sequence;
+  rep.textLen = clientCutTextLen;
+  if (client->swapped) {
+    swaps(&rep.sequenceNumber, n);
+    swapl(&rep.length, n);
+    swapl(&rep.textLen, n);
+  }
+  WriteToClient(client, sizeof(xVncExtGetClientCutTextReply), (char *)&rep);
+  if (clientCutText)
+    WriteToClient(client, clientCutTextLen, clientCutText);
+  return (client->noClientException);
+}
+
+static int SProcVncExtGetClientCutText(ClientPtr client)
+{
+  register char n;
+  REQUEST(xVncExtGetClientCutTextReq);
+  swaps(&stuff->length, n);
+  REQUEST_SIZE_MATCH(xVncExtGetClientCutTextReq);
+  return ProcVncExtGetClientCutText(client);
+}
+
+static int ProcVncExtSelectInput(ClientPtr client)
+{
+  REQUEST(xVncExtSelectInputReq);
+  REQUEST_SIZE_MATCH(xVncExtSelectInputReq);
+  VncInputSelect** nextPtr = &vncInputSelectHead;
+  VncInputSelect* cur;
+  for (cur = vncInputSelectHead; cur; cur = *nextPtr) {
+    if (cur->client == client && cur->window == stuff->window) {
+      cur->mask = stuff->mask;
+      if (!cur->mask) {
+        *nextPtr = cur->next;
+        delete cur;
+      }
+      break;
+    }
+    nextPtr = &cur->next;
+  }
+  if (!cur) {
+    cur = new VncInputSelect(client, stuff->window, stuff->mask);
+  }
+  return (client->noClientException);
+}
+
+static int SProcVncExtSelectInput(ClientPtr client)
+{
+  register char n;
+  REQUEST(xVncExtSelectInputReq);
+  swaps(&stuff->length, n);
+  REQUEST_SIZE_MATCH(xVncExtSelectInputReq);
+  swapl(&stuff->window, n);
+  swapl(&stuff->mask, n);
+  return ProcVncExtSelectInput(client);
+}
+
+static int ProcVncExtConnect(ClientPtr client)
+{
+  REQUEST(xVncExtConnectReq);
+  REQUEST_FIXED_SIZE(xVncExtConnectReq, stuff->strLen);
+  CharArray str(stuff->strLen+1);
+  strncpy(str.buf, (char*)&stuff[1], stuff->strLen);
+  str.buf[stuff->strLen] = 0;
+
+  xVncExtConnectReply rep;
+  rep.success = 0;
+  if (desktop[0]) {
+    if (stuff->strLen == 0) {
+      try {
+        desktop[0]->disconnectClients();
+        rep.success = 1;
+      } catch (rdr::Exception& e) {
+        vlog.error("Disconnecting all clients: %s",e.str());
+      }
+    } else {
+      int port = 5500;
+      for (int i = 0; i < stuff->strLen; i++) {
+        if (str.buf[i] == ':') {
+          port = atoi(&str.buf[i+1]);
+          str.buf[i] = 0;
+          break;
+        }
+      }
+
+      try {
+        network::Socket* sock = new network::TcpSocket(str.buf, port);
+        desktop[0]->addClient(sock, true);
+       rep.success = 1;
+      } catch (rdr::Exception& e) {
+        vlog.error("Reverse connection: %s",e.str());
+      }
+    }
+  }
+
+  rep.type = X_Reply;
+  rep.length = 0;
+  rep.sequenceNumber = client->sequence;
+  if (client->swapped) {
+    int n;
+    swaps(&rep.sequenceNumber, n);
+    swapl(&rep.length, n);
+  }
+  WriteToClient(client, sizeof(xVncExtConnectReply), (char *)&rep);
+  return (client->noClientException);
+}
+
+static int SProcVncExtConnect(ClientPtr client)
+{
+  register char n;
+  REQUEST(xVncExtConnectReq);
+  swaps(&stuff->length, n);
+  REQUEST_AT_LEAST_SIZE(xVncExtConnectReq);
+  return ProcVncExtConnect(client);
+}
+
+
+static int ProcVncExtGetQueryConnect(ClientPtr client)
+{
+  REQUEST(xVncExtGetQueryConnectReq);
+  REQUEST_SIZE_MATCH(xVncExtGetQueryConnectReq);
+
+  const char *qcAddress=0, *qcUsername=0;
+  int qcTimeout;
+  if (queryConnectDesktop)
+    qcTimeout = queryConnectDesktop->getQueryTimeout(queryConnectId,
+                                                     &qcAddress, &qcUsername);
+  else
+    qcTimeout = 0;
+
+  xVncExtGetQueryConnectReply rep;
+  int n;
+  rep.type = X_Reply;
+  rep.sequenceNumber = client->sequence;
+  rep.timeout = qcTimeout;
+  rep.addrLen = qcTimeout ? strlen(qcAddress) : 0;
+  rep.userLen = qcTimeout ? strlen(qcUsername) : 0;
+  rep.opaqueId = (CARD32)queryConnectId;
+  rep.length = (rep.userLen + rep.addrLen + 3) >> 2;
+  if (client->swapped) {
+    swaps(&rep.sequenceNumber, n);
+    swapl(&rep.userLen, n);
+    swapl(&rep.addrLen, n);
+    swapl(&rep.timeout, n);
+    swapl(&rep.opaqueId, n);
+  }
+  WriteToClient(client, sizeof(xVncExtGetQueryConnectReply), (char *)&rep);
+  if (qcTimeout)
+    WriteToClient(client, strlen(qcAddress), (char*)qcAddress);
+  if (qcTimeout)
+    WriteToClient(client, strlen(qcUsername), (char*)qcUsername);
+  return (client->noClientException);
+}
+
+static int SProcVncExtGetQueryConnect(ClientPtr client)
+{
+  register char n;
+  REQUEST(xVncExtGetQueryConnectReq);
+  swaps(&stuff->length, n);
+  REQUEST_SIZE_MATCH(xVncExtGetQueryConnectReq);
+  return ProcVncExtGetQueryConnect(client);
+}
+
+
+static int ProcVncExtApproveConnect(ClientPtr client)
+{
+  REQUEST(xVncExtApproveConnectReq);
+  REQUEST_SIZE_MATCH(xVncExtApproveConnectReq);
+  if (queryConnectId == (void*)stuff->opaqueId) {
+    for (int scr = 0; scr < screenInfo.numScreens; scr++) {
+      if (desktop[scr]) {
+        desktop[scr]->approveConnection(queryConnectId, stuff->approve,
+                                        "Connection rejected by local user");
+      }
+    }
+    // Inform other clients of the event and tidy up
+    vncQueryConnect(queryConnectDesktop, queryConnectId);
+  }
+  return (client->noClientException);
+}
+
+static int SProcVncExtApproveConnect(ClientPtr client)
+{
+  register char n;
+  REQUEST(xVncExtApproveConnectReq);
+  swaps(&stuff->length, n);
+  swapl(&stuff->opaqueId, n);
+  REQUEST_SIZE_MATCH(xVncExtApproveConnectReq);
+  return ProcVncExtApproveConnect(client);
+}
+
+
+static int ProcVncExtDispatch(ClientPtr client)
+{
+  REQUEST(xReq);
+  switch (stuff->data) {
+  case X_VncExtSetParam:
+    return ProcVncExtSetParam(client);
+  case X_VncExtGetParam:
+    return ProcVncExtGetParam(client);
+  case X_VncExtGetParamDesc:
+    return ProcVncExtGetParamDesc(client);
+  case X_VncExtListParams:
+    return ProcVncExtListParams(client);
+  case X_VncExtSetServerCutText:
+    return ProcVncExtSetServerCutText(client);
+  case X_VncExtGetClientCutText:
+    return ProcVncExtGetClientCutText(client);
+  case X_VncExtSelectInput:
+    return ProcVncExtSelectInput(client);
+  case X_VncExtConnect:
+    return ProcVncExtConnect(client);
+  case X_VncExtGetQueryConnect:
+    return ProcVncExtGetQueryConnect(client);
+  case X_VncExtApproveConnect:
+    return ProcVncExtApproveConnect(client);
+  default:
+    return BadRequest;
+  }
+}
+
+static int SProcVncExtDispatch(ClientPtr client)
+{
+  REQUEST(xReq);
+  switch (stuff->data) {
+  case X_VncExtSetParam:
+    return SProcVncExtSetParam(client);
+  case X_VncExtGetParam:
+    return SProcVncExtGetParam(client);
+  case X_VncExtGetParamDesc:
+    return SProcVncExtGetParamDesc(client);
+  case X_VncExtListParams:
+    return SProcVncExtListParams(client);
+  case X_VncExtSetServerCutText:
+    return SProcVncExtSetServerCutText(client);
+  case X_VncExtGetClientCutText:
+    return SProcVncExtGetClientCutText(client);
+  case X_VncExtSelectInput:
+    return SProcVncExtSelectInput(client);
+  case X_VncExtConnect:
+    return SProcVncExtConnect(client);
+  case X_VncExtGetQueryConnect:
+    return SProcVncExtGetQueryConnect(client);
+  case X_VncExtApproveConnect:
+    return SProcVncExtApproveConnect(client);
+  default:
+    return BadRequest;
+  }
+}
+
diff --git a/unix/xserver/hw/vnc/vncExtInit.h b/unix/xserver/hw/vnc/vncExtInit.h
new file mode 100644 (file)
index 0000000..45453e1
--- /dev/null
@@ -0,0 +1,32 @@
+/* Copyright (C) 2002-2005 RealVNC Ltd.  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.
+ */
+#ifndef __VNCEXTINIT_H__
+#define __VNCEXTINIT_H__
+
+#include <rfb/Configuration.h>
+#include "XserverDesktop.h"
+
+extern void vncClientCutText(const char* str, int len);
+extern void vncQueryConnect(XserverDesktop* desktop, void* opaqueId);
+extern void vncClientGone(int fd);
+extern void vncBell();
+extern void* vncFbptr[];
+extern int vncInetdSock;
+extern rfb::StringParameter httpDir;
+
+#endif
diff --git a/unix/xserver/hw/vnc/vncHooks.cc b/unix/xserver/hw/vnc/vncHooks.cc
new file mode 100644 (file)
index 0000000..ce8e7f0
--- /dev/null
@@ -0,0 +1,1533 @@
+/* Copyright (C) 2002-2005 RealVNC Ltd.  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 "XserverDesktop.h"
+#include "vncHooks.h"
+
+extern "C" {
+#define class c_class
+#define private c_private
+#include "scrnintstr.h"
+#include "windowstr.h"
+#include "gcstruct.h"
+#include "regionstr.h"
+#include "dixfontstr.h"
+#include "colormapst.h"
+#ifdef RENDER
+#include "picturestr.h"
+#endif
+
+#ifdef GC_HAS_COMPOSITE_CLIP
+#define COMPOSITE_CLIP(gc) ((gc)->pCompositeClip)
+#else
+#include "mfb.h"
+#define COMPOSITE_CLIP(gc) \
+  (((mfbPrivGCPtr)((gc)->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip)
+#endif
+
+#undef class
+#undef private
+}
+
+#include "RegionHelper.h"
+
+#define DBGPRINT(x) //(fprintf x)
+
+// MAX_RECTS_PER_OP is the maximum number of rectangles we generate from
+// operations like Polylines and PolySegment.  If the operation is more complex
+// than this, we simply use the bounding box.  Ideally it would be a
+// command-line option, but that would involve an extra malloc each time, so we
+// fix it here.
+#define MAX_RECTS_PER_OP 5
+
+static unsigned long vncHooksGeneration = 0;
+
+// vncHooksScreenRec and vncHooksGCRec contain pointers to the original
+// functions which we "wrap" in order to hook the screen changes.  The screen
+// functions are each wrapped individually, while the GC "funcs" and "ops" are
+// wrapped as a unit.
+
+typedef struct {
+  XserverDesktop* desktop;
+
+  CloseScreenProcPtr           CloseScreen;
+  CreateGCProcPtr              CreateGC;
+  PaintWindowBackgroundProcPtr PaintWindowBackground;
+  PaintWindowBorderProcPtr     PaintWindowBorder;
+  CopyWindowProcPtr            CopyWindow;
+  ClearToBackgroundProcPtr     ClearToBackground;
+  RestoreAreasProcPtr          RestoreAreas;
+  InstallColormapProcPtr       InstallColormap;
+  StoreColorsProcPtr           StoreColors;
+  DisplayCursorProcPtr         DisplayCursor;
+  ScreenBlockHandlerProcPtr    BlockHandler;
+#ifdef RENDER
+  CompositeProcPtr             Composite;
+#endif
+} vncHooksScreenRec, *vncHooksScreenPtr;
+
+typedef struct {
+    GCFuncs *wrappedFuncs;
+    GCOps *wrappedOps;
+} vncHooksGCRec, *vncHooksGCPtr;
+
+static int vncHooksScreenIndex;
+static int vncHooksGCIndex;
+
+
+// screen functions
+
+static Bool vncHooksCloseScreen(int i, ScreenPtr pScreen);
+static Bool vncHooksCreateGC(GCPtr pGC);
+static void vncHooksPaintWindowBackground(WindowPtr pWin, RegionPtr pRegion,
+                                          int what);
+static void vncHooksPaintWindowBorder(WindowPtr pWin, RegionPtr pRegion,
+                                      int what);
+static void vncHooksCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
+                               RegionPtr pOldRegion);
+static void vncHooksClearToBackground(WindowPtr pWin, int x, int y, int w,
+                                      int h, Bool generateExposures);
+static RegionPtr vncHooksRestoreAreas(WindowPtr pWin, RegionPtr prgnExposed);
+static void vncHooksInstallColormap(ColormapPtr pColormap);
+static void vncHooksStoreColors(ColormapPtr pColormap, int ndef,
+                                xColorItem* pdef);
+static Bool vncHooksDisplayCursor(ScreenPtr pScreen, CursorPtr cursor);
+static void vncHooksBlockHandler(int i, pointer blockData, pointer pTimeout,
+                                 pointer pReadmask);
+#ifdef RENDER
+static void vncHooksComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, 
+                             PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, 
+                             INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height);
+#endif
+
+// GC "funcs"
+
+static void vncHooksValidateGC(GCPtr pGC, unsigned long changes,
+                               DrawablePtr pDrawable);
+static void vncHooksChangeGC(GCPtr pGC, unsigned long mask);
+static void vncHooksCopyGC(GCPtr src, unsigned long mask, GCPtr dst);
+static void vncHooksDestroyGC(GCPtr pGC);
+static void vncHooksChangeClip(GCPtr pGC, int type, pointer pValue,int nrects);
+static void vncHooksDestroyClip(GCPtr pGC);
+static void vncHooksCopyClip(GCPtr dst, GCPtr src);
+
+static GCFuncs vncHooksGCFuncs = {
+  vncHooksValidateGC, vncHooksChangeGC, vncHooksCopyGC, vncHooksDestroyGC,
+  vncHooksChangeClip, vncHooksDestroyClip, vncHooksCopyClip,
+};
+
+// GC "ops"
+
+static void vncHooksFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nInit,
+                              DDXPointPtr pptInit, int *pwidthInit,
+                              int fSorted);
+static void vncHooksSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *psrc,
+                             DDXPointPtr ppt, int *pwidth, int nspans,
+                             int fSorted);
+static void vncHooksPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth,
+                             int x, int y, int w, int h, int leftPad,
+                             int format, char *pBits);
+static RegionPtr vncHooksCopyArea(DrawablePtr pSrc, DrawablePtr pDst,
+                                  GCPtr pGC, int srcx, int srcy, int w, int h,
+                                  int dstx, int dsty);
+static RegionPtr vncHooksCopyPlane(DrawablePtr pSrc, DrawablePtr pDst,
+                                   GCPtr pGC, int srcx, int srcy, int w, int h,
+                                   int dstx, int dsty, unsigned long plane);
+static void vncHooksPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode,
+                              int npt, xPoint *pts);
+static void vncHooksPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode,
+                              int npt, DDXPointPtr ppts);
+static void vncHooksPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg,
+                                xSegment *segs);
+static void vncHooksPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects,
+                                  xRectangle *rects);
+static void vncHooksPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs,
+                            xArc *arcs);
+static void vncHooksFillPolygon(DrawablePtr pDrawable, GCPtr pGC, int shape,
+                                int mode, int count, DDXPointPtr pts);
+static void vncHooksPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrects,
+                                 xRectangle *rects);
+static void vncHooksPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs,
+                                xArc *arcs);
+static int vncHooksPolyText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
+                             int count, char *chars);
+static int vncHooksPolyText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
+                              int count, unsigned short *chars);
+static void vncHooksImageText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
+                               int count, char *chars);
+static void vncHooksImageText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
+                                int count, unsigned short *chars);
+static void vncHooksImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x,
+                                  int y, unsigned int nglyph,
+                                  CharInfoPtr *ppci, pointer pglyphBase);
+static void vncHooksPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x,
+                                 int y, unsigned int nglyph,
+                                 CharInfoPtr *ppci, pointer pglyphBase);
+static void vncHooksPushPixels(GCPtr pGC, PixmapPtr pBitMap,
+                               DrawablePtr pDrawable, int w, int h, int x,
+                               int y);
+
+static GCOps vncHooksGCOps = {
+  vncHooksFillSpans, vncHooksSetSpans, vncHooksPutImage, vncHooksCopyArea,
+  vncHooksCopyPlane, vncHooksPolyPoint, vncHooksPolylines, vncHooksPolySegment,
+  vncHooksPolyRectangle, vncHooksPolyArc, vncHooksFillPolygon,
+  vncHooksPolyFillRect, vncHooksPolyFillArc, vncHooksPolyText8,
+  vncHooksPolyText16, vncHooksImageText8, vncHooksImageText16,
+  vncHooksImageGlyphBlt, vncHooksPolyGlyphBlt, vncHooksPushPixels
+};
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+// vncHooksInit() is called at initialisation time and every time the server
+// resets.  It is called once for each screen, but the indexes are only
+// allocated once for each server generation.
+
+Bool vncHooksInit(ScreenPtr pScreen, XserverDesktop* desktop)
+{
+  vncHooksScreenPtr vncHooksScreen;
+
+  if (vncHooksGeneration != serverGeneration) {
+    vncHooksGeneration = serverGeneration;
+
+    vncHooksScreenIndex = AllocateScreenPrivateIndex();
+    if (vncHooksScreenIndex < 0) {
+      ErrorF("vncHooksInit: AllocateScreenPrivateIndex failed\n");
+      return FALSE;
+    }
+
+    vncHooksGCIndex = AllocateGCPrivateIndex();
+    if (vncHooksGCIndex < 0) {
+      ErrorF("vncHooksInit: AllocateGCPrivateIndex failed\n");
+      return FALSE;
+    }
+  }
+
+  if (!AllocateGCPrivate(pScreen, vncHooksGCIndex, sizeof(vncHooksGCRec))) {
+    ErrorF("vncHooksInit: AllocateGCPrivate failed\n");
+    return FALSE;
+  }
+
+  vncHooksScreen = (vncHooksScreenPtr)xnfalloc(sizeof(vncHooksScreenRec));
+  pScreen->devPrivates[vncHooksScreenIndex].ptr = (pointer)vncHooksScreen;
+
+  vncHooksScreen->desktop = desktop;
+
+  vncHooksScreen->CloseScreen = pScreen->CloseScreen;
+  vncHooksScreen->CreateGC = pScreen->CreateGC;
+  vncHooksScreen->PaintWindowBackground = pScreen->PaintWindowBackground;
+  vncHooksScreen->PaintWindowBorder = pScreen->PaintWindowBorder;
+  vncHooksScreen->CopyWindow = pScreen->CopyWindow;
+  vncHooksScreen->ClearToBackground = pScreen->ClearToBackground;
+  vncHooksScreen->RestoreAreas = pScreen->RestoreAreas;
+  vncHooksScreen->InstallColormap = pScreen->InstallColormap;
+  vncHooksScreen->StoreColors = pScreen->StoreColors;
+  vncHooksScreen->DisplayCursor = pScreen->DisplayCursor;
+  vncHooksScreen->BlockHandler = pScreen->BlockHandler;
+#ifdef RENDER
+  PictureScreenPtr ps;
+  ps = GetPictureScreenIfSet(pScreen);
+  if (ps) {
+    vncHooksScreen->Composite = ps->Composite;
+  }
+#endif
+
+  pScreen->CloseScreen = vncHooksCloseScreen;
+  pScreen->CreateGC = vncHooksCreateGC;
+  pScreen->PaintWindowBackground = vncHooksPaintWindowBackground;
+  pScreen->PaintWindowBorder = vncHooksPaintWindowBorder;
+  pScreen->CopyWindow = vncHooksCopyWindow;
+  pScreen->ClearToBackground = vncHooksClearToBackground;
+  pScreen->RestoreAreas = vncHooksRestoreAreas;
+  pScreen->InstallColormap = vncHooksInstallColormap;
+  pScreen->StoreColors = vncHooksStoreColors;
+  pScreen->DisplayCursor = vncHooksDisplayCursor;
+  pScreen->BlockHandler = vncHooksBlockHandler;
+#ifdef RENDER
+  if (ps) {
+    ps->Composite = vncHooksComposite;
+  }
+#endif
+
+  return TRUE;
+}
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// screen functions
+//
+
+// SCREEN_UNWRAP and SCREEN_REWRAP unwrap and rewrap the given screen function.
+// It would be nice to do this with a C++ class, but each function is of a
+// distinct type, so it would have to use templates, and it's not worth that
+// much pain.
+
+#define SCREEN_UNWRAP(scrn,field)                                         \
+  ScreenPtr pScreen = scrn;                                               \
+  vncHooksScreenPtr vncHooksScreen                                        \
+    = ((vncHooksScreenPtr)pScreen->devPrivates[vncHooksScreenIndex].ptr); \
+  pScreen->field = vncHooksScreen->field;                                 \
+  DBGPRINT((stderr,"vncHooks" #field " called\n"));
+
+#define SCREEN_REWRAP(field) pScreen->field = vncHooks##field;
+
+
+// CloseScreen - unwrap the screen functions and call the original CloseScreen
+// function
+
+static Bool vncHooksCloseScreen(int i, ScreenPtr pScreen_)
+{
+  SCREEN_UNWRAP(pScreen_, CloseScreen);
+
+  pScreen->CreateGC = vncHooksScreen->CreateGC;
+  pScreen->PaintWindowBackground = vncHooksScreen->PaintWindowBackground;
+  pScreen->PaintWindowBorder = vncHooksScreen->PaintWindowBorder;
+  pScreen->CopyWindow = vncHooksScreen->CopyWindow;
+  pScreen->ClearToBackground = vncHooksScreen->ClearToBackground;
+  pScreen->RestoreAreas = vncHooksScreen->RestoreAreas;
+  pScreen->InstallColormap = vncHooksScreen->InstallColormap;
+  pScreen->StoreColors = vncHooksScreen->StoreColors;
+  pScreen->DisplayCursor = vncHooksScreen->DisplayCursor;
+  pScreen->BlockHandler = vncHooksScreen->BlockHandler;
+
+  xfree((pointer)vncHooksScreen);
+
+  DBGPRINT((stderr,"vncHooksCloseScreen: unwrapped screen functions\n"));
+
+  return (*pScreen->CloseScreen)(i, pScreen);
+}
+
+// CreateGC - wrap the "GC funcs"
+
+static Bool vncHooksCreateGC(GCPtr pGC)
+{
+  SCREEN_UNWRAP(pGC->pScreen, CreateGC);
+    
+  vncHooksGCPtr vncHooksGC
+    = (vncHooksGCPtr)pGC->devPrivates[vncHooksGCIndex].ptr;
+
+  Bool ret = (*pScreen->CreateGC) (pGC);
+
+  vncHooksGC->wrappedOps = 0;
+  vncHooksGC->wrappedFuncs = pGC->funcs;
+  pGC->funcs = &vncHooksGCFuncs;
+
+  SCREEN_REWRAP(CreateGC);
+
+  return ret;
+}
+
+// PaintWindowBackground - changed region is the given region
+
+static void vncHooksPaintWindowBackground(WindowPtr pWin, RegionPtr pRegion,
+                                          int what)
+{
+  SCREEN_UNWRAP(pWin->drawable.pScreen, PaintWindowBackground);
+
+  RegionHelper changed(pScreen, pRegion);
+
+  (*pScreen->PaintWindowBackground) (pWin, pRegion, what);
+
+  vncHooksScreen->desktop->add_changed(changed.reg);
+
+  SCREEN_REWRAP(PaintWindowBackground);
+}
+
+// PaintWindowBorder - changed region is the given region
+
+static void vncHooksPaintWindowBorder(WindowPtr pWin, RegionPtr pRegion,
+                                      int what)
+{
+  SCREEN_UNWRAP(pWin->drawable.pScreen, PaintWindowBorder);
+
+  RegionHelper changed(pScreen, pRegion);
+
+  (*pScreen->PaintWindowBorder) (pWin, pRegion, what);
+
+  vncHooksScreen->desktop->add_changed(changed.reg);
+
+  SCREEN_REWRAP(PaintWindowBorder);
+}
+
+// CopyWindow - destination of the copy is the old region, clipped by
+// borderClip, translated by the delta.  This call only does the copy - it
+// doesn't affect any other bits.
+
+static void vncHooksCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
+                               RegionPtr pOldRegion)
+{
+  SCREEN_UNWRAP(pWin->drawable.pScreen, CopyWindow);
+
+  RegionHelper copied(pScreen, pOldRegion);
+  int dx = pWin->drawable.x - ptOldOrg.x;
+  int dy = pWin->drawable.y - ptOldOrg.y;
+  REGION_TRANSLATE(pScreen, copied.reg, dx, dy);
+  REGION_INTERSECT(pWin->drawable.pScreen, copied.reg, copied.reg,
+                   &pWin->borderClip);
+
+  (*pScreen->CopyWindow) (pWin, ptOldOrg, pOldRegion);
+
+  vncHooksScreen->desktop->add_copied(copied.reg, dx, dy);
+
+  SCREEN_REWRAP(CopyWindow);
+}
+
+// ClearToBackground - changed region is the given rectangle, clipped by
+// clipList, but only if generateExposures is false.
+
+static void vncHooksClearToBackground(WindowPtr pWin, int x, int y, int w,
+                                      int h, Bool generateExposures)
+{
+  SCREEN_UNWRAP(pWin->drawable.pScreen, ClearToBackground);
+
+  BoxRec box;
+  box.x1 = x + pWin->drawable.x;
+  box.y1 = y + pWin->drawable.y;
+  box.x2 = w ? (box.x1 + w) : (pWin->drawable.x + pWin->drawable.width);
+  box.y2 = h ? (box.y1 + h) : (pWin->drawable.y + pWin->drawable.height);
+
+  RegionHelper changed(pScreen, &box, 0);
+
+  REGION_INTERSECT(pScreen, changed.reg, changed.reg, &pWin->clipList);
+
+  (*pScreen->ClearToBackground) (pWin, x, y, w, h, generateExposures);
+
+  if (!generateExposures) {
+    vncHooksScreen->desktop->add_changed(changed.reg);
+  }
+
+  SCREEN_REWRAP(ClearToBackground);
+}
+
+// RestoreAreas - changed region is the given region
+
+static RegionPtr vncHooksRestoreAreas(WindowPtr pWin, RegionPtr pRegion)
+{
+  SCREEN_UNWRAP(pWin->drawable.pScreen, RestoreAreas);
+
+  RegionHelper changed(pScreen, pRegion);
+
+  RegionPtr result = (*pScreen->RestoreAreas) (pWin, pRegion);
+
+  vncHooksScreen->desktop->add_changed(changed.reg);
+
+  SCREEN_REWRAP(RestoreAreas);
+
+  return result;
+}
+
+// InstallColormap - get the new colormap
+
+static void vncHooksInstallColormap(ColormapPtr pColormap)
+{
+  SCREEN_UNWRAP(pColormap->pScreen, InstallColormap);
+
+  (*pScreen->InstallColormap) (pColormap);
+
+  vncHooksScreen->desktop->setColormap(pColormap);
+
+  SCREEN_REWRAP(InstallColormap);
+}
+
+// StoreColors - get the colormap changes
+
+static void vncHooksStoreColors(ColormapPtr pColormap, int ndef,
+                                xColorItem* pdef)
+{
+  SCREEN_UNWRAP(pColormap->pScreen, StoreColors);
+
+  (*pScreen->StoreColors) (pColormap, ndef, pdef);
+
+  vncHooksScreen->desktop->setColourMapEntries(pColormap, ndef, pdef);
+
+  SCREEN_REWRAP(StoreColors);
+}
+
+// DisplayCursor - get the cursor shape
+
+static Bool vncHooksDisplayCursor(ScreenPtr pScreen_, CursorPtr cursor)
+{
+  SCREEN_UNWRAP(pScreen_, DisplayCursor);
+
+  Bool ret = (*pScreen->DisplayCursor) (pScreen, cursor);
+
+  vncHooksScreen->desktop->setCursor(cursor);
+
+  SCREEN_REWRAP(DisplayCursor);
+
+  return ret;
+}
+
+// BlockHandler - ignore any changes during the block handler - it's likely
+// these are just drawing the cursor.
+
+static void vncHooksBlockHandler(int i, pointer blockData, pointer pTimeout,
+                                 pointer pReadmask)
+{
+  SCREEN_UNWRAP(screenInfo.screens[i], BlockHandler);
+
+  vncHooksScreen->desktop->ignoreHooks(true);
+
+  (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
+
+  vncHooksScreen->desktop->ignoreHooks(false);
+
+  SCREEN_REWRAP(BlockHandler);
+}
+
+// Composite - needed for RENDER
+
+#ifdef RENDER
+void vncHooksComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, 
+                      PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, 
+                      INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
+{
+  ScreenPtr pScreen = pDst->pDrawable->pScreen;
+  vncHooksScreenPtr vncHooksScreen = ((vncHooksScreenPtr)pScreen->devPrivates[vncHooksScreenIndex].ptr); 
+  BoxRec box;
+  PictureScreenPtr ps = GetPictureScreen(pScreen);
+  rfb::Rect rect1, rect2;
+
+  rect1.setXYWH(pDst->pDrawable->x + xDst,
+               pDst->pDrawable->y + yDst,
+               width,
+               height);
+      
+  rect2 = rect1.intersect(vncHooksScreen->desktop->getRect());
+  if (!rect2.is_empty()) {
+    box.x1 = rect2.tl.x;
+    box.y1 = rect2.tl.y;
+    box.x2 = rect2.br.x;
+    box.y2 = rect2.br.y;
+    RegionHelper changed(pScreen, &box, 0);
+    vncHooksScreen->desktop->add_changed(changed.reg);
+  }
+
+  ps->Composite = vncHooksScreen->Composite;
+  (*ps->Composite)(op, pSrc, pMask, pDst, xSrc, ySrc,
+                  xMask, yMask, xDst, yDst, width, height);
+  ps->Composite = vncHooksComposite;
+}
+
+#endif /* RENDER */
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// GC "funcs"
+//
+
+// GCFuncUnwrapper is a helper class which unwraps the GC funcs and ops in its
+// constructor and rewraps them in its destructor.
+
+class GCFuncUnwrapper {
+public:
+  GCFuncUnwrapper(GCPtr pGC_) : pGC(pGC_) {
+    vncHooksGC = (vncHooksGCPtr)pGC->devPrivates[vncHooksGCIndex].ptr;
+    pGC->funcs = vncHooksGC->wrappedFuncs;
+    if (vncHooksGC->wrappedOps)
+      pGC->ops = vncHooksGC->wrappedOps;
+  }
+  ~GCFuncUnwrapper() {
+    vncHooksGC->wrappedFuncs = pGC->funcs;
+    pGC->funcs = &vncHooksGCFuncs;
+    if (vncHooksGC->wrappedOps) {
+      vncHooksGC->wrappedOps = pGC->ops;
+      pGC->ops = &vncHooksGCOps;
+    }
+  }
+  GCPtr pGC;
+  vncHooksGCPtr vncHooksGC;
+};
+
+
+// ValidateGC - wrap the "ops" if a viewable window
+
+static void vncHooksValidateGC(GCPtr pGC, unsigned long changes,
+                               DrawablePtr pDrawable)
+{
+  GCFuncUnwrapper u(pGC);
+
+  DBGPRINT((stderr,"vncHooksValidateGC called\n"));
+
+  (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable);
+    
+  u.vncHooksGC->wrappedOps = 0;
+  if (pDrawable->type == DRAWABLE_WINDOW && ((WindowPtr)pDrawable)->viewable) {
+    WindowPtr pWin = (WindowPtr)pDrawable;
+    RegionPtr pRegion = &pWin->clipList;
+
+    if (pGC->subWindowMode == IncludeInferiors)
+      pRegion = &pWin->borderClip;
+    if (REGION_NOTEMPTY(pDrawable->pScreen, pRegion)) {
+      u.vncHooksGC->wrappedOps = pGC->ops;
+      DBGPRINT((stderr,"vncHooksValidateGC: wrapped GC ops\n"));
+    }
+  }
+}
+
+// Other GC funcs - just unwrap and call on
+
+static void vncHooksChangeGC(GCPtr pGC, unsigned long mask) {
+  GCFuncUnwrapper u(pGC);
+  (*pGC->funcs->ChangeGC) (pGC, mask);
+}
+static void vncHooksCopyGC(GCPtr src, unsigned long mask, GCPtr dst) {
+  GCFuncUnwrapper u(dst);
+  (*dst->funcs->CopyGC) (src, mask, dst);
+}
+static void vncHooksDestroyGC(GCPtr pGC) {
+  GCFuncUnwrapper u(pGC);
+  (*pGC->funcs->DestroyGC) (pGC);
+}
+static void vncHooksChangeClip(GCPtr pGC, int type, pointer pValue, int nrects)
+{
+  GCFuncUnwrapper u(pGC);
+  (*pGC->funcs->ChangeClip) (pGC, type, pValue, nrects);
+}
+static void vncHooksDestroyClip(GCPtr pGC) {
+  GCFuncUnwrapper u(pGC);
+  (*pGC->funcs->DestroyClip) (pGC);
+}
+static void vncHooksCopyClip(GCPtr dst, GCPtr src) {
+  GCFuncUnwrapper u(dst);
+  (*dst->funcs->CopyClip) (dst, src);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// GC "ops"
+//
+
+// GCOpUnwrapper is a helper class which unwraps the GC funcs and ops in its
+// constructor and rewraps them in its destructor.
+
+class GCOpUnwrapper {
+public:
+  GCOpUnwrapper(DrawablePtr pDrawable, GCPtr pGC_)
+    : pGC(pGC_), pScreen(pDrawable->pScreen)
+  {
+    vncHooksGC = (vncHooksGCPtr)pGC->devPrivates[vncHooksGCIndex].ptr;
+    oldFuncs = pGC->funcs;
+    pGC->funcs = vncHooksGC->wrappedFuncs;
+    pGC->ops = vncHooksGC->wrappedOps;
+  }
+  ~GCOpUnwrapper() {
+    vncHooksGC->wrappedOps = pGC->ops;
+    pGC->funcs = oldFuncs;
+    pGC->ops = &vncHooksGCOps;
+  }
+  GCPtr pGC;
+  vncHooksGCPtr vncHooksGC;
+  GCFuncs* oldFuncs;
+  ScreenPtr pScreen;
+};
+
+#define GC_OP_UNWRAPPER(pDrawable, pGC, name)                             \
+  GCOpUnwrapper u(pDrawable, pGC);                                        \
+  ScreenPtr pScreen = (pDrawable)->pScreen;                               \
+  vncHooksScreenPtr vncHooksScreen                                        \
+    = ((vncHooksScreenPtr)pScreen->devPrivates[vncHooksScreenIndex].ptr); \
+  DBGPRINT((stderr,"vncHooks" #name " called\n"));
+
+
+// FillSpans - changed region is the whole of borderClip.  This is pessimistic,
+// but I believe this function is rarely used so it doesn't matter.
+
+static void vncHooksFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nInit,
+                              DDXPointPtr pptInit, int *pwidthInit,
+                              int fSorted)
+{
+  GC_OP_UNWRAPPER(pDrawable, pGC, FillSpans);
+
+  RegionHelper changed(pScreen, &((WindowPtr)pDrawable)->borderClip);
+
+  (*pGC->ops->FillSpans) (pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted);
+
+  vncHooksScreen->desktop->add_changed(changed.reg);
+}
+
+// SetSpans - changed region is the whole of borderClip.  This is pessimistic,
+// but I believe this function is rarely used so it doesn't matter.
+
+static void vncHooksSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *psrc,
+                             DDXPointPtr ppt, int *pwidth, int nspans,
+                             int fSorted)
+{
+  GC_OP_UNWRAPPER(pDrawable, pGC, SetSpans);
+
+  RegionHelper changed(pScreen, &((WindowPtr)pDrawable)->borderClip);
+
+  (*pGC->ops->SetSpans) (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted);
+
+  vncHooksScreen->desktop->add_changed(changed.reg);
+}
+
+// PutImage - changed region is the given rectangle, clipped by pCompositeClip
+
+static void vncHooksPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth,
+                             int x, int y, int w, int h, int leftPad,
+                             int format, char *pBits)
+{
+  GC_OP_UNWRAPPER(pDrawable, pGC, PutImage);
+
+  BoxRec box;
+  box.x1 = x + pDrawable->x;
+  box.y1 = y + pDrawable->y;
+  box.x2 = box.x1 + w;
+  box.y2 = box.y1 + h;
+
+  RegionHelper changed(pScreen, &box, 0);
+
+  REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
+
+  (*pGC->ops->PutImage) (pDrawable, pGC, depth, x, y, w, h, leftPad, format,
+                         pBits);
+
+  vncHooksScreen->desktop->add_changed(changed.reg);
+}
+
+// CopyArea - destination of the copy is the dest rectangle, clipped by
+// pCompositeClip.  Any parts of the destination which cannot be copied from
+// the source (could be all of it) go into the changed region.
+
+static RegionPtr vncHooksCopyArea(DrawablePtr pSrc, DrawablePtr pDst,
+                                  GCPtr pGC, int srcx, int srcy, int w, int h,
+                                  int dstx, int dsty)
+{
+  GC_OP_UNWRAPPER(pDst, pGC, CopyArea);
+
+  BoxRec box;
+  box.x1 = dstx + pDst->x;
+  box.y1 = dsty + pDst->y;
+  box.x2 = box.x1 + w;
+  box.y2 = box.y1 + h;
+
+  RegionHelper dst(pScreen, &box, 0);
+  REGION_INTERSECT(pScreen, dst.reg, dst.reg, COMPOSITE_CLIP(pGC));
+
+  RegionHelper src(pScreen);
+
+  if ((pSrc->type == DRAWABLE_WINDOW) && (pSrc->pScreen == pScreen)) {
+    box.x1 = srcx + pSrc->x;
+    box.y1 = srcy + pSrc->y;
+    box.x2 = box.x1 + w;
+    box.y2 = box.y1 + h;
+
+    src.init(&box, 0);
+    REGION_INTERSECT(pScreen, src.reg, src.reg, &((WindowPtr)pSrc)->clipList);
+    REGION_TRANSLATE(pScreen, src.reg,
+                     dstx + pDst->x - srcx - pSrc->x,
+                     dsty + pDst->y - srcy - pSrc->y);
+  } else {
+    src.init(NullBox, 0);
+  }
+
+  RegionHelper changed(pScreen, NullBox, 0);
+  REGION_SUBTRACT(pScreen, changed.reg, dst.reg, src.reg);
+  REGION_INTERSECT(pScreen, dst.reg, dst.reg, src.reg);
+
+  RegionPtr rgn = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, srcx, srcy, w, h,
+                                         dstx, dsty);
+
+  if (REGION_NOTEMPTY(pScreen, dst.reg))
+    vncHooksScreen->desktop->add_copied(dst.reg,
+                                        dstx + pDst->x - srcx - pSrc->x,
+                                        dsty + pDst->y - srcy - pSrc->y);
+
+  if (REGION_NOTEMPTY(pScreen, changed.reg))
+    vncHooksScreen->desktop->add_changed(changed.reg);
+
+  return rgn;
+}
+
+
+// CopyPlane - changed region is the destination rectangle, clipped by
+// pCompositeClip
+
+static RegionPtr vncHooksCopyPlane(DrawablePtr pSrc, DrawablePtr pDst,
+                                   GCPtr pGC, int srcx, int srcy, int w, int h,
+                                   int dstx, int dsty, unsigned long plane)
+{
+  GC_OP_UNWRAPPER(pDst, pGC, CopyPlane);
+
+  BoxRec box;
+  box.x1 = dstx + pDst->x;
+  box.y1 = dsty + pDst->y;
+  box.x2 = box.x1 + w;
+  box.y2 = box.y1 + h;
+
+  RegionHelper changed(pScreen, &box, 0);
+
+  REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
+
+  RegionPtr rgn = (*pGC->ops->CopyPlane) (pSrc, pDst, pGC, srcx, srcy, w, h,
+                                          dstx, dsty, plane);
+  vncHooksScreen->desktop->add_changed(changed.reg);
+
+  return rgn;
+}
+
+// PolyPoint - changed region is the bounding rect, clipped by pCompositeClip
+
+static void vncHooksPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode,
+                              int npt, xPoint *pts)
+{
+  GC_OP_UNWRAPPER(pDrawable, pGC, PolyPoint);
+
+  if (npt == 0) {
+    (*pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pts);
+    return;
+  }
+
+  int minX = pts[0].x;
+  int maxX = pts[0].x;
+  int minY = pts[0].y;
+  int maxY = pts[0].y;
+
+  if (mode == CoordModePrevious) {
+    int x = pts[0].x;
+    int y = pts[0].y;
+
+    for (int i = 1; i < npt; i++) {
+      x += pts[i].x;
+      y += pts[i].y;
+      if (x < minX) minX = x;
+      if (x > maxX) maxX = x;
+      if (y < minY) minY = y;
+      if (y > maxY) maxY = y;
+    }
+  } else {
+    for (int i = 1; i < npt; i++) {
+      if (pts[i].x < minX) minX = pts[i].x;
+      if (pts[i].x > maxX) maxX = pts[i].x;
+      if (pts[i].y < minY) minY = pts[i].y;
+      if (pts[i].y > maxY) maxY = pts[i].y;
+    }
+  }
+
+  BoxRec box;
+  box.x1 = minX + pDrawable->x;
+  box.y1 = minY + pDrawable->y;
+  box.x2 = maxX + 1 + pDrawable->x;
+  box.y2 = maxY + 1 + pDrawable->y;
+
+  RegionHelper changed(pScreen, &box, 0);
+
+  REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
+
+  (*pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pts);
+
+  vncHooksScreen->desktop->add_changed(changed.reg);
+}
+
+// Polylines - changed region is the union of the bounding rects of each line,
+// clipped by pCompositeClip.  If there are more than MAX_RECTS_PER_OP lines,
+// just use the bounding rect of all the lines.
+
+static void vncHooksPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode,
+                              int npt, DDXPointPtr ppts)
+{
+  GC_OP_UNWRAPPER(pDrawable, pGC, Polylines);
+
+  if (npt == 0) {
+    (*pGC->ops->Polylines) (pDrawable, pGC, mode, npt, ppts);
+    return;
+  }
+
+  int nRegRects = npt - 1;
+  xRectangle regRects[MAX_RECTS_PER_OP];
+
+  int lw = pGC->lineWidth;
+  if (lw == 0) lw = 1;
+
+  if (npt == 1)
+  {
+    // a single point
+    nRegRects = 1;
+    regRects[0].x = pDrawable->x + ppts[0].x - lw;
+    regRects[0].y = pDrawable->y + ppts[0].y - lw;
+    regRects[0].width = 2*lw;
+    regRects[0].height = 2*lw;
+  }
+  else
+  {
+    /*
+     * mitered joins can project quite a way from
+     * the line end; the 11 degree miter limit limits
+     * this extension to lw / (2 * tan(11/2)), rounded up
+     * and converted to int yields 6 * lw
+     */
+
+    int extra = lw / 2;
+    if (pGC->joinStyle == JoinMiter) {
+      extra = 6 * lw;
+    }
+
+    int prevX, prevY, curX, curY;
+    int rectX1, rectY1, rectX2, rectY2;
+    int minX, minY, maxX, maxY;
+
+    prevX = ppts[0].x + pDrawable->x;
+    prevY = ppts[0].y + pDrawable->y;
+    minX = maxX = prevX;
+    minY = maxY = prevY;
+
+    for (int i = 0; i < nRegRects; i++) {
+      if (mode == CoordModeOrigin) {
+        curX = pDrawable->x + ppts[i+1].x;
+        curY = pDrawable->y + ppts[i+1].y;
+      } else {
+        curX = prevX + ppts[i+1].x;
+        curY = prevY + ppts[i+1].y;
+      }
+
+      if (prevX > curX) {
+        rectX1 = curX - extra;
+        rectX2 = prevX + extra + 1;
+      } else {
+        rectX1 = prevX - extra;
+        rectX2 = curX + extra + 1;
+      }
+
+      if (prevY > curY) {
+        rectY1 = curY - extra;
+        rectY2 = prevY + extra + 1;
+      } else {
+        rectY1 = prevY - extra;
+        rectY2 = curY + extra + 1;
+      }
+
+      if (nRegRects <= MAX_RECTS_PER_OP) {
+        regRects[i].x = rectX1;
+        regRects[i].y = rectY1;
+        regRects[i].width = rectX2 - rectX1;
+        regRects[i].height = rectY2 - rectY1;
+      } else {
+        if (rectX1 < minX) minX = rectX1;
+        if (rectY1 < minY) minY = rectY1;
+        if (rectX2 > maxX) maxX = rectX2;
+        if (rectY2 > maxY) maxY = rectY2;
+      }
+
+      prevX = curX;
+      prevY = curY;
+    }
+
+    if (nRegRects > MAX_RECTS_PER_OP) {
+      regRects[0].x = minX;
+      regRects[0].y = minY;
+      regRects[0].width = maxX - minX;
+      regRects[0].height = maxY - minY;
+      nRegRects = 1;
+    }
+  }
+
+  RegionHelper changed(pScreen, nRegRects, regRects);
+
+  REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
+
+  (*pGC->ops->Polylines) (pDrawable, pGC, mode, npt, ppts);
+
+  vncHooksScreen->desktop->add_changed(changed.reg);
+}
+
+// PolySegment - changed region is the union of the bounding rects of each
+// segment, clipped by pCompositeClip.  If there are more than MAX_RECTS_PER_OP
+// segments, just use the bounding rect of all the segments.
+
+static void vncHooksPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg,
+                                xSegment *segs)
+{
+  GC_OP_UNWRAPPER(pDrawable, pGC, PolySegment);
+
+  if (nseg == 0) {
+    (*pGC->ops->PolySegment) (pDrawable, pGC, nseg, segs);
+    return;
+  }
+
+  xRectangle regRects[MAX_RECTS_PER_OP];
+  int nRegRects = nseg;
+
+  int lw = pGC->lineWidth;
+  int extra = lw / 2;
+
+  int rectX1, rectY1, rectX2, rectY2;
+  int minX, minY, maxX, maxY;
+
+  minX = maxX = segs[0].x1;
+  minY = maxY = segs[0].y1;
+
+  for (int i = 0; i < nseg; i++) {
+    if (segs[i].x1 > segs[i].x2) {
+      rectX1 = pDrawable->x + segs[i].x2 - extra;
+      rectX2 = pDrawable->x + segs[i].x1 + extra + 1;
+    } else {
+      rectX1 = pDrawable->x + segs[i].x1 - extra;
+      rectX2 = pDrawable->x + segs[i].x2 + extra + 1;
+    }
+
+    if (segs[i].y1 > segs[i].y2) {
+      rectY1 = pDrawable->y + segs[i].y2 - extra;
+      rectY2 = pDrawable->y + segs[i].y1 + extra + 1;
+    } else {
+      rectY1 = pDrawable->y + segs[i].y1 - extra;
+      rectY2 = pDrawable->y + segs[i].y2 + extra + 1;
+    }
+
+    if (nseg <= MAX_RECTS_PER_OP) {
+      regRects[i].x = rectX1;
+      regRects[i].y = rectY1;
+      regRects[i].width = rectX2 - rectX1;
+      regRects[i].height = rectY2 - rectY1;
+    } else {
+      if (rectX1 < minX) minX = rectX1;
+      if (rectY1 < minY) minY = rectY1;
+      if (rectX2 > maxX) maxX = rectX2;
+      if (rectY2 > maxY) maxY = rectY2;
+    }
+  }
+
+  if (nseg > MAX_RECTS_PER_OP) {
+    regRects[0].x = minX;
+    regRects[0].y = minY;
+    regRects[0].width = maxX - minX;
+    regRects[0].height = maxY - minY;
+    nRegRects = 1;
+  }
+
+  RegionHelper changed(pScreen, nRegRects, regRects);
+
+  REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
+
+  (*pGC->ops->PolySegment) (pDrawable, pGC, nseg, segs);
+
+  vncHooksScreen->desktop->add_changed(changed.reg);
+}
+
+// PolyRectangle - changed region is the union of the bounding rects around
+// each side of the outline rectangles, clipped by pCompositeClip.  If there
+// are more than MAX_RECTS_PER_OP rectangles, just use the bounding rect of all
+// the rectangles.
+
+static void vncHooksPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects,
+                                  xRectangle *rects)
+{
+  GC_OP_UNWRAPPER(pDrawable, pGC, PolyRectangle);
+
+  if (nrects == 0) {
+    (*pGC->ops->PolyRectangle) (pDrawable, pGC, nrects, rects);
+    return;
+  }
+
+  xRectangle regRects[MAX_RECTS_PER_OP*4];
+  int nRegRects = nrects * 4;
+
+  int lw = pGC->lineWidth;
+  int extra = lw / 2;
+
+  int rectX1, rectY1, rectX2, rectY2;
+  int minX, minY, maxX, maxY;
+
+  minX = maxX = rects[0].x;
+  minY = maxY = rects[0].y;
+
+  for (int i = 0; i < nrects; i++) {
+    if (nrects <= MAX_RECTS_PER_OP) {
+      regRects[i*4].x = rects[i].x - extra + pDrawable->x;
+      regRects[i*4].y = rects[i].y - extra + pDrawable->y;
+      regRects[i*4].width = rects[i].width + 1 + 2 * extra;
+      regRects[i*4].height = 1 + 2 * extra;
+
+      regRects[i*4+1].x = rects[i].x - extra + pDrawable->x;
+      regRects[i*4+1].y = rects[i].y - extra + pDrawable->y;
+      regRects[i*4+1].width = 1 + 2 * extra;
+      regRects[i*4+1].height = rects[i].height + 1 + 2 * extra;
+
+      regRects[i*4+2].x = rects[i].x + rects[i].width - extra + pDrawable->x;
+      regRects[i*4+2].y = rects[i].y - extra + pDrawable->y;
+      regRects[i*4+2].width = 1 + 2 * extra;
+      regRects[i*4+2].height = rects[i].height + 1 + 2 * extra;
+
+      regRects[i*4+3].x = rects[i].x - extra + pDrawable->x;
+      regRects[i*4+3].y = rects[i].y + rects[i].height - extra + pDrawable->y;
+      regRects[i*4+3].width = rects[i].width + 1 + 2 * extra;
+      regRects[i*4+3].height = 1 + 2 * extra;
+    } else {
+      rectX1 = pDrawable->x + rects[i].x - extra;
+      rectY1 = pDrawable->y + rects[i].y - extra;
+      rectX2 = pDrawable->x + rects[i].x + rects[i].width + extra+1;
+      rectY2 = pDrawable->y + rects[i].y + rects[i].height + extra+1;
+      if (rectX1 < minX) minX = rectX1;
+      if (rectY1 < minY) minY = rectY1;
+      if (rectX2 > maxX) maxX = rectX2;
+      if (rectY2 > maxY) maxY = rectY2;
+    }
+  }
+
+  if (nrects > MAX_RECTS_PER_OP) {
+    regRects[0].x = minX;
+    regRects[0].y = minY;
+    regRects[0].width = maxX - minX;
+    regRects[0].height = maxY - minY;
+    nRegRects = 1;
+  }
+
+  RegionHelper changed(pScreen, nRegRects, regRects);
+
+  REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
+
+  (*pGC->ops->PolyRectangle) (pDrawable, pGC, nrects, rects);
+
+  vncHooksScreen->desktop->add_changed(changed.reg);
+}
+
+// PolyArc - changed region is the union of bounding rects around each arc,
+// clipped by pCompositeClip.  If there are more than MAX_RECTS_PER_OP
+// arcs, just use the bounding rect of all the arcs.
+
+static void vncHooksPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs,
+                            xArc *arcs)
+{
+  GC_OP_UNWRAPPER(pDrawable, pGC, PolyArc);
+
+  if (narcs == 0) {
+    (*pGC->ops->PolyArc) (pDrawable, pGC, narcs, arcs);
+    return;
+  }
+
+  xRectangle regRects[MAX_RECTS_PER_OP];
+  int nRegRects = narcs;
+
+  int lw = pGC->lineWidth;
+  if (lw == 0) lw = 1;
+  int extra = lw / 2;
+
+  int rectX1, rectY1, rectX2, rectY2;
+  int minX, minY, maxX, maxY;
+
+  minX = maxX = arcs[0].x;
+  minY = maxY = arcs[0].y;
+
+  for (int i = 0; i < narcs; i++) {
+    if (narcs <= MAX_RECTS_PER_OP) {
+      regRects[i].x = arcs[i].x - extra + pDrawable->x;
+      regRects[i].y = arcs[i].y - extra + pDrawable->y;
+      regRects[i].width = arcs[i].width + lw;
+      regRects[i].height = arcs[i].height + lw;
+    } else {
+      rectX1 = pDrawable->x + arcs[i].x - extra;
+      rectY1 = pDrawable->y + arcs[i].y - extra;
+      rectX2 = pDrawable->x + arcs[i].x + arcs[i].width + lw;
+      rectY2 = pDrawable->y + arcs[i].y + arcs[i].height + lw;
+      if (rectX1 < minX) minX = rectX1;
+      if (rectY1 < minY) minY = rectY1;
+      if (rectX2 > maxX) maxX = rectX2;
+      if (rectY2 > maxY) maxY = rectY2;
+    }
+  }
+
+  if (narcs > MAX_RECTS_PER_OP) {
+    regRects[0].x = minX;
+    regRects[0].y = minY;
+    regRects[0].width = maxX - minX;
+    regRects[0].height = maxY - minY;
+    nRegRects = 1;
+  }
+
+  RegionHelper changed(pScreen, nRegRects, regRects);
+
+  REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
+
+  (*pGC->ops->PolyArc) (pDrawable, pGC, narcs, arcs);
+
+  vncHooksScreen->desktop->add_changed(changed.reg);
+}
+
+
+// FillPolygon - changed region is the bounding rect around the polygon,
+// clipped by pCompositeClip
+
+static void vncHooksFillPolygon(DrawablePtr pDrawable, GCPtr pGC, int shape,
+                                int mode, int count, DDXPointPtr pts)
+{
+  GC_OP_UNWRAPPER(pDrawable, pGC, FillPolygon);
+
+  if (count == 0) {
+    (*pGC->ops->FillPolygon) (pDrawable, pGC, shape, mode, count, pts);
+    return;
+  }
+
+  int minX = pts[0].x;
+  int maxX = pts[0].x;
+  int minY = pts[0].y;
+  int maxY = pts[0].y;
+
+  if (mode == CoordModePrevious) {
+    int x = pts[0].x;
+    int y = pts[0].y;
+
+    for (int i = 1; i < count; i++) {
+      x += pts[i].x;
+      y += pts[i].y;
+      if (x < minX) minX = x;
+      if (x > maxX) maxX = x;
+      if (y < minY) minY = y;
+      if (y > maxY) maxY = y;
+    }
+  } else {
+    for (int i = 1; i < count; i++) {
+      if (pts[i].x < minX) minX = pts[i].x;
+      if (pts[i].x > maxX) maxX = pts[i].x;
+      if (pts[i].y < minY) minY = pts[i].y;
+      if (pts[i].y > maxY) maxY = pts[i].y;
+    }
+  }
+
+  BoxRec box;
+  box.x1 = minX + pDrawable->x;
+  box.y1 = minY + pDrawable->y;
+  box.x2 = maxX + 1 + pDrawable->x;
+  box.y2 = maxY + 1 + pDrawable->y;
+
+  RegionHelper changed(pScreen, &box, 0);
+
+  REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
+
+  (*pGC->ops->FillPolygon) (pDrawable, pGC, shape, mode, count, pts);
+
+  vncHooksScreen->desktop->add_changed(changed.reg);
+}
+
+// PolyFillRect - changed region is the union of the rectangles, clipped by
+// pCompositeClip.  If there are more than MAX_RECTS_PER_OP rectangles, just
+// use the bounding rect of all the rectangles.
+
+static void vncHooksPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrects,
+                                 xRectangle *rects)
+{
+  GC_OP_UNWRAPPER(pDrawable, pGC, PolyFillRect);
+
+  if (nrects == 0) {
+    (*pGC->ops->PolyFillRect) (pDrawable, pGC, nrects, rects);
+    return;
+  }
+
+  xRectangle regRects[MAX_RECTS_PER_OP];
+  int nRegRects = nrects;
+  int rectX1, rectY1, rectX2, rectY2;
+  int minX, minY, maxX, maxY;
+  minX = maxX = rects[0].x;
+  minY = maxY = rects[0].y;
+
+  for (int i = 0; i < nrects; i++) {
+    if (nrects <= MAX_RECTS_PER_OP) {
+      regRects[i].x = rects[i].x + pDrawable->x;
+      regRects[i].y = rects[i].y + pDrawable->y;
+      regRects[i].width = rects[i].width;
+      regRects[i].height = rects[i].height;
+    } else {
+      rectX1 = pDrawable->x + rects[i].x;
+      rectY1 = pDrawable->y + rects[i].y;
+      rectX2 = pDrawable->x + rects[i].x + rects[i].width;
+      rectY2 = pDrawable->y + rects[i].y + rects[i].height;
+      if (rectX1 < minX) minX = rectX1;
+      if (rectY1 < minY) minY = rectY1;
+      if (rectX2 > maxX) maxX = rectX2;
+      if (rectY2 > maxY) maxY = rectY2;
+    }
+  }
+
+  if (nrects > MAX_RECTS_PER_OP) {
+    regRects[0].x = minX;
+    regRects[0].y = minY;
+    regRects[0].width = maxX - minX;
+    regRects[0].height = maxY - minY;
+    nRegRects = 1;
+  }
+
+  RegionHelper changed(pScreen, nRegRects, regRects);
+
+  REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
+
+  (*pGC->ops->PolyFillRect) (pDrawable, pGC, nrects, rects);
+
+  vncHooksScreen->desktop->add_changed(changed.reg);
+}
+
+// PolyFillArc - changed region is the union of bounding rects around each arc,
+// clipped by pCompositeClip.  If there are more than MAX_RECTS_PER_OP arcs,
+// just use the bounding rect of all the arcs.
+
+static void vncHooksPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs,
+                                xArc *arcs)
+{
+  GC_OP_UNWRAPPER(pDrawable, pGC, PolyFillArc);
+
+  if (narcs == 0) {
+    (*pGC->ops->PolyFillArc) (pDrawable, pGC, narcs, arcs);
+    return;
+  }
+
+  xRectangle regRects[MAX_RECTS_PER_OP];
+  int nRegRects = narcs;
+
+  int lw = pGC->lineWidth;
+  if (lw == 0) lw = 1;
+  int extra = lw / 2;
+
+  int rectX1, rectY1, rectX2, rectY2;
+  int minX, minY, maxX, maxY;
+
+  minX = maxX = arcs[0].x;
+  minY = maxY = arcs[0].y;
+
+  for (int i = 0; i < narcs; i++) {
+    if (narcs <= MAX_RECTS_PER_OP) {
+      regRects[i].x = arcs[i].x - extra + pDrawable->x;
+      regRects[i].y = arcs[i].y - extra + pDrawable->y;
+      regRects[i].width = arcs[i].width + lw;
+      regRects[i].height = arcs[i].height + lw;
+    } else {
+      rectX1 = pDrawable->x + arcs[i].x - extra;
+      rectY1 = pDrawable->y + arcs[i].y - extra;
+      rectX2 = pDrawable->x + arcs[i].x + arcs[i].width + lw;
+      rectY2 = pDrawable->y + arcs[i].y + arcs[i].height + lw;
+      if (rectX1 < minX) minX = rectX1;
+      if (rectY1 < minY) minY = rectY1;
+      if (rectX2 > maxX) maxX = rectX2;
+      if (rectY2 > maxY) maxY = rectY2;
+    }
+  }
+
+  if (narcs > MAX_RECTS_PER_OP) {
+    regRects[0].x = minX;
+    regRects[0].y = minY;
+    regRects[0].width = maxX - minX;
+    regRects[0].height = maxY - minY;
+    nRegRects = 1;
+  }
+
+  RegionHelper changed(pScreen, nRegRects, regRects);
+
+  REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
+
+  (*pGC->ops->PolyFillArc) (pDrawable, pGC, narcs, arcs);
+
+  vncHooksScreen->desktop->add_changed(changed.reg);
+}
+
+// GetTextBoundingRect - calculate a bounding rectangle around n chars of a
+// font.  Not particularly accurate, but good enough.
+
+static void GetTextBoundingRect(DrawablePtr pDrawable, FontPtr font, int x,
+                                int y, int nchars, BoxPtr box)
+{
+  int ascent = __rfbmax(FONTASCENT(font), FONTMAXBOUNDS(font, ascent));
+  int descent = __rfbmax(FONTDESCENT(font), FONTMAXBOUNDS(font, descent));
+  int charWidth = __rfbmax(FONTMAXBOUNDS(font,rightSideBearing),
+                           FONTMAXBOUNDS(font,characterWidth));
+
+  box->x1 = pDrawable->x + x;
+  box->y1 = pDrawable->y + y - ascent;
+  box->x2 = box->x1 + charWidth * nchars;
+  box->y2 = box->y1 + ascent + descent;
+
+  if (FONTMINBOUNDS(font,leftSideBearing) < 0)
+    box->x1 += FONTMINBOUNDS(font,leftSideBearing);
+}
+
+// PolyText8 - changed region is bounding rect around count chars, clipped by
+// pCompositeClip
+
+static int vncHooksPolyText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
+                             int count, char *chars)
+{
+  GC_OP_UNWRAPPER(pDrawable, pGC, PolyText8);
+
+  if (count == 0)
+    return (*pGC->ops->PolyText8) (pDrawable, pGC, x, y, count, chars);
+
+  BoxRec box;
+  GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box);
+
+  RegionHelper changed(pScreen, &box, 0);
+
+  REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
+
+  int ret = (*pGC->ops->PolyText8) (pDrawable, pGC, x, y, count, chars);
+
+  vncHooksScreen->desktop->add_changed(changed.reg);
+
+  return ret;
+}
+
+// PolyText16 - changed region is bounding rect around count chars, clipped by
+// pCompositeClip
+
+static int vncHooksPolyText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
+                              int count, unsigned short *chars)
+{
+  GC_OP_UNWRAPPER(pDrawable, pGC, PolyText16);
+
+  if (count == 0)
+    return (*pGC->ops->PolyText16) (pDrawable, pGC, x, y, count, chars);
+
+  BoxRec box;
+  GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box);
+
+  RegionHelper changed(pScreen, &box, 0);
+
+  REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
+
+  int ret = (*pGC->ops->PolyText16) (pDrawable, pGC, x, y, count, chars);
+
+  vncHooksScreen->desktop->add_changed(changed.reg);
+
+  return ret;
+}
+
+// ImageText8 - changed region is bounding rect around count chars, clipped by
+// pCompositeClip
+
+static void vncHooksImageText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
+                               int count, char *chars)
+{
+  GC_OP_UNWRAPPER(pDrawable, pGC, ImageText8);
+
+  if (count == 0) {
+    (*pGC->ops->ImageText8) (pDrawable, pGC, x, y, count, chars);
+    return;
+  }
+
+  BoxRec box;
+  GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box);
+
+  RegionHelper changed(pScreen, &box, 0);
+
+  REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
+
+  (*pGC->ops->ImageText8) (pDrawable, pGC, x, y, count, chars);
+
+  vncHooksScreen->desktop->add_changed(changed.reg);
+}
+
+// ImageText16 - changed region is bounding rect around count chars, clipped by
+// pCompositeClip
+
+static void vncHooksImageText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
+                                int count, unsigned short *chars)
+{
+  GC_OP_UNWRAPPER(pDrawable, pGC, ImageText16);
+
+  if (count == 0) {
+    (*pGC->ops->ImageText16) (pDrawable, pGC, x, y, count, chars);
+    return;
+  }
+
+  BoxRec box;
+  GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box);
+
+  RegionHelper changed(pScreen, &box, 0);
+
+  REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
+
+  (*pGC->ops->ImageText16) (pDrawable, pGC, x, y, count, chars);
+
+  vncHooksScreen->desktop->add_changed(changed.reg);
+}
+
+// ImageGlyphBlt - changed region is bounding rect around nglyph chars, clipped
+// by pCompositeClip
+
+static void vncHooksImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x,
+                                  int y, unsigned int nglyph,
+                                  CharInfoPtr *ppci, pointer pglyphBase)
+{
+  GC_OP_UNWRAPPER(pDrawable, pGC, ImageGlyphBlt);
+
+  if (nglyph == 0) {
+    (*pGC->ops->ImageGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci,pglyphBase);
+    return;
+  }
+
+  BoxRec box;
+  GetTextBoundingRect(pDrawable, pGC->font, x, y, nglyph, &box);
+
+  RegionHelper changed(pScreen, &box, 0);
+
+  REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
+
+  (*pGC->ops->ImageGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
+
+  vncHooksScreen->desktop->add_changed(changed.reg);
+}
+
+// PolyGlyphBlt - changed region is bounding rect around nglyph chars, clipped
+// by pCompositeClip
+
+static void vncHooksPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x,
+                                 int y, unsigned int nglyph,
+                                 CharInfoPtr *ppci, pointer pglyphBase)
+{
+  GC_OP_UNWRAPPER(pDrawable, pGC, PolyGlyphBlt);
+
+  if (nglyph == 0) {
+    (*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci,pglyphBase);
+    return;
+  }
+
+  BoxRec box;
+  GetTextBoundingRect(pDrawable, pGC->font, x, y, nglyph, &box);
+
+  RegionHelper changed(pScreen, &box, 0);
+
+  REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
+
+  (*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
+
+  vncHooksScreen->desktop->add_changed(changed.reg);
+}
+
+// PushPixels - changed region is the given rectangle, clipped by
+// pCompositeClip
+
+static void vncHooksPushPixels(GCPtr pGC, PixmapPtr pBitMap,
+                               DrawablePtr pDrawable, int w, int h, int x,
+                               int y)
+{
+  GC_OP_UNWRAPPER(pDrawable, pGC, PushPixels);
+
+  BoxRec box;
+  box.x1 = x + pDrawable->x;
+  box.y1 = y + pDrawable->y;
+  box.x2 = box.x1 + w;
+  box.y2 = box.y1 + h;
+
+  RegionHelper changed(pScreen, &box, 0);
+
+  REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
+
+  (*pGC->ops->PushPixels) (pGC, pBitMap, pDrawable, w, h, x, y);
+
+  vncHooksScreen->desktop->add_changed(changed.reg);
+}
diff --git a/unix/xserver/hw/vnc/vncHooks.h b/unix/xserver/hw/vnc/vncHooks.h
new file mode 100644 (file)
index 0000000..c556ef3
--- /dev/null
@@ -0,0 +1,26 @@
+/* Copyright (C) 2002-2005 RealVNC Ltd.  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.
+ */
+#ifndef __VNCHOOKS_H__
+#define __VNCHOOKS_H__
+
+extern "C" {
+#include <screenint.h>
+  extern Bool vncHooksInit(ScreenPtr pScreen, XserverDesktop* desktop);
+}
+
+#endif
diff --git a/unix/xserver/hw/vnc/xf86vncModule.cc b/unix/xserver/hw/vnc/xf86vncModule.cc
new file mode 100644 (file)
index 0000000..ef8ea50
--- /dev/null
@@ -0,0 +1,97 @@
+/* Copyright (C) 2002-2005 RealVNC Ltd.  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.
+ */
+/*  This is the xf86 module code for the vnc extension.
+ */
+
+#include <rfb/Configuration.h>
+#include <rfb/Logger_stdio.h>
+#include <rfb/LogWriter.h>
+
+extern "C" {
+#define class c_class
+#define private c_private
+#define bool c_bool
+#define new c_new
+#include "xf86.h"
+#include "xf86Module.h"
+#undef class
+#undef private
+#undef bool
+#undef new
+
+using namespace rfb;
+
+extern void vncExtensionInit();
+static void vncExtensionInitWithParams(INITARGS);
+
+#ifdef XFree86LOADER
+
+static MODULESETUPPROTO(vncSetup);
+
+ExtensionModule vncExt =
+{
+    vncExtensionInitWithParams,
+    "VNC",
+    NULL,
+    NULL,
+    NULL
+};
+
+static XF86ModuleVersionInfo vncVersRec =
+{
+    "vnc",
+    "Constantin Kaplinsky",
+    MODINFOSTRING1,
+    MODINFOSTRING2,
+    XF86_VERSION_CURRENT,
+    1, 0, 0,
+    ABI_CLASS_EXTENSION,         /* needs the server extension ABI */
+    ABI_EXTENSION_VERSION,
+    MOD_CLASS_EXTENSION,
+    {0,0,0,0}
+};
+
+XF86ModuleData vncModuleData = { &vncVersRec, vncSetup, NULL };
+
+static pointer
+vncSetup(pointer module, pointer opts, int *errmaj, int *errmin) {
+    LoadExtension(&vncExt, FALSE);
+    /* Need a non-NULL return value to indicate success */
+    return (pointer)1;
+}
+
+static void vncExtensionInitWithParams(INITARGS)
+{
+  rfb::initStdIOLoggers();
+  rfb::LogWriter::setLogParams("*:stderr:30");
+
+  for (int scr = 0; scr < screenInfo.numScreens; scr++) {
+    ScrnInfoPtr pScrn = xf86Screens[scr];
+
+    for (ParameterIterator i(Configuration::global()); i.param; i.next()) {
+      char* val = xf86FindOptionValue(pScrn->options, i.param->getName());
+      if (val)
+        i.param->setParam(val);
+    }
+  }
+
+  vncExtensionInit();
+}
+
+#endif /* XFree86LOADER */
+}
diff --git a/unix/xserver/hw/vnc/xvnc.cc b/unix/xserver/hw/vnc/xvnc.cc
new file mode 100644 (file)
index 0000000..5daf663
--- /dev/null
@@ -0,0 +1,1472 @@
+/* Copyright (c) 1993  X Consortium
+   Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
+
+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.
+
+*/
+
+#include <rfb/Configuration.h>
+#include <rfb/Logger_stdio.h>
+#include <rfb/LogWriter.h>
+#include <network/TcpSocket.h>
+#include "vncExtInit.h"
+
+extern "C" {
+#define class c_class
+#define public c_public
+#define xor c_xor
+#define and c_and
+#ifdef WIN32
+#include <X11/Xwinsock.h>
+#endif
+#include <stdio.h>
+#include "X11/X.h"
+#define NEED_EVENTS
+#include "X11/Xproto.h"
+#include "X11/Xos.h"
+#include "scrnintstr.h"
+#include "servermd.h"
+#include "fb.h"
+#include "mi.h"
+#include "mibstore.h"
+#include "colormapst.h"
+#include "gcstruct.h"
+#include "input.h"
+#include "mipointer.h"
+#define new New
+#include "micmap.h"
+#undef new
+#include <sys/types.h>
+#ifdef HAS_MMAP
+#include <sys/mman.h>
+#ifndef MAP_FILE
+#define MAP_FILE 0
+#endif
+#endif /* HAS_MMAP */
+#include <sys/stat.h>
+#include <errno.h>
+#ifndef WIN32
+#include <sys/param.h>
+#endif
+#include <X11/XWDFile.h>
+#ifdef HAS_SHM
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#endif /* HAS_SHM */
+#include "dix.h"
+#include "miline.h"
+#include "inputstr.h"
+#include "keysym.h"
+  extern int defaultColorVisualClass;
+  extern char buildtime[];
+#undef class
+#undef public
+#undef xor
+#undef and
+}
+
+#define XVNCVERSION "TightVNC 1.5 series"
+#define XVNCCOPYRIGHT ("Copyright (C) 2002-2005 RealVNC Ltd.\n" \
+                      "Copyright (C) 2000-2006 Constantin Kaplinsky\n" \
+                      "Copyright (C) 2004-2006 Peter Astrand, Cendio AB\n" \
+                       "See http://www.tightvnc.com for information on TightVNC.\n")
+
+
+extern char *display;
+extern int monitorResolution;
+
+#define VFB_DEFAULT_WIDTH  1024
+#define VFB_DEFAULT_HEIGHT 768
+#define VFB_DEFAULT_DEPTH  16
+#define VFB_DEFAULT_WHITEPIXEL 0xffff
+#define VFB_DEFAULT_BLACKPIXEL 0
+#define VFB_DEFAULT_LINEBIAS 0
+#define XWD_WINDOW_NAME_LEN 60
+
+typedef struct
+{
+    int scrnum;
+    int width;
+    int paddedBytesWidth;
+    int paddedWidth;
+    int height;
+    int depth;
+    int bitsPerPixel;
+    int sizeInBytes;
+    int ncolors;
+    char *pfbMemory;
+    XWDColor *pXWDCmap;
+    XWDFileHeader *pXWDHeader;
+    Pixel blackPixel;
+    Pixel whitePixel;
+    unsigned int lineBias;
+    CloseScreenProcPtr closeScreen;
+
+#ifdef HAS_MMAP
+    int mmap_fd;
+    char mmap_file[MAXPATHLEN];
+#endif
+
+#ifdef HAS_SHM
+    int shmid;
+#endif
+
+    Bool pixelFormatDefined;
+    Bool rgbNotBgr;
+    int redBits, greenBits, blueBits;
+
+} vfbScreenInfo, *vfbScreenInfoPtr;
+
+static int vfbNumScreens;
+static vfbScreenInfo vfbScreens[MAXSCREENS];
+static Bool vfbPixmapDepths[33];
+#ifdef HAS_MMAP
+static char *pfbdir = NULL;
+#endif
+typedef enum { NORMAL_MEMORY_FB, SHARED_MEMORY_FB, MMAPPED_FILE_FB } fbMemType;
+static fbMemType fbmemtype = NORMAL_MEMORY_FB;
+static char needswap = 0;
+static int lastScreen = -1;
+static Bool Render = TRUE;
+
+static bool displaySpecified = false;
+static bool wellKnownSocketsCreated = false;
+static char displayNumStr[16];
+
+#define swapcopy16(_dst, _src) \
+    if (needswap) { CARD16 _s = _src; cpswaps(_s, _dst); } \
+    else _dst = _src;
+
+#define swapcopy32(_dst, _src) \
+    if (needswap) { CARD32 _s = _src; cpswapl(_s, _dst); } \
+    else _dst = _src;
+
+
+static void
+vfbInitializePixmapDepths(void)
+{
+    int i;
+    vfbPixmapDepths[1] = TRUE; /* always need bitmaps */
+    for (i = 2; i <= 32; i++)
+       vfbPixmapDepths[i] = FALSE;
+}
+
+static void
+vfbInitializeDefaultScreens(void)
+{
+    int i;
+
+    for (i = 0; i < MAXSCREENS; i++)
+    {
+       vfbScreens[i].scrnum = i;
+       vfbScreens[i].width  = VFB_DEFAULT_WIDTH;
+       vfbScreens[i].height = VFB_DEFAULT_HEIGHT;
+       vfbScreens[i].depth  = VFB_DEFAULT_DEPTH;
+       vfbScreens[i].blackPixel = VFB_DEFAULT_BLACKPIXEL;
+       vfbScreens[i].whitePixel = VFB_DEFAULT_WHITEPIXEL;
+       vfbScreens[i].lineBias = VFB_DEFAULT_LINEBIAS;
+       vfbScreens[i].pixelFormatDefined = FALSE;
+       vfbScreens[i].pfbMemory = NULL;
+    }
+    vfbNumScreens = 1;
+}
+
+static int
+vfbBitsPerPixel(int depth)
+{
+    if (depth == 1) return 1;
+    else if (depth <= 8) return 8;
+    else if (depth <= 16) return 16;
+    else return 32;
+}
+
+
+extern "C" {
+
+  void ddxGiveUp()
+  {
+    int i;
+
+    /* clean up the framebuffers */
+
+    switch (fbmemtype)
+    {
+#ifdef HAS_MMAP
+    case MMAPPED_FILE_FB: 
+       for (i = 0; i < vfbNumScreens; i++)
+       {
+           if (-1 == unlink(vfbScreens[i].mmap_file))
+           {
+               perror("unlink");
+               ErrorF("unlink %s failed, errno %d",
+                      vfbScreens[i].mmap_file, errno);
+           }
+       }
+       break;
+#else /* HAS_MMAP */
+    case MMAPPED_FILE_FB:
+        break;
+#endif /* HAS_MMAP */
+       
+#ifdef HAS_SHM
+    case SHARED_MEMORY_FB:
+       for (i = 0; i < vfbNumScreens; i++)
+       {
+           if (-1 == shmdt((char *)vfbScreens[i].pXWDHeader))
+           {
+               perror("shmdt");
+               ErrorF("shmdt failed, errno %d", errno);
+           }
+       }
+       break;
+#else /* HAS_SHM */
+    case SHARED_MEMORY_FB:
+        break;
+#endif /* HAS_SHM */
+       
+    case NORMAL_MEMORY_FB:
+       for (i = 0; i < vfbNumScreens; i++)
+       {
+           Xfree(vfbScreens[i].pXWDHeader);
+       }
+       break;
+    }
+}
+
+void
+AbortDDX()
+{
+    ddxGiveUp();
+}
+
+#ifdef __DARWIN__
+void
+DarwinHandleGUI(int argc, char *argv[])
+{
+}
+
+void GlxExtensionInit();
+void GlxWrapInitVisuals(void *procPtr);
+
+void
+DarwinGlxExtensionInit()
+{
+    GlxExtensionInit();
+}
+
+void
+DarwinGlxWrapInitVisuals(
+    void *procPtr)
+{
+    GlxWrapInitVisuals(procPtr);
+}
+#endif
+
+void
+OsVendorInit()
+{
+}
+
+void
+OsVendorFatalError()
+{
+}
+
+void ddxBeforeReset(void)
+{
+    return;
+}
+
+void 
+ddxUseMsg()
+{
+    ErrorF("\nXvnc %s - built %s\n%s", XVNCVERSION, buildtime, XVNCCOPYRIGHT);
+    ErrorF("Underlying X server release %d, %s\n\n", VENDOR_RELEASE,
+           VENDOR_STRING);
+    ErrorF("-screen scrn WxHxD     set screen's width, height, depth\n");
+    ErrorF("-pixdepths list-of-int support given pixmap depths\n");
+#ifdef RENDER
+    ErrorF("+/-render             turn on/off RENDER extension support"
+          "(default on)\n");
+#endif
+    ErrorF("-linebias n            adjust thin line pixelization\n");
+    ErrorF("-blackpixel n          pixel value for black\n");
+    ErrorF("-whitepixel n          pixel value for white\n");
+
+#ifdef HAS_MMAP
+    ErrorF("-fbdir directory       put framebuffers in mmap'ed files in directory\n");
+#endif
+
+#ifdef HAS_SHM
+    ErrorF("-shmem                 put framebuffers in shared memory\n");
+#endif
+
+    ErrorF("-geometry WxH          set screen 0's width, height\n");
+    ErrorF("-depth D               set screen 0's depth\n");
+    ErrorF("-pixelformat fmt       set pixel format (rgbNNN or bgrNNN)\n");
+    ErrorF("-inetd                 has been launched from inetd\n");
+    ErrorF("\nVNC parameters:\n");
+
+    fprintf(stderr,"\n"
+            "Parameters can be turned on with -<param> or off with -<param>=0\n"
+            "Parameters which take a value can be specified as "
+            "-<param> <value>\n"
+            "Other valid forms are <param>=<value> -<param>=<value> "
+            "--<param>=<value>\n"
+            "Parameter names are case-insensitive.  The parameters are:\n\n");
+    rfb::Configuration::listParams(79, 14);
+  }
+}
+
+/* ddxInitGlobals - called by |InitGlobals| from os/util.c */
+void ddxInitGlobals(void)
+{
+}
+
+static 
+bool displayNumFree(int num)
+{
+    try {
+       network::TcpListener l(6000+num);
+    } catch (rdr::Exception& e) {
+       return false;
+    }
+    char file[256];
+    sprintf(file, "/tmp/.X%d-lock", num);
+    if (access(file, F_OK) == 0) return false;
+    sprintf(file, "/tmp/.X11-unix/X%d", num);
+    if (access(file, F_OK) == 0) return false;
+    sprintf(file, "/usr/spool/sockets/X11/%d", num);
+    if (access(file, F_OK) == 0) return false;
+    return true;
+}
+
+int 
+ddxProcessArgument(int argc, char *argv[], int i)
+{
+    static Bool firstTime = TRUE;
+
+    if (firstTime)
+    {
+       vfbInitializeDefaultScreens();
+       vfbInitializePixmapDepths();
+       firstTime = FALSE;
+       rfb::initStdIOLoggers();
+       rfb::LogWriter::setLogParams("*:stderr:30");
+    }
+
+    if (argv[i][0] ==  ':')
+       displaySpecified = true;
+
+    if (strcmp (argv[i], "-screen") == 0)      /* -screen n WxHxD */
+    {
+       int screenNum;
+       if (i + 2 >= argc) UseMsg();
+       screenNum = atoi(argv[i+1]);
+       if (screenNum < 0 || screenNum >= MAXSCREENS)
+       {
+           ErrorF("Invalid screen number %d\n", screenNum);
+           UseMsg();
+       }
+       if (3 != sscanf(argv[i+2], "%dx%dx%d",
+                       &vfbScreens[screenNum].width,
+                       &vfbScreens[screenNum].height,
+                       &vfbScreens[screenNum].depth))
+       {
+           ErrorF("Invalid screen configuration %s\n", argv[i+2]);
+           UseMsg();
+       }
+
+       if (screenNum >= vfbNumScreens)
+           vfbNumScreens = screenNum + 1;
+       lastScreen = screenNum;
+       return 3;
+    }
+
+    if (strcmp (argv[i], "-pixdepths") == 0)   /* -pixdepths list-of-depth */
+    {
+       int depth, ret = 1;
+
+       if (++i >= argc) UseMsg();
+       while ((i < argc) && (depth = atoi(argv[i++])) != 0)
+       {
+           if (depth < 0 || depth > 32)
+           {
+               ErrorF("Invalid pixmap depth %d\n", depth);
+               UseMsg();
+           }
+           vfbPixmapDepths[depth] = TRUE;
+           ret++;
+       }
+       return ret;
+    }
+    
+    if (strcmp (argv[i], "+render") == 0)      /* +render */
+    {
+       Render = TRUE;
+       return 1;
+    }
+  
+    if (strcmp (argv[i], "-render") == 0)      /* -render */
+    {
+       Render = FALSE;
+       return 1;
+    }
+
+    if (strcmp (argv[i], "-blackpixel") == 0)  /* -blackpixel n */
+    {
+       Pixel pix;
+       if (++i >= argc) UseMsg();
+       pix = atoi(argv[i]);
+       if (-1 == lastScreen)
+       {
+           int i;
+           for (i = 0; i < MAXSCREENS; i++)
+           {
+               vfbScreens[i].blackPixel = pix;
+           }
+       }
+       else
+       {
+           vfbScreens[lastScreen].blackPixel = pix;
+       }
+       return 2;
+    }
+
+    if (strcmp (argv[i], "-whitepixel") == 0)  /* -whitepixel n */
+    {
+       Pixel pix;
+       if (++i >= argc) UseMsg();
+       pix = atoi(argv[i]);
+       if (-1 == lastScreen)
+       {
+           int i;
+           for (i = 0; i < MAXSCREENS; i++)
+           {
+               vfbScreens[i].whitePixel = pix;
+           }
+       }
+       else
+       {
+           vfbScreens[lastScreen].whitePixel = pix;
+       }
+       return 2;
+    }
+    
+    if (strcmp (argv[i], "-linebias") == 0)    /* -linebias n */
+    {
+       unsigned int linebias;
+       if (++i >= argc) UseMsg();
+       linebias = atoi(argv[i]);
+       if (-1 == lastScreen)
+       {
+           int i;
+           for (i = 0; i < MAXSCREENS; i++)
+           {
+               vfbScreens[i].lineBias = linebias;
+           }
+       }
+       else
+       {
+           vfbScreens[lastScreen].lineBias = linebias;
+       }
+       return 2;
+    }
+
+#ifdef HAS_MMAP
+    if (strcmp (argv[i], "-fbdir") == 0)       /* -fbdir directory */
+    {
+       if (++i >= argc) UseMsg();
+       pfbdir = argv[i];
+       fbmemtype = MMAPPED_FILE_FB;
+       return 2;
+    }
+#endif /* HAS_MMAP */
+
+#ifdef HAS_SHM
+    if (strcmp (argv[i], "-shmem") == 0)       /* -shmem */
+    {
+       fbmemtype = SHARED_MEMORY_FB;
+       return 1;
+    }
+#endif
+    
+    if (strcmp(argv[i], "-geometry") == 0)
+    {
+       if (++i >= argc) UseMsg();
+       if (sscanf(argv[i],"%dx%d",&vfbScreens[0].width,
+                  &vfbScreens[0].height) != 2) {
+           ErrorF("Invalid geometry %s\n", argv[i]);
+           UseMsg();
+       }
+       return 2;
+    }
+    
+    if (strcmp(argv[i], "-depth") == 0)
+    {
+       if (++i >= argc) UseMsg();
+       vfbScreens[0].depth = atoi(argv[i]);
+       return 2;
+    }
+
+    if (strcmp(argv[i], "-pixelformat") == 0)
+    {
+       char rgbbgr[4];
+       int bits1, bits2, bits3;
+       if (++i >= argc) UseMsg();
+       if (sscanf(argv[i], "%3s%1d%1d%1d", rgbbgr,&bits1,&bits2,&bits3) < 4) {
+           ErrorF("Invalid pixel format %s\n", argv[i]);
+           UseMsg();
+       }
+
+#define SET_PIXEL_FORMAT(vfbScreen)                     \
+    (vfbScreen).pixelFormatDefined = TRUE;              \
+    (vfbScreen).depth = bits1 + bits2 + bits3;          \
+    (vfbScreen).greenBits = bits2;                      \
+    if (strcasecmp(rgbbgr, "bgr") == 0) {               \
+        (vfbScreen).rgbNotBgr = FALSE;                  \
+        (vfbScreen).redBits = bits3;                    \
+        (vfbScreen).blueBits = bits1;                   \
+    } else if (strcasecmp(rgbbgr, "rgb") == 0) {        \
+        (vfbScreen).rgbNotBgr = TRUE;                   \
+        (vfbScreen).redBits = bits1;                    \
+        (vfbScreen).blueBits = bits3;                   \
+    } else {                                            \
+        ErrorF("Invalid pixel format %s\n", argv[i]);   \
+        UseMsg();                                       \
+    }
+
+       if (-1 == lastScreen)
+       {
+           int i;
+           for (i = 0; i < MAXSCREENS; i++)
+           {
+               SET_PIXEL_FORMAT(vfbScreens[i]);
+           }
+       }
+       else
+       {
+           SET_PIXEL_FORMAT(vfbScreens[lastScreen]);
+       }
+
+       return 2;
+    }
+
+    if (strcmp(argv[i], "-inetd") == 0)
+    {
+       dup2(0,3);
+       vncInetdSock = 3;
+       close(2);
+       
+       if (!displaySpecified) {
+           int port = network::TcpSocket::getSockPort(vncInetdSock);
+           int displayNum = port - 5900;
+           if (displayNum < 0 || displayNum > 99 || !displayNumFree(displayNum)) {
+               for (displayNum = 1; displayNum < 100; displayNum++)
+                   if (displayNumFree(displayNum)) break;
+               
+               if (displayNum == 100)
+                   FatalError("Xvnc error: no free display number for -inetd");
+           }
+           
+           display = displayNumStr;
+           sprintf(displayNumStr, "%d", displayNum);
+       }
+       
+       return 1;
+    }
+    
+    if (rfb::Configuration::setParam(argv[i]))
+       return 1;
+    
+    if (argv[i][0] == '-' && i+1 < argc) {
+       if (rfb::Configuration::setParam(&argv[i][1], argv[i+1]))
+           return 2;
+    }
+    
+    return 0;
+}
+
+#ifdef DDXTIME /* from ServerOSDefines */
+CARD32
+GetTimeInMillis()
+{
+    struct timeval  tp;
+
+    X_GETTIMEOFDAY(&tp);
+    return(tp.tv_sec * 1000) + (tp.tv_usec / 1000);
+}
+#endif
+
+static ColormapPtr InstalledMaps[MAXSCREENS];
+
+static int 
+vfbListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps)
+{
+    /* By the time we are processing requests, we can guarantee that there
+     * is always a colormap installed */
+    *pmaps = InstalledMaps[pScreen->myNum]->mid;
+    return (1);
+}
+
+
+static void 
+vfbInstallColormap(ColormapPtr pmap)
+{
+    int index = pmap->pScreen->myNum;
+    ColormapPtr oldpmap = InstalledMaps[index];
+
+    if (pmap != oldpmap)
+    {
+       int entries;
+       XWDFileHeader *pXWDHeader;
+       XWDColor *pXWDCmap;
+       VisualPtr pVisual;
+       Pixel *     ppix;
+       xrgb *      prgb;
+       xColorItem *defs;
+       int i;
+
+       if(oldpmap != (ColormapPtr)None)
+           WalkTree(pmap->pScreen, TellLostMap, (char *)&oldpmap->mid);
+       /* Install pmap */
+       InstalledMaps[index] = pmap;
+       WalkTree(pmap->pScreen, TellGainedMap, (char *)&pmap->mid);
+
+       entries = pmap->pVisual->ColormapEntries;
+       pXWDHeader = vfbScreens[pmap->pScreen->myNum].pXWDHeader;
+       pXWDCmap = vfbScreens[pmap->pScreen->myNum].pXWDCmap;
+       pVisual = pmap->pVisual;
+
+       swapcopy32(pXWDHeader->visual_class, pVisual->c_class);
+       swapcopy32(pXWDHeader->red_mask, pVisual->redMask);
+       swapcopy32(pXWDHeader->green_mask, pVisual->greenMask);
+       swapcopy32(pXWDHeader->blue_mask, pVisual->blueMask);
+       swapcopy32(pXWDHeader->bits_per_rgb, pVisual->bitsPerRGBValue);
+       swapcopy32(pXWDHeader->colormap_entries, pVisual->ColormapEntries);
+
+       ppix = (Pixel *)ALLOCATE_LOCAL(entries * sizeof(Pixel));
+       prgb = (xrgb *)ALLOCATE_LOCAL(entries * sizeof(xrgb));
+       defs = (xColorItem *)ALLOCATE_LOCAL(entries * sizeof(xColorItem));
+
+       for (i = 0; i < entries; i++)  ppix[i] = i;
+       /* XXX truecolor */
+       QueryColors(pmap, entries, ppix, prgb);
+
+       for (i = 0; i < entries; i++) { /* convert xrgbs to xColorItems */
+           defs[i].pixel = ppix[i] & 0xff; /* change pixel to index */
+           defs[i].red = prgb[i].red;
+           defs[i].green = prgb[i].green;
+           defs[i].blue = prgb[i].blue;
+           defs[i].flags =  DoRed|DoGreen|DoBlue;
+       }
+       (*pmap->pScreen->StoreColors)(pmap, entries, defs);
+       
+       DEALLOCATE_LOCAL(ppix);
+       DEALLOCATE_LOCAL(prgb);
+       DEALLOCATE_LOCAL(defs);
+    }
+}
+
+static void
+vfbUninstallColormap(ColormapPtr pmap)
+{
+    ColormapPtr curpmap = InstalledMaps[pmap->pScreen->myNum];
+
+    if(pmap == curpmap)
+    {
+       if (pmap->mid != pmap->pScreen->defColormap)
+       {
+           curpmap = (ColormapPtr) LookupIDByType(pmap->pScreen->defColormap,
+                                                  RT_COLORMAP);
+           (*pmap->pScreen->InstallColormap)(curpmap);
+       }
+    }
+}
+
+static void
+vfbStoreColors(ColormapPtr pmap, int ndef, xColorItem *pdefs)
+{
+    XWDColor *pXWDCmap;
+    int i;
+
+    if (pmap != InstalledMaps[pmap->pScreen->myNum])
+    {
+       return;
+    }
+
+    pXWDCmap = vfbScreens[pmap->pScreen->myNum].pXWDCmap;
+
+    if ((pmap->pVisual->c_class | DynamicClass) == DirectColor)
+    {
+       return;
+    }
+
+    for (i = 0; i < ndef; i++)
+    {
+       if (pdefs[i].flags & DoRed)
+       {
+           swapcopy16(pXWDCmap[pdefs[i].pixel].red, pdefs[i].red);
+       }
+       if (pdefs[i].flags & DoGreen)
+       {
+           swapcopy16(pXWDCmap[pdefs[i].pixel].green, pdefs[i].green);
+       }
+       if (pdefs[i].flags & DoBlue)
+       {
+           swapcopy16(pXWDCmap[pdefs[i].pixel].blue, pdefs[i].blue);
+       }
+    }
+}
+
+static Bool
+vfbSaveScreen(ScreenPtr pScreen, int on)
+{
+    return TRUE;
+}
+
+#ifdef HAS_MMAP
+
+/* this flushes any changes to the screens out to the mmapped file */
+static void
+vfbBlockHandler(pointer blockData, OSTimePtr pTimeout, pointer pReadmask)
+{
+    int i;
+
+    for (i = 0; i < vfbNumScreens; i++)
+    {
+#ifdef MS_ASYNC
+       if (-1 == msync((caddr_t)vfbScreens[i].pXWDHeader,
+                       (size_t)vfbScreens[i].sizeInBytes, MS_ASYNC))
+#else
+       /* silly NetBSD and who else? */
+       if (-1 == msync((caddr_t)vfbScreens[i].pXWDHeader,
+                       (size_t)vfbScreens[i].sizeInBytes))
+#endif
+       {
+           perror("msync");
+           ErrorF("msync failed, errno %d", errno);
+       }
+    }
+}
+
+
+static void
+vfbWakeupHandler(pointer blockData, int result, pointer pReadmask)
+{
+}
+
+
+static void
+vfbAllocateMmappedFramebuffer(vfbScreenInfoPtr pvfb)
+{
+#define DUMMY_BUFFER_SIZE 65536
+    char dummyBuffer[DUMMY_BUFFER_SIZE];
+    int currentFileSize, writeThisTime;
+
+    sprintf(pvfb->mmap_file, "%s/Xvfb_screen%d", pfbdir, pvfb->scrnum);
+    if (-1 == (pvfb->mmap_fd = open(pvfb->mmap_file, O_CREAT|O_RDWR, 0666)))
+    {
+       perror("open");
+       ErrorF("open %s failed, errno %d", pvfb->mmap_file, errno);
+       return;
+    }
+
+    /* Extend the file to be the proper size */
+
+    bzero(dummyBuffer, DUMMY_BUFFER_SIZE);
+    for (currentFileSize = 0;
+        currentFileSize < pvfb->sizeInBytes;
+        currentFileSize += writeThisTime)
+    {
+       writeThisTime = min(DUMMY_BUFFER_SIZE,
+                           pvfb->sizeInBytes - currentFileSize);
+       if (-1 == write(pvfb->mmap_fd, dummyBuffer, writeThisTime))
+       {
+           perror("write");
+           ErrorF("write %s failed, errno %d", pvfb->mmap_file, errno);
+           return;
+       }
+    }
+
+    /* try to mmap the file */
+
+    pvfb->pXWDHeader = (XWDFileHeader *)mmap((caddr_t)NULL, pvfb->sizeInBytes,
+                                   PROT_READ|PROT_WRITE,
+                                   MAP_FILE|MAP_SHARED,
+                                   pvfb->mmap_fd, 0);
+    if (-1 == (long)pvfb->pXWDHeader)
+    {
+       perror("mmap");
+       ErrorF("mmap %s failed, errno %d", pvfb->mmap_file, errno);
+       pvfb->pXWDHeader = NULL;
+       return;
+    }
+
+    if (!RegisterBlockAndWakeupHandlers(vfbBlockHandler, vfbWakeupHandler,
+                                       NULL))
+    {
+       pvfb->pXWDHeader = NULL;
+    }
+}
+#endif /* HAS_MMAP */
+
+
+#ifdef HAS_SHM
+static void
+vfbAllocateSharedMemoryFramebuffer(vfbScreenInfoPtr pvfb)
+{
+    /* create the shared memory segment */
+
+    pvfb->shmid = shmget(IPC_PRIVATE, pvfb->sizeInBytes, IPC_CREAT|0777);
+    if (pvfb->shmid < 0)
+    {
+       perror("shmget");
+       ErrorF("shmget %d bytes failed, errno %d", pvfb->sizeInBytes, errno);
+       return;
+    }
+
+    /* try to attach it */
+
+    pvfb->pXWDHeader = (XWDFileHeader *)shmat(pvfb->shmid, 0, 0);
+    if (-1 == (long)pvfb->pXWDHeader)
+    {
+       perror("shmat");
+       ErrorF("shmat failed, errno %d", errno);
+       pvfb->pXWDHeader = NULL; 
+       return;
+    }
+
+    ErrorF("screen %d shmid %d\n", pvfb->scrnum, pvfb->shmid);
+}
+#endif /* HAS_SHM */
+
+
+static char *
+vfbAllocateFramebufferMemory(vfbScreenInfoPtr pvfb)
+{
+    if (pvfb->pfbMemory) return pvfb->pfbMemory; /* already done */
+
+    pvfb->sizeInBytes = pvfb->paddedBytesWidth * pvfb->height;
+
+    /* Calculate how many entries in colormap.  This is rather bogus, because
+     * the visuals haven't even been set up yet, but we need to know because we
+     * have to allocate space in the file for the colormap.  The number 10
+     * below comes from the MAX_PSEUDO_DEPTH define in cfbcmap.c.
+     */
+
+    if (pvfb->depth <= 10)
+    { /* single index colormaps */
+       pvfb->ncolors = 1 << pvfb->depth;
+    }
+    else
+    { /* decomposed colormaps */
+       int nplanes_per_color_component = pvfb->depth / 3;
+       if (pvfb->depth % 3) nplanes_per_color_component++;
+       pvfb->ncolors = 1 << nplanes_per_color_component;
+    }
+
+    /* add extra bytes for XWDFileHeader, window name, and colormap */
+
+    pvfb->sizeInBytes += SIZEOF(XWDheader) + XWD_WINDOW_NAME_LEN +
+                   pvfb->ncolors * SIZEOF(XWDColor);
+
+    pvfb->pXWDHeader = NULL; 
+    switch (fbmemtype)
+    {
+#ifdef HAS_MMAP
+    case MMAPPED_FILE_FB:  vfbAllocateMmappedFramebuffer(pvfb); break;
+#else
+    case MMAPPED_FILE_FB: break;
+#endif
+
+#ifdef HAS_SHM
+    case SHARED_MEMORY_FB: vfbAllocateSharedMemoryFramebuffer(pvfb); break;
+#else
+    case SHARED_MEMORY_FB: break;
+#endif
+
+    case NORMAL_MEMORY_FB:
+       pvfb->pXWDHeader = (XWDFileHeader *)Xalloc(pvfb->sizeInBytes);
+       break;
+    }
+
+    if (pvfb->pXWDHeader)
+    {
+       pvfb->pXWDCmap = (XWDColor *)((char *)pvfb->pXWDHeader
+                               + SIZEOF(XWDheader) + XWD_WINDOW_NAME_LEN);
+       pvfb->pfbMemory = (char *)(pvfb->pXWDCmap + pvfb->ncolors);
+
+       return pvfb->pfbMemory;
+    }
+    else
+       return NULL;
+}
+
+static void
+vfbWriteXWDFileHeader(ScreenPtr pScreen)
+{
+    vfbScreenInfoPtr pvfb = &vfbScreens[pScreen->myNum];
+    XWDFileHeader *pXWDHeader = pvfb->pXWDHeader;
+    char hostname[XWD_WINDOW_NAME_LEN];
+    unsigned long swaptest = 1;
+    int i;
+
+    needswap = *(char *) &swaptest;
+
+    pXWDHeader->header_size = (char *)pvfb->pXWDCmap - (char *)pvfb->pXWDHeader;
+    pXWDHeader->file_version = XWD_FILE_VERSION;
+
+    pXWDHeader->pixmap_format = ZPixmap;
+    pXWDHeader->pixmap_depth = pvfb->depth;
+    pXWDHeader->pixmap_height = pXWDHeader->window_height = pvfb->height;
+    pXWDHeader->xoffset = 0;
+    pXWDHeader->byte_order = IMAGE_BYTE_ORDER;
+    pXWDHeader->bitmap_bit_order = BITMAP_BIT_ORDER;
+#ifndef INTERNAL_VS_EXTERNAL_PADDING
+    pXWDHeader->pixmap_width = pXWDHeader->window_width = pvfb->width;
+    pXWDHeader->bitmap_unit = BITMAP_SCANLINE_UNIT;
+    pXWDHeader->bitmap_pad = BITMAP_SCANLINE_PAD;
+#else
+    pXWDHeader->pixmap_width = pXWDHeader->window_width = pvfb->paddedWidth;
+    pXWDHeader->bitmap_unit = BITMAP_SCANLINE_UNIT_PROTO;
+    pXWDHeader->bitmap_pad = BITMAP_SCANLINE_PAD_PROTO;
+#endif
+    pXWDHeader->bits_per_pixel = pvfb->bitsPerPixel;
+    pXWDHeader->bytes_per_line = pvfb->paddedBytesWidth;
+    pXWDHeader->ncolors = pvfb->ncolors;
+
+    /* visual related fields are written when colormap is installed */
+
+    pXWDHeader->window_x = pXWDHeader->window_y = 0;
+    pXWDHeader->window_bdrwidth = 0;
+
+    /* write xwd "window" name: Xvfb hostname:server.screen */
+
+    if (-1 == gethostname(hostname, sizeof(hostname)))
+       hostname[0] = 0;
+    else
+       hostname[XWD_WINDOW_NAME_LEN-1] = 0;
+    sprintf((char *)(pXWDHeader+1), "Xvfb %s:%s.%d", hostname, display,
+           pScreen->myNum);
+
+    /* write colormap pixel slot values */
+
+    for (i = 0; i < pvfb->ncolors; i++)
+    {
+       pvfb->pXWDCmap[i].pixel = i;
+    }
+
+    /* byte swap to most significant byte first */
+
+    if (needswap)
+    {
+       SwapLongs((CARD32 *)pXWDHeader, SIZEOF(XWDheader)/4);
+       for (i = 0; i < pvfb->ncolors; i++)
+       {
+           register char n;
+           swapl(&pvfb->pXWDCmap[i].pixel, n);
+       }
+    }
+}
+
+
+static Bool
+vfbCursorOffScreen (ScreenPtr *ppScreen, int *x, int *y)
+{
+    return FALSE;
+}
+
+static void
+vfbCrossScreen (ScreenPtr pScreen, Bool entering)
+{
+}
+
+static Bool vfbRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) {
+    return TRUE;
+}
+
+static Bool vfbUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) {
+    return TRUE;
+}
+
+static void vfbSetCursor(ScreenPtr pScreen, CursorPtr pCursor, int x, int y) 
+{
+}
+
+static void vfbMoveCursor(ScreenPtr pScreen, int x, int y) 
+{
+}
+
+static miPointerSpriteFuncRec vfbPointerSpriteFuncs = {
+    vfbRealizeCursor,
+    vfbUnrealizeCursor,
+    vfbSetCursor,
+    vfbMoveCursor
+};
+
+static miPointerScreenFuncRec vfbPointerCursorFuncs = {
+    vfbCursorOffScreen,
+    vfbCrossScreen,
+    miPointerWarpCursor
+};
+
+static Bool
+vfbCloseScreen(int index, ScreenPtr pScreen)
+{
+    vfbScreenInfoPtr pvfb = &vfbScreens[index];
+    int i;
+    pScreen->CloseScreen = pvfb->closeScreen;
+
+    /*
+     * XXX probably lots of stuff to clean.  For now,
+     * clear InstalledMaps[] so that server reset works correctly.
+     */
+    for (i = 0; i < MAXSCREENS; i++)
+       InstalledMaps[i] = NULL;
+
+    return pScreen->CloseScreen(index, pScreen);
+}
+
+static Bool
+vfbScreenInit(int index, ScreenPtr pScreen, int argc, char **argv)
+{
+    vfbScreenInfoPtr pvfb = &vfbScreens[index];
+    int dpi = 100;
+    int ret;
+    char *pbits;
+
+    if (monitorResolution) dpi = monitorResolution;
+
+    pvfb->paddedBytesWidth = PixmapBytePad(pvfb->width, pvfb->depth);
+    pvfb->bitsPerPixel = vfbBitsPerPixel(pvfb->depth);
+    pvfb->paddedWidth = pvfb->paddedBytesWidth * 8 / pvfb->bitsPerPixel;
+    pbits = vfbAllocateFramebufferMemory(pvfb);
+    if (!pbits) return FALSE;
+    vncFbptr[index] = pbits;
+
+    defaultColorVisualClass
+       = (pvfb->bitsPerPixel > 8) ? TrueColor : PseudoColor;
+
+    ret = fbScreenInit(pScreen, pbits, pvfb->width, pvfb->height,
+                      dpi, dpi, pvfb->paddedWidth, pvfb->bitsPerPixel);
+  
+#ifdef RENDER
+    if (ret && Render) 
+       fbPictureInit (pScreen, 0, 0);
+#endif
+
+    if (!ret) return FALSE;
+
+    /* miInitializeBackingStore(pScreen); */
+
+    /*
+     * Circumvent the backing store that was just initialised.  This amounts
+     * to a truely bizarre way of initialising SaveDoomedAreas and friends.
+     */
+
+    pScreen->InstallColormap = vfbInstallColormap;
+    pScreen->UninstallColormap = vfbUninstallColormap;
+    pScreen->ListInstalledColormaps = vfbListInstalledColormaps;
+
+    pScreen->SaveScreen = vfbSaveScreen;
+    pScreen->StoreColors = vfbStoreColors;
+    
+    miPointerInitialize(pScreen, &vfbPointerSpriteFuncs, &vfbPointerCursorFuncs,
+                       FALSE);
+    
+    vfbWriteXWDFileHeader(pScreen);
+
+    pScreen->blackPixel = pvfb->blackPixel;
+    pScreen->whitePixel = pvfb->whitePixel;
+
+    if (!pvfb->pixelFormatDefined && pvfb->depth == 16) {
+       pvfb->pixelFormatDefined = TRUE;
+       pvfb->rgbNotBgr = TRUE;
+       pvfb->blueBits = pvfb->redBits = 5;
+       pvfb->greenBits = 6;
+    }
+    
+    if (pvfb->pixelFormatDefined) {
+       VisualPtr vis = pScreen->visuals;
+       for (int i = 0; i < pScreen->numVisuals; i++) {
+           if (pvfb->rgbNotBgr) {
+               vis->offsetBlue = 0;
+               vis->blueMask = (1 << pvfb->blueBits) - 1;
+               vis->offsetGreen = pvfb->blueBits;
+               vis->greenMask = ((1 << pvfb->greenBits) - 1) << vis->offsetGreen;
+               vis->offsetRed = vis->offsetGreen + pvfb->greenBits;
+               vis->redMask = ((1 << pvfb->redBits) - 1) << vis->offsetRed;
+           } else {
+               vis->offsetRed = 0;
+               vis->redMask = (1 << pvfb->redBits) - 1;
+               vis->offsetGreen = pvfb->redBits;
+               vis->greenMask = ((1 << pvfb->greenBits) - 1) << vis->offsetGreen;
+               vis->offsetBlue = vis->offsetGreen + pvfb->greenBits;
+               vis->blueMask = ((1 << pvfb->blueBits) - 1) << vis->offsetBlue;
+           }
+           vis++;
+       }
+    }
+    
+    ret = fbCreateDefColormap(pScreen);
+
+    miSetZeroLineBias(pScreen, pvfb->lineBias);
+
+    pvfb->closeScreen = pScreen->CloseScreen;
+    pScreen->CloseScreen = vfbCloseScreen;
+
+#ifndef NO_INIT_BACKING_STORE
+  miInitializeBackingStore(pScreen);
+  pScreen->backingStoreSupport = Always;
+#endif
+
+  return ret;
+
+} /* end vfbScreenInit */
+
+
+static void vfbClientStateChange(CallbackListPtr*, pointer, pointer) {
+  dispatchException &= ~DE_RESET;
+}
+
+void
+InitOutput(ScreenInfo *screenInfo, int argc, char **argv)
+{
+  ErrorF("\nXvnc %s - built %s\n%s", XVNCVERSION, buildtime, XVNCCOPYRIGHT);
+  ErrorF("Underlying X server release %d, %s\n\n", VENDOR_RELEASE,
+         VENDOR_STRING);
+    int i;
+    int NumFormats = 0;
+
+    /* initialize pixmap formats */
+
+    /* must have a pixmap depth to match every screen depth */
+    for (i = 0; i < vfbNumScreens; i++)
+    {
+       vfbPixmapDepths[vfbScreens[i].depth] = TRUE;
+    }
+
+    /* RENDER needs a good set of pixmaps. */
+    if (Render) {
+       vfbPixmapDepths[1] = TRUE;
+       vfbPixmapDepths[4] = TRUE;
+       vfbPixmapDepths[8] = TRUE;
+/*     vfbPixmapDepths[15] = TRUE; */
+       vfbPixmapDepths[16] = TRUE;
+       vfbPixmapDepths[24] = TRUE;
+       vfbPixmapDepths[32] = TRUE;
+    }
+
+    for (i = 1; i <= 32; i++)
+    {
+       if (vfbPixmapDepths[i])
+       {
+           if (NumFormats >= MAXFORMATS)
+               FatalError ("MAXFORMATS is too small for this server\n");
+           screenInfo->formats[NumFormats].depth = i;
+           screenInfo->formats[NumFormats].bitsPerPixel = vfbBitsPerPixel(i);
+           screenInfo->formats[NumFormats].scanlinePad = BITMAP_SCANLINE_PAD;
+           NumFormats++;
+       }
+    }
+
+    screenInfo->imageByteOrder = IMAGE_BYTE_ORDER;
+    screenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
+    screenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
+    screenInfo->bitmapBitOrder = BITMAP_BIT_ORDER;
+    screenInfo->numPixmapFormats = NumFormats;
+
+    /* initialize screens */
+
+    for (i = 0; i < vfbNumScreens; i++)
+    {
+       if (-1 == AddScreen(vfbScreenInit, argc, argv))
+       {
+           FatalError("Couldn't add screen %d", i);
+       }
+    }
+
+    if (!AddCallback(&ClientStateCallback, vfbClientStateChange, 0)) {
+       FatalError("AddCallback failed\n");
+    }
+} /* end InitOutput */
+
+#ifdef DPMSExtension
+extern "C" {
+#if NeedFunctionPrototypes
+  void DPMSSet(CARD16 level)
+#else
+    void DPMSSet(level)
+    CARD16 level;
+#endif
+  {
+    return;
+  }
+
+  Bool DPMSSupported()
+  {
+    return FALSE;
+  }
+}
+#endif
+
+/* this is just to get the server to link on AIX */
+#ifdef AIXV3
+int SelectWaitTime = 10000; /* usec */
+#endif
+
+Bool LegalModifier(unsigned int key, DevicePtr pDev)
+{
+  return TRUE;
+}
+
+void ProcessInputEvents()
+{
+  mieqProcessInputEvents();
+  miPointerUpdate();
+}
+
+/* Fairly standard US PC Keyboard */
+
+#define VFB_MIN_KEY 8
+#define VFB_MAX_KEY 255
+#define VFB_MAP_LEN (VFB_MAX_KEY - VFB_MIN_KEY + 1)
+#define KEYSYMS_PER_KEY 2
+KeySym keyboardMap[VFB_MAP_LEN * KEYSYMS_PER_KEY] = {
+  NoSymbol, NoSymbol,
+  XK_Escape, NoSymbol,
+  XK_1, XK_exclam,
+  XK_2, XK_at,
+  XK_3, XK_numbersign,
+  XK_4, XK_dollar,
+  XK_5, XK_percent,
+  XK_6, XK_asciicircum,
+  XK_7, XK_ampersand,
+  XK_8, XK_asterisk,
+  XK_9, XK_parenleft,
+  XK_0, XK_parenright,
+  XK_minus, XK_underscore,
+  XK_equal, XK_plus,
+  XK_BackSpace, NoSymbol,
+  XK_Tab, NoSymbol,
+  XK_q, XK_Q,
+  XK_w, XK_W,
+  XK_e, XK_E,
+  XK_r, XK_R,
+  XK_t, XK_T,
+  XK_y, XK_Y,
+  XK_u, XK_U,
+  XK_i, XK_I,
+  XK_o, XK_O,
+  XK_p, XK_P,
+  XK_bracketleft, XK_braceleft,
+  XK_bracketright, XK_braceright,
+  XK_Return, NoSymbol,
+  XK_Control_L, NoSymbol,
+  XK_a, XK_A,
+  XK_s, XK_S,
+  XK_d, XK_D,
+  XK_f, XK_F,
+  XK_g, XK_G,
+  XK_h, XK_H,
+  XK_j, XK_J,
+  XK_k, XK_K,
+  XK_l, XK_L,
+  XK_semicolon, XK_colon,
+  XK_apostrophe, XK_quotedbl,
+  XK_grave, XK_asciitilde,
+  XK_Shift_L, NoSymbol,
+  XK_backslash, XK_bar,
+  XK_z, XK_Z,
+  XK_x, XK_X,
+  XK_c, XK_C,
+  XK_v, XK_V,
+  XK_b, XK_B,
+  XK_n, XK_N,
+  XK_m, XK_M,
+  XK_comma, XK_less,
+  XK_period, XK_greater,
+  XK_slash, XK_question,
+  XK_Shift_R, NoSymbol,
+  XK_KP_Multiply, NoSymbol,
+  XK_Alt_L, XK_Meta_L,
+  XK_space, NoSymbol,
+  /*XK_Caps_Lock*/ NoSymbol, NoSymbol,
+  XK_F1, NoSymbol,
+  XK_F2, NoSymbol,
+  XK_F3, NoSymbol,
+  XK_F4, NoSymbol,
+  XK_F5, NoSymbol,
+  XK_F6, NoSymbol,
+  XK_F7, NoSymbol,
+  XK_F8, NoSymbol,
+  XK_F9, NoSymbol,
+  XK_F10, NoSymbol,
+  XK_Num_Lock, XK_Pointer_EnableKeys,
+  XK_Scroll_Lock, NoSymbol,
+  XK_KP_Home, XK_KP_7,
+  XK_KP_Up, XK_KP_8,
+  XK_KP_Prior, XK_KP_9,
+  XK_KP_Subtract, NoSymbol,
+  XK_KP_Left, XK_KP_4,
+  XK_KP_Begin, XK_KP_5,
+  XK_KP_Right, XK_KP_6,
+  XK_KP_Add, NoSymbol,
+  XK_KP_End, XK_KP_1,
+  XK_KP_Down, XK_KP_2,
+  XK_KP_Next, XK_KP_3,
+  XK_KP_Insert, XK_KP_0,
+  XK_KP_Delete, XK_KP_Decimal,
+  NoSymbol, NoSymbol,
+  NoSymbol, NoSymbol,
+  NoSymbol, NoSymbol,
+  XK_F11, NoSymbol,
+  XK_F12, NoSymbol,
+  XK_Home, NoSymbol,
+  XK_Up, NoSymbol,
+  XK_Prior, NoSymbol,
+  XK_Left, NoSymbol,
+  NoSymbol, NoSymbol,
+  XK_Right, NoSymbol,
+  XK_End, NoSymbol,
+  XK_Down, NoSymbol,
+  XK_Next, NoSymbol,
+  XK_Insert, NoSymbol,
+  XK_Delete, NoSymbol,
+  XK_KP_Enter, NoSymbol,
+  XK_Control_R, NoSymbol,
+  XK_Pause, XK_Break,
+  XK_Print, XK_Execute,
+  XK_KP_Divide, NoSymbol,
+  XK_Alt_R, XK_Meta_R,
+};
+
+static Bool GetMappings(KeySymsPtr pKeySyms, CARD8 *pModMap)
+{
+  int i;
+
+  for (i = 0; i < MAP_LENGTH; i++)
+    pModMap[i] = NoSymbol;
+
+  for (i = 0; i < VFB_MAP_LEN; i++) {
+    if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Caps_Lock)
+      pModMap[i + VFB_MIN_KEY] = LockMask;
+    else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_L ||
+             keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_R)
+      pModMap[i + VFB_MIN_KEY] = ShiftMask;
+    else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_L ||
+             keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_R) {
+      pModMap[i + VFB_MIN_KEY] = ControlMask;
+    }
+    else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_L ||
+             keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_R)
+      pModMap[i + VFB_MIN_KEY] = Mod1Mask;
+  }
+
+  pKeySyms->minKeyCode = VFB_MIN_KEY;
+  pKeySyms->maxKeyCode = VFB_MAX_KEY;
+  pKeySyms->mapWidth = KEYSYMS_PER_KEY;
+  pKeySyms->map = keyboardMap;
+
+  return TRUE;
+}
+
+static void vfbBell(int percent, DeviceIntPtr device, pointer ctrl, int class_)
+{
+  if (percent > 0)
+    vncBell();
+}
+
+static int vfbKeybdProc(DeviceIntPtr pDevice, int onoff)
+{
+  KeySymsRec           keySyms;
+  CARD8                modMap[MAP_LENGTH];
+  DevicePtr pDev = (DevicePtr)pDevice;
+
+  switch (onoff)
+  {
+  case DEVICE_INIT: 
+    GetMappings(&keySyms, modMap);
+    InitKeyboardDeviceStruct(pDev, &keySyms, modMap,
+                             (BellProcPtr)vfbBell, (KbdCtrlProcPtr)NoopDDA);
+    break;
+  case DEVICE_ON: 
+    pDev->on = TRUE;
+    break;
+  case DEVICE_OFF: 
+    pDev->on = FALSE;
+    break;
+  case DEVICE_CLOSE:
+    break;
+  }
+  return Success;
+}
+
+static int vfbMouseProc(DeviceIntPtr pDevice, int onoff)
+{
+  BYTE map[6];
+  DevicePtr pDev = (DevicePtr)pDevice;
+
+  switch (onoff)
+  {
+  case DEVICE_INIT:
+    map[1] = 1;
+    map[2] = 2;
+    map[3] = 3;
+    map[4] = 4;
+    map[5] = 5;
+    InitPointerDeviceStruct(pDev, map, 5, miPointerGetMotionEvents,
+                            (PtrCtrlProcPtr)NoopDDA, miPointerGetMotionBufferSize());
+    break;
+
+  case DEVICE_ON:
+    pDev->on = TRUE;
+    break;
+
+  case DEVICE_OFF:
+    pDev->on = FALSE;
+    break;
+
+  case DEVICE_CLOSE:
+    break;
+  }
+  return Success;
+}
+
+// InitInput is called after InitExtensions, so we're guaranteed that
+// vncExtensionInit() has already been called.
+
+void InitInput(int argc, char *argv[])
+{
+  DeviceIntPtr p, k;
+  p = AddInputDevice(vfbMouseProc, TRUE);
+  k = AddInputDevice(vfbKeybdProc, TRUE);
+  RegisterPointerDevice(p);
+  RegisterKeyboardDevice(k);
+  miRegisterPointerDevice(screenInfo.screens[0], p);
+  (void)mieqInit ((DevicePtr)k, (DevicePtr)p);
+}