]> git.sesse.net Git - rdpsrv/blobdiff - Xserver/programs/Xserver/hw/vnc/init.c
Import X server from vnc-3.3.7.
[rdpsrv] / Xserver / programs / Xserver / hw / vnc / init.c
diff --git a/Xserver/programs/Xserver/hw/vnc/init.c b/Xserver/programs/Xserver/hw/vnc/init.c
new file mode 100644 (file)
index 0000000..a55b715
--- /dev/null
@@ -0,0 +1,921 @@
+/*
+ * init.c
+ */
+
+/*
+ *  Copyright (C) 2002-2003 RealVNC Ltd.
+ *  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.
+ *
+ *  This is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This software is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this software; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
+ *  USA.
+ */
+
+/*
+
+Copyright (c) 1993  X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from the X Consortium.
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include "X11/X.h"
+#define NEED_EVENTS
+#include "X11/Xproto.h"
+#include "X11/Xos.h"
+#include "scrnintstr.h"
+#include "servermd.h"
+#define PSZ 8
+#include "cfb.h"
+#include "mi.h"
+#include "mibstore.h"
+#include "colormapst.h"
+#include "gcstruct.h"
+#include "input.h"
+#include "mipointer.h"
+#include "dixstruct.h"
+#include "propertyst.h"
+#include <Xatom.h>
+#include <errno.h>
+#include <sys/param.h>
+#include "dix.h"
+#include "rfb.h"
+#include "dispcur.h"
+
+extern Bool cfb16ScreenInit(ScreenPtr, pointer, int, int, int, int, int);
+extern Bool cfb32ScreenInit(ScreenPtr, pointer, int, int, int, int, int);
+
+#define RFB_DEFAULT_WIDTH  640
+#define RFB_DEFAULT_HEIGHT 480
+#define RFB_DEFAULT_DEPTH  8
+#define RFB_DEFAULT_WHITEPIXEL 0
+#define RFB_DEFAULT_BLACKPIXEL 1
+
+rfbScreenInfo rfbScreen;
+int rfbGCIndex;
+
+static Bool initOutputCalled = FALSE;
+static Bool noCursor = FALSE;
+char *desktopName = "x11";
+Bool rfbTrace = FALSE;
+
+char rfbThisHost[256];
+
+Atom VNC_LAST_CLIENT_ID;
+Atom VNC_CONNECT;
+Atom VNC_DEFER_UPDATE;
+
+static HWEventQueueType alwaysCheckForInput[2] = { 0, 1 };
+static HWEventQueueType *mieqCheckForInput[2];
+
+static char primaryOrder[4] = "";
+static int redBits, greenBits, blueBits;
+
+
+static Bool rfbScreenInit(int index, ScreenPtr pScreen, int argc,
+                         char **argv);
+static int rfbKeybdProc(DeviceIntPtr pDevice, int onoff);
+static int rfbMouseProc(DeviceIntPtr pDevice, int onoff);
+static Bool CheckDisplayNumber(int n);
+
+static Bool rfbAlwaysTrue();
+static char *rfbAllocateFramebufferMemory(rfbScreenInfoPtr prfb);
+static Bool rfbCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y);
+static void rfbCrossScreen(ScreenPtr pScreen, Bool entering);
+static void rfbClientStateChange(CallbackListPtr *, pointer myData,
+                                pointer client);
+
+static miPointerScreenFuncRec rfbPointerCursorFuncs = {
+    rfbCursorOffScreen,
+    rfbCrossScreen,
+    miPointerWarpCursor
+};
+
+
+int inetdSock = -1;
+static char inetdDisplayNumStr[10];
+
+extern char buildtime[];
+
+
+/*
+ * ddxProcessArgument is our first entry point and will be called at the
+ * very start for each argument.  It is not called again on server reset.
+ */
+
+int
+ddxProcessArgument (argc, argv, i)
+    int argc;
+    char *argv[];
+    int i;
+{
+    static Bool firstTime = TRUE;
+
+    if (firstTime)
+    {
+       rfbScreen.width  = RFB_DEFAULT_WIDTH;
+       rfbScreen.height = RFB_DEFAULT_HEIGHT;
+       rfbScreen.depth  = RFB_DEFAULT_DEPTH;
+       rfbScreen.blackPixel = RFB_DEFAULT_BLACKPIXEL;
+       rfbScreen.whitePixel = RFB_DEFAULT_WHITEPIXEL;
+       rfbScreen.pfbMemory = NULL;
+       gethostname(rfbThisHost, 255);
+        firstTime = FALSE;
+    }
+
+    if (strcasecmp (argv[i], "-geometry") == 0)        /* -geometry WxH */
+    {
+       if (i + 1 >= argc) UseMsg();
+       if (sscanf(argv[i+1],"%dx%d",
+                  &rfbScreen.width,&rfbScreen.height) != 2) {
+           ErrorF("Invalid geometry %s\n", argv[i+1]);
+           UseMsg();
+       }
+       return 2;
+    }
+
+    if (strcasecmp (argv[i], "-depth") == 0)   /* -depth D */
+    {
+       if (i + 1 >= argc) UseMsg();
+       rfbScreen.depth = atoi(argv[i+1]);
+       return 2;
+    }
+
+    if (strcasecmp (argv[i], "-pixelformat") == 0) {
+       if (i + 1 >= argc) UseMsg();
+       if (sscanf(argv[i+1], "%3s%1d%1d%1d", primaryOrder,
+                  &redBits, &greenBits, &blueBits) < 4) {
+           ErrorF("Invalid pixel format %s\n", argv[i+1]);
+           UseMsg();
+       }
+
+       if (strcasecmp(primaryOrder, "bgr") == 0) {
+           int tmp = redBits;
+           redBits = blueBits;
+           blueBits = tmp;
+       } else if (strcasecmp(primaryOrder, "rgb") != 0) {
+           ErrorF("Invalid pixel format %s\n", argv[i+1]);
+           UseMsg();
+       }
+
+       return 2;
+    }
+
+    if (strcasecmp (argv[i], "-blackpixel") == 0) {    /* -blackpixel n */
+       if (i + 1 >= argc) UseMsg();
+       rfbScreen.blackPixel = atoi(argv[i+1]);
+       return 2;
+    }
+
+    if (strcasecmp (argv[i], "-whitepixel") == 0) {    /* -whitepixel n */
+       if (i + 1 >= argc) UseMsg();
+       rfbScreen.whitePixel = atoi(argv[i+1]);
+       return 2;
+    }
+
+    if (strcasecmp(argv[i], "-rfbport") == 0) {        /* -rfbport port */
+       if (i + 1 >= argc) UseMsg();
+       rfbPort = atoi(argv[i+1]);
+       return 2;
+    }
+
+    if (strcasecmp(argv[i], "-rfbwait") == 0) {        /* -rfbwait ms */
+       if (i + 1 >= argc) UseMsg();
+       rfbMaxClientWait = atoi(argv[i+1]);
+       return 2;
+    }
+
+    if (strcasecmp(argv[i], "-nocursor") == 0) {
+       noCursor = TRUE;
+       return 1;
+    }
+
+    if (strcasecmp(argv[i], "-rfbauth") == 0) {        /* -rfbauth passwd-file */
+       if (i + 1 >= argc) UseMsg();
+       rfbAuthPasswdFile = argv[i+1];
+       return 2;
+    }
+
+    if (strcasecmp(argv[i], "-httpd") == 0) {
+       if (i + 1 >= argc) UseMsg();
+       httpDir = argv[i+1];
+       return 2;
+    }
+
+    if (strcasecmp(argv[i], "-httpport") == 0) {
+       if (i + 1 >= argc) UseMsg();
+       httpPort = atoi(argv[i+1]);
+       return 2;
+    }
+
+    if (strcasecmp(argv[i], "-deferupdate") == 0) {    /* -deferupdate ms */
+       if (i + 1 >= argc) UseMsg();
+       rfbDeferUpdateTime = atoi(argv[i+1]);
+       return 2;
+    }
+
+    if (strcasecmp(argv[i], "-economictranslate") == 0) {
+       rfbEconomicTranslate = TRUE;
+       return 1;
+    }
+
+    if (strcasecmp(argv[i], "-maxrects") == 0) {
+       if (i + 1 >= argc) UseMsg();
+       rfbMaxRects = atoi(argv[i+1]);
+       return 2;
+    }
+
+    if (strcasecmp(argv[i], "-trace") == 0) {
+        rfbTrace = TRUE;
+       return 1;
+    }
+
+    if (strcasecmp(argv[i], "-desktop") == 0) {        /* -desktop desktop-name */
+       if (i + 1 >= argc) UseMsg();
+       desktopName = argv[i+1];
+       return 2;
+    }
+
+    if (strcasecmp(argv[i], "-alwaysshared") == 0) {
+       rfbAlwaysShared = TRUE;
+       return 1;
+    }
+
+    if (strcasecmp(argv[i], "-nevershared") == 0) {
+       rfbNeverShared = TRUE;
+       return 1;
+    }
+
+    if (strcasecmp(argv[i], "-dontdisconnect") == 0) {
+       rfbDontDisconnect = TRUE;
+       return 1;
+    }
+
+    if (strcasecmp(argv[i], "-localhost") == 0) {
+       rfbLocalhostOnly = TRUE;
+       return 1;
+    }
+
+    if (strcasecmp(argv[i], "-inetd") == 0) {  /* -inetd */ 
+       int n;
+       for (n = 1; n < 100; n++) {
+           if (CheckDisplayNumber(n))
+               break;
+       }
+
+       if (n >= 100)
+           FatalError("-inetd: couldn't find free display number");
+
+       sprintf(inetdDisplayNumStr, "%d", n);
+       display = inetdDisplayNumStr;
+
+       /* fds 0, 1 and 2 (stdin, out and err) are all the same socket to the
+           RFB client.  OsInit() closes stdout and stdin, and we don't want
+           stderr to go to the RFB client, so make the client socket 3 and
+           close stderr.  OsInit() will redirect stderr logging to an
+           appropriate log file or /dev/null if that doesn't work. */
+
+       dup2(0,3);
+       inetdSock = 3;
+       close(2);
+
+       return 1;
+    }
+
+    if (inetdSock != -1 && argv[i][0] == ':') {
+       FatalError("can't specify both -inetd and :displaynumber");
+    }
+
+    return 0;
+}
+
+
+/*
+ * InitOutput is called every time the server resets.  It should call
+ * AddScreen for each screen (but we only ever have one), and in turn this
+ * will call rfbScreenInit.
+ */
+
+void
+InitOutput(screenInfo, argc, argv)
+    ScreenInfo *screenInfo;
+    int argc;
+    char **argv;
+{
+    initOutputCalled = TRUE;
+
+    rfbLog("Xvnc version %s - built %s\n", XVNCRELEASE, buildtime);
+    rfbLog("Copyright (C) 2002-2003 RealVNC Ltd.\n");
+    rfbLog("Copyright (C) 1994-2000 AT&T Laboratories Cambridge.\n");
+    rfbLog("All Rights Reserved.\n");
+    rfbLog("See http://www.realvnc.com for information on VNC\n");
+    rfbLog("Desktop name '%s' (%s:%s)\n",desktopName,rfbThisHost,display);
+    rfbLog("Protocol version supported %d.%d\n", rfbProtocolMajorVersion,
+          rfbProtocolMinorVersion);
+
+    VNC_LAST_CLIENT_ID = MakeAtom("VNC_LAST_CLIENT_ID",
+                                 strlen("VNC_LAST_CLIENT_ID"), TRUE);
+    VNC_CONNECT = MakeAtom("VNC_CONNECT", strlen("VNC_CONNECT"), TRUE);
+    VNC_DEFER_UPDATE = MakeAtom("VNC_DEFER_UPDATE",
+                                strlen("VNC_DEFER_UPDATE"), TRUE);
+    rfbInitSockets();
+    if (inetdSock == -1)
+       httpInitSockets();
+   
+
+    /* initialize pixmap formats */
+
+    screenInfo->imageByteOrder = IMAGE_BYTE_ORDER;
+    screenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
+    screenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
+    screenInfo->bitmapBitOrder = BITMAP_BIT_ORDER;
+    screenInfo->numPixmapFormats = 2;
+
+    screenInfo->formats[0].depth = 1;
+    screenInfo->formats[0].bitsPerPixel = 1;
+    screenInfo->formats[0].scanlinePad = BITMAP_SCANLINE_PAD;
+
+    screenInfo->formats[1].depth = rfbScreen.depth;
+    screenInfo->formats[1].bitsPerPixel = rfbBitsPerPixel(rfbScreen.depth);
+    screenInfo->formats[1].scanlinePad = BITMAP_SCANLINE_PAD;
+
+    rfbGCIndex = AllocateGCPrivateIndex();
+    if (rfbGCIndex < 0) {
+       FatalError("InitOutput: AllocateGCPrivateIndex failed\n");
+    }
+
+    if (!AddCallback(&ClientStateCallback, rfbClientStateChange, NULL)) {
+       rfbLog("InitOutput: AddCallback failed\n");
+       return;
+    }
+
+    /* initialize screen */
+
+    if (AddScreen(rfbScreenInit, argc, argv) == -1) {
+       FatalError("Couldn't add screen");
+    }
+}
+
+
+static Bool
+rfbScreenInit(index, pScreen, argc, argv)
+    int index;
+    ScreenPtr pScreen;
+    int argc;
+    char ** argv;
+{
+    rfbScreenInfoPtr prfb = &rfbScreen;
+    int dpix = 75, dpiy = 75;
+    int ret;
+    char *pbits;
+    VisualPtr vis;
+    extern int monitorResolution;
+
+    if (monitorResolution != 0) {
+       dpix = monitorResolution;
+       dpiy = monitorResolution;
+    }
+
+    prfb->paddedWidthInBytes = PixmapBytePad(prfb->width, prfb->depth);
+    prfb->bitsPerPixel = rfbBitsPerPixel(prfb->depth);
+    pbits = rfbAllocateFramebufferMemory(prfb);
+    if (!pbits) return FALSE;
+
+    if (prfb->bitsPerPixel > 1) {
+       extern int defaultColorVisualClass;
+       if (defaultColorVisualClass != -1) {
+           cfbSetVisualTypes(prfb->depth, (1 << defaultColorVisualClass), 8);
+       } else {
+           cfbSetVisualTypes(prfb->depth, (1 << TrueColor), 8);
+       }
+    }
+
+    switch (prfb->bitsPerPixel)
+    {
+    case 1:
+       ret = mfbScreenInit(pScreen, pbits, prfb->width, prfb->height,
+                           dpix, dpiy, prfb->paddedWidthInBytes * 8);
+       break;
+    case 8:
+       ret = cfbScreenInit(pScreen, pbits, prfb->width, prfb->height,
+                           dpix, dpiy, prfb->paddedWidthInBytes);
+       break;
+    case 16:
+       ret = cfb16ScreenInit(pScreen, pbits, prfb->width, prfb->height,
+                             dpix, dpiy, prfb->paddedWidthInBytes / 2);
+       break;
+    case 32:
+       ret = cfb32ScreenInit(pScreen, pbits, prfb->width, prfb->height,
+                             dpix, dpiy, prfb->paddedWidthInBytes / 4);
+       break;
+    default:
+       return FALSE;
+    }
+
+    if (!ret) return FALSE;
+
+    if (!AllocateGCPrivate(pScreen, rfbGCIndex, sizeof(rfbGCRec))) {
+       FatalError("rfbScreenInit: AllocateGCPrivate failed\n");
+    }
+
+    prfb->cursorIsDrawn = FALSE;
+    prfb->dontSendFramebufferUpdate = FALSE;
+
+    prfb->CloseScreen = pScreen->CloseScreen;
+    prfb->CreateGC = pScreen->CreateGC;
+    prfb->PaintWindowBackground = pScreen->PaintWindowBackground;
+    prfb->PaintWindowBorder = pScreen->PaintWindowBorder;
+    prfb->CopyWindow = pScreen->CopyWindow;
+    prfb->ClearToBackground = pScreen->ClearToBackground;
+    prfb->RestoreAreas = pScreen->RestoreAreas;
+
+    pScreen->CloseScreen = rfbCloseScreen;
+    pScreen->CreateGC = rfbCreateGC;
+    pScreen->PaintWindowBackground = rfbPaintWindowBackground;
+    pScreen->PaintWindowBorder = rfbPaintWindowBorder;
+    pScreen->CopyWindow = rfbCopyWindow;
+    pScreen->ClearToBackground = rfbClearToBackground;
+    pScreen->RestoreAreas = rfbRestoreAreas;
+
+    pScreen->InstallColormap = rfbInstallColormap;
+    pScreen->UninstallColormap = rfbUninstallColormap;
+    pScreen->ListInstalledColormaps = rfbListInstalledColormaps;
+    pScreen->StoreColors = rfbStoreColors;
+
+    pScreen->SaveScreen = rfbAlwaysTrue;
+
+    rfbDCInitialize(pScreen, &rfbPointerCursorFuncs);
+
+    if (noCursor) {
+       pScreen->DisplayCursor = rfbAlwaysTrue;
+       prfb->cursorIsDrawn = TRUE;
+    }
+
+    pScreen->blackPixel = prfb->blackPixel;
+    pScreen->whitePixel = prfb->whitePixel;
+
+    for (vis = pScreen->visuals; vis->vid != pScreen->rootVisual; vis++)
+       ;
+
+    if (!vis) {
+       rfbLog("rfbScreenInit: couldn't find root visual\n");
+       exit(1);
+    }
+
+    if (strcmp(primaryOrder, "") == 0) {
+      if (prfb->depth == 16) { /* use rgb565 for depth 16 */
+        strcpy(primaryOrder, "rgb");
+        redBits = 5;
+        greenBits = 6;
+        blueBits = 5;
+      } else if (prfb->depth == 24) { /* use rgb888 for depth 24 */
+        strcpy(primaryOrder, "rgb");
+        redBits = 8;
+        greenBits = 8;
+        blueBits = 8;
+      }
+    }
+
+    if (strcasecmp(primaryOrder, "rgb") == 0) {
+       vis->offsetBlue = 0;
+       vis->blueMask = (1 << blueBits) - 1;
+       vis->offsetGreen = blueBits;
+       vis->greenMask = ((1 << greenBits) - 1) << vis->offsetGreen;
+       vis->offsetRed = vis->offsetGreen + greenBits;
+       vis->redMask = ((1 << redBits) - 1) << vis->offsetRed;
+    } else if (strcasecmp(primaryOrder, "bgr") == 0) {
+       rfbLog("BGR format %d %d %d\n", blueBits, greenBits, redBits);
+       vis->offsetRed = 0;
+       vis->redMask = (1 << redBits) - 1;
+       vis->offsetGreen = redBits;
+       vis->greenMask = ((1 << greenBits) - 1) << vis->offsetGreen;
+       vis->offsetBlue = vis->offsetGreen + greenBits;
+       vis->blueMask = ((1 << blueBits) - 1) << vis->offsetBlue;
+    }
+
+    rfbServerFormat.bitsPerPixel = prfb->bitsPerPixel;
+    rfbServerFormat.depth = prfb->depth;
+    rfbServerFormat.bigEndian = !(*(char *)&rfbEndianTest);
+    rfbServerFormat.trueColour = (vis->class == TrueColor);
+    if (rfbServerFormat.trueColour) {
+       rfbServerFormat.redMax = vis->redMask >> vis->offsetRed;
+       rfbServerFormat.greenMax = vis->greenMask >> vis->offsetGreen;
+       rfbServerFormat.blueMax = vis->blueMask >> vis->offsetBlue;
+       rfbServerFormat.redShift = vis->offsetRed;
+       rfbServerFormat.greenShift = vis->offsetGreen;
+       rfbServerFormat.blueShift = vis->offsetBlue;
+    } else {
+       rfbServerFormat.redMax
+           = rfbServerFormat.greenMax = rfbServerFormat.blueMax = 0;
+       rfbServerFormat.redShift
+           = rfbServerFormat.greenShift = rfbServerFormat.blueShift = 0;
+    }
+
+    if (prfb->bitsPerPixel == 1)
+    {
+       ret = mfbCreateDefColormap(pScreen);
+    }
+    else
+    {
+       ret = cfbCreateDefColormap(pScreen);
+    }
+
+    return ret;
+
+} /* end rfbScreenInit */
+
+
+
+/*
+ * InitInput is also called every time the server resets.  It is called after
+ * InitOutput so we can assume that rfbInitSockets has already been called.
+ */
+
+void
+InitInput(argc, argv)
+    int argc;
+    char *argv[];
+{
+    DeviceIntPtr p, k;
+    k = AddInputDevice(rfbKeybdProc, TRUE);
+    p = AddInputDevice(rfbMouseProc, TRUE);
+    RegisterKeyboardDevice(k);
+    RegisterPointerDevice(p);
+    miRegisterPointerDevice(screenInfo.screens[0], p);
+    mieqInit((DevicePtr)k, (DevicePtr)p);
+    mieqCheckForInput[0] = checkForInput[0];
+    mieqCheckForInput[1] = checkForInput[1];
+    SetInputCheck(&alwaysCheckForInput[0], &alwaysCheckForInput[1]);
+}
+
+
+static int
+rfbKeybdProc(pDevice, onoff)
+    DeviceIntPtr pDevice;
+    int onoff;
+{
+    KeySymsRec         keySyms;
+    CARD8              modMap[MAP_LENGTH];
+    DevicePtr pDev = (DevicePtr)pDevice;
+
+    switch (onoff)
+    {
+    case DEVICE_INIT: 
+       KbdDeviceInit(pDevice, &keySyms, modMap);
+       InitKeyboardDeviceStruct(pDev, &keySyms, modMap,
+                                (BellProcPtr)rfbSendBell,
+                                (KbdCtrlProcPtr)NoopDDA);
+           break;
+    case DEVICE_ON: 
+       pDev->on = TRUE;
+       KbdDeviceOn();
+       break;
+    case DEVICE_OFF: 
+       pDev->on = FALSE;
+       KbdDeviceOff();
+       break;
+    case DEVICE_CLOSE:
+       if (pDev->on)
+           KbdDeviceOff();
+       break;
+    }
+    return Success;
+}
+
+static int
+rfbMouseProc(pDevice, onoff)
+    DeviceIntPtr pDevice;
+    int onoff;
+{
+    BYTE map[6];
+    DevicePtr pDev = (DevicePtr)pDevice;
+
+    switch (onoff)
+    {
+    case DEVICE_INIT:
+       PtrDeviceInit();
+       map[1] = 1;
+       map[2] = 2;
+       map[3] = 3;
+       map[4] = 4;
+       map[5] = 5;
+       InitPointerDeviceStruct(pDev, map, 5, miPointerGetMotionEvents,
+                               PtrDeviceControl,
+                               miPointerGetMotionBufferSize());
+       break;
+
+    case DEVICE_ON:
+       pDev->on = TRUE;
+       PtrDeviceOn(pDevice);
+        break;
+
+    case DEVICE_OFF:
+       pDev->on = FALSE;
+       PtrDeviceOff();
+       break;
+
+    case DEVICE_CLOSE:
+       if (pDev->on)
+           PtrDeviceOff();
+       break;
+    }
+    return Success;
+}
+
+
+Bool
+LegalModifier(key, pDev)
+    unsigned int key;
+    DevicePtr  pDev;
+{
+    return TRUE;
+}
+
+
+void
+ProcessInputEvents()
+{
+    rfbCheckFds();
+    httpCheckFds();
+    if (*mieqCheckForInput[0] != *mieqCheckForInput[1]) {
+       mieqProcessInputEvents();
+       miPointerUpdate();
+    }
+}
+
+
+static Bool CheckDisplayNumber(int n)
+{
+    char fname[32];
+    int sock;
+    struct sockaddr_in addr;
+
+    sock = socket(AF_INET, SOCK_STREAM, 0);
+    addr.sin_family = AF_INET;
+    addr.sin_addr.s_addr = htonl(INADDR_ANY);
+    addr.sin_port = htons(6000+n);
+    if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+       close(sock);
+       return FALSE;
+    }
+    close(sock);
+
+    sprintf(fname, "/tmp/.X%d-lock", n);
+    if (access(fname, F_OK) == 0)
+       return FALSE;
+
+    sprintf(fname, "/tmp/.X11-unix/X%d", n);
+    if (access(fname, F_OK) == 0)
+       return FALSE;
+
+    sprintf(fname, "/usr/spool/sockets/X11/%d", n);
+    if (access(fname, F_OK) == 0)
+       return FALSE;
+
+    return TRUE;
+}
+
+
+void
+rfbRootPropertyChange(PropertyPtr pProp)
+{
+    if ((pProp->propertyName == XA_CUT_BUFFER0) && (pProp->type == XA_STRING)
+       && (pProp->format == 8))
+    {
+       rfbGotXCutText(pProp->data, pProp->size);
+    }
+    else if ((pProp->propertyName == VNC_CONNECT) && (pProp->type == XA_STRING)
+             && (pProp->format == 8))
+    {
+       if (pProp->size == 0) {
+          rfbClientPtr cl, nextCl;
+          rfbLog("VNC_CONNECT message: disconnecting all clients\n");
+          for (cl = rfbClientHead; cl; cl = nextCl) {
+            nextCl = cl->next;
+            rfbCloseSock(cl->sock);
+          }
+        } else {
+          int i;
+          rfbClientPtr cl;
+          int port = 5500;
+          char *host = (char *)Xalloc(pProp->size+1);
+          memcpy(host, pProp->data, pProp->size);
+          host[pProp->size] = 0;
+          for (i = 0; i < pProp->size; i++) {
+           if (host[i] == ':') {
+              port = atoi(&host[i+1]);
+              host[i] = 0;
+           }
+          }
+
+          cl = rfbReverseConnection(host, port);
+
+          free(host);
+        }
+        return;
+    }
+    else if ((pProp->propertyName == VNC_DEFER_UPDATE) &&
+             (pProp->type == XA_STRING) && (pProp->format == 8))
+    {
+      char *str = (char *)Xalloc(pProp->size+1);
+      memcpy(str, pProp->data, pProp->size);
+      str[pProp->size] = 0;
+      rfbDeferUpdateTime = atoi(str);
+      free(str);
+    }
+}
+
+
+int
+rfbBitsPerPixel(depth)
+    int depth;
+{
+    if (depth == 1) return 1;
+    else if (depth <= 8) return 8;
+    else if (depth <= 16) return 16;
+    else return 32;
+}
+
+
+static Bool
+rfbAlwaysTrue()
+{
+    return TRUE;
+}
+
+
+static char *
+rfbAllocateFramebufferMemory(prfb)
+    rfbScreenInfoPtr prfb;
+{
+    if (prfb->pfbMemory) return prfb->pfbMemory; /* already done */
+
+    prfb->sizeInBytes = (prfb->paddedWidthInBytes * prfb->height);
+
+    prfb->pfbMemory = (char *)Xalloc(prfb->sizeInBytes);
+
+    return prfb->pfbMemory;
+}
+
+
+static Bool
+rfbCursorOffScreen (ppScreen, x, y)
+    ScreenPtr   *ppScreen;
+    int         *x, *y;
+{
+    return FALSE;
+}
+
+static void
+rfbCrossScreen (pScreen, entering)
+    ScreenPtr   pScreen;
+    Bool        entering;
+{
+}
+
+static void
+rfbClientStateChange(cbl, myData, clt)
+    CallbackListPtr *cbl;
+    pointer myData;
+    pointer clt;
+{
+    dispatchException &= ~DE_RESET;    /* hack - force server not to reset */
+}
+
+void
+ddxGiveUp()
+{
+    Xfree(rfbScreen.pfbMemory);
+    if (initOutputCalled) {
+       char unixSocketName[256];
+       sprintf(unixSocketName,"/tmp/.X11-unix/X%s",display);
+       unlink(unixSocketName);
+       sprintf(unixSocketName,"/usr/spool/sockets/X11/%s",display);
+       unlink(unixSocketName);
+    }
+}
+
+void
+AbortDDX()
+{
+    ddxGiveUp();
+}
+
+void
+OsVendorInit()
+{
+}
+
+void
+OsVendorFatalError()
+{
+}
+
+#ifdef DDXTIME /* from ServerOSDefines */
+CARD32
+GetTimeInMillis()
+{
+    struct timeval  tp;
+
+    X_GETTIMEOFDAY(&tp);
+    return(tp.tv_sec * 1000) + (tp.tv_usec / 1000);
+}
+#endif
+
+void
+ddxUseMsg()
+{
+    ErrorF("\nXvnc version %s - built %s\n\n", XVNCRELEASE, buildtime);
+    ErrorF("-geometry WxH          set framebuffer width & height\n");
+    ErrorF("-depth D               set framebuffer depth\n");
+    ErrorF("-pixelformat format    set pixel format (BGRnnn or RGBnnn)\n");
+    ErrorF("-rfbport port          TCP port for RFB protocol\n");
+    ErrorF("-rfbwait time          max time in ms to wait for RFB client\n");
+    ErrorF("-nocursor              don't put up a cursor\n");
+    ErrorF("-rfbauth passwd-file   use authentication on RFB protocol\n");
+    ErrorF("-httpd dir             serve files via HTTP from here\n");
+    ErrorF("-httpport port         port for HTTP\n");
+    ErrorF("-deferupdate time      time in ms to defer updates "
+                                                            "(default 40)\n");
+    ErrorF("-economictranslate     less memory-hungry translation\n");
+    ErrorF("-maxrects num          max number of rectangles in an update "
+                                                            "(default 50)\n");
+    ErrorF("-desktop name          VNC desktop name (default x11)\n");
+    ErrorF("-alwaysshared          always treat new clients as shared\n");
+    ErrorF("-nevershared           never treat new clients as shared\n");
+    ErrorF("-dontdisconnect        don't disconnect existing clients when a "
+                                                             "new non-shared\n"
+          "                       connection comes in (refuse new connection "
+                                                                "instead)\n");
+    ErrorF("-localhost             only allow connections from localhost\n");
+    ErrorF("-inetd                 Xvnc is launched by inetd\n");
+    exit(1);
+}
+
+/*
+ * rfbLog prints a time-stamped message to the log file (stderr).
+ */
+
+void rfbLog(char *format, ...)
+{
+    va_list args;
+    char buf[256];
+    time_t clock;
+
+    va_start(args, format);
+
+    time(&clock);
+    strftime(buf, 255, "%d/%m/%y %T ", localtime(&clock));
+    fprintf(stderr, buf);
+
+    vfprintf(stderr, format, args);
+    fflush(stderr);
+
+    va_end(args);
+}
+
+void rfbLogPerror(char *str)
+{
+    rfbLog("");
+    perror(str);
+}